diff options
Diffstat (limited to '')
-rw-r--r-- | src/nautilus-history-controls.c | 313 |
1 files changed, 313 insertions, 0 deletions
diff --git a/src/nautilus-history-controls.c b/src/nautilus-history-controls.c new file mode 100644 index 0000000..8b14cd6 --- /dev/null +++ b/src/nautilus-history-controls.c @@ -0,0 +1,313 @@ +/* + * Copyright (C) 2022 The GNOME project contributors + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "nautilus-history-controls.h" + +#include "nautilus-bookmark.h" +#include "nautilus-window.h" + +struct _NautilusHistoryControls +{ + AdwBin parent_instance; + + GtkWidget *back_button; + GtkWidget *back_menu; + + GtkWidget *forward_button; + GtkWidget *forward_menu; + + NautilusWindowSlot *window_slot; +}; + +G_DEFINE_FINAL_TYPE (NautilusHistoryControls, nautilus_history_controls, ADW_TYPE_BIN) + +enum +{ + PROP_0, + PROP_WINDOW_SLOT, + N_PROPS +}; + +static GParamSpec *properties[N_PROPS]; + +static void +fill_menu (NautilusHistoryControls *self, + GMenu *menu, + gboolean back) +{ + guint index; + GList *list; + const gchar *name; + + list = back ? nautilus_window_slot_get_back_history (self->window_slot) : + nautilus_window_slot_get_forward_history (self->window_slot); + + index = 0; + while (list != NULL) + { + g_autoptr (GMenuItem) item = NULL; + + name = nautilus_bookmark_get_name (NAUTILUS_BOOKMARK (list->data)); + item = g_menu_item_new (name, NULL); + g_menu_item_set_action_and_target (item, + back ? "win.back-n" : "win.forward-n", + "u", index); + g_menu_append_item (menu, item); + + list = g_list_next (list); + ++index; + } +} + +static void +show_menu (NautilusHistoryControls *self, + GtkWidget *widget) +{ + g_autoptr (GMenu) menu = NULL; + NautilusNavigationDirection direction; + GtkPopoverMenu *popover; + + menu = g_menu_new (); + + direction = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (widget), + "nav-direction")); + + switch (direction) + { + case NAUTILUS_NAVIGATION_DIRECTION_FORWARD: + { + fill_menu (self, menu, FALSE); + popover = GTK_POPOVER_MENU (self->forward_menu); + } + break; + + case NAUTILUS_NAVIGATION_DIRECTION_BACK: + { + fill_menu (self, menu, TRUE); + popover = GTK_POPOVER_MENU (self->back_menu); + } + break; + + default: + { + g_assert_not_reached (); + } + break; + } + + gtk_popover_menu_set_menu_model (popover, G_MENU_MODEL (menu)); + gtk_popover_popup (GTK_POPOVER (popover)); +} + +static void +navigation_button_press_cb (GtkGestureClick *gesture, + gint n_press, + gdouble x, + gdouble y, + gpointer user_data) +{ + NautilusHistoryControls *self; + NautilusWindow *window; + GtkWidget *widget; + guint button; + + self = NAUTILUS_HISTORY_CONTROLS (user_data); + button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (gesture)); + widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture)); + window = NAUTILUS_WINDOW (gtk_widget_get_root (GTK_WIDGET (self))); + + if (button == GDK_BUTTON_PRIMARY) + { + /* Don't do anything, primary click is handled through activate */ + gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_DENIED); + return; + } + else if (button == GDK_BUTTON_MIDDLE) + { + NautilusNavigationDirection direction; + + direction = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (widget), + "nav-direction")); + + nautilus_window_back_or_forward_in_new_tab (window, direction); + } + else if (button == GDK_BUTTON_SECONDARY) + { + show_menu (self, widget); + } +} + +static void +back_button_longpress_cb (GtkGestureLongPress *gesture, + double x, + double y, + gpointer user_data) +{ + NautilusHistoryControls *self = user_data; + + show_menu (self, self->back_button); +} + +static void +forward_button_longpress_cb (GtkGestureLongPress *gesture, + double x, + double y, + gpointer user_data) +{ + NautilusHistoryControls *self = user_data; + + show_menu (self, self->forward_button); +} + + +static void +nautilus_history_controls_contructed (GObject *object) +{ + NautilusHistoryControls *self; + GtkEventController *controller; + + self = NAUTILUS_HISTORY_CONTROLS (object); + + controller = GTK_EVENT_CONTROLLER (gtk_gesture_long_press_new ()); + gtk_widget_add_controller (self->back_button, controller); + g_signal_connect (controller, "pressed", + G_CALLBACK (back_button_longpress_cb), self); + + controller = GTK_EVENT_CONTROLLER (gtk_gesture_long_press_new ()); + gtk_widget_add_controller (self->forward_button, controller); + g_signal_connect (controller, "pressed", + G_CALLBACK (forward_button_longpress_cb), self); + + g_object_set_data (G_OBJECT (self->back_button), "nav-direction", + GUINT_TO_POINTER (NAUTILUS_NAVIGATION_DIRECTION_BACK)); + g_object_set_data (G_OBJECT (self->forward_button), "nav-direction", + GUINT_TO_POINTER (NAUTILUS_NAVIGATION_DIRECTION_FORWARD)); + + controller = GTK_EVENT_CONTROLLER (gtk_gesture_click_new ()); + gtk_widget_add_controller (self->back_button, controller); + gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (controller), 0); + g_signal_connect (controller, "pressed", + G_CALLBACK (navigation_button_press_cb), self); + + controller = GTK_EVENT_CONTROLLER (gtk_gesture_click_new ()); + gtk_widget_add_controller (self->forward_button, controller); + gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (controller), 0); + g_signal_connect (controller, "pressed", + G_CALLBACK (navigation_button_press_cb), self); +} + +static void +nautilus_history_controls_dispose (GObject *object) +{ + NautilusHistoryControls *self; + + self = NAUTILUS_HISTORY_CONTROLS (object); + + g_clear_pointer (&self->back_menu, gtk_widget_unparent); + g_clear_pointer (&self->forward_menu, gtk_widget_unparent); + + G_OBJECT_CLASS (nautilus_history_controls_parent_class)->dispose (object); +} + +static void +nautilus_history_controls_set_window_slot (NautilusHistoryControls *self, + NautilusWindowSlot *window_slot) +{ + g_return_if_fail (NAUTILUS_IS_HISTORY_CONTROLS (self)); + g_return_if_fail (window_slot == NULL || NAUTILUS_IS_WINDOW_SLOT (window_slot)); + + if (self->window_slot == window_slot) + { + return; + } + + self->window_slot = window_slot; + + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_WINDOW_SLOT]); +} + +static void +nautilus_history_controls_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + NautilusHistoryControls *self = NAUTILUS_HISTORY_CONTROLS (object); + + switch (prop_id) + { + case PROP_WINDOW_SLOT: + { + g_value_set_object (value, G_OBJECT (self->window_slot)); + break; + } + + default: + { + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } + } +} + +static void +nautilus_history_controls_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + NautilusHistoryControls *self = NAUTILUS_HISTORY_CONTROLS (object); + + switch (prop_id) + { + case PROP_WINDOW_SLOT: + { + nautilus_history_controls_set_window_slot (self, NAUTILUS_WINDOW_SLOT (g_value_get_object (value))); + break; + } + + default: + { + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } + } +} + +static void +nautilus_history_controls_class_init (NautilusHistoryControlsClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + object_class->constructed = nautilus_history_controls_contructed; + object_class->dispose = nautilus_history_controls_dispose; + object_class->set_property = nautilus_history_controls_set_property; + object_class->get_property = nautilus_history_controls_get_property; + + properties[PROP_WINDOW_SLOT] = g_param_spec_object ("window-slot", + NULL, NULL, + NAUTILUS_TYPE_WINDOW_SLOT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY); + + g_object_class_install_properties (object_class, N_PROPS, properties); + + gtk_widget_class_set_template_from_resource (widget_class, + "/org/gnome/nautilus/ui/nautilus-history-controls.ui"); + gtk_widget_class_bind_template_child (widget_class, NautilusHistoryControls, back_button); + gtk_widget_class_bind_template_child (widget_class, NautilusHistoryControls, back_menu); + gtk_widget_class_bind_template_child (widget_class, NautilusHistoryControls, forward_button); + gtk_widget_class_bind_template_child (widget_class, NautilusHistoryControls, forward_menu); +} + +static void +nautilus_history_controls_init (NautilusHistoryControls *self) +{ + gtk_widget_init_template (GTK_WIDGET (self)); + + gtk_widget_set_parent (self->back_menu, self->back_button); + g_signal_connect (self->back_menu, "destroy", G_CALLBACK (gtk_widget_unparent), NULL); + gtk_widget_set_parent (self->forward_menu, self->forward_button); + g_signal_connect (self->forward_menu, "destroy", G_CALLBACK (gtk_widget_unparent), NULL); +} |