diff -Nru pidgin-2.14.8/debian/changelog pidgin-2.14.8/debian/changelog --- pidgin-2.14.8/debian/changelog 2022-02-06 12:48:26.000000000 +0000 +++ pidgin-2.14.8/debian/changelog 2023-07-11 16:56:57.000000000 +0000 @@ -1,3 +1,9 @@ +pidgin (1:2.14.8-1ubuntu2.1) jammy; urgency=medium + + * Fix freezes when creating long message or resizing window (LP: #1975519) + + -- Julian Andres Klode Tue, 11 Jul 2023 18:56:57 +0200 + pidgin (1:2.14.8-1ubuntu2) jammy; urgency=medium * No-change rebuild for the perl update. diff -Nru pidgin-2.14.8/debian/control pidgin-2.14.8/debian/control --- pidgin-2.14.8/debian/control 2021-12-01 14:10:42.000000000 +0000 +++ pidgin-2.14.8/debian/control 2023-07-11 16:56:57.000000000 +0000 @@ -1,7 +1,8 @@ Source: pidgin Section: net Priority: optional -Maintainer: Richard Laager +Maintainer: Ubuntu Developers +XSBC-Original-Maintainer: Richard Laager Uploaders: Ari Pollak , Build-Depends: ca-certificates, cdbs, diff -Nru pidgin-2.14.8/debian/patches/rb1342.patch pidgin-2.14.8/debian/patches/rb1342.patch --- pidgin-2.14.8/debian/patches/rb1342.patch 1970-01-01 00:00:00.000000000 +0000 +++ pidgin-2.14.8/debian/patches/rb1342.patch 2023-07-11 16:56:54.000000000 +0000 @@ -0,0 +1,462 @@ +Description: Fix the infinite resizing freeze +This appears related to libpango somehow, as in Debian +Bullseye, libpango splits URLs with dashes at the end, +but in Debian Bookworm, the URLs are not split with dashes +at the end, and the bug does not appear to be triggered +in Bookworm. + + +This patch makes the assumption that the gtkimhtml widgets +stored in a PidginConversation normally resize in an +alternating manner. However, when the bug is triggered, +only the "entry" gtkimhtml member of PidginConversation +resizes, so we allow "entry" to resize only up to 3 times +in a row. +Origin: upstream, https://reviews.imfreedom.org/r/1342/diff/10/ +Bug-Ubuntu: https://bugs.launchpad.net/bugs/1975519 +Last-Update: 2023-07-11 +--- +This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ +--- a/pidgin/gtkconv.c ++++ b/pidgin/gtkconv.c +@@ -118,6 +118,9 @@ enum { + static GdkColor *nick_colors = NULL; + static guint nbr_nick_colors; + ++/* GTK_IMHTML_MAX_CONSEC_RESIZES is also defined in gtkimhtml.c */ ++#define GTK_IMHTML_MAX_CONSEC_RESIZES 6 ++ + typedef struct { + GtkWidget *window; + +@@ -264,8 +267,17 @@ close_conv_cb(GtkButton *button, PidginC + static gboolean + lbox_size_allocate_cb(GtkWidget *w, GtkAllocation *allocation, gpointer data) + { ++ PidginConversation *gtkconv = data; ++ + purple_prefs_set_int(PIDGIN_PREFS_ROOT "/conversations/chat/userlist_width", allocation->width == 1 ? 0 : allocation->width); + ++ if(gtkconv != NULL) { ++ g_object_set_data(G_OBJECT(gtkconv->entry), "resize-count", ++ GINT_TO_POINTER(0)); ++ g_object_set_data(G_OBJECT(gtkconv->imhtml), "resize-count", ++ GINT_TO_POINTER(0)); ++ } ++ + return FALSE; + } + +@@ -2361,6 +2373,9 @@ insert_text_cb(GtkTextBuffer *textbuffer + + g_return_if_fail(gtkconv != NULL); + ++ g_object_set_data(G_OBJECT(gtkconv->imhtml), "resize-count", ++ GINT_TO_POINTER(0)); ++ + if (!purple_prefs_get_bool("/purple/conversations/im/send_typing")) + return; + +@@ -2378,6 +2393,9 @@ delete_text_cb(GtkTextBuffer *textbuffer + + g_return_if_fail(gtkconv != NULL); + ++ g_object_set_data(G_OBJECT(gtkconv->imhtml), "resize-count", ++ GINT_TO_POINTER(0)); ++ + conv = gtkconv->active_conv; + + if (!purple_prefs_get_bool("/purple/conversations/im/send_typing")) +@@ -2806,6 +2824,9 @@ change_size_cb(GtkWidget *widget, Pidgin + PurpleContact *contact = purple_buddy_get_contact(buddy); + purple_blist_node_set_int((PurpleBlistNode*)contact, "pidgin-infopane-iconsize", size); + } ++ ++ g_object_set_data(G_OBJECT(gtkconv->imhtml), "resize-count", ++ GINT_TO_POINTER(0)); + } + + static void +@@ -4331,6 +4352,11 @@ static void topic_callback(GtkWidget *w, + new_topic); + + g_free(new_topic); ++ ++ g_object_set_data(G_OBJECT(gtkconv->imhtml), "resize-count", ++ GINT_TO_POINTER(0)); ++ g_object_set_data(G_OBJECT(gtkconv->entry), "resize-count", ++ GINT_TO_POINTER(0)); + } + + static gint +@@ -4596,6 +4622,17 @@ static gboolean resize_imhtml_cb(PidginC + gboolean interior_focus; + int focus_width; + ++ if(GPOINTER_TO_INT( ++ g_object_get_data( ++ G_OBJECT(gtkconv->entry), "resize-count")) == ++ GTK_IMHTML_MAX_CONSEC_RESIZES + 1) { ++ g_object_set_data(G_OBJECT(gtkconv->entry), "resize-count", ++ GINT_TO_POINTER(0)); ++ g_object_set_data(G_OBJECT(gtkconv->imhtml), "resize-count", ++ GINT_TO_POINTER(0)); ++ return; ++ } ++ + pad_top = gtk_text_view_get_pixels_above_lines(GTK_TEXT_VIEW(gtkconv->entry)); + pad_bottom = gtk_text_view_get_pixels_below_lines(GTK_TEXT_VIEW(gtkconv->entry)); + pad_inside = gtk_text_view_get_pixels_inside_wrap(GTK_TEXT_VIEW(gtkconv->entry)); +@@ -4630,7 +4667,7 @@ static gboolean resize_imhtml_cb(PidginC + + diff = height - gtkconv->entry->allocation.height; + if (ABS(diff) < oneline.height / 2) +- return FALSE; ++ diff = 0; + + gtk_widget_set_size_request(gtkconv->lower_hbox, -1, + diff + gtkconv->lower_hbox->allocation.height); +@@ -5056,6 +5093,7 @@ setup_common_pane(PidginConversation *gt + gtk_widget_set_name(gtkconv->entry, "pidgin_conv_entry"); + gtk_imhtml_set_protocol_name(GTK_IMHTML(gtkconv->entry), + purple_account_get_protocol_name(conv->account)); ++ g_object_set_data(G_OBJECT(gtkconv->entry), "gtkconv", gtkconv); + + g_signal_connect(G_OBJECT(gtkconv->entry), "populate-popup", + G_CALLBACK(entry_popup_menu_cb), gtkconv); +@@ -7380,6 +7418,11 @@ show_formatting_toolbar_pref_cb(const ch + gtk_widget_hide(gtkconv->toolbar); + + g_idle_add((GSourceFunc)resize_imhtml_cb,gtkconv); ++ ++ g_object_set_data(G_OBJECT(gtkconv->imhtml), "resize-count", ++ GINT_TO_POINTER(0)); ++ g_object_set_data(G_OBJECT(gtkconv->entry), "resize-count", ++ GINT_TO_POINTER(0)); + } + } + +@@ -9074,6 +9117,12 @@ infopane_entry_activate(PidginConversati + PurpleConversation *conv = gtkconv->active_conv; + const char *text = NULL; + ++ g_object_set_data(G_OBJECT(gtkconv->imhtml), "resize-count", ++ GINT_TO_POINTER(0)); ++ ++ g_object_set_data(G_OBJECT(gtkconv->entry), "resize-count", ++ GINT_TO_POINTER(0)); ++ + if (!GTK_WIDGET_VISIBLE(gtkconv->infopane)) { + /* There's already an entry for alias. Let's not create another one. */ + return FALSE; +@@ -9233,6 +9282,21 @@ plugin_changed_cb(PurplePlugin *p, gpoin + + static gboolean gtk_conv_configure_cb(GtkWidget *w, GdkEventConfigure *event, gpointer data) { + int x, y; ++ GList *gtkconvs; ++ PidginWindow *win = data; ++ PidginConversation *gtkconv; ++ ++ if(win != NULL) { ++ for (gtkconvs = win->gtkconvs; gtkconvs != NULL; gtkconvs = gtkconvs->next) { ++ gtkconv = gtkconvs->data; ++ if(gtkconv != NULL) { ++ g_object_set_data(G_OBJECT(gtkconv->imhtml), "resize-count", ++ GINT_TO_POINTER(0)); ++ g_object_set_data(G_OBJECT(gtkconv->entry), "resize-count", ++ GINT_TO_POINTER(0)); ++ } ++ } ++ } + + if (GTK_WIDGET_VISIBLE(w)) + gtk_window_get_position(GTK_WINDOW(w), &x, &y); +@@ -9266,6 +9330,9 @@ static void + pidgin_conv_set_position_size(PidginWindow *win, int conv_x, int conv_y, + int conv_width, int conv_height) + { ++ GList *gtkconvs; ++ PidginConversation *gtkconvs_data; ++ + /* if the window exists, is hidden, we're saving positions, and the + * position is sane... */ + if (win && win->window && +@@ -9288,6 +9355,18 @@ pidgin_conv_set_position_size(PidginWind + #endif + gtk_window_resize(GTK_WINDOW(win->window), conv_width, conv_height); + } ++ ++ if(win != NULL) { ++ for (gtkconvs = win->gtkconvs; gtkconvs != NULL; gtkconvs = gtkconvs->next) { ++ gtkconvs_data = gtkconvs->data; ++ if(gtkconvs_data != NULL) { ++ g_object_set_data(G_OBJECT(gtkconvs_data->imhtml), "resize-count", ++ GINT_TO_POINTER(0)); ++ g_object_set_data(G_OBJECT(gtkconvs_data->entry), "resize-count", ++ GINT_TO_POINTER(0)); ++ } ++ } ++ } + } + + static void +@@ -9495,6 +9574,8 @@ pidgin_conv_window_add_gtkconv(PidginWin + GtkWidget *tab_cont = gtkconv->tab_cont; + PurpleConversationType conv_type; + const gchar *tmp_lab; ++ GList *gtkconvs; ++ PidginConversation *gtkconvs_data; + + conv_type = purple_conversation_get_type(conv); + +@@ -9563,6 +9644,21 @@ pidgin_conv_window_add_gtkconv(PidginWin + + if (pidgin_conv_window_get_gtkconv_count(win) == 1) + update_send_to_selection(win); ++ ++ for (gtkconvs = win->gtkconvs; gtkconvs != NULL; gtkconvs = gtkconvs->next) { ++ gtkconvs_data = gtkconvs->data; ++ if(gtkconvs_data != NULL) { ++ g_object_set_data(G_OBJECT(gtkconvs_data->imhtml), "resize-count", ++ GINT_TO_POINTER(0)); ++ g_object_set_data(G_OBJECT(gtkconvs_data->entry), "resize-count", ++ GINT_TO_POINTER(0)); ++ } ++ } ++ ++ g_object_set_data(G_OBJECT(gtkconv->imhtml), "resize-count", ++ GINT_TO_POINTER(0)); ++ g_object_set_data(G_OBJECT(gtkconv->entry), "resize-count", ++ GINT_TO_POINTER(0)); + } + + static void +@@ -9572,6 +9668,11 @@ pidgin_conv_tab_pack(PidginWindow *win, + gint angle = 0; + GtkWidget *first, *third, *ebox; + ++ g_object_set_data(G_OBJECT(gtkconv->imhtml), "resize-count", ++ GINT_TO_POINTER(0)); ++ g_object_set_data(G_OBJECT(gtkconv->entry), "resize-count", ++ GINT_TO_POINTER(0)); ++ + if (purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/tab_side") == GTK_POS_LEFT || + purple_prefs_get_int(PIDGIN_PREFS_ROOT "/conversations/tab_side") == GTK_POS_RIGHT) + tabs_side = TRUE; +@@ -9667,6 +9768,8 @@ void + pidgin_conv_window_remove_gtkconv(PidginWindow *win, PidginConversation *gtkconv) + { + unsigned int index; ++ GList *gtkconvs; ++ PidginConversation *gtkconvs_data; + + index = gtk_notebook_page_num(GTK_NOTEBOOK(win->notebook), gtkconv->tab_cont); + +@@ -9685,6 +9788,14 @@ pidgin_conv_window_remove_gtkconv(Pidgin + + if (!win->gtkconvs && win != hidden_convwin) + pidgin_conv_window_destroy(win); ++ ++ for (gtkconvs = win->gtkconvs; gtkconvs != NULL; gtkconvs = gtkconvs->next) { ++ gtkconvs_data = gtkconvs->data; ++ if(gtkconvs_data != NULL) { ++ g_object_set_data(G_OBJECT(gtkconvs_data->imhtml), "resize-count", ++ GINT_TO_POINTER(0)); ++ } ++ } + } + + PidginConversation * +@@ -9858,7 +9969,7 @@ conv_placement_last_created_win(PidginCo + win = pidgin_conv_window_new(); + + g_signal_connect(G_OBJECT(win->window), "configure_event", +- G_CALLBACK(gtk_conv_configure_cb), NULL); ++ G_CALLBACK(gtk_conv_configure_cb), win); + + pidgin_conv_window_add_gtkconv(win, conv); + pidgin_conv_window_show(win); +@@ -9876,6 +9987,11 @@ conv_placement_last_created_win_type_con + PurpleConversationType type = purple_conversation_get_type(conv->active_conv); + GList *all; + ++ g_object_set_data(G_OBJECT(conv->imhtml), "resize-count", ++ GINT_TO_POINTER(0)); ++ g_object_set_data(G_OBJECT(conv->entry), "resize-count", ++ GINT_TO_POINTER(0)); ++ + if (GTK_WIDGET_VISIBLE(w)) + gtk_window_get_position(GTK_WINDOW(w), &x, &y); + else +@@ -9958,7 +10074,7 @@ conv_placement_new_window(PidginConversa + win = pidgin_conv_window_new(); + + g_signal_connect(G_OBJECT(win->window), "configure_event", +- G_CALLBACK(gtk_conv_configure_cb), NULL); ++ G_CALLBACK(gtk_conv_configure_cb), win); + + pidgin_conv_window_add_gtkconv(win, conv); + +--- a/pidgin/gtkimhtml.c ++++ b/pidgin/gtkimhtml.c +@@ -67,6 +67,9 @@ + + #define TOOLTIP_TIMEOUT 500 + ++/* GTK_IMHTML_MAX_CONSEC_RESIZES is also defined in gtkconv.c */ ++#define GTK_IMHTML_MAX_CONSEC_RESIZES 6 ++ + static GtkTextViewClass *parent_class = NULL; + + struct scalable_data { +@@ -395,6 +398,59 @@ static void gtk_imhtml_size_allocate(Gtk + int height = 0, y = 0; + GtkTextIter iter; + gboolean scroll = TRUE; ++ PidginConversation *gtkconv; ++ GtkIMHtml *entry, *messages; ++ int resize_count; ++ int entry_rc; ++ int messages_rc; ++ ++ gtkconv = g_object_get_data(G_OBJECT(imhtml), "gtkconv"); ++ ++ if(gtkconv != NULL) { ++ entry = GTK_IMHTML(gtkconv->entry); ++ messages = GTK_IMHTML(gtkconv->imhtml); ++ ++ entry_rc = GPOINTER_TO_INT( ++ g_object_get_data( ++ G_OBJECT(entry), "resize-count")); ++ ++ messages_rc = GPOINTER_TO_INT( ++ g_object_get_data( ++ G_OBJECT(messages), "resize-count")); ++ ++ resize_count = GPOINTER_TO_INT( ++ g_object_get_data( ++ G_OBJECT(imhtml), "resize-count")); ++ ++ if(imhtml == entry) { ++ if(entry_rc >= GTK_IMHTML_MAX_CONSEC_RESIZES || ++ messages_rc >= GTK_IMHTML_MAX_CONSEC_RESIZES) { ++ return; ++ } ++ } else if(imhtml == messages) { ++ if(resize_count >= GTK_IMHTML_MAX_CONSEC_RESIZES) { ++ g_object_set_data( ++ G_OBJECT(entry), "resize-count", ++ GINT_TO_POINTER( ++ GTK_IMHTML_MAX_CONSEC_RESIZES + 1)); ++ ++ return; ++ } ++ ++ if(entry_rc == GTK_IMHTML_MAX_CONSEC_RESIZES + 1) { ++ g_object_set_data(G_OBJECT(messages), "resize-count", ++ GINT_TO_POINTER(0)); ++ return; ++ } ++ ++ g_object_set_data(G_OBJECT(entry), "resize-count", ++ GINT_TO_POINTER(0)); ++ } ++ ++ resize_count++; ++ g_object_set_data(G_OBJECT(imhtml), "resize-count", ++ GINT_TO_POINTER(resize_count)); ++ } + + gtk_text_buffer_get_end_iter(imhtml->text_buffer, &iter); + +@@ -1167,6 +1223,8 @@ static void imhtml_paste_insert(GtkIMHtm + if (!imhtml->wbfo && !plaintext) + gtk_imhtml_close_tags(imhtml, &iter); + ++ g_object_set_data(G_OBJECT(imhtml), "resize-count", ++ GINT_TO_POINTER(0)); + } + + static void paste_plaintext_received_cb (GtkClipboard *clipboard, const gchar *text, gpointer data) +@@ -1186,6 +1244,9 @@ static void paste_received_cb (GtkClipbo + char *text; + GtkIMHtml *imhtml = data; + ++ g_object_set_data(G_OBJECT(imhtml), "resize-count", ++ GINT_TO_POINTER(0)); ++ + if (!gtk_text_view_get_editable(GTK_TEXT_VIEW(imhtml))) + return; + +@@ -1282,6 +1343,9 @@ static void smart_backspace_cb(GtkIMHtml + + /* ok, then we need to insert the image buffer text before the anchor */ + gtk_text_buffer_insert(imhtml->text_buffer, &iter, text, -1); ++ ++ g_object_set_data(G_OBJECT(imhtml), "resize-count", ++ GINT_TO_POINTER(0)); + } + + static void paste_clipboard_cb(GtkIMHtml *imhtml, gpointer blah) +@@ -1307,6 +1371,8 @@ static void imhtml_realized_remove_prima + gtk_text_buffer_remove_selection_clipboard(GTK_IMHTML(imhtml)->text_buffer, + gtk_widget_get_clipboard(GTK_WIDGET(imhtml), GDK_SELECTION_PRIMARY)); + ++ g_object_set_data(G_OBJECT(imhtml), "resize-count", ++ GINT_TO_POINTER(0)); + } + + static void imhtml_destroy_add_primary(GtkIMHtml *imhtml, gpointer unused) +@@ -1387,6 +1453,9 @@ imhtml_paste_cb(GtkIMHtml *imhtml, const + g_signal_emit_by_name(imhtml, "paste_clipboard"); + else if (purple_strequal(str, "text")) + paste_unformatted_cb(NULL, imhtml); ++ ++ g_object_set_data(G_OBJECT(imhtml), "resize-count", ++ GINT_TO_POINTER(0)); + } + + static void imhtml_toggle_format(GtkIMHtml *imhtml, GtkIMHtmlButtons buttons) +@@ -4355,6 +4424,7 @@ static void insert_ca_cb(GtkTextBuffer * + + static void insert_cb(GtkTextBuffer *buffer, GtkTextIter *end, gchar *text, gint len, GtkIMHtml *imhtml) + { ++ PidginConversation *gtkconv; + GtkTextIter start; + + if (!len) +@@ -4364,10 +4434,19 @@ static void insert_cb(GtkTextBuffer *buf + gtk_text_iter_set_offset(&start, imhtml->insert_offset); + + gtk_imhtml_apply_tags_on_insert(imhtml, &start, end); ++ ++ gtkconv = g_object_get_data(G_OBJECT(imhtml), "gtkconv"); ++ if(gtkconv != NULL) { ++ g_object_set_data(G_OBJECT(gtkconv->entry), "resize-count", ++ GINT_TO_POINTER(0)); ++ g_object_set_data(G_OBJECT(gtkconv->imhtml), "resize-count", ++ GINT_TO_POINTER(0)); ++ } + } + + static void delete_cb(GtkTextBuffer *buffer, GtkTextIter *start, GtkTextIter *end, GtkIMHtml *imhtml) + { ++ PidginConversation *gtkconv; + GList *l; + GSList *tags, *sl; + GtkTextIter i; +@@ -4422,6 +4501,14 @@ static void delete_cb(GtkTextBuffer *buf + } + sl = next; + } ++ ++ gtkconv = g_object_get_data(G_OBJECT(imhtml), "gtkconv"); ++ if(gtkconv != NULL) { ++ g_object_set_data(G_OBJECT(gtkconv->entry), "resize-count", ++ GINT_TO_POINTER(0)); ++ g_object_set_data(G_OBJECT(gtkconv->imhtml), "resize-count", ++ GINT_TO_POINTER(0)); ++ } + } + + static void gtk_imhtml_apply_tags_on_insert(GtkIMHtml *imhtml, GtkTextIter *start, GtkTextIter *end) diff -Nru pidgin-2.14.8/debian/patches/series pidgin-2.14.8/debian/patches/series --- pidgin-2.14.8/debian/patches/series 2021-12-01 14:10:18.000000000 +0000 +++ pidgin-2.14.8/debian/patches/series 2023-07-11 16:55:07.000000000 +0000 @@ -6,3 +6,4 @@ 60_1024x600_gtkpounce.c.patch 60_1024x600_gtkprefs.c.patch pounce-webview.patch +rb1342.patch