X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkimcontext.c;h=f0f351fbda1657e63e4733ea0090435c7f73463c;hb=HEAD;hp=3f993cfa401761c1d5c01c5605e99841cece6f01;hpb=53d2169b643d0c01d0b47702ae5302426eb6e3d8;p=~andy%2Fgtk diff --git a/gtk/gtkimcontext.c b/gtk/gtkimcontext.c index 3f993cfa4..f0f351fbd 100644 --- a/gtk/gtkimcontext.c +++ b/gtk/gtkimcontext.c @@ -12,17 +12,91 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library. If not, see . */ -#include +#include "config.h" #include -#include "gtkalias.h" #include "gtkimcontext.h" -#include "gtkmain.h" /* For _gtk_boolean_handled_accumulator */ +#include "gtkprivate.h" +#include "gtktypebuiltins.h" #include "gtkmarshalers.h" +#include "gtkintl.h" + +/** + * SECTION:gtkimcontext + * @title: GtkIMContext + * @short_description: Base class for input method contexts + * @include: gtk/gtk.h,gtk/gtkimmodule.h + * + * #GtkIMContext defines the interface for GTK+ input methods. An input method + * is used by GTK+ text input widgets like #GtkEntry to map from key events to + * Unicode character strings. + * + * The user may change the current input method via a context menu, unless the + * #GtkSettings:gtk-show-input-method-menu GtkSettings property is set to FALSE. + * The default input method can be set programmatically via the + * #GtkSettings:gtk-im-module GtkSettings property. Alternatively, you may set + * the GTK_IM_MODULE environment variable as documented in #gtk-running. + * + * The #GtkEntry #GtkEntry:im-module and #GtkTextView #GtkTextView:im-module + * properties may also be used to set input methods for specific widget + * instances. For instance, a certain entry widget might be expected to contain + * certain characters which would be easier to input with a certain input + * method. + * + * An input method may consume multiple key events in sequence and finally + * output the composed result. This is called preediting, and an input method + * may provide feedback about this process by displaying the intermediate + * composition states as preedit text. For instance, the default GTK+ input + * method implements the input of arbitrary Unicode code points by holding down + * the Control and Shift keys and then typing "U" followed by the hexadecimal + * digits of the code point. When releasing the Control and Shift keys, + * preediting ends and the character is inserted as text. Ctrl+Shift+u20AC for + * example results in the € sign. + * + * Additional input methods can be made available for use by GTK+ widgets as + * loadable modules. An input method module is a small shared library which + * implements a subclass of #GtkIMContext or #GtkIMContextSimple and exports + * these four functions: + * + * + * void im_module_init(#GTypeModule *module); + * + * This function should register the #GType of the #GtkIMContext subclass which + * implements the input method by means of g_type_module_register_type(). Note + * that g_type_register_static() cannot be used as the type needs to be + * registered dynamically. + * + * + * void im_module_exit(void); + * + * Here goes any cleanup code your input method might require on module unload. + * + * + * void im_module_list(const #GtkIMContextInfo ***contexts, int *n_contexts) + * { + * *contexts = info_list; + * *n_contexts = G_N_ELEMENTS (info_list); + * } + * + * This function returns the list of input methods provided by the module. The + * example implementation above shows a common solution and simply returns a + * pointer to statically defined array of #GtkIMContextInfo items for each + * provided input method. + * + * + * #GtkIMContext * im_module_create(const #gchar *context_id); + * + * This function should return a pointer to a newly created instance of the + * #GtkIMContext subclass identified by @context_id. The context ID is the same + * as specified in the #GtkIMContextInfo array returned by im_module_list(). + * + * After a new loadable input method module has been installed on the system, + * the configuration file gtk.immodules needs to be + * regenerated by gtk-query-immodules-3.0, + * in order for the new input method to become available to GTK+ applications. + */ enum { PREEDIT_START, @@ -34,10 +108,20 @@ enum { LAST_SIGNAL }; -static guint im_context_signals[LAST_SIGNAL] = { 0 }; +enum { + PROP_INPUT_PURPOSE = 1, + PROP_INPUT_HINTS, + LAST_PROPERTY +}; + +static guint im_context_signals[LAST_SIGNAL] = { 0, }; +static GParamSpec *properties[LAST_PROPERTY] = { NULL, }; -static void gtk_im_context_class_init (GtkIMContextClass *class); -static void gtk_im_context_init (GtkIMContext *im_context); +typedef struct _GtkIMContextPrivate GtkIMContextPrivate; +struct _GtkIMContextPrivate { + GtkInputPurpose purpose; + GtkInputHints hints; +}; static void gtk_im_context_real_get_preedit_string (GtkIMContext *context, gchar **str, @@ -53,72 +137,146 @@ static void gtk_im_context_real_set_surrounding (GtkIMContext *context, gint len, gint cursor_index); -GType -gtk_im_context_get_type (void) -{ - static GType im_context_type = 0; +static void gtk_im_context_get_property (GObject *obj, + guint property_id, + GValue *value, + GParamSpec *pspec); +static void gtk_im_context_set_property (GObject *obj, + guint property_id, + const GValue *value, + GParamSpec *pspec); - if (!im_context_type) - { - static const GTypeInfo im_context_info = - { - sizeof (GtkIMContextClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) gtk_im_context_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (GtkIMContext), - 0, /* n_preallocs */ - (GInstanceInitFunc) gtk_im_context_init, - NULL, /* value_table */ - }; - - im_context_type = - g_type_register_static (G_TYPE_OBJECT, "GtkIMContext", - &im_context_info, G_TYPE_FLAG_ABSTRACT); - } - return im_context_type; -} +G_DEFINE_ABSTRACT_TYPE (GtkIMContext, gtk_im_context, G_TYPE_OBJECT) +/** + * GtkIMContextClass: + * @preedit_start: Default handler of the #GtkIMContext::preedit-start signal. + * @preedit_end: Default handler of the #GtkIMContext::preedit-end signal. + * @preedit_changed: Default handler of the #GtkIMContext::preedit-changed + * signal. + * @commit: Default handler of the #GtkIMContext::commit signal. + * @retrieve_surrounding: Default handler of the + * #GtkIMContext::retrieve-surrounding signal. + * @delete_surrounding: Default handler of the + * #GtkIMContext::delete-surrounding signal. + * @set_client_window: Called via gtk_im_context_set_client_window() when the + * input window where the entered text will appear changes. Override this to + * keep track of the current input window, for instance for the purpose of + * positioning a status display of your input method. + * @get_preedit_string: Called via gtk_im_context_get_preedit_string() to + * retrieve the text currently being preedited for display at the cursor + * position. Any input method which composes complex characters or any + * other compositions from multiple sequential key presses should override + * this method to provide feedback. + * @filter_keypress: Called via gtk_im_context_filter_keypress() on every + * key press or release event. Every non-trivial input method needs to + * override this in order to implement the mapping from key events to text. + * A return value of %TRUE indicates to the caller that the event was + * consumed by the input method. In that case, the #GtkIMContext::commit + * signal should be emitted upon completion of a key sequence to pass the + * resulting text back to the input widget. Alternatively, %FALSE may be + * returned to indicate that the event wasn't handled by the input method. + * If a builtin mapping exists for the key, it is used to produce a + * character. + * @focus_in: Called via gtk_im_context_focus_in() when the input widget + * has gained focus. May be overridden to keep track of the current focus. + * @focus_out: Called via gtk_im_context_focus_out() when the input widget + * has lost focus. May be overridden to keep track of the current focus. + * @reset: Called via gtk_im_context_reset() to signal a change such as a + * change in cursor position. An input method that implements preediting + * should override this method to clear the preedit state on reset. + * @set_cursor_location: Called via gtk_im_context_set_cursor_location() + * to inform the input method of the current cursor location relative to + * the client window. May be overridden to implement the display of popup + * windows at the cursor position. + * @set_use_preedit: Called via gtk_im_context_set_use_preedit() to control + * the use of the preedit string. Override this to display feedback by some + * other means if turned off. + * @set_surrounding: Called via gtk_im_context_set_surrounding() in response + * to signal #GtkIMContext::retrieve-surrounding to update the input + * method's idea of the context around the cursor. It is not necessary to + * override this method even with input methods which implement + * context-dependent behavior. The base implementation is sufficient for + * gtk_im_context_get_surrounding() to work. + * @get_surrounding: Called via gtk_im_context_get_surrounding() to update + * the context around the cursor location. It is not necessary to override + * this method even with input methods which implement context-dependent + * behavior. The base implementation emits + * #GtkIMContext::retrieve-surrounding and records the context received + * by the subsequent invocation of @get_surrounding. + */ static void gtk_im_context_class_init (GtkIMContextClass *klass) { + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->get_property = gtk_im_context_get_property; + object_class->set_property = gtk_im_context_set_property; + klass->get_preedit_string = gtk_im_context_real_get_preedit_string; klass->filter_keypress = gtk_im_context_real_filter_keypress; klass->get_surrounding = gtk_im_context_real_get_surrounding; klass->set_surrounding = gtk_im_context_real_set_surrounding; + /** + * GtkIMContext::preedit-start: + * @context: the object on which the signal is emitted + * + * The ::preedit-start signal is emitted when a new preediting sequence + * starts. + */ im_context_signals[PREEDIT_START] = - g_signal_new ("preedit_start", + g_signal_new (I_("preedit-start"), G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GtkIMContextClass, preedit_start), NULL, NULL, _gtk_marshal_VOID__VOID, G_TYPE_NONE, 0); - + /** + * GtkIMContext::preedit-end: + * @context: the object on which the signal is emitted + * + * The ::preedit-end signal is emitted when a preediting sequence + * has been completed or canceled. + */ im_context_signals[PREEDIT_END] = - g_signal_new ("preedit_end", + g_signal_new (I_("preedit-end"), G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GtkIMContextClass, preedit_end), NULL, NULL, _gtk_marshal_VOID__VOID, G_TYPE_NONE, 0); - + /** + * GtkIMContext::preedit-changed: + * @context: the object on which the signal is emitted + * + * The ::preedit-changed signal is emitted whenever the preedit sequence + * currently being entered has changed. It is also emitted at the end of + * a preedit sequence, in which case + * gtk_im_context_get_preedit_string() returns the empty string. + */ im_context_signals[PREEDIT_CHANGED] = - g_signal_new ("preedit_changed", + g_signal_new (I_("preedit-changed"), G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GtkIMContextClass, preedit_changed), NULL, NULL, _gtk_marshal_VOID__VOID, G_TYPE_NONE, 0); - + /** + * GtkIMContext::commit: + * @context: the object on which the signal is emitted + * @str: the completed character(s) entered by the user + * + * The ::commit signal is emitted when a complete input sequence + * has been entered by the user. This can be a single character + * immediately after a key press or the final result of preediting. + */ im_context_signals[COMMIT] = - g_signal_new ("commit", + g_signal_new (I_("commit"), G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GtkIMContextClass, commit), @@ -126,17 +284,40 @@ gtk_im_context_class_init (GtkIMContextClass *klass) _gtk_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); - + /** + * GtkIMContext::retrieve-surrounding: + * @context: the object on which the signal is emitted + * + * The ::retrieve-surrounding signal is emitted when the input method + * requires the context surrounding the cursor. The callback should set + * the input method surrounding context by calling the + * gtk_im_context_set_surrounding() method. + * + * Return value: %TRUE if the signal was handled. + */ im_context_signals[RETRIEVE_SURROUNDING] = - g_signal_new ("retrieve_surrounding", + g_signal_new (I_("retrieve-surrounding"), G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GtkIMContextClass, retrieve_surrounding), _gtk_boolean_handled_accumulator, NULL, _gtk_marshal_BOOLEAN__VOID, G_TYPE_BOOLEAN, 0); + /** + * GtkIMContext::delete-surrounding: + * @context: the object on which the signal is emitted + * @offset: the character offset from the cursor position of the text + * to be deleted. A negative value indicates a position before + * the cursor. + * @n_chars: the number of characters to be deleted + * + * The ::delete-surrounding signal is emitted when the input method + * needs to delete all or part of the context surrounding the cursor. + * + * Return value: %TRUE if the signal was handled. + */ im_context_signals[DELETE_SURROUNDING] = - g_signal_new ("delete_surrounding", + g_signal_new (I_("delete-surrounding"), G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GtkIMContextClass, delete_surrounding), @@ -145,6 +326,25 @@ gtk_im_context_class_init (GtkIMContextClass *klass) G_TYPE_BOOLEAN, 2, G_TYPE_INT, G_TYPE_INT); + + properties[PROP_INPUT_PURPOSE] = + g_param_spec_enum ("input-purpose", + P_("Purpose"), + P_("Purpose of the text field"), + GTK_TYPE_INPUT_PURPOSE, + GTK_INPUT_PURPOSE_FREE_FORM, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + properties[PROP_INPUT_HINTS] = + g_param_spec_flags ("input-hints", + P_("hints"), + P_("Hints for the text field behaviour"), + GTK_TYPE_INPUT_HINTS, + GTK_INPUT_HINT_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + g_type_class_add_private (klass, sizeof (GtkIMContextPrivate)); + g_object_class_install_properties (object_class, LAST_PROPERTY, properties); } static void @@ -185,7 +385,8 @@ gtk_im_context_real_set_surrounding (GtkIMContext *context, gint len, gint cursor_index) { - SurroundingInfo *info = g_object_get_data (G_OBJECT (context), "gtk-im-surrounding-info"); + SurroundingInfo *info = g_object_get_data (G_OBJECT (context), + "gtk-im-surrounding-info"); if (info) { @@ -209,7 +410,7 @@ gtk_im_context_real_get_surrounding (GtkIMContext *context, if (!info) { info = &local_info; - g_object_set_data (G_OBJECT (context), "gtk-im-surrounding-info", info); + g_object_set_data (G_OBJECT (context), I_("gtk-im-surrounding-info"), info); info_is_local = TRUE; } @@ -231,7 +432,7 @@ gtk_im_context_real_get_surrounding (GtkIMContext *context, if (info_is_local) { g_free (info->text); - g_object_set_data (G_OBJECT (context), "gtk-im-surrounding-info", NULL); + g_object_set_data (G_OBJECT (context), I_("gtk-im-surrounding-info"), NULL); } return result; @@ -240,7 +441,7 @@ gtk_im_context_real_get_surrounding (GtkIMContext *context, /** * gtk_im_context_set_client_window: * @context: a #GtkIMContext - * @window: the client window. This may be %NULL to indicate + * @window: (allow-none): the client window. This may be %NULL to indicate * that the previous client window no longer exists. * * Set the client window for the input context; this is the @@ -264,12 +465,12 @@ gtk_im_context_set_client_window (GtkIMContext *context, /** * gtk_im_context_get_preedit_string: * @context: a #GtkIMContext - * @str: location to store the retrieved string. The - * string retrieved must be freed with g_free (). - * @attrs: location to store the retrieved attribute list. - * When you are done with this list, you must - * unreference it with pango_attr_list_unref(). - * @cursor_pos: location to store position of cursor (in characters) + * @str: (out) (transfer full): location to store the retrieved + * string. The string retrieved must be freed with g_free(). + * @attrs: (out) (transfer full): location to store the retrieved + * attribute list. When you are done with this list, you + * must unreference it with pango_attr_list_unref(). + * @cursor_pos: (out): location to store position of cursor (in characters) * within the preedit string. * * Retrieve the current preedit string for the input context, @@ -297,11 +498,11 @@ gtk_im_context_get_preedit_string (GtkIMContext *context, * @context: a #GtkIMContext * @event: the key event * - * Allow an input method to internally handle a key press event. - * If this function returns %TRUE, then no further processing - * should be done for this keystroke. + * Allow an input method to internally handle key press and release + * events. If this function returns %TRUE, then no further processing + * should be done for this key event. * - * Return value: %TRUE if the input method handled the keystroke. + * Return value: %TRUE if the input method handled the key event. * **/ gboolean @@ -390,8 +591,8 @@ gtk_im_context_reset (GtkIMContext *context) * window. **/ void -gtk_im_context_set_cursor_location (GtkIMContext *context, - GdkRectangle *area) +gtk_im_context_set_cursor_location (GtkIMContext *context, + const GdkRectangle *area) { GtkIMContextClass *klass; @@ -399,7 +600,7 @@ gtk_im_context_set_cursor_location (GtkIMContext *context, klass = GTK_IM_CONTEXT_GET_CLASS (context); if (klass->set_cursor_location) - klass->set_cursor_location (context, area); + klass->set_cursor_location (context, (GdkRectangle *) area); } /** @@ -465,12 +666,12 @@ gtk_im_context_set_surrounding (GtkIMContext *context, /** * gtk_im_context_get_surrounding: * @context: a #GtkIMContext - * @text: location to store a UTF-8 encoded string of text - * holding context around the insertion point. - * If the function returns %TRUE, then you must free - * the result stored in this location with g_free(). - * @cursor_index: location to store byte index of the insertion cursor - * within @text. + * @text: (out) (transfer full): location to store a UTF-8 encoded + * string of text holding context around the insertion point. + * If the function returns %TRUE, then you must free the result + * stored in this location with g_free(). + * @cursor_index: (out): location to store byte index of the insertion + * cursor within @text. * * Retrieves context around the insertion point. Input methods * typically want context in order to constrain input text based on @@ -554,3 +755,46 @@ gtk_im_context_delete_surrounding (GtkIMContext *context, return result; } +static void +gtk_im_context_get_property (GObject *obj, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GtkIMContextPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (obj, GTK_TYPE_IM_CONTEXT, GtkIMContextPrivate); + + switch (property_id) + { + case PROP_INPUT_PURPOSE: + g_value_set_enum (value, priv->purpose); + break; + case PROP_INPUT_HINTS: + g_value_set_flags (value, priv->hints); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec); + break; + } +} + +static void +gtk_im_context_set_property (GObject *obj, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GtkIMContextPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (obj, GTK_TYPE_IM_CONTEXT, GtkIMContextPrivate); + + switch (property_id) + { + case PROP_INPUT_PURPOSE: + priv->purpose = g_value_get_enum (value); + break; + case PROP_INPUT_HINTS: + priv->hints = g_value_get_flags (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, property_id, pspec); + break; + } +}