qulogic/talkatu

Parents f7389fc91eeb
Children e10028a8caee
Wire up links to work again by clicking and using the context menu.
--- a/talkatu/talkatuview.c Sat Jul 13 09:07:50 2019 -0500
+++ b/talkatu/talkatuview.c Sat Jul 13 09:08:29 2019 -0500
@@ -59,11 +59,6 @@
GtkTextMark *context_mark;
} TalkatuViewPrivate;
-typedef struct {
- TalkatuView *view;
- const gchar *url;
-} TalkatuViewOpenLinkData;
-
enum {
PROP_0 = 0,
PROP_SEND_BINDING,
@@ -86,36 +81,136 @@
* Callbacks
*****************************************************************************/
static void
-talkatu_view_insert_anchor_cb(GtkTextBuffer *buffer,
- GtkTextIter *iter,
- GtkTextChildAnchor *anchor,
- gpointer user_data)
+talkatu_view_open_url_cb(GtkMenuItem *item, gpointer data) {
+ TalkatuView *view = g_object_get_data(G_OBJECT(item), "view");
+ gchar *url = g_object_get_data(G_OBJECT(item), "url");
+
+ g_signal_emit(view, signals[SIG_OPEN_URL], 0, url);
+}
+
+static void
+talkatu_view_copy_url_cb(GtkMenuItem *item, gpointer data) {
+ GtkClipboard *clipboard = gtk_widget_get_clipboard(
+ GTK_WIDGET(item),
+ GDK_SELECTION_CLIPBOARD
+ );
+
+ gtk_clipboard_set_text(clipboard, (gchar *)data, -1);
+}
+
+gboolean
+talkatu_view_anchor_tag_event_cb(GtkTextTag *tag,
+ GObject *object,
+ GdkEvent *event,
+ GtkTextIter *iter,
+ gpointer data)
{
- GtkTextView *view = GTK_TEXT_VIEW(user_data);
- gpointer data = NULL;
+ GdkEventType event_type = gdk_event_get_event_type(event);
- /* first check if talkatu-url is added */
- data = g_object_get_data(G_OBJECT(anchor), "talkatu-url");
- if(data != NULL) {
- GtkWidget *link = NULL;
- gpointer label = g_object_get_data(G_OBJECT(anchor), "talkatu-url-label");
+ if(event_type == GDK_BUTTON_PRESS) {
+ GdkEventButton *event_button = (GdkEventButton *)event;
+
+ /* the user is right clicking on a link so stop the default handler */
+ if(event_button->button == GDK_BUTTON_SECONDARY) {
+ return TRUE;
+ }
+ } else if(event_type == GDK_BUTTON_RELEASE) {
+ GdkEventButton *event_button = (GdkEventButton *)event;
+ TalkatuView *view = TALKATU_VIEW(object);
+ GSList *tags = NULL, *tag = NULL;
+ gchar *url;
- if(label != NULL) {
- link = gtk_link_button_new_with_label((gchar *)data, (gchar *)label);
- } else {
- link = gtk_link_button_new((gchar *)data);
+ /* walk through the tags here and look for the tag that has the url */
+ tags = gtk_text_iter_get_tags(iter);
+ for(tag = tags; tag != NULL; tag = tag->next) {
+ if(tag->data == NULL) {
+ continue;
+ }
+
+ url = g_object_get_data(G_OBJECT(tag->data), "talkatu-anchor-url");
+ if(url != NULL) {
+ break;
+ }
+ }
+ g_slist_free(tags);
+
+ /* if we didn't find a url, bail */
+ if(url == NULL) {
+ return FALSE;
}
- gtk_text_view_add_child_at_anchor(view, link, anchor);
+ if(event_button->button == GDK_BUTTON_PRIMARY) {
+ GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view));
+
+ /* old behavior from pidgin2, if the users has something selected
+ * we don't open links. Other clients don't do this.. but it seems
+ * to be a work around for someone pressing a button over text,
+ * then moving the cursor to the link and then releasing. Without
+ * the selection check that'll cause that to open the link if the
+ * button is released in the middle of the link.
+ */
+ if(gtk_text_buffer_get_has_selection(buffer)) {
+ return FALSE;
+ }
+
+ g_signal_emit(view, signals[SIG_OPEN_URL], 0, url);
+
+ return TRUE;
+ } else if(event_button->button == GDK_BUTTON_SECONDARY) {
+ GtkWidget *menu = gtk_menu_new();
+ GtkWidget *item = NULL;
- gtk_widget_show(link);
+ item = gtk_menu_item_new_with_label("Open Link");
+ /* to make it easier to deal with the life cycle, we just add data
+ * to the menu item itself with destroy notifies.
+ */
+ g_object_set_data_full(
+ G_OBJECT(item),
+ "view",
+ g_object_ref(view),
+ g_object_unref
+ );
+ g_object_set_data_full(
+ G_OBJECT(item),
+ "url",
+ g_strdup(url),
+ g_free
+ );
+ g_signal_connect(
+ G_OBJECT(item),
+ "activate",
+ G_CALLBACK(talkatu_view_open_url_cb),
+ NULL
+ );
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+
+ item = gtk_menu_item_new_with_label("Copy Link");
+ g_signal_connect(
+ G_OBJECT(item),
+ "activate",
+ G_CALLBACK(talkatu_view_copy_url_cb),
+ url
+ );
+ gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+
+ gtk_widget_show_all(menu);
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, 0, event_button->time);
+ G_GNUC_END_IGNORE_DEPRECATIONS
+
+ return TRUE;
+ }
}
+
+ return FALSE;
}
static void
talkatu_view_buffer_set_cb(GObject *view, GParamSpec *pspec, gpointer data) {
TalkatuViewPrivate *priv = talkatu_view_get_instance_private(TALKATU_VIEW(view));
GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(view));
+ GtkTextTagTable *table = gtk_text_buffer_get_tag_table(buffer);
+ GtkTextTag *anchor = NULL;
GtkTextIter start;
if(TALKATU_IS_BUFFER(buffer)) {
@@ -125,14 +220,18 @@
gtk_text_buffer_get_start_iter(buffer, &start);
priv->context_mark = gtk_text_buffer_create_mark(buffer, NULL, &start, TRUE);
- gspell_text_view_basic_setup(priv->gspell_view);
+ /* check for the anchor tag, if we have it, add a signal handler to it */
+ anchor = gtk_text_tag_table_lookup(table, TALKATU_TAG_ANCHOR);
+ if(anchor != NULL) {
+ g_signal_connect(
+ anchor,
+ "event",
+ G_CALLBACK(talkatu_view_anchor_tag_event_cb),
+ NULL
+ );
+ }
- g_signal_connect_after(
- gtk_text_view_get_buffer(GTK_TEXT_VIEW(view)),
- "insert-child-anchor",
- G_CALLBACK(talkatu_view_insert_anchor_cb),
- view
- );
+ gspell_text_view_basic_setup(priv->gspell_view);
}
/******************************************************************************
@@ -191,30 +290,6 @@
}
static void
-talkatu_view_open_url_cb(GtkMenuItem *item, gpointer data) {
- TalkatuViewOpenLinkData *open_link_data = (TalkatuViewOpenLinkData *)data;
-
- g_signal_emit(
- open_link_data->view,
- signals[SIG_OPEN_URL],
- 0,
- open_link_data->url
- );
-
- g_slice_free(TalkatuViewOpenLinkData, data);
-}
-
-static void
-talkatu_view_copy_url_cb(GtkMenuItem *item, gpointer data) {
- GtkClipboard *clipboard = gtk_widget_get_clipboard(
- GTK_WIDGET(item),
- GDK_SELECTION_CLIPBOARD
- );
-
- gtk_clipboard_set_text(clipboard, (gchar *)data, -1);
-}
-
-static void
talkatu_view_populate_popup_cb(GtkTextView *view, GtkWidget *popup) {
TalkatuViewPrivate *priv = NULL;
GtkTextBuffer *buffer = NULL;