Q:

Создать ссылку с реакциями на клики

Нужно добавить текст в GtkTextBuffer с тегом на который повесить калбек открытия браузера (левый и правый клики разные). Покажите пример, потому что мой вариант перехватывает все и выходит что теряется возможность выделить текст.
#include <stdio.h>
#include <gtk/gtk.h>

static void
tag_link_cb(GtkTextTag *tag, GObject *o, GdkEvent *e, GtkTextIter *text_iter, gpointer user_data)
{
    switch (e->type) {
    case GDK_BUTTON_PRESS:
        printf("Event: button press\n");
        break;
    default:
        break;
    }

    return;
}

int
main(int argc, char *argv[], const char *envp[])
{
    gtk_init(&argc, &argv);

    GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
    gtk_window_set_default_size(GTK_WINDOW(window), 400, 350);

    GtkWidget *textarea = gtk_text_view_new();
    GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textarea));

    GtkTextIter iter;
    gtk_text_buffer_get_end_iter(buf, &iter);

    GtkTextTag *tag_link;
    tag_link = gtk_text_buffer_create_tag(buf,
            "link", "foreground", "#EEEEFF", "underline", PANGO_UNDERLINE_SINGLE, NULL);
    g_signal_connect(G_OBJECT(tag_link), "event", G_CALLBACK(tag_link_cb), NULL);

    gtk_text_buffer_insert(buf, &iter, "   ", -1);
    gtk_text_buffer_insert_with_tags_by_name(buf, &iter, "test link", -1, "link", NULL);
    gtk_text_buffer_insert(buf, &iter, ",   other text", -1);

    gtk_container_add(GTK_CONTAINER(window), textarea);
    gtk_widget_show_all(window);
    gtk_main();

    return 0;
}

A:

Нужно внимательнее читать документацию:
static gboolean
tag_link_cb(GtkTextTag *tag, GObject *o, GdkEvent *e, GtkTextIter *text_iter, gpointer user_data)
{
    switch (e->type) {
        case GDK_BUTTON_PRESS:
            printf("Event: button pressed\n");
            return TRUE;
    }
    return FALSE;
}

Можно победить только вот таким чудом техно-строения :)
#include <stdio.h>
#include <stdbool.h>
#include <gtk/gtk.h>

static bool
tag_link_cb(GtkTextTag *tag, GObject *o, GdkEvent *e, GtkTextIter *text_iter, gpointer user_data)
{
    switch (e->type) {
    case GDK_BUTTON_PRESS:
        printf("Event: button press\n");
        return true;
    default:
        return false;
    }
}

static GdkCursor *cur_hand = NULL;

bool
chat_text_view_event_cb(GtkWidget *w, GdkEventMotion *event, GtkTextTag *tag)
{
    GtkTextWindowType type;
    GtkTextIter iter;
    GdkWindow *win;
    gint x, y, buf_x, buf_y;

    type = gtk_text_view_get_window_type(GTK_TEXT_VIEW(w), event->window);
    if (type != GTK_TEXT_WINDOW_TEXT) {
        return false;
    }

    /* Get where the pointer really is. */
    win = gtk_text_view_get_window(GTK_TEXT_VIEW(w), type);
    if (!win) {
        return false;
    }

    gdk_window_get_pointer(win, &x, &y, NULL);

    /* Get the iter where the cursor is at */
    gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(w), type, x, y, &buf_x, &buf_y);

    gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(w), &iter, buf_x, buf_y);

    if (gtk_text_iter_has_tag(&iter, tag)) {
        if (cur_hand == NULL) {
            cur_hand = gdk_cursor_new(GDK_HAND2);
        }
        gdk_window_set_cursor(win, cur_hand);
    } else {
        gdk_window_set_cursor(win, NULL);
    }

    return false;
}

int
main(int argc, char *argv[], const char *envp[])
{
    gtk_init(&argc, &argv);

    GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
    gtk_window_set_default_size(GTK_WINDOW(window), 400, 350);

    GtkWidget *textarea = gtk_text_view_new();
    GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textarea));

    GtkTextIter iter;
    gtk_text_buffer_get_end_iter(buf, &iter);

    GtkTextTag *tag_link;
    tag_link = gtk_text_buffer_create_tag(buf, "link", "foreground", "#EEEEFF", "underline", PANGO_UNDERLINE_SINGLE, NULL);
    g_signal_connect(G_OBJECT(tag_link), "event", G_CALLBACK(&tag_link_cb), textarea);
    g_signal_connect(G_OBJECT(textarea), "motion-notify-event", G_CALLBACK(&chat_text_view_event_cb), tag_link);

    gtk_text_buffer_insert(buf, &iter, "  blah blah ", -1);
    gtk_text_buffer_insert_with_tags_by_name(buf, &iter, "test link", -1, "link", NULL);
    gtk_text_buffer_insert(buf, &iter, ",   other text", -1);

    gtk_container_add(GTK_CONTAINER(window), textarea);
    gtk_widget_show_all(window);
    gtk_main();

    return 0;
}

