aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/interface-gtk/gtk-info-popup.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/interface-gtk/gtk-info-popup.c')
-rw-r--r--src/interface-gtk/gtk-info-popup.c57
1 files changed, 46 insertions, 11 deletions
diff --git a/src/interface-gtk/gtk-info-popup.c b/src/interface-gtk/gtk-info-popup.c
index 4e25224..aaa0a65 100644
--- a/src/interface-gtk/gtk-info-popup.c
+++ b/src/interface-gtk/gtk-info-popup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2024 Robin Haberkorn
+ * Copyright (C) 2012-2025 Robin Haberkorn
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -47,12 +47,15 @@ struct _TecoGtkInfoPopup {
GtkAdjustment *hadjustment, *vadjustment;
GtkWidget *flow_box;
+ GdkCursor *cursor; /*< pointer/hand cursor */
GStringChunk *chunk;
teco_stailq_head_t list;
guint idle_id;
gboolean frozen;
};
+static guint teco_gtk_info_popup_clicked_signal;
+
static gboolean teco_gtk_info_popup_scroll_event(GtkWidget *widget, GdkEventScroll *event);
static void teco_gtk_info_popup_show(GtkWidget *widget);
static void teco_gtk_info_popup_vadjustment_changed(GtkAdjustment *vadjustment, GtkWidget *scrollbar);
@@ -72,6 +75,9 @@ teco_gtk_info_popup_finalize(GObject *obj_self)
while ((entry = teco_stailq_remove_head(&self->list)))
g_free(entry);
+ if (self->cursor)
+ g_object_unref(self->cursor);
+
/* chain up to parent class */
G_OBJECT_CLASS(teco_gtk_info_popup_parent_class)->finalize(obj_self);
}
@@ -82,6 +88,31 @@ teco_gtk_info_popup_class_init(TecoGtkInfoPopupClass *klass)
GTK_WIDGET_CLASS(klass)->scroll_event = teco_gtk_info_popup_scroll_event;
GTK_WIDGET_CLASS(klass)->show = teco_gtk_info_popup_show;
G_OBJECT_CLASS(klass)->finalize = teco_gtk_info_popup_finalize;
+
+ teco_gtk_info_popup_clicked_signal =
+ g_signal_new("clicked", G_TYPE_FROM_CLASS(klass),
+ G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
+ 0, NULL, NULL, NULL,
+ G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_ULONG);
+}
+
+static void
+teco_gtk_info_popup_activated_cb(GtkFlowBox *box, GtkFlowBoxChild *child, gpointer user_data)
+{
+ TecoGtkInfoPopup *popup = TECO_GTK_INFO_POPUP(user_data);
+
+ /*
+ * Find the TecoGtkLabel in the flow box child.
+ */
+ GtkWidget *hbox = gtk_bin_get_child(GTK_BIN(child));
+ g_autoptr(GList) child_list = gtk_container_get_children(GTK_CONTAINER(hbox));
+ GList *entry;
+ for (entry = child_list; entry != NULL && !TECO_IS_GTK_LABEL(entry->data); entry = g_list_next(entry));
+ g_assert(entry != NULL);
+ const teco_string_t *str = teco_gtk_label_get_text(TECO_GTK_LABEL(entry->data));
+
+ g_signal_emit(popup, teco_gtk_info_popup_clicked_signal, 0,
+ str->data, (gulong)str->len);
}
static void
@@ -106,6 +137,8 @@ teco_gtk_info_popup_init(TecoGtkInfoPopup *self)
G_CALLBACK(teco_gtk_info_popup_vadjustment_changed), scrollbar);
self->flow_box = gtk_flow_box_new();
+ g_signal_connect(self->flow_box, "child-activated",
+ G_CALLBACK(teco_gtk_info_popup_activated_cb), self);
/* take as little height as necessary */
gtk_orientable_set_orientation(GTK_ORIENTABLE(self->flow_box),
GTK_ORIENTATION_HORIZONTAL);
@@ -311,12 +344,6 @@ teco_gtk_info_popup_idle_add(TecoGtkInfoPopup *self, teco_popup_entry_type_t typ
gtk_widget_set_halign(label, GTK_ALIGN_START);
gtk_widget_set_valign(label, GTK_ALIGN_CENTER);
- /*
- * FIXME: This makes little sense once we've got mouse support.
- * But for the time being, it's a useful setting.
- */
- gtk_label_set_selectable(GTK_LABEL(label), TRUE);
-
switch (type) {
case TECO_POPUP_PLAIN:
gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_START);
@@ -331,6 +358,16 @@ teco_gtk_info_popup_idle_add(TecoGtkInfoPopup *self, teco_popup_entry_type_t typ
gtk_widget_show_all(hbox);
gtk_container_add(GTK_CONTAINER(self->flow_box), hbox);
+
+ GtkWidget *flow_box_child = gtk_widget_get_parent(hbox);
+ g_assert(GTK_IS_FLOW_BOX_CHILD(flow_box_child));
+ GdkWindow *window = gtk_widget_get_window(flow_box_child);
+ g_assert(window != NULL);
+
+ if (G_UNLIKELY(!self->cursor))
+ /* we only initialize it now after guaranteed widget realization */
+ self->cursor = gdk_cursor_new_from_name(gdk_window_get_display(window), "pointer");
+ gdk_window_set_cursor(window, self->cursor);
}
static gboolean
@@ -417,12 +454,10 @@ teco_gtk_info_popup_scroll_page(TecoGtkInfoPopup *self)
* Adjust this so only complete entries are shown.
* Effectively, this rounds down to the line height.
*/
- GList *child_list = gtk_container_get_children(GTK_CONTAINER(self->flow_box));
- if (child_list) {
+ g_autoptr(GList) child_list = gtk_container_get_children(GTK_CONTAINER(self->flow_box));
+ if (child_list)
new_value -= (gint)new_value %
gtk_widget_get_allocated_height(GTK_WIDGET(child_list->data));
- g_list_free(child_list);
- }
/* clip to the maximum possible value */
new_value = MIN(new_value, gtk_adjustment_get_upper(adj));