1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 2000 Red Hat, Inc.
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
22 #ifdef GDK_WINDOWING_X11
23 #include <X11/Xlocale.h> /* so we get the right setlocale */
28 #include "gtksignal.h"
29 #include "gtkimmulticontext.h"
30 #include "gtkimmodule.h"
31 #include "gtkmenuitem.h"
33 static void gtk_im_multicontext_class_init (GtkIMMulticontextClass *class);
34 static void gtk_im_multicontext_init (GtkIMMulticontext *im_multicontext);
35 static void gtk_im_multicontext_finalize (GObject *object);
37 static void gtk_im_multicontext_set_slave (GtkIMMulticontext *multicontext,
40 static void gtk_im_multicontext_set_client_window (GtkIMContext *context,
42 static void gtk_im_multicontext_get_preedit_string (GtkIMContext *context,
44 PangoAttrList **attrs,
46 static gboolean gtk_im_multicontext_filter_keypress (GtkIMContext *context,
48 static void gtk_im_multicontext_focus_in (GtkIMContext *context);
49 static void gtk_im_multicontext_focus_out (GtkIMContext *context);
50 static void gtk_im_multicontext_reset (GtkIMContext *context);
52 void gtk_im_multicontext_preedit_start_cb (GtkIMContext *slave,
53 GtkIMMulticontext *multicontext);
54 void gtk_im_multicontext_preedit_end_cb (GtkIMContext *slave,
55 GtkIMMulticontext *multicontext);
56 void gtk_im_multicontext_preedit_changed_cb (GtkIMContext *slave,
57 GtkIMMulticontext *multicontext);
58 void gtk_im_multicontext_commit_cb (GtkIMContext *slave,
60 GtkIMMulticontext *multicontext);
62 static GtkIMContextClass *parent_class;
64 static const gchar *global_context_id = NULL;
67 gtk_im_multicontext_get_type (void)
69 static GtkType im_multicontext_type = 0;
71 if (!im_multicontext_type)
73 static const GtkTypeInfo im_multicontext_info =
76 sizeof (GtkIMMulticontext),
77 sizeof (GtkIMMulticontextClass),
78 (GtkClassInitFunc) gtk_im_multicontext_class_init,
79 (GtkObjectInitFunc) gtk_im_multicontext_init,
80 /* reserved_1 */ NULL,
81 /* reserved_2 */ NULL,
82 (GtkClassInitFunc) NULL,
85 im_multicontext_type = gtk_type_unique (GTK_TYPE_IM_CONTEXT, &im_multicontext_info);
88 return im_multicontext_type;
92 gtk_im_multicontext_class_init (GtkIMMulticontextClass *class)
94 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
95 GtkIMContextClass *im_context_class = GTK_IM_CONTEXT_CLASS (class);
97 parent_class = g_type_class_peek_parent (class);
99 im_context_class->set_client_window = gtk_im_multicontext_set_client_window;
100 im_context_class->get_preedit_string = gtk_im_multicontext_get_preedit_string;
101 im_context_class->filter_keypress = gtk_im_multicontext_filter_keypress;
102 im_context_class->focus_in = gtk_im_multicontext_focus_in;
103 im_context_class->focus_out = gtk_im_multicontext_focus_out;
104 im_context_class->reset = gtk_im_multicontext_reset;
106 gobject_class->finalize = gtk_im_multicontext_finalize;
110 gtk_im_multicontext_init (GtkIMMulticontext *multicontext)
112 multicontext->slave = NULL;
116 gtk_im_multicontext_new (void)
118 return GTK_IM_CONTEXT (gtk_type_new (GTK_TYPE_IM_MULTICONTEXT));
122 gtk_im_multicontext_finalize (GObject *object)
124 gtk_im_multicontext_set_slave (GTK_IM_MULTICONTEXT (object), NULL);
126 G_OBJECT_CLASS (parent_class)->finalize (object);
130 gtk_im_multicontext_set_slave (GtkIMMulticontext *multicontext,
133 if (multicontext->slave)
135 gtk_signal_disconnect_by_data (GTK_OBJECT (multicontext->slave), multicontext);
136 gtk_object_unref (GTK_OBJECT (multicontext->slave));
139 multicontext->slave = slave;
141 if (multicontext->slave)
143 gtk_object_ref (GTK_OBJECT (multicontext->slave));
144 gtk_object_sink (GTK_OBJECT (multicontext->slave));
146 gtk_signal_connect (GTK_OBJECT (multicontext->slave), "preedit_start",
147 GTK_SIGNAL_FUNC (gtk_im_multicontext_preedit_start_cb),
149 gtk_signal_connect (GTK_OBJECT (multicontext->slave), "preedit_end",
150 GTK_SIGNAL_FUNC (gtk_im_multicontext_preedit_end_cb),
152 gtk_signal_connect (GTK_OBJECT (multicontext->slave), "preedit_changed",
153 GTK_SIGNAL_FUNC (gtk_im_multicontext_preedit_changed_cb),
155 gtk_signal_connect (GTK_OBJECT (multicontext->slave), "commit",
156 GTK_SIGNAL_FUNC (gtk_im_multicontext_commit_cb),
159 if (multicontext->client_window)
160 gtk_im_context_set_client_window (slave, multicontext->client_window);
164 static GtkIMContext *
165 gtk_im_multicontext_get_slave (GtkIMMulticontext *multicontext)
167 if (!multicontext->slave)
169 if (!global_context_id)
173 #ifdef HAVE_LC_MESSAGES
174 locale = setlocale (LC_MESSAGES, NULL);
176 locale = setlocale (LC_CTYPE, NULL);
178 global_context_id = _gtk_im_module_get_default_context_id (locale);
181 gtk_im_multicontext_set_slave (multicontext, _gtk_im_module_create (global_context_id));
182 multicontext->context_id = global_context_id;
185 return multicontext->slave;
189 gtk_im_multicontext_set_client_window (GtkIMContext *context,
192 GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
193 GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
195 multicontext->client_window = window;
198 gtk_im_context_set_client_window (slave, window);
202 gtk_im_multicontext_get_preedit_string (GtkIMContext *context,
204 PangoAttrList **attrs,
207 GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
208 GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
211 gtk_im_context_get_preedit_string (slave, str, attrs, cursor_pos);
215 *str = g_strdup ("");
217 *attrs = pango_attr_list_new ();
222 gtk_im_multicontext_filter_keypress (GtkIMContext *context,
225 GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
226 GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
229 return gtk_im_context_filter_keypress (slave, event);
235 gtk_im_multicontext_focus_in (GtkIMContext *context)
237 GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
240 /* If the global context type is different from the context we were
241 * using before, get rid of the old slave and create a new one
242 * for the new global context type.
244 if (!multicontext->context_id ||
245 strcmp (global_context_id, multicontext->context_id) != 0)
246 gtk_im_multicontext_set_slave (multicontext, NULL);
248 slave = gtk_im_multicontext_get_slave (multicontext);
251 gtk_im_context_focus_in (slave);
255 gtk_im_multicontext_focus_out (GtkIMContext *context)
257 GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
258 GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
261 gtk_im_context_focus_out (slave);
265 gtk_im_multicontext_reset (GtkIMContext *context)
267 GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
268 GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
271 gtk_im_context_reset (slave);
275 gtk_im_multicontext_preedit_start_cb (GtkIMContext *slave,
276 GtkIMMulticontext *multicontext)
278 gtk_signal_emit_by_name (GTK_OBJECT (multicontext), "preedit_start");
282 gtk_im_multicontext_preedit_end_cb (GtkIMContext *slave,
283 GtkIMMulticontext *multicontext)
285 gtk_signal_emit_by_name (GTK_OBJECT (multicontext), "preedit_end");
289 gtk_im_multicontext_preedit_changed_cb (GtkIMContext *slave,
290 GtkIMMulticontext *multicontext)
292 gtk_signal_emit_by_name (GTK_OBJECT (multicontext), "preedit_changed");
296 gtk_im_multicontext_commit_cb (GtkIMContext *slave,
298 GtkIMMulticontext *multicontext)
300 gtk_signal_emit_by_name (GTK_OBJECT (multicontext), "commit", str);;
304 activate_cb (GtkWidget *menuitem,
305 GtkIMMulticontext *context)
307 const gchar *id = gtk_object_get_data (GTK_OBJECT (menuitem), "gtk-context-id");
309 gtk_im_context_reset (GTK_IM_CONTEXT (context));
311 global_context_id = id;
312 gtk_im_multicontext_set_slave (context, NULL);
316 * gtk_im_multicontext_append_menuitems:
317 * @context: a #GtkIMMultiContext
318 * @menushell: a #GtkMenuShell
320 * Add menuitems for various available input methods to a menu;
321 * the menuitems, when selected, will switch the input method
322 * for the context and the global default input method.
325 gtk_im_multicontext_append_menuitems (GtkIMMulticontext *context,
326 GtkMenuShell *menushell)
328 const GtkIMContextInfo **contexts;
331 _gtk_im_module_list (&contexts, &n_contexts);
333 for (i=0; i < n_contexts; i++)
337 menuitem = gtk_menu_item_new_with_label (contexts[i]->context_name);
339 gtk_object_set_data (GTK_OBJECT (menuitem), "gtk-context-id",
340 (char *)contexts[i]->context_id);
341 gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
342 activate_cb, context);
344 gtk_widget_show (menuitem);
345 gtk_menu_shell_append (menushell, menuitem);