changeset 15341:ca7cc867fa58

[gaim-migrate @ 18134] Syncing up my tree. I've gotten smileys, <hr>'s and IM images to *mostly* work. Scrolling's the only obviously busted thing right now. I also made blist headlines set the URGENT hint. committer: Tailor Script <tailor@pidgin.im>
author Sean Egan <seanegan@gmail.com>
date Tue, 16 Jan 2007 02:48:36 +0000
parents 29e9a2373d32
children 965f7e53e7c5
files gtk/gtkblist.c gtk/gtkimhtml.c gtk/gtkimhtml.h gtk/gtkutils.c gtk/gtkutils.h
diffstat 5 files changed, 138 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/gtk/gtkblist.c	Mon Jan 15 23:33:50 2007 +0000
+++ b/gtk/gtkblist.c	Tue Jan 16 02:48:36 2007 +0000
@@ -3807,6 +3807,7 @@
 	gtkblist->headline_callback = NULL;
 	gtkblist->headline_data = NULL;
 	gtkblist->headline_destroy = NULL;
+	gaim_gtk_set_urgent(gtkblist->window->window, FALSE);
 }
 
 static gboolean
@@ -5707,6 +5708,7 @@
 	gtkblist->headline_callback = callback;
 	gtkblist->headline_data = user_data;
 	gtkblist->headline_destroy = destroy;
+	gaim_gtk_set_urgent(gtkblist->window->window, TRUE);
 	gtk_widget_show_all(gtkblist->headline_hbox);
 }
 
--- a/gtk/gtkimhtml.c	Mon Jan 15 23:33:50 2007 +0000
+++ b/gtk/gtkimhtml.c	Tue Jan 16 02:48:36 2007 +0000
@@ -1215,7 +1215,13 @@
 		g_free(imhtml->clipboard_text_string);
 		g_free(imhtml->clipboard_html_string);
 	}
-
+	
+	for (l = imhtml->anchors; l; l = l->next) {
+		GtkIMHtmlAnchor *anchor = l->data;
+		gtk_imhtml_anchor_free(anchor);
+	}
+
+	g_slist_free(imhtml->anchors);
 	g_list_free(imhtml->scalables);
 	g_slist_free(imhtml->im_images);
 	g_free(imhtml->protocol_name);
@@ -2362,6 +2368,7 @@
 set_adj_idle_cb(gpointer data)
 {
 	GtkIMHtml *imhtml = data;
+
 	gtk_adjustment_set_value(GTK_TEXT_VIEW(imhtml)->vadjustment, imhtml->adj);
 	return FALSE;
 }
@@ -2373,6 +2380,7 @@
 {
 	GdkRectangle rect;
 	GtkAdjustment *adj = GTK_TEXT_VIEW(imhtml)->vadjustment;
+	GSList *anchors;
 	gint pos = 0;
 	gchar *ws;
 	gchar *tag;
@@ -2383,6 +2391,7 @@
 	const gchar *c;
 	gchar *amp;
 	gint len_protocol;
+	gboolean refocus = GTK_WIDGET_HAS_FOCUS(imhtml);
 
 
 	guint	bold = 0,
@@ -2395,7 +2404,6 @@
 		pre = 0;
 
 	gboolean br = FALSE;
-
 	GSList *fonts = NULL;
 	GObject *object;
 	GtkIMHtmlScalable *scalable = NULL;
@@ -2409,6 +2417,17 @@
 	ws[0] = 0;
 
 	imhtml->adj = gtk_adjustment_get_value(adj);
+
+	for (anchors = imhtml->anchors; anchors; anchors = anchors->next) {
+		GtkIMHtmlAnchor *anchor = anchors->data;
+		if (gtk_text_child_anchor_get_deleted(anchor->anchor)) {
+			imhtml->anchors = g_slist_remove(imhtml->anchors, anchor);
+			gtk_imhtml_anchor_free(anchor);
+			continue;
+		}
+		gtk_container_remove(GTK_CONTAINER(imhtml), anchor->widget);
+
+	}
 	gtk_widget_hide(GTK_WIDGET(imhtml));
 	gtk_widget_unrealize(GTK_WIDGET(imhtml));
 	gtk_text_view_set_buffer(GTK_TEXT_VIEW(imhtml), imhtml->empty_buffer);
@@ -3070,10 +3089,18 @@
 		gtk_imhtml_close_tags(imhtml, iter);
 
 	gtk_text_view_set_buffer(GTK_TEXT_VIEW(imhtml), imhtml->text_buffer);
+	for (anchors = imhtml->anchors; anchors; anchors = anchors->next) {
+		GtkIMHtmlAnchor *anchor = anchors->data;
+		gtk_imhtml_add_anchor(imhtml, anchor);
+	}
+	object = g_object_ref(G_OBJECT(imhtml));
 	gtk_widget_realize(GTK_WIDGET(imhtml));
 	gtk_widget_show_all(GTK_WIDGET(imhtml));
-	object = g_object_ref(G_OBJECT(imhtml));
-	g_idle_add(set_adj_idle_cb, imhtml);
+	g_idle_add_full(G_PRIORITY_HIGH_IDLE, set_adj_idle_cb, imhtml, NULL);
+	if (refocus){
+		printf("refocusing\n");
+		gtk_widget_grab_focus(GTK_WIDGET(imhtml));
+	}
 	g_signal_emit(object, signals[UPDATE_FORMAT], 0);
 	g_object_unref(object);
 }
