GNOME Bugzilla – Bug 66636
GtkEntry and GtkText buggy if unparented with active selection
Last modified: 2011-02-04 16:09:06 UTC
I have noticed a buggy behavior of GtkEntry and GtkText widgets in GTK+ 1.2.10, in case they are unrealized when they own the selection. The problem was initially noticed in the Sylpheed mail client (http://sylpheed.good-day.net); I have written a small test program which exercises the bug. The test program (test-selection.c) creates a window with several buttons and a GtkFrame, and two GtkVBox'es, each containing a GtkEntry and a GtkText. The button labeled "Show text 1" puts the first VBox into the GtkFrame. The button labeled "Show text 2" puts the second VBox into the GtkFrame. The button labeled "Hide all" removes any of the VBox'es from the GtkFrame. Compilation command: gcc -o test-selection -g -O2 -Wall `gtk-config --cflags` \ test-selection.c `gtk-config --libs` Buggy behavior observed: 1. Select some text in the first GtkEntry and check that it can be pasted into another application. Then click "Hide all" or "Show text 2", and then click "Show text 1" to restore the first GtkEntry. At this step the text appears selected, but cannot be pasted to another application. Moreover, making another selection in this GtkEntry does not work -- again, the text appears selected but cannot be pasted to another application. 2. Restart the test program and do the same thing as in step 1, but with GtkText instead of the GtkEntry. It fails in the same way: after unparenting the widget which owns the selection, copying selection from the widget stops working. 3. Finally, restart the test program again and select some text in the first GtkText. Then click "Show text 2" and select some text in either the GtkText or GtkEntry. At this point a warning appears, and sometimes SIGSEGV occurs: Gdk-CRITICAL **: file gdkwindow.c: line 1390 (gdk_window_get_size): assertion `window != NULL' failed. Program received signal SIGSEGV, Segmentation fault. 0x400fbdf6 in gtk_text_update_text (editable=0x8087c90, start_pos=0, end_pos=14) at gtktext.c:5401 5401 if (CACHE_DATA(cache).start.index < end_pos) (gdb) where
+ Trace 14872
I have tried to investigate the source of this problem and found that neither GtkText nor GtkEntry drop the selection ownership when the widget is unrealized. Because of this, the structures in gtkselection.c (namely, the current_selections list) continue to hold a pointer to the widget even after it is unrealized. Later, when the widget is realized again, gtk_selection_owner_set() finds that the widget is already registered in current_selections and does nothing to reestablish the selection. Also, because gtk_text_unrealize() destroys some internal structures, when gtk_selection_owner_set() for another widget sends GDK_SELECTION_CLEAR to unrealized GtkText, the program crashes. A simple way to fix this is to add the following call to gtk_text_unrealize() and gtk_entry_unrealize(): gtk_editable_claim_selection (GTK_EDITABLE (widget), FALSE, GDK_CURRENT_TIME); The attached patch does exactly this, and after doing this change none of the problems described above occur. Note that gtk_text_realize() and gtk_entry_realize() call gtk_editable_claim_selection() conditionally -- only when the selection is not empty. When unrealizing, though, this does not work, because in some cases GtkText or GtkEntry can own the selection even when it is empty. One way to get such situation is to delete all selected text by gtk_text_forward_delete() or something like this -- it updates the selection boundaries but does not drop the selection ownership when the selection ends up empty. So dropping the selection ownership in unrealize handler must be done in any case, even if the selection appears empty.
Created attachment 6199 [details] test program to demonstrate the bug
Created attachment 6200 [details] [review] proposed patch to fix selection handling
Created attachment 6428 [details] [review] Patch applied to HEAD fixing warning/crash
The patch applied to HEAD fixes the warning crash. Putting the bug on 1.2.11 for backporting. The misbehavior is no longer relevant for GTK+-1.3/2.0 because GtkTextView/GtkEntry/ GtkLabel use GtkClipboard so can handle selection when not realized, and GtkText is only provided for temporary porting purposes ... you need to define G_ENABLE_BROKEN to get it. Thu Jan 17 17:02:38 2002 Owen Taylor <otaylor@redhat.com> * gtk/gtkwidget.c (gtk_widget_real_unrealize): Call gtk_selection_remove_all() here, not in destroy/ finalize. (#66636, Sergey Vlasov) * gtk/gtkselection.c (gtk_selection_request): Fix reentrancy problem with multiple conversions. * gtk/gtkselection.c (gtk_selection_remove_all): Don't remove incrs, we don't need the widget for maintain the incr. * gtk/gtkselection.c (struct _GtkIncrInfo): Remove the widget field from here, we don't need it.
Wasn't meant to be resolved, just moved to 1.2.11 milestone.
*** Bug 51800 has been marked as a duplicate of this bug. ***
*** Bug 60887 has been marked as a duplicate of this bug. ***
*** Bug 94746 has been marked as a duplicate of this bug. ***
No 1.2.11 is planned, so closing all 1.2.11 specific bugs.
*Really* close all 1.2.11 bugs, instead of just adding a comment...