]> Pileus Git - ~andy/gtk/blob - gtk/gtkimcontext.c
6d619470cf03c0591268e16ca11b6e0a8edcbc84
[~andy/gtk] / gtk / gtkimcontext.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 2000 Red Hat, Inc.
3  *
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.
8  *
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.
13  *
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.
18  */
19
20 #include "gtkimcontext.h"
21 #include "gtksignal.h"
22
23 enum {
24   PREEDIT_START,
25   PREEDIT_END,
26   PREEDIT_CHANGED,
27   COMMIT,
28   LAST_SIGNAL
29 };
30
31 static guint im_context_signals[LAST_SIGNAL] = { 0 };
32
33 static void gtk_im_context_class_init (GtkIMContextClass *class);
34 static void gtk_im_context_init (GtkIMContext *im_context);
35
36 static void     gtk_im_context_real_get_preedit_string (GtkIMContext       *context,
37                                                         gchar             **str,
38                                                         PangoAttrList     **attrs,
39                                                         gint               *cursor_pos);
40 static gboolean gtk_im_context_real_filter_keypress    (GtkIMContext       *context,
41                                                         GdkEventKey        *event);
42
43 GtkType
44 gtk_im_context_get_type (void)
45 {
46   static GtkType im_context_type = 0;
47
48   if (!im_context_type)
49     {
50       static const GtkTypeInfo im_context_info =
51       {
52         "GtkIMContext",
53         sizeof (GtkIMContext),
54         sizeof (GtkIMContextClass),
55         (GtkClassInitFunc) gtk_im_context_class_init,
56         (GtkObjectInitFunc) gtk_im_context_init,
57         /* reserved_1 */ NULL,
58         /* reserved_2 */ NULL,
59         (GtkClassInitFunc) NULL,
60       };
61
62       im_context_type = gtk_type_unique (GTK_TYPE_OBJECT, &im_context_info);
63     }
64
65   return im_context_type;
66 }
67
68 static void
69 gtk_im_context_class_init (GtkIMContextClass *klass)
70 {
71   GtkObjectClass *object_class;
72   
73   object_class = (GtkObjectClass*) klass;
74
75   im_context_signals[PREEDIT_START] =
76     gtk_signal_new ("preedit_start",
77                     GTK_RUN_LAST,
78                     GTK_CLASS_TYPE (object_class),
79                     GTK_SIGNAL_OFFSET (GtkIMContextClass, preedit_start),
80                     gtk_marshal_VOID__VOID,
81                     GTK_TYPE_NONE, 0);
82   
83   im_context_signals[PREEDIT_END] =
84     gtk_signal_new ("preedit_end",
85                     GTK_RUN_LAST,
86                     GTK_CLASS_TYPE (object_class),
87                     GTK_SIGNAL_OFFSET (GtkIMContextClass, preedit_end),
88                     gtk_marshal_VOID__VOID,
89                     GTK_TYPE_NONE, 0);
90   
91   im_context_signals[PREEDIT_CHANGED] =
92     gtk_signal_new ("preedit_changed",
93                     GTK_RUN_LAST,
94                     GTK_CLASS_TYPE (object_class),
95                     GTK_SIGNAL_OFFSET (GtkIMContextClass, preedit_changed),
96                     gtk_marshal_VOID__VOID,
97                     GTK_TYPE_NONE, 0);
98   
99   im_context_signals[COMMIT] =
100     gtk_signal_new ("commit",
101                     GTK_RUN_LAST,
102                     GTK_CLASS_TYPE (object_class),
103                     GTK_SIGNAL_OFFSET (GtkIMContextClass, commit),
104                     gtk_marshal_VOID__POINTER,
105                     GTK_TYPE_NONE, 1,
106                     GTK_TYPE_STRING);
107
108   klass->get_preedit_string = gtk_im_context_real_get_preedit_string;
109   klass->filter_keypress = gtk_im_context_real_filter_keypress;
110   
111   gtk_object_class_add_signals (object_class, im_context_signals, LAST_SIGNAL);
112 }
113
114 static void
115 gtk_im_context_init (GtkIMContext *im_context)
116 {
117 }
118
119 static void
120 gtk_im_context_real_get_preedit_string (GtkIMContext       *context,
121                                         gchar             **str,
122                                         PangoAttrList     **attrs,
123                                         gint               *cursor_pos)
124 {
125   if (str)
126     *str = g_strdup ("");
127   if (attrs)
128     *attrs = pango_attr_list_new ();
129   if (cursor_pos)
130     *cursor_pos = 0;
131 }
132
133 static gboolean
134 gtk_im_context_real_filter_keypress (GtkIMContext       *context,
135                                      GdkEventKey        *event)
136 {
137   return FALSE;
138 }
139
140 /**
141  * gtk_im_context_set_client_window:
142  * @context: a #GtkIMContext
143  * @window:  the client window. This may be %NULL to indicate
144  *           that the previous client window no longer exists.
145  * 
146  * Set the client window for the input context; this is the
147  * #GdkWindow in which the input appears. This window is
148  * used in order to correctly position status windows, and may
149  * also be used for purposes internal to the input method.
150  **/
151 void
152 gtk_im_context_set_client_window (GtkIMContext *context,
153                                   GdkWindow    *window)
154 {
155   GtkIMContextClass *klass;
156   
157   g_return_if_fail (context != NULL);
158   g_return_if_fail (GTK_IS_IM_CONTEXT (context));
159
160   klass = GTK_IM_CONTEXT_GET_CLASS (context);
161   if (klass->set_client_window)
162     klass->set_client_window (context, window);
163 }
164
165 /**
166  * gtk_im_context_get_preedit_string:
167  * @context:    a #GtkIMContext
168  * @str:        location to store the retrieved string. The
169  *              string retrieved must be freed with g_free ().
170  * @attrs:      location to store the retrieved attribute list.
171  *              When you are done with this list, you must
172  *              unreference it with pango_attr_list_unref().
173  * @cursor_pos: location to store position of cursor (in bytes)
174  *              within the preedit string.  
175  * 
176  * Retrieve the current preedit string for the input context,
177  * and a list of attributes to apply to the string.
178  * This string should be displayed inserted at the insertion
179  * point.
180  **/
181 void
182 gtk_im_context_get_preedit_string (GtkIMContext   *context,
183                                    gchar         **str,
184                                    PangoAttrList **attrs,
185                                    gint           *cursor_pos)
186 {
187   GtkIMContextClass *klass;
188   
189   g_return_if_fail (context != NULL);
190   g_return_if_fail (GTK_IS_IM_CONTEXT (context));
191   
192   klass = GTK_IM_CONTEXT_GET_CLASS (context);
193   klass->get_preedit_string (context, str, attrs, cursor_pos);
194   g_return_if_fail (str == NULL || g_utf8_validate (*str, -1, NULL));    
195 }
196
197 /**
198  * gtk_im_context_filter_keypress:
199  * @context: a #GtkIMContext
200  * @event: the key event
201  * 
202  * Allow an input method to internally handle a key press event.
203  * if this function returns %TRUE, then no further processing
204  * should be done for this keystroke.
205  * 
206  * Return value: %TRUE if the input method handled the keystroke.
207  *
208  **/
209 gboolean
210 gtk_im_context_filter_keypress (GtkIMContext *context,
211                                 GdkEventKey  *key)
212 {
213   GtkIMContextClass *klass;
214   
215   g_return_val_if_fail (context != NULL, FALSE);
216   g_return_val_if_fail (GTK_IS_IM_CONTEXT (context), FALSE);
217   g_return_val_if_fail (key != NULL, FALSE);
218
219   klass = GTK_IM_CONTEXT_GET_CLASS (context);
220   return klass->filter_keypress (context, key);
221 }
222
223 /**
224  * gtk_im_context_focus_in:
225  * @context: a #GtkIMContext
226  *
227  * Notify the input method that the widget to which this
228  * input context corresponds has lost gained. The input method
229  * may, for example, change the displayed feedback to reflect
230  * this change.
231  **/
232 void
233 gtk_im_context_focus_in (GtkIMContext   *context)
234 {
235   GtkIMContextClass *klass;
236   
237   g_return_if_fail (context != NULL);
238   g_return_if_fail (GTK_IS_IM_CONTEXT (context));
239   
240   klass = GTK_IM_CONTEXT_GET_CLASS (context);
241   if (klass->focus_in)
242     klass->focus_in (context);
243 }
244
245 /**
246  * gtk_im_context_focus_out:
247  * @context: a #GtkIMContext
248  *
249  * Notify the input method that the widget to which this
250  * input context corresponds has lost focus. The input method
251  * may, for example, change the displayed feedback or reset the contexts
252  * state to reflect this change.
253  **/
254 void
255 gtk_im_context_focus_out (GtkIMContext   *context)
256 {
257   GtkIMContextClass *klass;
258   
259   g_return_if_fail (context != NULL);
260   g_return_if_fail (GTK_IS_IM_CONTEXT (context));
261
262   klass = GTK_IM_CONTEXT_GET_CLASS (context);
263   if (klass->focus_out)
264     klass->focus_out (context);
265 }
266
267 /**
268  * gtk_im_context_reset:
269  * @context: a #GtkIMContext
270  *
271  * Notify the input method that a change such as a change in cursor
272  * position has been made. This will typically cause the input
273  * method to clear the preedit state.
274  **/
275 void
276 gtk_im_context_reset (GtkIMContext   *context)
277 {
278   GtkIMContextClass *klass;
279   
280   g_return_if_fail (context != NULL);
281   g_return_if_fail (GTK_IS_IM_CONTEXT (context));
282
283   klass = GTK_IM_CONTEXT_GET_CLASS (context);
284   if (klass->reset)
285     klass->reset (context);
286 }
287
288