diff --git a/src/meson.build b/src/meson.build index 4e4fe96e5839f957dfc0b7251f1675d5ca7a2021..f8626684e98975de34da96816d9f8792c1cef72f 100644 --- a/src/meson.build +++ b/src/meson.build @@ -14,6 +14,7 @@ libnautilus_sources = [ c_template: 'nautilus-enum-types.c.template', h_template: 'nautilus-enum-types.h.template', sources: [ + 'nautilus-enums.h', 'nautilus-search-popover.h', 'nautilus-special-location-bar.h', 'nautilus-query.h', diff --git a/src/nautilus-application.c b/src/nautilus-application.c index 973e1b52199c0409b2b1afd9eca28dcd9fbebf26..89a26615f15e41f043fd1763171f27cf60c4c775 100644 --- a/src/nautilus-application.c +++ b/src/nautilus-application.c @@ -341,12 +341,12 @@ get_window_slot_for_location (NautilusApplication *self, } void -nautilus_application_open_location_full (NautilusApplication *self, - GFile *location, - NautilusWindowOpenFlags flags, - GList *selection, - NautilusWindow *target_window, - NautilusWindowSlot *target_slot) +nautilus_application_open_location_full (NautilusApplication *self, + GFile *location, + NautilusOpenFlags flags, + GList *selection, + NautilusWindow *target_window, + NautilusWindowSlot *target_slot) { NAUTILUS_APPLICATION_CLASS (G_OBJECT_GET_CLASS (self))->open_location_full (self, location, @@ -357,12 +357,12 @@ nautilus_application_open_location_full (NautilusApplication *self, } static void -real_open_location_full (NautilusApplication *self, - GFile *location, - NautilusWindowOpenFlags flags, - GList *selection, - NautilusWindow *target_window, - NautilusWindowSlot *target_slot) +real_open_location_full (NautilusApplication *self, + GFile *location, + NautilusOpenFlags flags, + GList *selection, + NautilusWindow *target_window, + NautilusWindowSlot *target_slot) { NautilusWindowSlot *active_slot = NULL; NautilusWindow *active_window; @@ -415,11 +415,11 @@ real_open_location_full (NautilusApplication *self, target_window = nautilus_window_slot_get_window (target_slot); } - g_assert (!((flags & NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW) != 0 && - (flags & NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB) != 0)); + g_assert (!((flags & NAUTILUS_OPEN_FLAG_NEW_WINDOW) != 0 && + (flags & NAUTILUS_OPEN_FLAG_NEW_TAB) != 0)); /* and if the flags specify so, this is overridden */ - if ((flags & NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW) != 0) + if ((flags & NAUTILUS_OPEN_FLAG_NEW_WINDOW) != 0) { use_same = FALSE; } @@ -454,7 +454,7 @@ real_open_location_full (NautilusApplication *self, /* Application is the one that manages windows, so this flag shouldn't use * it anymore by any client */ - flags &= ~NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW; + flags &= ~NAUTILUS_OPEN_FLAG_NEW_WINDOW; nautilus_window_open_location_full (target_window, location, flags, selection, target_slot); } @@ -690,7 +690,7 @@ action_new_window (GSimpleAction *action, home = g_file_new_for_path (g_get_home_dir ()); nautilus_application_open_location_full (application, home, - NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW, + NAUTILUS_OPEN_FLAG_NEW_WINDOW, NULL, NULL, NULL); } @@ -732,7 +732,7 @@ action_clone_window (GSimpleAction *action, } nautilus_application_open_location_full (NAUTILUS_APPLICATION (application), location, - NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW, NULL, NULL, NULL); + NAUTILUS_OPEN_FLAG_NEW_WINDOW, NULL, NULL, NULL); } static void diff --git a/src/nautilus-application.h b/src/nautilus-application.h index f915b0d4d1bce6f9a045bb73880c3eade854b6ef..cbef1231200b31a8e4a4331b14eae63a63431fd0 100644 --- a/src/nautilus-application.h +++ b/src/nautilus-application.h @@ -35,7 +35,7 @@ struct _NautilusApplicationClass { void (*open_location_full) (NautilusApplication *application, GFile *location, - NautilusWindowOpenFlags flags, + NautilusOpenFlags flags, GList *selection, NautilusWindow *target_window, NautilusWindowSlot *target_slot); @@ -63,7 +63,7 @@ void nautilus_application_open_location (NautilusApplication *application, void nautilus_application_open_location_full (NautilusApplication *application, GFile *location, - NautilusWindowOpenFlags flags, + NautilusOpenFlags flags, GList *selection, NautilusWindow *target_window, NautilusWindowSlot *target_slot); diff --git a/src/nautilus-canvas-view.c b/src/nautilus-canvas-view.c index ce162d41482c8443cf51be4193aa5d213c1bb08e..b3e07cf193d25e24aa7360e613def535d19fd2a6 100644 --- a/src/nautilus-canvas-view.c +++ b/src/nautilus-canvas-view.c @@ -1074,7 +1074,7 @@ canvas_container_activate_alternate_callback (NautilusCanvasContainer *container GdkEventButton *button_event; GdkEventKey *key_event; gboolean open_in_tab, open_in_window; - NautilusWindowOpenFlags flags; + NautilusOpenFlags flags; g_assert (NAUTILUS_IS_CANVAS_VIEW (canvas_view)); g_assert (container == get_canvas_container (canvas_view)); @@ -1102,13 +1102,13 @@ canvas_container_activate_alternate_callback (NautilusCanvasContainer *container if (open_in_tab) { - flags |= NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB; - flags |= NAUTILUS_WINDOW_OPEN_FLAG_DONT_MAKE_ACTIVE; + flags |= NAUTILUS_OPEN_FLAG_NEW_TAB; + flags |= NAUTILUS_OPEN_FLAG_DONT_MAKE_ACTIVE; } if (open_in_window) { - flags |= NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW; + flags |= NAUTILUS_OPEN_FLAG_NEW_WINDOW; } DEBUG ("Activate alternate, open in tab %d, new window %d\n", diff --git a/src/nautilus-enums.h b/src/nautilus-enums.h index edfd999198e7eaae35c590480161ab5a2ab4394d..9f43800caf929287fdb9e00c9672684c3550e195 100644 --- a/src/nautilus-enums.h +++ b/src/nautilus-enums.h @@ -76,8 +76,9 @@ typedef enum typedef enum { - NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW = 1 << 0, - NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB = 1 << 1, - NAUTILUS_WINDOW_OPEN_SLOT_APPEND = 1 << 2, - NAUTILUS_WINDOW_OPEN_FLAG_DONT_MAKE_ACTIVE = 1 << 3, -} NautilusWindowOpenFlags; + NAUTILUS_OPEN_FLAG_NORMAL = 1 << 0, + NAUTILUS_OPEN_FLAG_NEW_WINDOW = 1 << 1, + NAUTILUS_OPEN_FLAG_NEW_TAB = 1 << 2, + NAUTILUS_OPEN_FLAG_SLOT_APPEND = 1 << 3, + NAUTILUS_OPEN_FLAG_DONT_MAKE_ACTIVE = 1 << 4, +} NautilusOpenFlags; diff --git a/src/nautilus-files-view-dnd.c b/src/nautilus-files-view-dnd.c index 485a7661f3b6f2244b179a19d9d93ab0fcecafa8..9c803b54ddef5636376eba7d34edd520dd005111 100644 --- a/src/nautilus-files-view-dnd.c +++ b/src/nautilus-files-view-dnd.c @@ -401,7 +401,7 @@ nautilus_files_view_handle_hover (NautilusFilesView *view, !(current_location != NULL && g_file_equal (location, current_location))) { nautilus_application_open_location_full (NAUTILUS_APPLICATION (g_application_get_default ()), - location, NAUTILUS_WINDOW_OPEN_FLAG_DONT_MAKE_ACTIVE, + location, NAUTILUS_OPEN_FLAG_DONT_MAKE_ACTIVE, NULL, NULL, slot); } g_object_unref (location); diff --git a/src/nautilus-files-view.c b/src/nautilus-files-view.c index 63b26fb582b25ded88bcecc4596e5d2fddf82a5f..37513963671c237585517ef7fd9522decde5c058 100644 --- a/src/nautilus-files-view.c +++ b/src/nautilus-files-view.c @@ -1335,10 +1335,10 @@ nautilus_files_view_activate_selection (NautilusFilesView *view) } void -nautilus_files_view_activate_files (NautilusFilesView *view, - GList *files, - NautilusWindowOpenFlags flags, - gboolean confirm_multiple) +nautilus_files_view_activate_files (NautilusFilesView *view, + GList *files, + NautilusOpenFlags flags, + gboolean confirm_multiple) { NautilusFilesViewPrivate *priv; GList *files_to_extract; @@ -1389,9 +1389,9 @@ nautilus_files_view_activate_files (NautilusFilesView *view, } void -nautilus_files_view_activate_file (NautilusFilesView *view, - NautilusFile *file, - NautilusWindowOpenFlags flags) +nautilus_files_view_activate_file (NautilusFilesView *view, + NautilusFile *file, + NautilusOpenFlags flags) { g_autoptr (GList) files = NULL; @@ -1473,8 +1473,8 @@ action_open_item_new_tab (GSimpleAction *action, { nautilus_files_view_activate_files (view, selection, - NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB | - NAUTILUS_WINDOW_OPEN_FLAG_DONT_MAKE_ACTIVE, + NAUTILUS_OPEN_FLAG_NEW_TAB | + NAUTILUS_OPEN_FLAG_DONT_MAKE_ACTIVE, FALSE); } } @@ -4900,7 +4900,7 @@ open_one_in_new_window (gpointer data, nautilus_files_view_activate_file (NAUTILUS_FILES_VIEW (callback_data), NAUTILUS_FILE (data), - NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW); + NAUTILUS_OPEN_FLAG_NEW_WINDOW); } NautilusFile * diff --git a/src/nautilus-files-view.h b/src/nautilus-files-view.h index f1b31d46429d3691983561380358ebe000e4877f..92a5a3e53938f65d99b5d83f23f33622dc87be5a 100644 --- a/src/nautilus-files-view.h +++ b/src/nautilus-files-view.h @@ -259,13 +259,13 @@ gboolean nautilus_files_view_get_loading (Nautil /* Hooks for subclasses to call. These are normally called only by * NautilusFilesView and its subclasses */ -void nautilus_files_view_activate_files (NautilusFilesView *view, - GList *files, - NautilusWindowOpenFlags flags, - gboolean confirm_multiple); -void nautilus_files_view_activate_file (NautilusFilesView *view, - NautilusFile *file, - NautilusWindowOpenFlags flags); +void nautilus_files_view_activate_files (NautilusFilesView *view, + GList *files, + NautilusOpenFlags flags, + gboolean confirm_multiple); +void nautilus_files_view_activate_file (NautilusFilesView *view, + NautilusFile *file, + NautilusOpenFlags flags); void nautilus_files_view_preview_files (NautilusFilesView *view, GList *files, GArray *locations); diff --git a/src/nautilus-gtk4-helpers.c b/src/nautilus-gtk4-helpers.c index 60da7672aa757da2fb6023a383f3ddb90e85194b..b81c955dcdbd0ad5a63bd041a6628a211d763b18 100644 --- a/src/nautilus-gtk4-helpers.c +++ b/src/nautilus-gtk4-helpers.c @@ -9,6 +9,15 @@ gtk_button_set_child (GtkButton *button, gtk_container_add (GTK_CONTAINER (button), child); } +void +gtk_menu_button_set_child (GtkMenuButton *menu_button, + GtkWidget *child) +{ + g_assert (GTK_IS_MENU_BUTTON (menu_button)); + + gtk_container_add (GTK_CONTAINER (menu_button), child); +} + void gtk_box_append (GtkBox *box, GtkWidget *child) diff --git a/src/nautilus-gtk4-helpers.h b/src/nautilus-gtk4-helpers.h index 201183c1569d3db0bfbc0abcb77e19a75098d4a7..ff1e0049fd6b79c7cf162bbe43424d005b46fcaf 100644 --- a/src/nautilus-gtk4-helpers.h +++ b/src/nautilus-gtk4-helpers.h @@ -9,6 +9,8 @@ G_BEGIN_DECLS void gtk_button_set_child (GtkButton *button, GtkWidget *child); +void gtk_menu_button_set_child (GtkMenuButton *menu_button, + GtkWidget *child); void gtk_box_append (GtkBox *box, GtkWidget *child); void gtk_box_remove (GtkBox *box, diff --git a/src/nautilus-list-view.c b/src/nautilus-list-view.c index 23619e57b9c664ba0b68dc563d932dcd4a2db329..eef9dd5dfbbed5773f4c8bdf44e7ae486af5863a 100644 --- a/src/nautilus-list-view.c +++ b/src/nautilus-list-view.c @@ -212,18 +212,18 @@ activate_selected_items_alternate (NautilusListView *view, gboolean open_in_tab) { GList *file_list; - NautilusWindowOpenFlags flags; + NautilusOpenFlags flags; flags = 0; if (open_in_tab) { - flags |= NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB; - flags |= NAUTILUS_WINDOW_OPEN_FLAG_DONT_MAKE_ACTIVE; + flags |= NAUTILUS_OPEN_FLAG_NEW_TAB; + flags |= NAUTILUS_OPEN_FLAG_DONT_MAKE_ACTIVE; } else { - flags |= NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW; + flags |= NAUTILUS_OPEN_FLAG_NEW_WINDOW; } if (file != NULL) diff --git a/src/nautilus-location-entry.c b/src/nautilus-location-entry.c index 2e06e60123b531b6e236d9043bcc35c7fb40ab28..de2a9daec3794e4937fdea4c57ab1f5bccb4d043 100644 --- a/src/nautilus-location-entry.c +++ b/src/nautilus-location-entry.c @@ -309,7 +309,7 @@ drag_data_received_callback (GtkWidget *widget, { location = g_file_new_for_uri (names[i]); nautilus_application_open_location_full (NAUTILUS_APPLICATION (g_application_get_default ()), - location, NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW, NULL, NULL, NULL); + location, NAUTILUS_OPEN_FLAG_NEW_WINDOW, NULL, NULL, NULL); g_object_unref (location); } } diff --git a/src/nautilus-mime-actions.c b/src/nautilus-mime-actions.c index eb331e9d1eb2269236ebfdcc45d864409df97ac6..f57b94e6d8753fd8f5cf5c17ea24b2215d20a606 100644 --- a/src/nautilus-mime-actions.c +++ b/src/nautilus-mime-actions.c @@ -76,7 +76,7 @@ typedef struct GList *mountables; GList *start_mountables; GList *not_mounted; - NautilusWindowOpenFlags flags; + NautilusOpenFlags flags; char *timed_wait_prompt; gboolean timed_wait_active; NautilusFileListHandle *files_handle; @@ -990,7 +990,7 @@ typedef struct GtkWindow *parent_window; NautilusFile *file; GList *files; - NautilusWindowOpenFlags flags; + NautilusOpenFlags flags; char *activation_directory; gboolean user_confirmation; char *uri; @@ -1433,7 +1433,7 @@ static void activate_files (ActivateParameters *parameters) { NautilusFile *file; - NautilusWindowOpenFlags flags; + NautilusOpenFlags flags; g_autoptr (GList) open_in_app_parameters = NULL; g_autoptr (GList) unhandled_open_in_app_uris = NULL; ApplicationLaunchParameters *one_parameters; @@ -1563,22 +1563,22 @@ activate_files (ActivateParameters *parameters) flags = parameters->flags; if (count > 1) { - if ((parameters->flags & NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW) == 0) + if ((parameters->flags & NAUTILUS_OPEN_FLAG_NEW_WINDOW) == 0) { - flags |= NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB; + flags |= NAUTILUS_OPEN_FLAG_NEW_TAB; } else { - flags |= NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW; + flags |= NAUTILUS_OPEN_FLAG_NEW_WINDOW; } } if (parameters->slot != NULL && (!parameters->user_confirmation || confirm_multiple_windows (parameters->parent_window, count, - (flags & NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB) != 0))) + (flags & NAUTILUS_OPEN_FLAG_NEW_TAB) != 0))) { - if ((flags & NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB) != 0 && + if ((flags & NAUTILUS_OPEN_FLAG_NEW_TAB) != 0 && g_settings_get_enum (nautilus_preferences, NAUTILUS_PREFERENCES_NEW_TAB_POSITION) == NAUTILUS_NEW_TAB_POSITION_AFTER_CURRENT_TAB) { @@ -2171,12 +2171,12 @@ activation_start_mountables (ActivateParameters *parameters) * **/ void -nautilus_mime_activate_files (GtkWindow *parent_window, - NautilusWindowSlot *slot, - GList *files, - const char *launch_directory, - NautilusWindowOpenFlags flags, - gboolean user_confirmation) +nautilus_mime_activate_files (GtkWindow *parent_window, + NautilusWindowSlot *slot, + GList *files, + const char *launch_directory, + NautilusOpenFlags flags, + gboolean user_confirmation) { ActivateParameters *parameters; char *file_name; @@ -2268,11 +2268,11 @@ nautilus_mime_activate_files (GtkWindow *parent_window, **/ void -nautilus_mime_activate_file (GtkWindow *parent_window, - NautilusWindowSlot *slot, - NautilusFile *file, - const char *launch_directory, - NautilusWindowOpenFlags flags) +nautilus_mime_activate_file (GtkWindow *parent_window, + NautilusWindowSlot *slot, + NautilusFile *file, + const char *launch_directory, + NautilusOpenFlags flags) { GList *files; diff --git a/src/nautilus-mime-actions.h b/src/nautilus-mime-actions.h index 9765894cb07a432241b1e75a51070c8f5f84903d..24b891b3bd41595d22bc0a79f2bfd34d75173711 100644 --- a/src/nautilus-mime-actions.h +++ b/src/nautilus-mime-actions.h @@ -39,16 +39,16 @@ gboolean nautilus_mime_file_extracts (Nauti gboolean nautilus_mime_file_opens_in_external_app (NautilusFile *file); gboolean nautilus_mime_file_launches (NautilusFile *file); void nautilus_mime_activate_files (GtkWindow *parent_window, - NautilusWindowSlot *slot, - GList *files, - const char *launch_directory, - NautilusWindowOpenFlags flags, - gboolean user_confirmation); + NautilusWindowSlot *slot, + GList *files, + const char *launch_directory, + NautilusOpenFlags flags, + gboolean user_confirmation); void nautilus_mime_activate_file (GtkWindow *parent_window, - NautilusWindowSlot *slot_info, - NautilusFile *file, - const char *launch_directory, - NautilusWindowOpenFlags flags); + NautilusWindowSlot *slot_info, + NautilusFile *file, + const char *launch_directory, + NautilusOpenFlags flags); gint nautilus_mime_types_get_number_of_groups (void); const gchar* nautilus_mime_types_group_get_name (gint group_index); GPtrArray* nautilus_mime_types_group_get_mimetypes (gint group_index); diff --git a/src/nautilus-pathbar.c b/src/nautilus-pathbar.c index 6d0dd92d50d4629c7efc55a414b70fd3f7492169..4dea6168fe2b670c5246a57ca3d0022448e2983a 100644 --- a/src/nautilus-pathbar.c +++ b/src/nautilus-pathbar.c @@ -25,19 +25,21 @@ #include "nautilus-pathbar.h" #include "nautilus-properties-window.h" +#include "nautilus-enums.h" +#include "nautilus-enum-types.h" #include "nautilus-file.h" #include "nautilus-file-utilities.h" #include "nautilus-global-preferences.h" #include "nautilus-icon-names.h" #include "nautilus-trash-monitor.h" #include "nautilus-ui-utilities.h" +#include "nautilus-gtk4-helpers.h" #include "nautilus-window-slot-dnd.h" enum { OPEN_LOCATION, - PATH_CLICKED, LAST_SIGNAL }; @@ -58,7 +60,7 @@ typedef enum static guint path_bar_signals[LAST_SIGNAL] = { 0 }; -#define NAUTILUS_PATH_BAR_BUTTON_MAX_WIDTH 175 +#define NAUTILUS_PATH_BAR_BUTTON_ELLISPIZE_MINIMUM_CHARS 7 typedef struct { @@ -72,7 +74,6 @@ typedef struct GtkWidget *image; GtkWidget *label; GtkWidget *separator; - GtkWidget *disclosure_arrow; GtkWidget *container; NautilusPathBar *path_bar; @@ -85,7 +86,10 @@ typedef struct struct _NautilusPathBar { - GtkContainer parent_instance; + GtkBox parent_instance; + + GtkWidget *scrolled; + GtkWidget *buttons_box; GFile *current_path; gpointer current_button_data; @@ -97,6 +101,7 @@ struct _NautilusPathBar NautilusFile *context_menu_file; GtkPopover *current_view_menu_popover; + GtkWidget *current_view_menu_button; GtkPopover *button_menu_popover; GMenu *current_view_menu; GMenu *extensions_section; @@ -104,7 +109,7 @@ struct _NautilusPathBar GMenu *button_menu; }; -G_DEFINE_TYPE (NautilusPathBar, nautilus_path_bar, GTK_TYPE_CONTAINER); +G_DEFINE_TYPE (NautilusPathBar, nautilus_path_bar, GTK_TYPE_BOX); static void nautilus_path_bar_check_icon_theme (NautilusPathBar *self); static void nautilus_path_bar_update_button_appearance (ButtonData *button_data, @@ -154,7 +159,7 @@ action_pathbar_open_item_new_tab (GSimpleAction *action, if (location) { - g_signal_emit (user_data, path_bar_signals[OPEN_LOCATION], 0, location, GTK_PLACES_OPEN_NEW_TAB); + g_signal_emit (user_data, path_bar_signals[OPEN_LOCATION], 0, location, NAUTILUS_OPEN_FLAG_NEW_TAB); g_object_unref (location); } } @@ -178,7 +183,7 @@ action_pathbar_open_item_new_window (GSimpleAction *action, if (location) { - g_signal_emit (user_data, path_bar_signals[OPEN_LOCATION], 0, location, GTK_PLACES_OPEN_NEW_WINDOW); + g_signal_emit (user_data, path_bar_signals[OPEN_LOCATION], 0, location, NAUTILUS_OPEN_FLAG_NEW_WINDOW); g_object_unref (location); } } @@ -203,12 +208,49 @@ action_pathbar_properties (GSimpleAction *action, nautilus_file_list_free (files); } +static void +on_adjustment_changed (GtkAdjustment *adjustment) +{ + /* Automatically scroll to the end, to keep the current folder visible */ + gtk_adjustment_set_value (adjustment, gtk_adjustment_get_upper (adjustment)); +} + +static gboolean +bind_current_view_menu_model_to_popover (NautilusPathBar *self) +{ + gtk_popover_bind_model (self->current_view_menu_popover, + G_MENU_MODEL (self->current_view_menu), + NULL); + return G_SOURCE_REMOVE; +} + static void nautilus_path_bar_init (NautilusPathBar *self) { + GtkAdjustment *adjustment; GtkBuilder *builder; g_autoptr (GError) error = NULL; + self->scrolled = gtk_scrolled_window_new (NULL, NULL); + /* Scroll horizontally only and don't use internal scrollbar. */ + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (self->scrolled), + /* hscrollbar-policy */ GTK_POLICY_EXTERNAL, + /* vscrollbar-policy */ GTK_POLICY_NEVER); + gtk_widget_set_hexpand (self->scrolled, TRUE); + gtk_box_append (GTK_BOX (self), self->scrolled); + + adjustment = gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (self->scrolled)); + g_signal_connect (adjustment, "changed", (GCallback) on_adjustment_changed, NULL); + + self->buttons_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); + gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (self->scrolled), self->buttons_box); + + self->current_view_menu_button = gtk_menu_button_new (); + gtk_menu_button_set_child (GTK_MENU_BUTTON (self->current_view_menu_button), + gtk_image_new_from_icon_name ("view-more-symbolic", + GTK_ICON_SIZE_MENU)); + gtk_box_append (GTK_BOX (self), self->current_view_menu_button); + builder = gtk_builder_new (); /* Add context menu for pathbar buttons */ @@ -238,12 +280,16 @@ nautilus_path_bar_init (NautilusPathBar *self) g_object_unref (builder); - gtk_widget_set_has_window (GTK_WIDGET (self), FALSE); + gtk_menu_button_set_popover (GTK_MENU_BUTTON (self->current_view_menu_button), + GTK_WIDGET (self->current_view_menu_popover)); + bind_current_view_menu_model_to_popover (self); gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (self)), - GTK_STYLE_CLASS_LINKED); + "linked"); gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (self)), "nautilus-path-bar"); + gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (self->buttons_box)), + "path-buttons-box"); /* Action group */ self->action_group = G_ACTION_GROUP (g_simple_action_group_new ()); @@ -341,237 +387,6 @@ get_dir_name (ButtonData *button_data) } } -/* We always want to request the same size for the label, whether - * or not the contents are bold - */ -static void -set_label_size_request (ButtonData *button_data) -{ - gint width; - GtkRequisition nat_req; - - if (button_data->label == NULL) - { - return; - } - - gtk_widget_get_preferred_size (button_data->label, NULL, &nat_req); - - width = MIN (nat_req.width, NAUTILUS_PATH_BAR_BUTTON_MAX_WIDTH); - - gtk_widget_set_size_request (button_data->label, width, nat_req.height); -} - -/* Size requisition: - * - * Ideally, our size is determined by another widget, and we are just filling - * available space. - */ -static void -nautilus_path_bar_get_preferred_width (GtkWidget *widget, - gint *minimum, - gint *natural) -{ - ButtonData *button_data; - NautilusPathBar *self; - GList *list; - gint child_height; - gint height; - gint child_min, child_nat; - - self = NAUTILUS_PATH_BAR (widget); - - *minimum = *natural = 0; - height = 0; - - for (list = self->button_list; list; list = list->next) - { - button_data = BUTTON_DATA (list->data); - set_label_size_request (button_data); - - gtk_widget_get_preferred_width (button_data->button, &child_min, &child_nat); - gtk_widget_get_preferred_height (button_data->button, &child_height, NULL); - height = MAX (height, child_height); - - if (button_data->type == NORMAL_BUTTON) - { - /* Use 2*Height as button width because of ellipsized label. */ - child_min = MAX (child_min, child_height * 2); - child_nat = MAX (child_min, child_height * 2); - } - - *minimum = MAX (*minimum, child_min); - *natural = *natural + child_nat; - } -} - -static void -nautilus_path_bar_get_preferred_height (GtkWidget *widget, - gint *minimum, - gint *natural) -{ - ButtonData *button_data; - NautilusPathBar *self; - GList *list; - gint child_min, child_nat; - - self = NAUTILUS_PATH_BAR (widget); - - *minimum = *natural = 0; - - for (list = self->button_list; list; list = list->next) - { - button_data = BUTTON_DATA (list->data); - set_label_size_request (button_data); - - gtk_widget_get_preferred_height (button_data->button, &child_min, &child_nat); - - *minimum = MAX (*minimum, child_min); - *natural = MAX (*natural, child_nat); - } -} - -/* This is a tad complicated */ -static void -nautilus_path_bar_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) -{ - NautilusPathBar *self; - GtkWidget *child; - GtkTextDirection direction; - GtkAllocation child_allocation; - GList *list, *first_button; - gint width; - gint largest_width; - GtkRequisition child_requisition; - - self = NAUTILUS_PATH_BAR (widget); - - /* No path is set so we don't have to allocate anything. */ - if (self->button_list == NULL) - { - return; - } - direction = gtk_widget_get_direction (widget); - - width = 0; - - gtk_widget_get_preferred_size (BUTTON_DATA (self->button_list->data)->button, - &child_requisition, NULL); - width += child_requisition.width; - - for (list = self->button_list->next; list; list = list->next) - { - child = BUTTON_DATA (list->data)->button; - gtk_widget_get_preferred_size (child, &child_requisition, NULL); - width += child_requisition.width; - } - - if (width <= allocation->width) - { - first_button = g_list_last (self->button_list); - } - else - { - gboolean reached_end; - reached_end = FALSE; - - first_button = self->button_list; - - /* To see how much space we have, and how many buttons we can display. - * We start at the first button, count forward until hit the new - * button, then count backwards. - */ - /* Count down the path chain towards the end. */ - gtk_widget_get_preferred_size (BUTTON_DATA (first_button->data)->button, - &child_requisition, NULL); - width = child_requisition.width; - list = first_button->prev; - while (list && !reached_end) - { - child = BUTTON_DATA (list->data)->button; - gtk_widget_get_preferred_size (child, &child_requisition, NULL); - - if (width + child_requisition.width > allocation->width) - { - reached_end = TRUE; - } - else - { - width += child_requisition.width; - } - - list = list->prev; - } - - /* Finally, we walk up, seeing how many of the previous buttons we can add*/ - - while (first_button->next && !reached_end) - { - child = BUTTON_DATA (first_button->next->data)->button; - gtk_widget_get_preferred_size (child, &child_requisition, NULL); - - if (width + child_requisition.width > allocation->width) - { - reached_end = TRUE; - } - else - { - width += child_requisition.width; - first_button = first_button->next; - } - } - } - - /* Now, we allocate space to the buttons */ - child_allocation.y = allocation->y; - child_allocation.height = allocation->height; - - if (direction == GTK_TEXT_DIR_RTL) - { - child_allocation.x = allocation->x + allocation->width; - } - else - { - child_allocation.x = allocation->x; - } - - /* Determine the largest possible allocation size */ - largest_width = allocation->width; - for (list = first_button; list; list = list->prev) - { - child = BUTTON_DATA (list->data)->button; - gtk_widget_get_preferred_size (child, &child_requisition, NULL); - - child_allocation.width = MIN (child_requisition.width, largest_width); - if (direction == GTK_TEXT_DIR_RTL) - { - child_allocation.x -= child_allocation.width; - } - /* Check to see if we've don't have any more space to allocate buttons */ - - gtk_widget_set_child_visible (child, TRUE); - gtk_widget_size_allocate (child, &child_allocation); - - if (direction == GTK_TEXT_DIR_LTR) - { - child_allocation.x += child_allocation.width; - } - } - /* Now we go hide all the widgets that don't fit */ - while (list) - { - child = BUTTON_DATA (list->data)->button; - gtk_widget_set_child_visible (child, FALSE); - list = list->prev; - } - for (list = first_button->next; list; list = list->next) - { - child = BUTTON_DATA (list->data)->button; - gtk_widget_set_child_visible (child, FALSE); - } -} - static void nautilus_path_bar_style_updated (GtkWidget *widget) { @@ -596,25 +411,6 @@ nautilus_path_bar_screen_changed (GtkWidget *widget, nautilus_path_bar_check_icon_theme (NAUTILUS_PATH_BAR (widget)); } -static void -nautilus_path_bar_add (GtkContainer *container, - GtkWidget *widget) -{ - gtk_widget_set_parent (widget, GTK_WIDGET (container)); -} - -static void -nautilus_path_bar_remove_1 (GtkContainer *container, - GtkWidget *widget) -{ - gboolean was_visible = gtk_widget_get_visible (widget); - gtk_widget_unparent (widget); - if (was_visible) - { - gtk_widget_queue_resize (GTK_WIDGET (container)); - } -} - static void button_data_free (ButtonData *button_data) { @@ -633,156 +429,21 @@ button_data_free (ButtonData *button_data) g_free (button_data); } -static void -nautilus_path_bar_remove (GtkContainer *container, - GtkWidget *widget) -{ - NautilusPathBar *self; - GList *children; - - self = NAUTILUS_PATH_BAR (container); - - children = self->button_list; - while (children != NULL) - { - if (widget == BUTTON_DATA (children->data)->button) - { - nautilus_path_bar_remove_1 (container, widget); - self->button_list = g_list_remove_link (self->button_list, children); - button_data_free (children->data); - g_list_free_1 (children); - return; - } - children = children->next; - } -} - -static void -nautilus_path_bar_forall (GtkContainer *container, - gboolean include_internals, - GtkCallback callback, - gpointer callback_data) -{ - NautilusPathBar *self; - GList *children; - - g_return_if_fail (callback != NULL); - self = NAUTILUS_PATH_BAR (container); - - children = self->button_list; - while (children != NULL) - { - GtkWidget *child; - child = BUTTON_DATA (children->data)->button; - children = children->next; - (*callback)(child, callback_data); - } -} - -static GtkWidgetPath * -nautilus_path_bar_get_path_for_child (GtkContainer *container, - GtkWidget *child) -{ - NautilusPathBar *self; - GtkWidgetPath *path; - - self = NAUTILUS_PATH_BAR (container); - path = gtk_widget_path_copy (gtk_widget_get_path (GTK_WIDGET (self))); - - if (gtk_widget_get_visible (child) && - gtk_widget_get_child_visible (child)) - { - GtkWidgetPath *sibling_path; - GList *visible_children; - GList *l; - int pos; - - /* 1. Build the list of visible children, in visually left-to-right order - * (i.e. independently of the widget's direction). Note that our - * button_list is stored in innermost-to-outermost path order! - */ - - visible_children = NULL; - - for (l = self->button_list; l; l = l->next) - { - ButtonData *data = l->data; - - if (gtk_widget_get_visible (data->button) && - gtk_widget_get_child_visible (data->button)) - { - visible_children = g_list_prepend (visible_children, data->button); - } - } - - if (gtk_widget_get_direction (GTK_WIDGET (self)) == GTK_TEXT_DIR_RTL) - { - visible_children = g_list_reverse (visible_children); - } - - /* 2. Find the index of the child within that list */ - - pos = 0; - - for (l = visible_children; l; l = l->next) - { - GtkWidget *button = l->data; - - if (button == child) - { - break; - } - - pos++; - } - - /* 3. Build the path */ - - sibling_path = gtk_widget_path_new (); - - for (l = visible_children; l; l = l->next) - { - gtk_widget_path_append_for_widget (sibling_path, l->data); - } - - gtk_widget_path_append_with_siblings (path, sibling_path, pos); - - g_list_free (visible_children); - gtk_widget_path_unref (sibling_path); - } - else - { - gtk_widget_path_append_for_widget (path, child); - } - - return path; -} - static void nautilus_path_bar_class_init (NautilusPathBarClass *path_bar_class) { GObjectClass *gobject_class; GtkWidgetClass *widget_class; - GtkContainerClass *container_class; gobject_class = (GObjectClass *) path_bar_class; widget_class = (GtkWidgetClass *) path_bar_class; - container_class = (GtkContainerClass *) path_bar_class; gobject_class->finalize = nautilus_path_bar_finalize; gobject_class->dispose = nautilus_path_bar_dispose; - widget_class->get_preferred_height = nautilus_path_bar_get_preferred_height; - widget_class->get_preferred_width = nautilus_path_bar_get_preferred_width; - widget_class->size_allocate = nautilus_path_bar_size_allocate; widget_class->style_updated = nautilus_path_bar_style_updated; widget_class->screen_changed = nautilus_path_bar_screen_changed; - container_class->add = nautilus_path_bar_add; - container_class->forall = nautilus_path_bar_forall; - container_class->remove = nautilus_path_bar_remove; - container_class->get_path_for_child = nautilus_path_bar_get_path_for_child; - path_bar_signals [OPEN_LOCATION] = g_signal_new ("open-location", G_OBJECT_CLASS_TYPE (path_bar_class), @@ -791,16 +452,7 @@ nautilus_path_bar_class_init (NautilusPathBarClass *path_bar_class) NULL, NULL, NULL, G_TYPE_NONE, 2, G_TYPE_FILE, - GTK_TYPE_PLACES_OPEN_FLAGS); - path_bar_signals [PATH_CLICKED] = - g_signal_new ("path-clicked", - G_OBJECT_CLASS_TYPE (path_bar_class), - G_SIGNAL_RUN_FIRST, - 0, - NULL, NULL, - g_cclosure_marshal_VOID__OBJECT, - G_TYPE_NONE, 1, - G_TYPE_FILE); + NAUTILUS_TYPE_OPEN_FLAGS); } void @@ -822,13 +474,13 @@ nautilus_path_bar_set_templates_menu (NautilusPathBar *self, { /* Workaround to avoid leaking duplicated GtkStack pages each time the * templates menu is set. Unbinding the model is the only way to clear - * all children. For that reason, we need to rebind the popover before - * it is shown again. + * all children. After that's done, on idle, we rebind it. * See https://gitlab.gnome.org/GNOME/nautilus/-/issues/1705 */ gtk_popover_bind_model (self->current_view_menu_popover, NULL, NULL); } nautilus_gmenu_set_from_model (self->templates_submenu, menu); + g_idle_add ((GSourceFunc) bind_current_view_menu_model_to_popover, self); } /* Changes the icons wherever it is needed */ @@ -892,17 +544,27 @@ nautilus_path_bar_clear_buttons (NautilusPathBar *self) button_data = BUTTON_DATA (self->button_list->data); - gtk_container_remove (GTK_CONTAINER (self), button_data->button); + gtk_box_remove (GTK_BOX (self->buttons_box), button_data->container); + + self->button_list = g_list_remove (self->button_list, button_data); + button_data_free (button_data); } } +void +nautilus_path_bar_show_current_location_menu (NautilusPathBar *self) +{ + g_return_if_fail (NAUTILUS_IS_PATH_BAR (self)); + + g_signal_emit_by_name (self->current_view_menu_button, "activate"); +} + static void button_clicked_cb (GtkButton *button, gpointer data) { ButtonData *button_data; NautilusPathBar *self; - GdkModifierType state; button_data = BUTTON_DATA (data); if (button_data->ignore_changes) @@ -912,34 +574,15 @@ button_clicked_cb (GtkButton *button, self = button_data->path_bar; - gtk_get_current_event_state (&state); - - if ((state & GDK_CONTROL_MASK) != 0) + if (g_file_equal (button_data->path, self->current_path)) { - g_signal_emit (button_data->path_bar, path_bar_signals[OPEN_LOCATION], 0, - button_data->path, - GTK_PLACES_OPEN_NEW_WINDOW); + nautilus_path_bar_show_current_location_menu (self); } else { - if (g_file_equal (button_data->path, self->current_path)) - { - /* Workaround to avoid leaking duplicated GtkStack pages each time the - * templates menu is set. Unbinding the model is the only way to clear - * all children. For that reason, we need to rebind the popover before - * it is shown again. - * See https://gitlab.gnome.org/GNOME/nautilus/-/issues/1705 */ - gtk_popover_bind_model (self->current_view_menu_popover, - G_MENU_MODEL (self->current_view_menu), - NULL); - gtk_popover_popup (self->current_view_menu_popover); - } - else - { - g_signal_emit (self, path_bar_signals[OPEN_LOCATION], 0, - button_data->path, - 0); - } + g_signal_emit (self, path_bar_signals[OPEN_LOCATION], 0, + button_data->path, + 0); } } @@ -1028,6 +671,7 @@ on_multi_press_gesture_pressed (GtkGestureMultiPress *gesture, ButtonData *button_data; NautilusPathBar *self; guint current_button; + GdkModifierType state; if (n_press != 1) { @@ -1037,20 +681,17 @@ on_multi_press_gesture_pressed (GtkGestureMultiPress *gesture, button_data = BUTTON_DATA (user_data); self = button_data->path_bar; current_button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture)); + gtk_get_current_event_state (&state); switch (current_button) { case GDK_BUTTON_MIDDLE: { - GdkModifierType state; - - gtk_get_current_event_state (&state); - state &= gtk_accelerator_get_default_mod_mask (); - if (state == 0) + if ((state & gtk_accelerator_get_default_mod_mask ()) == 0) { g_signal_emit (self, path_bar_signals[OPEN_LOCATION], 0, button_data->path, - GTK_PLACES_OPEN_NEW_TAB); + NAUTILUS_OPEN_FLAG_NEW_TAB); } } break; @@ -1059,15 +700,7 @@ on_multi_press_gesture_pressed (GtkGestureMultiPress *gesture, { if (g_file_equal (button_data->path, self->current_path)) { - /* Workaround to avoid leaking duplicated GtkStack pages each time the - * templates menu is set. Unbinding the model is the only way to clear - * all children. For that reason, we need to rebind the popover before - * it is shown again. - * See https://gitlab.gnome.org/GNOME/nautilus/-/issues/1705 */ - gtk_popover_bind_model (self->current_view_menu_popover, - G_MENU_MODEL (self->current_view_menu), - NULL); - gtk_popover_popup (self->current_view_menu_popover); + nautilus_path_bar_show_current_location_menu (self); } else { @@ -1078,11 +711,27 @@ on_multi_press_gesture_pressed (GtkGestureMultiPress *gesture, } break; + case GDK_BUTTON_PRIMARY: + { + if ((state & GDK_CONTROL_MASK) != 0) + { + g_signal_emit (button_data->path_bar, path_bar_signals[OPEN_LOCATION], 0, + button_data->path, + NAUTILUS_OPEN_FLAG_NEW_WINDOW); + } + else + { + /* GtkButton will claim the primary button presses and emit the + * "clicked" signal. Handle it in the singal callback, not here. + */ + return; + } + } + break; + default: { - /* Ignore other buttons in this gesture. GtkButton will claim the - * primary button presses and emit the "clicked" signal. - */ + /* Ignore other buttons in this gesture. */ return; } break; @@ -1168,30 +817,53 @@ nautilus_path_bar_update_button_appearance (ButtonData *button_data, gboolean current_dir) { const gchar *dir_name = get_dir_name (button_data); + gint min_chars = NAUTILUS_PATH_BAR_BUTTON_ELLISPIZE_MINIMUM_CHARS; GIcon *icon; if (button_data->label != NULL) { gtk_label_set_text (GTK_LABEL (button_data->label), dir_name); + + if (current_dir) + { + /* We want to avoid ellipsizing the current directory name, but + * still need to set a limit. */ + min_chars = 4 * min_chars; + } + + /* Labels can ellipsize until they become a single ellipsis character. + * We don't want that, so we must set a minimum. + * + * However, for labels shorter than the minimum, setting this minimum + * width would make them unnecessarily wide. In that case, just make it + * not ellipsize instead. + * + * Due to variable width fonts, labels can be shorter than the space + * that would be reserved by setting a minimum amount of characters. + * Compensate for this with a tolerance of +1 characters. + */ + if (g_utf8_strlen (dir_name, -1) > min_chars + 1) + { + gtk_label_set_width_chars (GTK_LABEL (button_data->label), min_chars); + gtk_label_set_ellipsize (GTK_LABEL (button_data->label), PANGO_ELLIPSIZE_MIDDLE); + } + else + { + gtk_label_set_width_chars (GTK_LABEL (button_data->label), -1); + gtk_label_set_ellipsize (GTK_LABEL (button_data->label), PANGO_ELLIPSIZE_NONE); + } } icon = get_gicon (button_data); if (icon != NULL) { gtk_image_set_from_gicon (GTK_IMAGE (button_data->image), icon, GTK_ICON_SIZE_MENU); - gtk_style_context_add_class (gtk_widget_get_style_context (button_data->button), - "image-button"); gtk_widget_show (GTK_WIDGET (button_data->image)); g_object_unref (icon); } else { gtk_widget_hide (GTK_WIDGET (button_data->image)); - if (!current_dir) - { - gtk_style_context_remove_class (gtk_widget_get_style_context (button_data->button), - "image-button"); - } } } @@ -1202,7 +874,6 @@ nautilus_path_bar_update_button_state (ButtonData *button_data, if (button_data->label != NULL) { gtk_label_set_label (GTK_LABEL (button_data->label), NULL); - gtk_label_set_use_markup (GTK_LABEL (button_data->label), current_dir); } nautilus_path_bar_update_button_appearance (button_data, current_dir); @@ -1371,7 +1042,9 @@ button_data_file_changed (NautilusFile *file, data = BUTTON_DATA (self->button_list->data); - gtk_container_remove (GTK_CONTAINER (self), data->button); + gtk_box_remove (GTK_BOX (self->buttons_box), data->container); + self->button_list = g_list_remove (self->button_list, data); + button_data_free (data); } } } @@ -1404,8 +1077,8 @@ make_button_data (NautilusPathBar *self, gboolean current_dir) { GFile *path; + GtkWidget *child = NULL; ButtonData *button_data; - GtkStyleContext *style_context; path = nautilus_file_get_location (file); @@ -1416,8 +1089,6 @@ make_button_data (NautilusPathBar *self, button_data->button = gtk_button_new (); gtk_widget_set_focus_on_click (button_data->button, FALSE); - style_context = gtk_widget_get_style_context (button_data->button); - gtk_style_context_add_class (style_context, "text-button"); /* TODO update button type when xdg directories change */ button_data->image = gtk_image_new (); @@ -1434,15 +1105,12 @@ make_button_data (NautilusPathBar *self, case OTHER_LOCATIONS_BUTTON: { button_data->label = gtk_label_new (NULL); - button_data->disclosure_arrow = gtk_image_new_from_icon_name ("pan-down-symbolic", - GTK_ICON_SIZE_MENU); - gtk_widget_set_margin_start (button_data->disclosure_arrow, 0); + child = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); button_data->container = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); - gtk_container_add (GTK_CONTAINER (button_data->button), button_data->container); + gtk_box_append (GTK_BOX (button_data->container), button_data->button); - gtk_box_pack_start (GTK_BOX (button_data->container), button_data->image, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (button_data->container), button_data->label, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (button_data->container), button_data->disclosure_arrow, FALSE, FALSE, 0); + gtk_box_append (GTK_BOX (child), button_data->image); + gtk_box_append (GTK_BOX (child), button_data->label); } break; @@ -1450,32 +1118,45 @@ make_button_data (NautilusPathBar *self, /* Fall through */ default: { + GtkWidget *separator_label; + + separator_label = gtk_label_new (G_DIR_SEPARATOR_S); + gtk_style_context_add_class (gtk_widget_get_style_context (separator_label), "dim-label"); button_data->label = gtk_label_new (NULL); - button_data->disclosure_arrow = gtk_image_new_from_icon_name ("pan-down-symbolic", - GTK_ICON_SIZE_MENU); - gtk_widget_set_margin_start (button_data->disclosure_arrow, 0); - button_data->container = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); - gtk_container_add (GTK_CONTAINER (button_data->button), button_data->container); + child = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 2); + button_data->container = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); + gtk_box_append (GTK_BOX (button_data->container), separator_label); + gtk_box_append (GTK_BOX (button_data->container), button_data->button); - gtk_box_pack_start (GTK_BOX (button_data->container), button_data->label, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (button_data->container), button_data->disclosure_arrow, FALSE, FALSE, 0); + gtk_box_append (GTK_BOX (child), button_data->label); } break; } - gtk_widget_set_no_show_all (button_data->disclosure_arrow, TRUE); if (current_dir) { - gtk_widget_show (button_data->disclosure_arrow); - gtk_popover_set_relative_to (self->current_view_menu_popover, button_data->button); gtk_style_context_add_class (gtk_widget_get_style_context (button_data->button), - "image-button"); + "current-dir"); + gtk_widget_set_hexpand (button_data->button, TRUE); + gtk_widget_set_halign (button_data->label, GTK_ALIGN_START); } if (button_data->label != NULL) { - gtk_label_set_ellipsize (GTK_LABEL (button_data->label), PANGO_ELLIPSIZE_MIDDLE); + PangoAttrList *attrs; + gtk_label_set_single_line_mode (GTK_LABEL (button_data->label), TRUE); + + attrs = pango_attr_list_new (); + pango_attr_list_insert (attrs, pango_attr_weight_new (PANGO_WEIGHT_BOLD)); + gtk_label_set_attributes (GTK_LABEL (button_data->label), attrs); + pango_attr_list_unref (attrs); + + if (!current_dir) + { + gtk_style_context_add_class (gtk_widget_get_style_context (button_data->label), "dim-label"); + gtk_style_context_add_class (gtk_widget_get_style_context (button_data->image), "dim-label"); + } } if (button_data->path == NULL) @@ -1497,7 +1178,8 @@ make_button_data (NautilusPathBar *self, button_data); } - gtk_widget_show_all (button_data->button); + gtk_button_set_child (GTK_BUTTON (button_data->button), child); + gtk_widget_show_all (button_data->container); nautilus_path_bar_update_button_state (button_data, current_dir); @@ -1565,13 +1247,13 @@ nautilus_path_bar_update_path (NautilusPathBar *self, } nautilus_path_bar_clear_buttons (self); - self->button_list = g_list_reverse (new_buttons); + self->button_list = new_buttons; for (l = self->button_list; l; l = l->next) { - GtkWidget *button; - button = BUTTON_DATA (l->data)->button; - gtk_container_add (GTK_CONTAINER (self), button); + GtkWidget *container; + container = BUTTON_DATA (l->data)->container; + gtk_box_append (GTK_BOX (self->buttons_box), container); } } @@ -1584,8 +1266,6 @@ nautilus_path_bar_set_path (NautilusPathBar *self, g_return_if_fail (NAUTILUS_IS_PATH_BAR (self)); g_return_if_fail (file_path != NULL); - /* Check whether the new path is already present in the pathbar as buttons. - * This could be a parent directory or a previous selected subdirectory. */ nautilus_path_bar_update_path (self, file_path); button_data = g_list_nth_data (self->button_list, 0); diff --git a/src/nautilus-pathbar.h b/src/nautilus-pathbar.h index 2e91e2922008799406563b43e3ff2a03bef1f3ce..1052e4d2d57f9e54b3e52a0cefc50cd27a386d49 100644 --- a/src/nautilus-pathbar.h +++ b/src/nautilus-pathbar.h @@ -22,7 +22,7 @@ #include #define NAUTILUS_TYPE_PATH_BAR (nautilus_path_bar_get_type ()) -G_DECLARE_FINAL_TYPE (NautilusPathBar, nautilus_path_bar, NAUTILUS, PATH_BAR, GtkContainer) +G_DECLARE_FINAL_TYPE (NautilusPathBar, nautilus_path_bar, NAUTILUS, PATH_BAR, GtkBox) void nautilus_path_bar_set_path (NautilusPathBar *path_bar, GFile *file); @@ -31,3 +31,4 @@ void nautilus_path_bar_set_extensions_background_menu (NautilusPathBar *path GMenuModel *menu); void nautilus_path_bar_set_templates_menu (NautilusPathBar *path_bar, GMenuModel *menu); +void nautilus_path_bar_show_current_location_menu (NautilusPathBar *path_bar); diff --git a/src/nautilus-places-view.c b/src/nautilus-places-view.c index a167ce02c0bafe4f633c8b56768689f5649861fe..2e4372b0648ef98878f91d1e3d351f9dba406c2c 100644 --- a/src/nautilus-places-view.c +++ b/src/nautilus-places-view.c @@ -66,7 +66,7 @@ open_location_cb (NautilusPlacesView *view, GFile *location, GtkPlacesOpenFlags open_flags) { - NautilusWindowOpenFlags flags; + NautilusOpenFlags flags; GtkWidget *slot; slot = gtk_widget_get_ancestor (GTK_WIDGET (view), NAUTILUS_TYPE_WINDOW_SLOT); @@ -75,14 +75,14 @@ open_location_cb (NautilusPlacesView *view, { case GTK_PLACES_OPEN_NEW_TAB: { - flags = NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB | - NAUTILUS_WINDOW_OPEN_FLAG_DONT_MAKE_ACTIVE; + flags = NAUTILUS_OPEN_FLAG_NEW_TAB | + NAUTILUS_OPEN_FLAG_DONT_MAKE_ACTIVE; } break; case GTK_PLACES_OPEN_NEW_WINDOW: { - flags = NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW; + flags = NAUTILUS_OPEN_FLAG_NEW_WINDOW; } break; diff --git a/src/nautilus-window-slot-dnd.c b/src/nautilus-window-slot-dnd.c index 6af9e20aad579f3a5445a0e623297d30d13de437..8f5bd33837c085d0698ec58c5a3ad8689440d2d0 100644 --- a/src/nautilus-window-slot-dnd.c +++ b/src/nautilus-window-slot-dnd.c @@ -94,7 +94,7 @@ switch_location (NautilusDragSlotProxyInfo *drag_info) location = nautilus_file_get_location (drag_info->target_file); nautilus_application_open_location_full (NAUTILUS_APPLICATION (g_application_get_default ()), - location, NAUTILUS_WINDOW_OPEN_FLAG_DONT_MAKE_ACTIVE, + location, NAUTILUS_OPEN_FLAG_DONT_MAKE_ACTIVE, NULL, NAUTILUS_WINDOW (window), NULL); g_object_unref (location); } diff --git a/src/nautilus-window-slot.c b/src/nautilus-window-slot.c index 52389641d0fe81a4913d488266bf0cc24992eb6c..bde3337dca249f831e3360a9a2e49ce89a864211 100644 --- a/src/nautilus-window-slot.c +++ b/src/nautilus-window-slot.c @@ -1178,10 +1178,10 @@ static void load_new_location (NautilusWindowSlot *slot, gboolean tell_new_content_view); void -nautilus_window_slot_open_location_full (NautilusWindowSlot *self, - GFile *location, - NautilusWindowOpenFlags flags, - GList *new_selection) +nautilus_window_slot_open_location_full (NautilusWindowSlot *self, + GFile *location, + NautilusOpenFlags flags, + GList *new_selection) { GFile *old_location; g_autolist (NautilusFile) old_selection = NULL; @@ -1468,8 +1468,8 @@ viewed_file_changed_callback (NautilusFile *file, } static void -nautilus_window_slot_go_home (NautilusWindowSlot *self, - NautilusWindowOpenFlags flags) +nautilus_window_slot_go_home (NautilusWindowSlot *self, + NautilusOpenFlags flags) { GFile *home; diff --git a/src/nautilus-window-slot.h b/src/nautilus-window-slot.h index 0a6f1a1d0c6f0d7d337dd74d6df10e372cc87ffd..3746e8fcdef3e56c2736f89ce700236c7a7b0922 100644 --- a/src/nautilus-window-slot.h +++ b/src/nautilus-window-slot.h @@ -52,10 +52,10 @@ NautilusWindow * nautilus_window_slot_get_window (NautilusWindowSlot * void nautilus_window_slot_set_window (NautilusWindowSlot *slot, NautilusWindow *window); -void nautilus_window_slot_open_location_full (NautilusWindowSlot *slot, - GFile *location, - NautilusWindowOpenFlags flags, - GList *new_selection); +void nautilus_window_slot_open_location_full (NautilusWindowSlot *slot, + GFile *location, + NautilusOpenFlags flags, + GList *new_selection); GFile * nautilus_window_slot_get_location (NautilusWindowSlot *slot); GFile * nautilus_window_slot_get_pending_location (NautilusWindowSlot *slot); diff --git a/src/nautilus-window.c b/src/nautilus-window.c index f052de77b3e2f6192fceaf93632165b77dd05dac..eb442ad162d02b976759778b7a6f06816c9125d2 100644 --- a/src/nautilus-window.c +++ b/src/nautilus-window.c @@ -440,6 +440,19 @@ action_toggle_state_view_button (GSimpleAction *action, g_variant_unref (current_state); } +static void +action_show_current_location_menu (GSimpleAction *action, + GVariant *state, + gpointer user_data) +{ + NautilusWindow *window = user_data; + GtkWidget *path_bar; + + path_bar = nautilus_toolbar_get_path_bar (NAUTILUS_TOOLBAR (window->toolbar)); + + nautilus_path_bar_show_current_location_menu (NAUTILUS_PATH_BAR (path_bar)); +} + static void on_location_changed (NautilusWindow *window) { @@ -494,8 +507,8 @@ disconnect_slot (NautilusWindow *window, } static NautilusWindowSlot * -nautilus_window_create_and_init_slot (NautilusWindow *window, - NautilusWindowOpenFlags flags) +nautilus_window_create_and_init_slot (NautilusWindow *window, + NautilusOpenFlags flags) { NautilusWindowSlot *slot; @@ -506,9 +519,9 @@ nautilus_window_create_and_init_slot (NautilusWindow *window, } void -nautilus_window_initialize_slot (NautilusWindow *window, - NautilusWindowSlot *slot, - NautilusWindowOpenFlags flags) +nautilus_window_initialize_slot (NautilusWindow *window, + NautilusWindowSlot *slot, + NautilusOpenFlags flags) { g_assert (NAUTILUS_IS_WINDOW (window)); g_assert (NAUTILUS_IS_WINDOW_SLOT (slot)); @@ -520,7 +533,7 @@ nautilus_window_initialize_slot (NautilusWindow *window, window); nautilus_notebook_add_tab (NAUTILUS_NOTEBOOK (window->notebook), slot, - (flags & NAUTILUS_WINDOW_OPEN_SLOT_APPEND) != 0 ? + (flags & NAUTILUS_OPEN_FLAG_SLOT_APPEND) != 0 ? -1 : gtk_notebook_get_current_page (GTK_NOTEBOOK (window->notebook)) + 1, FALSE); @@ -533,24 +546,24 @@ nautilus_window_initialize_slot (NautilusWindow *window, } void -nautilus_window_open_location_full (NautilusWindow *window, - GFile *location, - NautilusWindowOpenFlags flags, - GList *selection, - NautilusWindowSlot *target_slot) +nautilus_window_open_location_full (NautilusWindow *window, + GFile *location, + NautilusOpenFlags flags, + GList *selection, + NautilusWindowSlot *target_slot) { NautilusWindowSlot *active_slot; gboolean new_tab_at_end; /* Assert that we are not managing new windows */ - g_assert (!(flags & NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW)); + g_assert (!(flags & NAUTILUS_OPEN_FLAG_NEW_WINDOW)); /* if the flags say we want a new tab, open a slot in the current window */ - if ((flags & NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB) != 0) + if ((flags & NAUTILUS_OPEN_FLAG_NEW_TAB) != 0) { new_tab_at_end = g_settings_get_enum (nautilus_preferences, NAUTILUS_PREFERENCES_NEW_TAB_POSITION) == NAUTILUS_NEW_TAB_POSITION_END; if (new_tab_at_end) { - flags |= NAUTILUS_WINDOW_OPEN_SLOT_APPEND; + flags |= NAUTILUS_OPEN_FLAG_SLOT_APPEND; } } @@ -560,14 +573,14 @@ nautilus_window_open_location_full (NautilusWindow *window, target_slot = active_slot; } - if (target_slot == NULL || (flags & NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB) != 0) + if (target_slot == NULL || (flags & NAUTILUS_OPEN_FLAG_NEW_TAB) != 0) { target_slot = nautilus_window_create_and_init_slot (window, flags); } /* Make the opened location the one active if we weren't ask for the * oposite, since it's the most usual use case */ - if (!(flags & NAUTILUS_WINDOW_OPEN_FLAG_DONT_MAKE_ACTIVE)) + if (!(flags & NAUTILUS_OPEN_FLAG_DONT_MAKE_ACTIVE)) { gtk_window_present (GTK_WINDOW (window)); nautilus_window_set_active_slot (window, target_slot); @@ -703,7 +716,7 @@ nautilus_window_new_tab (NautilusWindow *window) } nautilus_window_open_location_full (window, location, - NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB, + NAUTILUS_OPEN_FLAG_NEW_TAB, NULL, NULL); g_object_unref (location); } @@ -847,21 +860,21 @@ open_location_cb (NautilusWindow *window, GFile *location, GtkPlacesOpenFlags open_flags) { - NautilusWindowOpenFlags flags; + NautilusOpenFlags flags; NautilusApplication *application; switch (open_flags) { case GTK_PLACES_OPEN_NEW_TAB: { - flags = NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB | - NAUTILUS_WINDOW_OPEN_FLAG_DONT_MAKE_ACTIVE; + flags = NAUTILUS_OPEN_FLAG_NEW_TAB | + NAUTILUS_OPEN_FLAG_DONT_MAKE_ACTIVE; } break; case GTK_PLACES_OPEN_NEW_WINDOW: { - flags = NAUTILUS_WINDOW_OPEN_FLAG_NEW_WINDOW; + flags = NAUTILUS_OPEN_FLAG_NEW_WINDOW; } break; @@ -1132,7 +1145,7 @@ action_restore_tab (GSimpleAction *action, gpointer user_data) { NautilusWindow *window = NAUTILUS_WINDOW (user_data); - NautilusWindowOpenFlags flags; + NautilusOpenFlags flags; g_autoptr (GFile) location = NULL; NautilusWindowSlot *slot; NautilusNavigationState *data; @@ -1142,7 +1155,7 @@ action_restore_tab (GSimpleAction *action, return; } - flags = NAUTILUS_WINDOW_OPEN_FLAG_NEW_TAB | NAUTILUS_WINDOW_OPEN_FLAG_DONT_MAKE_ACTIVE; + flags = NAUTILUS_OPEN_FLAG_NEW_TAB | NAUTILUS_OPEN_FLAG_DONT_MAKE_ACTIVE; data = g_queue_pop_head (window->tab_data_queue); @@ -1711,11 +1724,11 @@ nautilus_window_show_operation_notification (NautilusWindow *window, } static void -path_bar_location_changed_callback (GtkWidget *widget, - GFile *location, - NautilusWindow *window) +on_path_bar_open_location (NautilusWindow *window, + GFile *location, + NautilusOpenFlags open_flags) { - nautilus_window_open_location_full (window, location, 0, NULL, NULL); + nautilus_window_open_location_full (window, location, open_flags, NULL, NULL); } static void @@ -1875,10 +1888,8 @@ setup_toolbar (NautilusWindow *window) /* connect to the pathbar signals */ path_bar = nautilus_toolbar_get_path_bar (NAUTILUS_TOOLBAR (window->toolbar)); - g_signal_connect_object (path_bar, "path-clicked", - G_CALLBACK (path_bar_location_changed_callback), window, 0); g_signal_connect_swapped (path_bar, "open-location", - G_CALLBACK (open_location_cb), window); + G_CALLBACK (on_path_bar_open_location), window); /* connect to the location entry signals */ location_entry = nautilus_toolbar_get_location_entry (NAUTILUS_TOOLBAR (window->toolbar)); @@ -2005,6 +2016,7 @@ const GActionEntry win_entries[] = { "forward", action_forward }, { "up", action_up }, { "view-menu", action_toggle_state_view_button, NULL, "false", NULL }, + { "current-location-menu", action_show_current_location_menu }, { "reload", action_reload }, { "stop", action_stop }, { "new-tab", action_new_tab }, @@ -2070,7 +2082,7 @@ nautilus_window_initialize_actions (NautilusWindow *window) nautilus_application_set_accelerators (app, "win.prompt-root-location", ACCELS ("slash", "KP_Divide")); /* Support keyboard layouts which have a dead tilde key but not a tilde key. */ nautilus_application_set_accelerators (app, "win.prompt-home-location", ACCELS ("asciitilde", "dead_tilde")); - nautilus_application_set_accelerator (app, "win.view-menu", "F10"); + nautilus_application_set_accelerator (app, "win.current-location-menu", "F10"); nautilus_application_set_accelerator (app, "win.restore-tab", "t"); /* Alt+N for the first 9 tabs */ diff --git a/src/nautilus-window.h b/src/nautilus-window.h index 5b9bf91338ff44b866c9946d21a88fc2fbf74625..6341d865f228733597ddf1816a71a24cc40e0a63 100644 --- a/src/nautilus-window.h +++ b/src/nautilus-window.h @@ -60,11 +60,11 @@ typedef void (* NautilusWindowHandleExported) (NautilusWindow *window, NautilusWindow * nautilus_window_new (GdkScreen *screen); void nautilus_window_close (NautilusWindow *window); -void nautilus_window_open_location_full (NautilusWindow *window, - GFile *location, - NautilusWindowOpenFlags flags, - GList *selection, - NautilusWindowSlot *target_slot); +void nautilus_window_open_location_full (NautilusWindow *window, + GFile *location, + NautilusOpenFlags flags, + GList *selection, + NautilusWindowSlot *target_slot); void nautilus_window_new_tab (NautilusWindow *window); NautilusWindowSlot * nautilus_window_get_active_slot (NautilusWindow *window); @@ -105,9 +105,9 @@ void nautilus_window_end_dnd (NautilusWindow *window, void nautilus_window_search (NautilusWindow *window, NautilusQuery *query); -void nautilus_window_initialize_slot (NautilusWindow *window, - NautilusWindowSlot *slot, - NautilusWindowOpenFlags flags); +void nautilus_window_initialize_slot (NautilusWindow *window, + NautilusWindowSlot *slot, + NautilusOpenFlags flags); gboolean nautilus_window_export_handle (NautilusWindow *window, NautilusWindowHandleExported callback, diff --git a/src/resources/css/Adwaita.css b/src/resources/css/Adwaita.css index 4bc40e21bc2520b6bf87c30f10bf47d4b79caf99..448c2cadec222809174e25d5221d0036703e20a9 100644 --- a/src/resources/css/Adwaita.css +++ b/src/resources/css/Adwaita.css @@ -54,28 +54,41 @@ /* Path bar */ -.path-bar-box { - border-radius: 5px; +.nautilus-path-bar scrolledwindow { + border-radius: 5px 0px 0px 5px; border: 1px @borders solid; + border-right-width: 0px; background-color: @theme_bg_color; - padding-right: 6px; +} +.path-bar-box scrolledwindow undershoot.left { + border-radius: 5px 0px 0px 5px; + background: linear-gradient(to right, @theme_bg_color 6px, alpha(@theme_bg_color, 0) 24px); +} +.path-bar-box scrolledwindow undershoot.right { + background: linear-gradient(to left, @theme_bg_color 6px, alpha(@theme_bg_color, 0) 24px); } -.nautilus-path-bar button { +.nautilus-path-bar > button, +.path-buttons-box button { margin: 0px; } -.nautilus-path-bar button:first-child { - border-width: 0px 1px 0px 0px; - border-radius: 3.5px 0px 0px 3.5px; +.path-buttons-box button { + background-image: none; + box-shadow: none; + border-radius: 7px; + border-width: 0px; + -gtk-icon-shadow: none; } -.nautilus-path-bar button:not(:first-child) { - border-width: 0px 1px 0px 1px; - border-radius: 0px 0px 0px 0px; +.path-buttons-box button:not(.current-dir):not(:backdrop):hover { + background: alpha(@theme_fg_color, 0.15); + box-shadow: inset 0 0 0 2px @theme_bg_color; } -.nautilus-path-bar button:not(:checked) image { opacity: 0.8; } /* dim the icon when not checked */ +.path-buttons-box button:not(.current-dir):not(:backdrop):hover * { + opacity: 1; +} /* Make the tags fit into the box */ entry.search > * { diff --git a/src/resources/ui/nautilus-toolbar.ui b/src/resources/ui/nautilus-toolbar.ui index 359f80aec26e6de4096fff64584a60536f488184..09145eac3839ccc6a81516b4d6345e8c9c2764f8 100644 --- a/src/resources/ui/nautilus-toolbar.ui +++ b/src/resources/ui/nautilus-toolbar.ui @@ -443,9 +443,6 @@ False center - pathbar