diff --git a/ChangeLog b/ChangeLog index 7a783ea209..73b281e849 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +Fri May 17 14:40:24 2002 Owen Taylor + + * gtk/gtkimmulticontext.c (gtk_im_multicontext_set_slave): + Protect against reentrancy problems by emitting + ::preedit_changed at the end, fixing input context + leak. (Yao Zhang) + + * modules/input/gtkimcontextxim.c (status_window_free): + Patch from Federico Mena Quintero to fix problem where + references to IMContextXIM were kept around after + module was unloaded. + + * gtk/gtkdnd.c (gtk_drag_dest_set): NULL initialize + proxy window. + Fri May 17 13:56:23 2002 Owen Taylor * gtk/gtkplug.c (gtk_plug_filter_func): Fix a missing diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 7a783ea209..73b281e849 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,18 @@ +Fri May 17 14:40:24 2002 Owen Taylor + + * gtk/gtkimmulticontext.c (gtk_im_multicontext_set_slave): + Protect against reentrancy problems by emitting + ::preedit_changed at the end, fixing input context + leak. (Yao Zhang) + + * modules/input/gtkimcontextxim.c (status_window_free): + Patch from Federico Mena Quintero to fix problem where + references to IMContextXIM were kept around after + module was unloaded. + + * gtk/gtkdnd.c (gtk_drag_dest_set): NULL initialize + proxy window. + Fri May 17 13:56:23 2002 Owen Taylor * gtk/gtkplug.c (gtk_plug_filter_func): Fix a missing diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 7a783ea209..73b281e849 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,18 @@ +Fri May 17 14:40:24 2002 Owen Taylor + + * gtk/gtkimmulticontext.c (gtk_im_multicontext_set_slave): + Protect against reentrancy problems by emitting + ::preedit_changed at the end, fixing input context + leak. (Yao Zhang) + + * modules/input/gtkimcontextxim.c (status_window_free): + Patch from Federico Mena Quintero to fix problem where + references to IMContextXIM were kept around after + module was unloaded. + + * gtk/gtkdnd.c (gtk_drag_dest_set): NULL initialize + proxy window. + Fri May 17 13:56:23 2002 Owen Taylor * gtk/gtkplug.c (gtk_plug_filter_func): Fix a missing diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 7a783ea209..73b281e849 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,18 @@ +Fri May 17 14:40:24 2002 Owen Taylor + + * gtk/gtkimmulticontext.c (gtk_im_multicontext_set_slave): + Protect against reentrancy problems by emitting + ::preedit_changed at the end, fixing input context + leak. (Yao Zhang) + + * modules/input/gtkimcontextxim.c (status_window_free): + Patch from Federico Mena Quintero to fix problem where + references to IMContextXIM were kept around after + module was unloaded. + + * gtk/gtkdnd.c (gtk_drag_dest_set): NULL initialize + proxy window. + Fri May 17 13:56:23 2002 Owen Taylor * gtk/gtkplug.c (gtk_plug_filter_func): Fix a missing diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 7a783ea209..73b281e849 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,18 @@ +Fri May 17 14:40:24 2002 Owen Taylor + + * gtk/gtkimmulticontext.c (gtk_im_multicontext_set_slave): + Protect against reentrancy problems by emitting + ::preedit_changed at the end, fixing input context + leak. (Yao Zhang) + + * modules/input/gtkimcontextxim.c (status_window_free): + Patch from Federico Mena Quintero to fix problem where + references to IMContextXIM were kept around after + module was unloaded. + + * gtk/gtkdnd.c (gtk_drag_dest_set): NULL initialize + proxy window. + Fri May 17 13:56:23 2002 Owen Taylor * gtk/gtkplug.c (gtk_plug_filter_func): Fix a missing diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 7a783ea209..73b281e849 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,18 @@ +Fri May 17 14:40:24 2002 Owen Taylor + + * gtk/gtkimmulticontext.c (gtk_im_multicontext_set_slave): + Protect against reentrancy problems by emitting + ::preedit_changed at the end, fixing input context + leak. (Yao Zhang) + + * modules/input/gtkimcontextxim.c (status_window_free): + Patch from Federico Mena Quintero to fix problem where + references to IMContextXIM were kept around after + module was unloaded. + + * gtk/gtkdnd.c (gtk_drag_dest_set): NULL initialize + proxy window. + Fri May 17 13:56:23 2002 Owen Taylor * gtk/gtkplug.c (gtk_plug_filter_func): Fix a missing diff --git a/gtk/gtkdnd.c b/gtk/gtkdnd.c index f3917bcbd7..cf50b769be 100644 --- a/gtk/gtkdnd.c +++ b/gtk/gtkdnd.c @@ -846,9 +846,9 @@ gtk_drag_dest_set (GtkWidget *widget, site->target_list = gtk_target_list_new (targets, n_targets); else site->target_list = NULL; - site->actions = actions; site->do_proxy = FALSE; + site->proxy_window = NULL; gtk_drag_dest_set_internal (widget, site); } diff --git a/gtk/gtkimmulticontext.c b/gtk/gtkimmulticontext.c index 20796f1e73..8ab0207bd1 100644 --- a/gtk/gtkimmulticontext.c +++ b/gtk/gtkimmulticontext.c @@ -157,6 +157,8 @@ gtk_im_multicontext_set_slave (GtkIMMulticontext *multicontext, GtkIMContext *slave, gboolean finalizing) { + gboolean need_preedit_changed = FALSE; + if (multicontext->slave) { if (!finalizing) @@ -179,7 +181,7 @@ gtk_im_multicontext_set_slave (GtkIMMulticontext *multicontext, multicontext->slave = NULL; if (!finalizing) - g_signal_emit_by_name (multicontext, "preedit_changed"); + need_preedit_changed = TRUE; } multicontext->slave = slave; @@ -210,6 +212,9 @@ gtk_im_multicontext_set_slave (GtkIMMulticontext *multicontext, if (multicontext->client_window) gtk_im_context_set_client_window (slave, multicontext->client_window); } + + if (need_preedit_changed) + g_signal_emit_by_name (multicontext, "preedit_changed"); } static GtkIMContext * diff --git a/modules/input/gtkimcontextxim.c b/modules/input/gtkimcontextxim.c index a76b667de1..eec08cd98f 100644 --- a/modules/input/gtkimcontextxim.c +++ b/modules/input/gtkimcontextxim.c @@ -25,6 +25,8 @@ #include "gtk/gtkwindow.h" #include "gtkimcontextxim.h" +typedef struct _StatusWindow StatusWindow; + struct _GtkXIMInfo { XIM im; @@ -32,6 +34,19 @@ struct _GtkXIMInfo XIMStyle style; }; +/* A context status window; these are kept in the status_windows list. */ +struct _StatusWindow +{ + GtkWidget *window; + + /* Toplevel window to which the status window corresponds */ + GtkWidget *toplevel; + + /* Signal connection ids; we connect to the toplevel */ + guint destroy_handler_id; + guint configure_handler_id; +}; + static void gtk_im_context_xim_class_init (GtkIMContextXIMClass *class); static void gtk_im_context_xim_init (GtkIMContextXIM *im_context_xim); static void gtk_im_context_xim_finalize (GObject *obj); @@ -63,6 +78,9 @@ GType gtk_type_im_context_xim = 0; static GSList *open_ims = NULL; +/* List of status windows for different toplevels */ +static GSList *status_windows = NULL; + void gtk_im_context_xim_register_type (GTypeModule *type_module) { @@ -941,32 +959,38 @@ status_window_style_set (GtkWidget *toplevel, gtk_widget_modify_fg (label, i, &toplevel->style->text[i]); } +/* Frees a status window and removes its link from the status_windows list */ static void -status_window_destroy (GtkWidget *toplevel, - GtkWidget *status_window) +status_window_free (StatusWindow *status_window) { - gtk_widget_destroy (status_window); - g_object_set_data (G_OBJECT (toplevel), "gtk-im-xim-status-window", NULL); + status_windows = g_slist_remove (status_windows, status_window); + + g_signal_handler_disconnect (status_window->toplevel, status_window->destroy_handler_id); + g_signal_handler_disconnect (status_window->toplevel, status_window->configure_handler_id); + gtk_widget_destroy (status_window->window); + g_object_set_data (G_OBJECT (status_window->toplevel), "gtk-im-xim-status-window", NULL); + + g_free (status_window); } - + static gboolean status_window_configure (GtkWidget *toplevel, GdkEventConfigure *event, - GtkWidget *status_window) + StatusWindow *status_window) { GdkRectangle rect; GtkRequisition requisition; gint y; gdk_window_get_frame_extents (toplevel->window, &rect); - gtk_widget_size_request (status_window, &requisition); + gtk_widget_size_request (status_window->window, &requisition); if (rect.y + rect.height + requisition.height < gdk_screen_height ()) y = rect.y + rect.height; else y = gdk_screen_height () - requisition.height; - gtk_window_move (GTK_WINDOW (status_window), rect.x, y); + gtk_window_move (GTK_WINDOW (status_window->window), rect.x, y); return FALSE; } @@ -977,7 +1001,8 @@ status_window_get (GtkIMContextXIM *context_xim, { GdkWindow *toplevel_gdk; GtkWidget *toplevel; - GtkWidget *status_window; + GtkWidget *window; + StatusWindow *status_window; GtkWidget *status_label; if (!context_xim->client_window) @@ -998,35 +1023,45 @@ status_window_get (GtkIMContextXIM *context_xim, return NULL; status_window = g_object_get_data (G_OBJECT (toplevel), "gtk-im-xim-status-window"); - if (status_window || !create) - return status_window; + if (status_window) + return status_window->window; + else if (!create) + return NULL; - status_window = gtk_window_new (GTK_WINDOW_POPUP); + status_window = g_new (StatusWindow, 1); + status_window->window = gtk_window_new (GTK_WINDOW_POPUP); + status_window->toplevel = toplevel; - gtk_window_set_policy (GTK_WINDOW (status_window), FALSE, FALSE, FALSE); - gtk_widget_set_app_paintable (status_window, TRUE); + status_windows = g_slist_prepend (status_windows, status_window); + + window = status_window->window; + + gtk_window_set_policy (GTK_WINDOW (window), FALSE, FALSE, FALSE); + gtk_widget_set_app_paintable (window, TRUE); status_label = gtk_label_new (""); gtk_misc_set_padding (GTK_MISC (status_label), 1, 1); gtk_widget_show (status_label); - gtk_container_add (GTK_CONTAINER (status_window), status_label); + gtk_container_add (GTK_CONTAINER (window), status_label); - g_signal_connect (toplevel, "destroy", - G_CALLBACK (status_window_destroy), status_window); - g_signal_connect (toplevel, "configure_event", - G_CALLBACK (status_window_configure), status_window); + status_window->destroy_handler_id = g_signal_connect_swapped (toplevel, "destroy", + G_CALLBACK (status_window_free), + status_window); + status_window->configure_handler_id = g_signal_connect (toplevel, "configure_event", + G_CALLBACK (status_window_configure), + status_window); status_window_configure (toplevel, NULL, status_window); - - g_signal_connect (status_window, "style_set", + + g_signal_connect (window, "style_set", G_CALLBACK (status_window_style_set), status_label); - g_signal_connect (status_window, "expose_event", + g_signal_connect (window, "expose_event", G_CALLBACK (status_window_expose_event), NULL); - + g_object_set_data (G_OBJECT (toplevel), "gtk-im-xim-status-window", status_window); - return status_window; + return window; } static gboolean @@ -1077,3 +1112,16 @@ status_window_set_text (GtkIMContextXIM *context_xim, gtk_widget_hide (status_window); } } + +/** + * gtk_im_context_xim_shutdown: + * + * Destroys all the status windows that are kept by the XIM contexts. This + * function should only be called by the XIM module exit routine. + **/ +void +gtk_im_context_xim_shutdown (void) +{ + while (status_windows) + status_window_free (status_windows->data); +} diff --git a/modules/input/gtkimcontextxim.h b/modules/input/gtkimcontextxim.h index ddda56826a..51a09c8844 100644 --- a/modules/input/gtkimcontextxim.h +++ b/modules/input/gtkimcontextxim.h @@ -83,6 +83,8 @@ struct _GtkIMContextXIMClass void gtk_im_context_xim_register_type (GTypeModule *type_module); GtkIMContext *gtk_im_context_xim_new (void); +void gtk_im_context_xim_shutdown (void); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/modules/input/imxim.c b/modules/input/imxim.c index f37a57ae50..503e555923 100644 --- a/modules/input/imxim.c +++ b/modules/input/imxim.c @@ -43,6 +43,7 @@ im_module_init (GTypeModule *type_module) void im_module_exit (void) { + gtk_im_context_xim_shutdown (); } void