# HG changeset patch # User Sean Egan # Date 1168915716 0 # Node ID ca7cc867fa5840cec1071bc8b975b607f1c10407 # Parent 29e9a2373d32b6b337549931a96d33dde110e390 [gaim-migrate @ 18134] Syncing up my tree. I've gotten smileys,
'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 diff -r 29e9a2373d32 -r ca7cc867fa58 gtk/gtkblist.c --- 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); } diff -r 29e9a2373d32 -r ca7cc867fa58 gtk/gtkimhtml.c --- 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", "
"); 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); diff -r 29e9a2373d32 -r ca7cc867fa58 gtk/gtkimhtml.h --- 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. diff -r 29e9a2373d32 -r ca7cc867fa58 gtk/gtkutils.c --- 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 * diff -r 29e9a2373d32 -r ca7cc867fa58 gtk/gtkutils.h --- 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