@@ -3466,6 +3493,7 @@
 
 void gtk_imhtml_image_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter)
 {
+	GtkIMHtmlAnchor *ianchor;
 	GtkIMHtmlImage *image = (GtkIMHtmlImage *)scale;
 	GtkWidget *box = gtk_event_box_new();
 	char *tag;
@@ -3483,7 +3511,9 @@
 	g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_htmltext", tag, g_free);
 	g_object_set_data(G_OBJECT(anchor), "gtkimhtml_plaintext", "[Image]");
 
-	gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), box, anchor);
+	ianchor = gtk_imhtml_anchor_new(anchor, box);
+	imhtml->anchors = g_slist_append(imhtml->anchors, ianchor);
+
 	g_signal_connect(G_OBJECT(box), "event", G_CALLBACK(gtk_imhtml_image_clicked), image);
 }
 
@@ -3509,11 +3539,13 @@
 
 void gtk_imhtml_hr_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter)
 {
+	GtkIMHtmlAnchor *ianchor;
 	GtkIMHtmlHr *hr = (GtkIMHtmlHr *)scale;
 	GtkTextChildAnchor *anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter);
 	g_object_set_data(G_OBJECT(anchor), "gtkimhtml_htmltext", "<hr>");
 	g_object_set_data(G_OBJECT(anchor), "gtkimhtml_plaintext", "\n---\n");
-	gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), hr->sep, anchor);
+	ianchor = gtk_imhtml_anchor_new(anchor, hr->sep);
+	imhtml->anchors = g_slist_append(imhtml->anchors, ianchor);
 }
 
 void gtk_imhtml_hr_free(GtkIMHtmlScalable *scale)
@@ -3521,6 +3553,36 @@
 	g_free(scale);
 }
 
+GtkIMHtmlAnchor *gtk_imhtml_anchor_new(GtkTextChildAnchor *anchor, GtkWidget *widget)
+{
+	GtkIMHtmlAnchor *a = g_new0(GtkIMHtmlAnchor, 1);
+	a->anchor = anchor;
+	a->widget = widget;
+	
+	g_object_ref(anchor);
+	g_object_ref(widget);
+	
+	return a;
+}
+
+void gtk_imhtml_anchor_free(GtkIMHtmlAnchor *anchor)
+{
+	g_object_unref(anchor->anchor);
+	g_object_unref(anchor->widget);
+	g_free(anchor);
+}
+
+void gtk_imhtml_add_anchor(GtkIMHtml *imhtml, GtkIMHtmlAnchor *anchor)
+{
+	if (gtk_text_child_anchor_get_deleted(anchor->anchor)) {
+		imhtml->anchors = g_slist_remove(imhtml->anchors, anchor);
+		gtk_imhtml_anchor_free(anchor);
+		return;
+	}
+
+	gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), anchor->widget, anchor->anchor);
+}
+
 gboolean gtk_imhtml_search_find(GtkIMHtml *imhtml, const gchar *text)
 {
 	GtkTextIter iter, start, end;
@@ -4470,6 +4532,7 @@
 	}
 
 	if (icon) {
+		GtkIMHtmlAnchor *ianchor;
 		anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter);
 		g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_plaintext", g_strdup(unescaped), g_free);
 		g_object_set_data_full(G_OBJECT(anchor), "gtkimhtml_htmltext", g_strdup(smiley), g_free);
@@ -4481,7 +4544,8 @@
 		g_signal_connect(G_OBJECT(icon), "expose-event", G_CALLBACK(image_expose), NULL);
 
 		gtk_widget_show(icon);
