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.
25 #include "gtkimmulticontext.h"
26 #include "gtkimmodule.h"
27 #include "gtkradiomenuitem.h"
29 static void gtk_im_multicontext_class_init (GtkIMMulticontextClass *class);
30 static void gtk_im_multicontext_init (GtkIMMulticontext *im_multicontext);
31 static void gtk_im_multicontext_finalize (GObject *object);
33 static void gtk_im_multicontext_set_slave (GtkIMMulticontext *multicontext,
37 static void gtk_im_multicontext_set_client_window (GtkIMContext *context,
39 static void gtk_im_multicontext_get_preedit_string (GtkIMContext *context,
41 PangoAttrList **attrs,
43 static gboolean gtk_im_multicontext_filter_keypress (GtkIMContext *context,
45 static void gtk_im_multicontext_focus_in (GtkIMContext *context);
46 static void gtk_im_multicontext_focus_out (GtkIMContext *context);
47 static void gtk_im_multicontext_reset (GtkIMContext *context);
48 static void gtk_im_multicontext_set_cursor_location (GtkIMContext *context,
50 static void gtk_im_multicontext_set_use_preedit (GtkIMContext *context,
51 gboolean use_preedit);
52 static gboolean gtk_im_multicontext_get_surrounding (GtkIMContext *context,
55 static void gtk_im_multicontext_set_surrounding (GtkIMContext *context,
60 static void gtk_im_multicontext_preedit_start_cb (GtkIMContext *slave,
61 GtkIMMulticontext *multicontext);
62 static void gtk_im_multicontext_preedit_end_cb (GtkIMContext *slave,
63 GtkIMMulticontext *multicontext);
64 static void gtk_im_multicontext_preedit_changed_cb (GtkIMContext *slave,
65 GtkIMMulticontext *multicontext);
66 static void gtk_im_multicontext_commit_cb (GtkIMContext *slave,
68 GtkIMMulticontext *multicontext);
69 static gboolean gtk_im_multicontext_retrieve_surrounding_cb (GtkIMContext *slave,
70 GtkIMMulticontext *multicontext);
71 static gboolean gtk_im_multicontext_delete_surrounding_cb (GtkIMContext *slave,
74 GtkIMMulticontext *multicontext);
75 static GtkIMContextClass *parent_class;
77 static const gchar *global_context_id = NULL;
80 gtk_im_multicontext_get_type (void)
82 static GType im_multicontext_type = 0;
84 if (!im_multicontext_type)
86 static const GTypeInfo im_multicontext_info =
88 sizeof (GtkIMMulticontextClass),
90 (GBaseFinalizeFunc) NULL,
91 (GClassInitFunc) gtk_im_multicontext_class_init,
92 NULL, /* class_finalize */
93 NULL, /* class_data */
94 sizeof (GtkIMMulticontext),
96 (GInstanceInitFunc) gtk_im_multicontext_init,
99 im_multicontext_type =
100 g_type_register_static (GTK_TYPE_IM_CONTEXT, "GtkIMMulticontext",
101 &im_multicontext_info, 0);
104 return im_multicontext_type;
108 gtk_im_multicontext_class_init (GtkIMMulticontextClass *class)
110 GObjectClass *gobject_class = G_OBJECT_CLASS (class);
111 GtkIMContextClass *im_context_class = GTK_IM_CONTEXT_CLASS (class);
113 parent_class = g_type_class_peek_parent (class);
115 im_context_class->set_client_window = gtk_im_multicontext_set_client_window;
116 im_context_class->get_preedit_string = gtk_im_multicontext_get_preedit_string;
117 im_context_class->filter_keypress = gtk_im_multicontext_filter_keypress;
118 im_context_class->focus_in = gtk_im_multicontext_focus_in;
119 im_context_class->focus_out = gtk_im_multicontext_focus_out;
120 im_context_class->reset = gtk_im_multicontext_reset;
121 im_context_class->set_cursor_location = gtk_im_multicontext_set_cursor_location;
122 im_context_class->set_use_preedit = gtk_im_multicontext_set_use_preedit;
123 im_context_class->set_surrounding = gtk_im_multicontext_set_surrounding;
124 im_context_class->get_surrounding = gtk_im_multicontext_get_surrounding;
126 gobject_class->finalize = gtk_im_multicontext_finalize;
130 gtk_im_multicontext_init (GtkIMMulticontext *multicontext)
132 multicontext->slave = NULL;
136 * gtk_im_multicontext_new:
138 * Creates a new #GtkIMMulticontext.
140 * Returns: a new #GtkIMMulticontext.
143 gtk_im_multicontext_new (void)
145 return g_object_new (GTK_TYPE_IM_MULTICONTEXT, NULL);
149 gtk_im_multicontext_finalize (GObject *object)
151 gtk_im_multicontext_set_slave (GTK_IM_MULTICONTEXT (object), NULL, TRUE);
153 G_OBJECT_CLASS (parent_class)->finalize (object);
157 gtk_im_multicontext_set_slave (GtkIMMulticontext *multicontext,
161 gboolean need_preedit_changed = FALSE;
163 if (multicontext->slave)
166 gtk_im_context_reset (multicontext->slave);
168 g_signal_handlers_disconnect_by_func (multicontext->slave,
169 gtk_im_multicontext_preedit_start_cb,
171 g_signal_handlers_disconnect_by_func (multicontext->slave,
172 gtk_im_multicontext_preedit_end_cb,
174 g_signal_handlers_disconnect_by_func (multicontext->slave,
175 gtk_im_multicontext_preedit_changed_cb,
177 g_signal_handlers_disconnect_by_func (multicontext->slave,
178 gtk_im_multicontext_commit_cb,
181 g_object_unref (multicontext->slave);
182 multicontext->slave = NULL;
185 need_preedit_changed = TRUE;
188 multicontext->slave = slave;
190 if (multicontext->slave)
192 g_object_ref (multicontext->slave);
194 g_signal_connect (multicontext->slave, "preedit_start",
195 G_CALLBACK (gtk_im_multicontext_preedit_start_cb),
197 g_signal_connect (multicontext->slave, "preedit_end",
198 G_CALLBACK (gtk_im_multicontext_preedit_end_cb),
200 g_signal_connect (multicontext->slave, "preedit_changed",
201 G_CALLBACK (gtk_im_multicontext_preedit_changed_cb),
203 g_signal_connect (multicontext->slave, "commit",
204 G_CALLBACK (gtk_im_multicontext_commit_cb),
206 g_signal_connect (multicontext->slave, "retrieve_surrounding",
207 G_CALLBACK (gtk_im_multicontext_retrieve_surrounding_cb),
209 g_signal_connect (multicontext->slave, "delete_surrounding",
210 G_CALLBACK (gtk_im_multicontext_delete_surrounding_cb),
213 if (multicontext->client_window)
214 gtk_im_context_set_client_window (slave, multicontext->client_window);
217 if (need_preedit_changed)
218 g_signal_emit_by_name (multicontext, "preedit_changed");
221 static GtkIMContext *
222 gtk_im_multicontext_get_slave (GtkIMMulticontext *multicontext)
224 if (!multicontext->slave)
228 if (!global_context_id)
232 #ifdef HAVE_LC_MESSAGES
233 locale = setlocale (LC_MESSAGES, NULL);
235 locale = setlocale (LC_CTYPE, NULL);
237 global_context_id = _gtk_im_module_get_default_context_id (locale);
240 slave = _gtk_im_module_create (global_context_id);
241 gtk_im_multicontext_set_slave (multicontext, slave, FALSE);
242 g_object_unref (slave);
244 multicontext->context_id = global_context_id;
247 return multicontext->slave;
251 gtk_im_multicontext_set_client_window (GtkIMContext *context,
254 GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
255 GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
257 multicontext->client_window = window;
260 gtk_im_context_set_client_window (slave, window);
264 gtk_im_multicontext_get_preedit_string (GtkIMContext *context,
266 PangoAttrList **attrs,
269 GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
270 GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
273 gtk_im_context_get_preedit_string (slave, str, attrs, cursor_pos);
277 *str = g_strdup ("");
279 *attrs = pango_attr_list_new ();
284 gtk_im_multicontext_filter_keypress (GtkIMContext *context,
287 GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
288 GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
291 return gtk_im_context_filter_keypress (slave, event);
297 gtk_im_multicontext_focus_in (GtkIMContext *context)
299 GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
302 /* If the global context type is different from the context we were
303 * using before, get rid of the old slave and create a new one
304 * for the new global context type.
306 if (!multicontext->context_id ||
307 strcmp (global_context_id, multicontext->context_id) != 0)
308 gtk_im_multicontext_set_slave (multicontext, NULL, FALSE);
310 slave = gtk_im_multicontext_get_slave (multicontext);
313 gtk_im_context_focus_in (slave);
317 gtk_im_multicontext_focus_out (GtkIMContext *context)
319 GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
320 GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
323 gtk_im_context_focus_out (slave);
327 gtk_im_multicontext_reset (GtkIMContext *context)
329 GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
330 GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
333 gtk_im_context_reset (slave);
337 gtk_im_multicontext_set_cursor_location (GtkIMContext *context,
340 GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
341 GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
344 gtk_im_context_set_cursor_location (slave, area);
348 gtk_im_multicontext_set_use_preedit (GtkIMContext *context,
349 gboolean use_preedit)
351 GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
352 GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
355 gtk_im_context_set_use_preedit (slave, use_preedit);
359 gtk_im_multicontext_get_surrounding (GtkIMContext *context,
363 GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
364 GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
367 return gtk_im_context_get_surrounding (slave, text, cursor_index);
380 gtk_im_multicontext_set_surrounding (GtkIMContext *context,
385 GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
386 GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
389 gtk_im_context_set_surrounding (slave, text, len, cursor_index);
393 gtk_im_multicontext_preedit_start_cb (GtkIMContext *slave,
394 GtkIMMulticontext *multicontext)
396 g_signal_emit_by_name (multicontext, "preedit_start");
400 gtk_im_multicontext_preedit_end_cb (GtkIMContext *slave,
401 GtkIMMulticontext *multicontext)
403 g_signal_emit_by_name (multicontext, "preedit_end");
407 gtk_im_multicontext_preedit_changed_cb (GtkIMContext *slave,
408 GtkIMMulticontext *multicontext)
410 g_signal_emit_by_name (multicontext, "preedit_changed");
414 gtk_im_multicontext_commit_cb (GtkIMContext *slave,
416 GtkIMMulticontext *multicontext)
418 g_signal_emit_by_name (multicontext, "commit", str);;
422 gtk_im_multicontext_retrieve_surrounding_cb (GtkIMContext *slave,
423 GtkIMMulticontext *multicontext)
427 g_signal_emit_by_name (multicontext, "retrieve_surrounding", &result);
433 gtk_im_multicontext_delete_surrounding_cb (GtkIMContext *slave,
436 GtkIMMulticontext *multicontext)
440 g_signal_emit_by_name (multicontext, "delete_surrounding",
441 offset, n_chars, &result);
447 activate_cb (GtkWidget *menuitem,
448 GtkIMMulticontext *context)
450 if (GTK_CHECK_MENU_ITEM (menuitem)->active)
452 const gchar *id = g_object_get_data (G_OBJECT (menuitem), "gtk-context-id");
454 gtk_im_context_reset (GTK_IM_CONTEXT (context));
456 global_context_id = id;
457 gtk_im_multicontext_set_slave (context, NULL, FALSE);
462 * gtk_im_multicontext_append_menuitems:
463 * @context: a #GtkIMMultiContext
464 * @menushell: a #GtkMenuShell
466 * Add menuitems for various available input methods to a menu;
467 * the menuitems, when selected, will switch the input method
468 * for the context and the global default input method.
471 gtk_im_multicontext_append_menuitems (GtkIMMulticontext *context,
472 GtkMenuShell *menushell)
474 const GtkIMContextInfo **contexts;
476 GSList *group = NULL;
478 _gtk_im_module_list (&contexts, &n_contexts);
480 for (i=0; i < n_contexts; i++)
484 menuitem = gtk_radio_menu_item_new_with_label (group,
485 contexts[i]->context_name);
487 if ((global_context_id == NULL && group == NULL) ||
488 (global_context_id &&
489 strcmp (contexts[i]->context_id, global_context_id) == 0))
490 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem),
493 group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menuitem));
495 g_object_set_data (G_OBJECT (menuitem), "gtk-context-id",
496 (char *)contexts[i]->context_id);
497 g_signal_connect (menuitem, "activate",
498 G_CALLBACK (activate_cb), context);
500 gtk_widget_show (menuitem);
501 gtk_menu_shell_append (menushell, menuitem);