]> Pileus Git - ~andy/gtk/blob - gtk/gtkimcontext.c
2d6018b34e80cbcd7c11b2bc94a8139cbf81ef82
[~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   klass->get_preedit_string = gtk_im_context_real_get_preedit_string;
76   klass->filter_keypress = gtk_im_context_real_filter_keypress;
77
78   im_context_signals[PREEDIT_START] =
79     gtk_signal_new ("preedit_start",
80                     GTK_RUN_LAST,
81                     GTK_CLASS_TYPE (object_class),
82                     GTK_SIGNAL_OFFSET (GtkIMContextClass, preedit_start),
83                     gtk_marshal_VOID__VOID,
84                     GTK_TYPE_NONE, 0);
85   
86   im_context_signals[PREEDIT_END] =
87     gtk_signal_new ("preedit_end",
88                     GTK_RUN_LAST,
89                     GTK_CLASS_TYPE (object_class),
90                     GTK_SIGNAL_OFFSET (GtkIMContextClass, preedit_end),
91                     gtk_marshal_VOID__VOID,
92                     GTK_TYPE_NONE, 0);
93   
94   im_context_signals[PREEDIT_CHANGED] =
95     gtk_signal_new ("preedit_changed",
96                     GTK_RUN_LAST,
97                     GTK_CLASS_TYPE (object_class),
98                     GTK_SIGNAL_OFFSET (GtkIMContextClass, preedit_changed),
99                     gtk_marshal_VOID__VOID,
100                     GTK_TYPE_NONE, 0);
101   
102   im_context_signals[COMMIT] =
103     gtk_signal_new ("commit",
104                     GTK_RUN_LAST,
105                     GTK_CLASS_TYPE (object_class),
106                     GTK_SIGNAL_OFFSET (GtkIMContextClass, commit),
107                     gtk_marshal_VOID__STRING,
108                     GTK_TYPE_NONE, 1,
109                     GTK_TYPE_STRING);
110 }
111
112 static void
113 gtk_im_context_init (GtkIMContext *im_context)
114 {
115 }
116
117 static void
118 gtk_im_context_real_get_preedit_string (GtkIMContext       *context,
119                                         gchar             **str,
120                                         PangoAttrList     **attrs,
121                                         gint               *cursor_pos)
122 {
123   if (str)
124     *str = g_strdup ("");
125   if (attrs)
126     *attrs = pango_attr_list_new ();
127   if (cursor_pos)
128     *cursor_pos = 0;
129 }
130
131 static gboolean
132 gtk_im_context_real_filter_keypress (GtkIMContext       *context,
133                                      GdkEventKey        *event)
134 {
135   return FALSE;
136 }
137
138 /**
139  * gtk_im_context_set_client_window:
140  * @context: a #GtkIMContext
141  * @window:  the client window. This may be %NULL to indicate
142  *           that the previous client window no longer exists.
143  * 
144  * Set the client window for the input context; this is the
145  * #GdkWindow in which the input appears. This window is
146  * used in order to correctly position status windows, and may
147  * also be used for purposes internal to the input method.
148  **/
149 void
150 gtk_im_context_set_client_window (GtkIMContext *context,
151                                   GdkWindow    *window)
152 {
153   GtkIMContextClass *klass;
154   
155   g_return_if_fail (GTK_IS_IM_CONTEXT (context));
156
157   klass = GTK_IM_CONTEXT_GET_CLASS (context);
158   if (klass->set_client_window)
159     klass->set_client_window (context, window);
160 }
161
162 /**
163  * gtk_im_context_get_preedit_string:
164  * @context:    a #GtkIMContext
165  * @str:        location to store the retrieved string. The
166  *              string retrieved must be freed with g_free ().
167  * @attrs:      location to store the retrieved attribute list.
168  *              When you are done with this list, you must
169  *              unreference it with pango_attr_list_unref().
170  * @cursor_pos: location to store position of cursor (in bytes)
171  *              within the preedit string.  
172  * 
173  * Retrieve the current preedit string for the input context,
174  * and a list of attributes to apply to the string.
175  * This string should be displayed inserted at the insertion
176  * point.
177  **/
178 void
179 gtk_im_context_get_preedit_string (GtkIMContext   *context,
180                                    gchar         **str,
181                                    PangoAttrList **attrs,
182                                    gint           *cursor_pos)
183 {
184   GtkIMContextClass *klass;
185   
186   g_return_if_fail (GTK_IS_IM_CONTEXT (context));
187   
188   klass = GTK_IM_CONTEXT_GET_CLASS (context);
189   klass->get_preedit_string (context, str, attrs, cursor_pos);
190   g_return_if_fail (str == NULL || g_utf8_validate (*str, -1, NULL));
191 }
192
193 /**
194  * gtk_im_context_filter_keypress:
195  * @context: a #GtkIMContext
196  * @event: the key event
197  * 
198  * Allow an input method to internally handle a key press event.
199  * if this function returns %TRUE, then no further processing
200  * should be done for this keystroke.
201  * 
202  * Return value: %TRUE if the input method handled the keystroke.
203  *
204  **/
205 gboolean
206 gtk_im_context_filter_keypress (GtkIMContext *context,
207                                 GdkEventKey  *key)
208 {
209   GtkIMContextClass *klass;
210   
211   g_return_val_if_fail (GTK_IS_IM_CONTEXT (context), FALSE);
212   g_return_val_if_fail (key != NULL, FALSE);
213
214   klass = GTK_IM_CONTEXT_GET_CLASS (context);
215   return klass->filter_keypress (context, key);
216 }
217
218 /**
219  * gtk_im_context_focus_in:
220  * @context: a #GtkIMContext
221  *
222  * Notify the input method that the widget to which this
223  * input context corresponds has lost gained. The input method
224  * may, for example, change the displayed feedback to reflect
225  * this change.
226  **/
227 void
228 gtk_im_context_focus_in (GtkIMContext   *context)
229 {
230   GtkIMContextClass *klass;
231   
232   g_return_if_fail (GTK_IS_IM_CONTEXT (context));
233   
234   klass = GTK_IM_CONTEXT_GET_CLASS (context);
235   if (klass->focus_in)
236     klass->focus_in (context);
237 }
238
239 /**
240  * gtk_im_context_focus_out:
241  * @context: a #GtkIMContext
242  *
243  * Notify the input method that the widget to which this
244  * input context corresponds has lost focus. The input method
245  * may, for example, change the displayed feedback or reset the contexts
246  * state to reflect this change.
247  **/
248 void
249 gtk_im_context_focus_out (GtkIMContext   *context)
250 {
251   GtkIMContextClass *klass;
252   
253   g_return_if_fail (GTK_IS_IM_CONTEXT (context));
254
255   klass = GTK_IM_CONTEXT_GET_CLASS (context);
256   if (klass->focus_out)
257     klass->focus_out (context);
258 }
259
260 /**
261  * gtk_im_context_reset:
262  * @context: a #GtkIMContext
263  *
264  * Notify the input method that a change such as a change in cursor
265  * position has been made. This will typically cause the input
266  * method to clear the preedit state.
267  **/
268 void
269 gtk_im_context_reset (GtkIMContext   *context)
270 {
271   GtkIMContextClass *klass;
272   
273   g_return_if_fail (GTK_IS_IM_CONTEXT (context));
274
275   klass = GTK_IM_CONTEXT_GET_CLASS (context);
276   if (klass->reset)
277     klass->reset (context);
278 }
279
280
281 /**
282  * gtk_im_context_set_cursor_location:
283  * @context: a #GtkIMContext
284  * @area: new location
285  *
286  * Notify the input method that a change in cursor 
287  * position has been made.
288  **/
289 void
290 gtk_im_context_set_cursor_location (GtkIMContext *context,
291                                     GdkRectangle *area)
292 {
293   GtkIMContextClass *klass;
294   
295   g_return_if_fail (GTK_IS_IM_CONTEXT (context));
296
297   klass = GTK_IM_CONTEXT_GET_CLASS (context);
298   if (klass->set_cursor_location)
299     klass->set_cursor_location (context, area);
300 }
301
302 /**
303  * gtk_im_context_set_use_preedit:
304  * @context: a #GtkIMContext
305  * @use_preedit: whether the IM context should use the preedit string.
306  * 
307  * Sets whether the IM context should use the preedit string
308  * to display feedback. If @use_preedit is FALSE (default
309  * is TRUE), then the IM context may use some other method to display
310  * feedback, such as displaying it in a child of the root window.
311  **/
312 void
313 gtk_im_context_set_use_preedit (GtkIMContext *context,
314                                 gboolean      use_preedit)
315 {
316   GtkIMContextClass *klass;
317   
318   g_return_if_fail (GTK_IS_IM_CONTEXT (context));
319
320   klass = GTK_IM_CONTEXT_GET_CLASS (context);
321   if (klass->set_use_preedit)
322     klass->set_use_preedit (context, use_preedit);
323 }