-		gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(imhtml), icon, anchor);
+		ianchor = gtk_imhtml_anchor_new(anchor, icon);
+		imhtml->anchors = g_slist_append(imhtml->anchors, ianchor);
 	} else if (imhtml_smiley != NULL && (imhtml->format_functions & GTK_IMHTML_SMILEY)) {
 		anchor = gtk_text_buffer_create_child_anchor(imhtml->text_buffer, iter);
 		imhtml_smiley->anchors = g_slist_append(imhtml_smiley->anchors, anchor);
--- a/gtk/gtkimhtml.h	Mon Jan 15 23:33:50 2007 +0000
+++ b/gtk/gtkimhtml.h	Tue Jan 16 02:48:36 2007 +0000
@@ -53,6 +53,7 @@
 typedef struct _GtkIMHtmlImage		GtkIMHtmlImage;
 typedef struct _GtkIMHtmlHr			GtkIMHtmlHr;
 typedef struct _GtkIMHtmlFuncs		GtkIMHtmlFuncs;
+typedef struct _GtkIMHtmlAnchor         GtkIMHtmlAnchor;
 
 typedef enum {
 	GTK_IMHTML_BOLD =       1 << 0,
@@ -125,6 +126,7 @@
 	char *clipboard_html_string;
 
 	GSList *im_images;
+	GSList *anchors;
 	GtkIMHtmlFuncs *funcs;
 };
 
@@ -190,6 +192,11 @@
 	GtkWidget *sep;
 };
 
+struct _GtkIMHtmlAnchor {
+	GtkTextChildAnchor *anchor;
+	GtkWidget *widget;
+};
+
 typedef enum {
 	GTK_IMHTML_NO_COLOURS          = 1 << 0,
 	GTK_IMHTML_NO_FONTS            = 1 << 1,
@@ -474,6 +481,31 @@
 void gtk_imhtml_hr_add_to(GtkIMHtmlScalable *scale, GtkIMHtml *imhtml, GtkTextIter *iter);
 
 /**
+ * Creates a new anchor for GTK+ widgets, taking care of reference counting
+ *
+ * @param anchor The GtkTextChildAnchor
+ * @param widget The GtkWidget
+ *
+ * @return The GtkIMHtmlAnchor
+ */
+GtkIMHtmlAnchor *gtk_imhtml_anchor_new(GtkTextChildAnchor *anchor, GtkWidget *widget);
+
+/**
+ * Frees an anchor, taking care of refcounting
+ *
+ * @param anchor The anchor
+ */
+void gtk_imhtml_anchor_free(GtkIMHtmlAnchor *anchor);
+
+/**
+ * Associates an anchor with an imhtml
+ *
+ * @param imhtml  The IMHTML to associate with.
+ * @param anchor  The anchor to associate
+ */
+void gtk_imhtml_add_anchor(GtkIMHtml *imhtml, GtkIMHtmlAnchor *anchor);
+
+/**
  * Finds and highlights a given string in a GTK+ IM/HTML.
  *
  * @param imhtml The GTK+ IM/HTML.
--- a/gtk/gtkutils.c	Mon Jan 15 23:33:50 2007 +0000
+++ b/gtk/gtkutils.c	Tue Jan 16 02:48:36 2007 +0000
@@ -2876,6 +2876,30 @@
 	return ret;
 }
 
+void gaim_gtk_set_urgent(GdkWindow *window, gboolean urgent)
+{
+#ifdef _WIN32
+#error Hey, Daniel! Make this work!
+#else
+	XWMHints *hints;
+
+	g_return_if_fail(window != NULL);
+
+	hints = XGetWMHints(GDK_WINDOW_XDISPLAY(window),
+	                    GDK_WINDOW_XWINDOW(window));
+	if(!hints)
+		hints = XAllocWMHints();
+
+	if (urgent)
+		hints->flags |= XUrgencyHint;
+	else
+		hints->flags &= ~XUrgencyHint;
+	XSetWMHints(GDK_WINDOW_XDISPLAY(window),
+	            GDK_WINDOW_XWINDOW(window), hints);
+	XFree(hints);
+#endif
+}
+
 GSList *minidialogs = NULL;
 
 static void *
--- a/gtk/gtkutils.h	Mon Jan 15 23:33:50 2007 +0000
+++ b/gtk/gtkutils.h	Tue Jan 16 02:48:36 2007 +0000
@@ -533,6 +533,15 @@
 gboolean gaim_gtk_tree_view_search_equal_func(GtkTreeModel *model, gint column,
 			const gchar *key, GtkTreeIter *iter, gpointer data);
 
+/**
+ * Sets or resets a window to 'urgent,' by setting the URGENT hint in X 
+ * or blinking in the win32 taskbar
+ *
+ * @param window  The window to draw attention to
+ * @param urgent  Whether to set the urgent hint or not
+ */
+void gaim_gtk_set_urgent(GdkWindow *window, gboolean urgent);
+
 #if !GTK_CHECK_VERSION(2,2,0)
 /**
  * This is copied from Gtk to support Gtk 2.0