diff options
author | Owen Taylor <otaylor@redhat.com> | 2002-05-17 19:27:53 +0000 |
---|---|---|
committer | Owen Taylor <otaylor@src.gnome.org> | 2002-05-17 19:27:53 +0000 |
commit | 3fe86a489daac550a65035d60677b839390310ea (patch) | |
tree | f3332227326a20de9286b3287bb6a03cf0cc5abc /modules | |
parent | 0274195e19cd5da38728374e4d7d6f93ebf568bc (diff) | |
download | gtk+-3fe86a489daac550a65035d60677b839390310ea.tar.gz |
Protect against reentrancy problems by emitting ::preedit_changed at the
Fri May 17 14:40:24 2002 Owen Taylor <otaylor@redhat.com>
* 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.
Diffstat (limited to 'modules')
-rw-r--r-- | modules/input/gtkimcontextxim.c | 95 | ||||
-rw-r--r-- | modules/input/gtkimcontextxim.h | 2 | ||||
-rw-r--r-- | modules/input/imxim.c | 1 |
3 files changed, 74 insertions, 24 deletions
diff --git a/modules/input/gtkimcontextxim.c b/modules/input/gtkimcontextxim.c index 193edb5745..febc44aa19 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 { GdkDisplay *display; @@ -33,6 +35,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); @@ -64,6 +79,9 @@ GType gtk_type_im_context_xim = 0; 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) { @@ -948,34 +966,39 @@ 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; gint height = gdk_screen_get_height (gtk_widget_get_screen (toplevel)); - 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 < height) y = rect.y + rect.height; else y = 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; } @@ -986,7 +1009,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) @@ -1007,35 +1031,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 = g_new (StatusWindow, 1); + status_window->window = gtk_window_new (GTK_WINDOW_POPUP); + status_window->toplevel = toplevel; + + status_windows = g_slist_prepend (status_windows, status_window); - status_window = gtk_window_new (GTK_WINDOW_POPUP); + window = status_window->window; - gtk_window_set_policy (GTK_WINDOW (status_window), FALSE, FALSE, FALSE); - gtk_widget_set_app_paintable (status_window, TRUE); + 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 @@ -1086,3 +1120,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 d8c31f75ce..0c23f948bf 100644 --- a/modules/input/gtkimcontextxim.h +++ b/modules/input/gtkimcontextxim.h @@ -84,6 +84,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 |