summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorOwen Taylor <otaylor@redhat.com>2002-05-17 19:27:53 +0000
committerOwen Taylor <otaylor@src.gnome.org>2002-05-17 19:27:53 +0000
commit3fe86a489daac550a65035d60677b839390310ea (patch)
treef3332227326a20de9286b3287bb6a03cf0cc5abc /modules
parent0274195e19cd5da38728374e4d7d6f93ebf568bc (diff)
downloadgtk+-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.c95
-rw-r--r--modules/input/gtkimcontextxim.h2
-rw-r--r--modules/input/imxim.c1
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