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);
51 static void gtk_im_multicontext_set_cursor_pos (GtkIMContext *context,
54 void gtk_im_multicontext_preedit_start_cb (GtkIMContext *slave,
55 GtkIMMulticontext *multicontext);
56 void gtk_im_multicontext_preedit_end_cb (GtkIMContext *slave,
57 GtkIMMulticontext *multicontext);
58 void gtk_im_multicontext_preedit_changed_cb (GtkIMContext *slave,
59 GtkIMMulticontext *multicontext);
60 void gtk_im_multicontext_commit_cb (GtkIMContext *slave,
62 GtkIMMulticontext *multicontext);
64 static GtkIMContextClass *parent_class;
66 static const gchar *global_context_id = NULL;
69 gtk_im_multicontext_get_type (void)
71 static GtkType im_multicontext_type = 0;
73 if (!im_multicontext_type)
75 static const GtkTypeInfo im_multicontext_info =
78 sizeof (GtkIMMulticontext),
79 sizeof (GtkIMMulticontextClass),
80 (GtkClassInitFunc) gtk_im_multicontext_class_init,
81 (GtkObjectInitFunc) gtk_im_multicontext_init,
82 /* reserved_1 */ NULL,
83 /* reserved_2 */ NULL,
84 (GtkClassInitFunc) NULL,
87 im_multicontext_type = gtk_type_unique (GTK_TYPE_IM_CONTEXT, &im_multicontext_info);
90 return im_multicontext_type;
94 gtk_im_multicontext_class_init (GtkIMMulticontextClass *class)
96 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
97 GtkIMContextClass *im_context_class = GTK_IM_CONTEXT_CLASS (class);
99 parent_class = g_type_class_peek_parent (class);
101 im_context_class->set_client_window = gtk_im_multicontext_set_client_window;
102 im_context_class->get_preedit_string = gtk_im_multicontext_get_preedit_string;
103 im_context_class->filter_keypress = gtk_im_multicontext_filter_keypress;
104 im_context_class->focus_in = gtk_im_multicontext_focus_in;
105 im_context_class->focus_out = gtk_im_multicontext_focus_out;
106 im_context_class->reset = gtk_im_multicontext_reset;
107 im_context_class->set_cursor_pos = gtk_im_multicontext_set_cursor_pos;
109 gobject_class->finalize = gtk_im_multicontext_finalize;
113 gtk_im_multicontext_init (GtkIMMulticontext *multicontext)
115 multicontext->slave = NULL;
119 gtk_im_multicontext_new (void)
121 return GTK_IM_CONTEXT (gtk_type_new (GTK_TYPE_IM_MULTICONTEXT));
125 gtk_im_multicontext_finalize (GObject *object)
127 gtk_im_multicontext_set_slave (GTK_IM_MULTICONTEXT (object), NULL);
129 G_OBJECT_CLASS (parent_class)->finalize (object);
133 gtk_im_multicontext_set_slave (GtkIMMulticontext *multicontext,
136 if (multicontext->slave)
138 gtk_signal_disconnect_by_data (GTK_OBJECT (multicontext->slave), multicontext);
139 gtk_object_unref (GTK_OBJECT (multicontext->slave));
142 multicontext->slave = slave;
144 if (multicontext->slave)
146 gtk_object_ref (GTK_OBJECT (multicontext->slave));
147 gtk_object_sink (GTK_OBJECT (multicontext->slave));
149 gtk_signal_connect (GTK_OBJECT (multicontext->slave), "preedit_start",
150 GTK_SIGNAL_FUNC (gtk_im_multicontext_preedit_start_cb),
152 gtk_signal_connect (GTK_OBJECT (multicontext->slave), "preedit_end",
153 GTK_SIGNAL_FUNC (gtk_im_multicontext_preedit_end_cb),
155 gtk_signal_connect (GTK_OBJECT (multicontext->slave), "preedit_changed",
156 GTK_SIGNAL_FUNC (gtk_im_multicontext_preedit_changed_cb),
158 gtk_signal_connect (GTK_OBJECT (multicontext->slave), "commit",
159 GTK_SIGNAL_FUNC (gtk_im_multicontext_commit_cb),
162 if (multicontext->client_window)
163 gtk_im_context_set_client_window (slave, multicontext->client_window);
167 static GtkIMContext *
168 gtk_im_multicontext_get_slave (GtkIMMulticontext *multicontext)
170 if (!multicontext->slave)
172 if (!global_context_id)
176 #ifdef HAVE_LC_MESSAGES
177 locale = setlocale (LC_MESSAGES, NULL);
179 locale = setlocale (LC_CTYPE, NULL);
181 global_context_id = _gtk_im_module_get_default_context_id (locale);
184 gtk_im_multicontext_set_slave (multicontext, _gtk_im_module_create (global_context_id));
185 multicontext->context_id = global_context_id;
188 return multicontext->slave;
192 gtk_im_multicontext_set_client_window (GtkIMContext *context,
195 GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
196 GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
198 multicontext->client_window = window;
201 gtk_im_context_set_client_window (slave, window);
205 gtk_im_multicontext_get_preedit_string (GtkIMContext *context,
207 PangoAttrList **attrs,
210 GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
211 GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
214 gtk_im_context_get_preedit_string (slave, str, attrs, cursor_pos);
218 *str = g_strdup ("");
220 *attrs = pango_attr_list_new ();
225 gtk_im_multicontext_filter_keypress (GtkIMContext *context,
228 GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
229 GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
232 return gtk_im_context_filter_keypress (slave, event);
238 gtk_im_multicontext_focus_in (GtkIMContext *context)
240 GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
243 /* If the global context type is different from the context we were
244 * using before, get rid of the old slave and create a new one
245 * for the new global context type.
247 if (!multicontext->context_id ||
248 strcmp (global_context_id, multicontext->context_id) != 0)
249 gtk_im_multicontext_set_slave (multicontext, NULL);
251 slave = gtk_im_multicontext_get_slave (multicontext);
254 gtk_im_context_focus_in (slave);
258 gtk_im_multicontext_focus_out (GtkIMContext *context)
260 GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
261 GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
264 gtk_im_context_focus_out (slave);
268 gtk_im_multicontext_reset (GtkIMContext *context)
270 GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
271 GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
274 gtk_im_context_reset (slave);
278 gtk_im_multicontext_set_cursor_pos (GtkIMContext *context,
281 GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
282 GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
285 gtk_im_context_set_cursor_pos (slave, area);
289 gtk_im_multicontext_preedit_start_cb (GtkIMContext *slave,
290 GtkIMMulticontext *multicontext)
292 gtk_signal_emit_by_name (GTK_OBJECT (multicontext), "preedit_start");
296 gtk_im_multicontext_preedit_end_cb (GtkIMContext *slave,
297 GtkIMMulticontext *multicontext)
299 gtk_signal_emit_by_name (GTK_OBJECT (multicontext), "preedit_end");
303 gtk_im_multicontext_preedit_changed_cb (GtkIMContext *slave,
304 GtkIMMulticontext *multicontext)
306 gtk_signal_emit_by_name (GTK_OBJECT (multicontext), "preedit_changed");
310 gtk_im_multicontext_commit_cb (GtkIMContext *slave,
312 GtkIMMulticontext *multicontext)
314 gtk_signal_emit_by_name (GTK_OBJECT (multicontext), "commit", str);;
318 activate_cb (GtkWidget *menuitem,
319 GtkIMMulticontext *context)
321 const gchar *id = gtk_object_get_data (GTK_OBJECT (menuitem), "gtk-context-id");
323 gtk_im_context_reset (GTK_IM_CONTEXT (context));
325 global_context_id = id;
326 gtk_im_multicontext_set_slave (context, NULL);
330 * gtk_im_multicontext_append_menuitems:
331 * @context: a #GtkIMMultiContext
332 * @menushell: a #GtkMenuShell
334 * Add menuitems for various available input methods to a menu;
335 * the menuitems, when selected, will switch the input method
336 * for the context and the global default input method.
339 gtk_im_multicontext_append_menuitems (GtkIMMulticontext *context,
340 GtkMenuShell *menushell)
342 const GtkIMContextInfo **contexts;
345 _gtk_im_module_list (&contexts, &n_contexts);
347 for (i=0; i < n_contexts; i++)
351 menuitem = gtk_menu_item_new_with_label (contexts[i]->context_name);
353 gtk_object_set_data (GTK_OBJECT (menuitem), "gtk-context-id",
354 (char *)contexts[i]->context_id);
355 gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
356 activate_cb, context);
358 gtk_widget_show (menuitem);
359 gtk_menu_shell_append (menushell, menuitem);