diff options
author | Daiki Ueno <ueno@unixuser.org> | 2013-08-14 13:29:45 +0200 |
---|---|---|
committer | Daiki Ueno <ueno@unixuser.org> | 2013-08-14 13:29:45 +0200 |
commit | 3b3a7ceccbf75f36dee0df45589d79f7e96131f4 (patch) | |
tree | 7e230ec8fde7008482dbd30f12497da11d31bc48 /bus | |
parent | 5136dbc59fd3048445826c534fd6b5f3f8ca6b1e (diff) |
Notify engines of the content-type of input context
Add a new D-Bus method SetContentType to InputContext and Engine, to
notify engines of the content-type (primary purpose and hints) of
input context. This is useful to implement intelligent features in
engines, such as automatic input-mode switch and text prediction.
The "purpose" and "hints" arguments are compatible with
GtkInputPurpose and GtkInputHints:
https://developer.gnome.org/gtk3/unstable/GtkEntry.html#GtkInputPurpose
https://developer.gnome.org/gtk3/unstable/GtkEntry.html#GtkInputHints
and the API is similar to the content_type event in the Wayland Input
Method Framework:
http://cgit.freedesktop.org/wayland/weston/tree/protocol/input-method.xml#n202
BUG=
Review URL: https://codereview.appspot.com/11422043
Diffstat (limited to 'bus')
-rw-r--r-- | bus/engineproxy.c | 40 | ||||
-rw-r--r-- | bus/engineproxy.h | 221 | ||||
-rw-r--r-- | bus/inputcontext.c | 249 |
3 files changed, 374 insertions, 136 deletions
diff --git a/bus/engineproxy.c b/bus/engineproxy.c index 200b89be..19c28616 100644 --- a/bus/engineproxy.c +++ b/bus/engineproxy.c @@ -1,8 +1,8 @@ /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ /* vim:set et sts=4: */ /* ibus - The Input Bus - * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com> - * Copyright (C) 2008-2010 Red Hat, Inc. + * Copyright (C) 2008-2013 Peng Huang <shawn.p.huang@gmail.com> + * Copyright (C) 2008-2013 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -642,8 +642,7 @@ bus_engine_proxy_new_internal (const gchar *path, g_assert (IBUS_IS_ENGINE_DESC (desc)); g_assert (G_IS_DBUS_CONNECTION (connection)); - GDBusProxyFlags flags = G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START | - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES; + GDBusProxyFlags flags = G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START; BusEngineProxy *engine = (BusEngineProxy *) g_initable_new (BUS_TYPE_ENGINE_PROXY, NULL, @@ -1134,6 +1133,39 @@ void bus_engine_proxy_set_surrounding_text (BusEngineProxy *engine, } } +void +bus_engine_proxy_set_content_type (BusEngineProxy *engine, + guint purpose, + guint hints) +{ + g_assert (BUS_IS_ENGINE_PROXY (engine)); + + GVariant *cached_content_type = + g_dbus_proxy_get_cached_property ((GDBusProxy *) engine, + "ContentType"); + GVariant *content_type = g_variant_new ("(uu)", purpose, hints); + + g_variant_ref_sink (content_type); + if (cached_content_type == NULL || + !g_variant_equal (content_type, cached_content_type)) { + g_dbus_proxy_call ((GDBusProxy *) engine, + "org.freedesktop.DBus.Properties.Set", + g_variant_new ("(ssv)", + IBUS_INTERFACE_ENGINE, + "ContentType", + content_type), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + NULL, + NULL); + } + + if (cached_content_type != NULL) + g_variant_unref (cached_content_type); + g_variant_unref (content_type); +} + /* a macro to generate a function to call a nullary D-Bus method. */ #define DEFINE_FUNCTION(Name, name) \ void \ diff --git a/bus/engineproxy.h b/bus/engineproxy.h index 8fe025db..528e61b7 100644 --- a/bus/engineproxy.h +++ b/bus/engineproxy.h @@ -1,8 +1,8 @@ /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ /* vim:set et sts=4: */ /* ibus - The Input Bus - * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com> - * Copyright (C) 2008-2010 Red Hat, Inc. + * Copyright (C) 2008-2013 Peng Huang <shawn.p.huang@gmail.com> + * Copyright (C) 2008-2013 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -49,7 +49,7 @@ G_BEGIN_DECLS typedef struct _BusEngineProxy BusEngineProxy; typedef struct _BusEngineProxyClass BusEngineProxyClass; -GType bus_engine_proxy_get_type (void); +GType bus_engine_proxy_get_type (void); /** * bus_engine_proxy_new: @@ -59,196 +59,271 @@ GType bus_engine_proxy_get_type (void); * @callback: a function to be called when the method invocation is done. * @user_data: a pointer that will be passed to the callback. */ -void bus_engine_proxy_new (IBusEngineDesc *desc, - gint timeout, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data); +void bus_engine_proxy_new (IBusEngineDesc *desc, + gint timeout, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); /** * bus_engine_proxy_new_finish: - * @returns: On success, return an engine object. On error, return NULL. + * @res: A #GAsyncResult. + * @error: Return location for error or %NULL. + * @returns: On success, return an engine object. On error, return %NULL. * - * Get the result of bus_engine_proxy_new call. You have to call this function in the GAsyncReadyCallback function. + * Get the result of bus_engine_proxy_new() call. You have to call this + * function in the #GAsyncReadyCallback function. */ -BusEngineProxy *bus_engine_proxy_new_finish (GAsyncResult *res, - GError **error); +BusEngineProxy *bus_engine_proxy_new_finish (GAsyncResult *res, + GError **error); /** * bus_engine_proxy_get_desc: + * @engine: A #BusEngineProxy. * - * Get an IBusEngineDesc object associated with the engine. + * Get an #IBusEngineDesc object associated with the engine. */ -IBusEngineDesc *bus_engine_proxy_get_desc (BusEngineProxy *engine); +IBusEngineDesc *bus_engine_proxy_get_desc (BusEngineProxy *engine); /** * bus_engine_proxy_process_key_event: - * @callback: a function to be called when the method invocation is done. + * @engine: A #BusEngineProxy. + * @keyval: Key symbol of the key press. + * @keycode: KeyCode of the key press. + * @state: Key modifier flags. + * @callback: A function to be called when the method invocation is done. + * @user_data: Data supplied to @callback. * * Call "ProcessKeyEvent" method of an engine asynchronously. */ -void bus_engine_proxy_process_key_event (BusEngineProxy *engine, - guint keyval, - guint keycode, - guint state, - GAsyncReadyCallback callback, - gpointer user_data); +void bus_engine_proxy_process_key_event + (BusEngineProxy *engine, + guint keyval, + guint keycode, + guint state, + GAsyncReadyCallback callback, + gpointer user_data); /** * bus_engine_proxy_set_cursor_location: + * @engine: A #BusEngineProxy. + * @x: X coordinate of the cursor. + * @y: Y coordinate of the cursor. + * @w: Width of the cursor. + * @h: Height of the cursor. * - * Call "SetCursorLocation" method of an engine asynchronously. Unlike bus_engine_proxy_process_key_event, there's no way to know the - * result of the method invocation. If the same coordinate is given twice or more, the function does nothing from the second time. + * Call "SetCursorLocation" method of an engine asynchronously. Unlike + * bus_engine_proxy_process_key_event(), there's no way to know the + * result of the method invocation. If the same coordinate is given + * twice or more, the function does nothing from the second time. */ -void bus_engine_proxy_set_cursor_location - (BusEngineProxy *engine, - gint x, - gint y, - gint w, - gint h); +void bus_engine_proxy_set_cursor_location + (BusEngineProxy *engine, + gint x, + gint y, + gint w, + gint h); /** * bus_engine_proxy_focus_in: + * @engine: A #BusEngineProxy. * - * Call "FocusIn" method of an engine asynchronously. Do nothing if the engine already has a focus. + * Call "FocusIn" method of an engine asynchronously. Do nothing if + * the engine already has a focus. */ -void bus_engine_proxy_focus_in (BusEngineProxy *engine); +void bus_engine_proxy_focus_in (BusEngineProxy *engine); /** * bus_engine_proxy_focus_out: + * @engine: A #BusEngineProxy. * - * Call "FocusOut" method of an engine asynchronously. Do nothing if the engine does not have a focus. + * Call "FocusOut" method of an engine asynchronously. Do nothing if + * the engine does not have a focus. */ -void bus_engine_proxy_focus_out (BusEngineProxy *engine); +void bus_engine_proxy_focus_out (BusEngineProxy *engine); /** * bus_engine_proxy_reset: + * @engine: A #BusEngineProxy. * * Call "Reset" method of an engine asynchronously. */ -void bus_engine_proxy_reset (BusEngineProxy *engine); +void bus_engine_proxy_reset (BusEngineProxy *engine); /** * bus_engine_proxy_set_capabilities: + * @engine: A #BusEngineProxy. + * @caps: Capabilities flags of IBusEngine, see #IBusCapabilite. * * Call "SetCapabilities" method of an engine asynchronously. */ -void bus_engine_proxy_set_capabilities (BusEngineProxy *engine, - guint caps); +void bus_engine_proxy_set_capabilities + (BusEngineProxy *engine, + guint caps); /** * bus_engine_proxy_page_up: + * @engine: A #BusEngineProxy. * * Call "PageUp" method of an engine asynchronously. */ -void bus_engine_proxy_page_up (BusEngineProxy *engine); +void bus_engine_proxy_page_up (BusEngineProxy *engine); /** * bus_engine_proxy_page_down: + * @engine: A #BusEngineProxy. * * Call "PageDown" method of an engine asynchronously. */ -void bus_engine_proxy_page_down (BusEngineProxy *engine); +void bus_engine_proxy_page_down (BusEngineProxy *engine); /** * bus_engine_proxy_cursor_up: + * @engine: A #BusEngineProxy. * * Call "CursorUp" method of an engine asynchronously. */ -void bus_engine_proxy_cursor_up (BusEngineProxy *engine); +void bus_engine_proxy_cursor_up (BusEngineProxy *engine); /** * bus_engine_proxy_cursor_down: + * @engine: A #BusEngineProxy. * * Call "CursorDown" method of an engine asynchronously. */ -void bus_engine_proxy_cursor_down (BusEngineProxy *engine); +void bus_engine_proxy_cursor_down (BusEngineProxy *engine); /** * bus_engine_proxy_candidate_clicked: + * @engine: A #BusEngineProxy. + * @index: Index of candidate be clicked. + * @button: Mouse button. + * @state: Keyboard state. * * Call "CandidateClicked" method of an engine asynchronously. */ -void bus_engine_proxy_candidate_clicked (BusEngineProxy *engine, - guint index, - guint button, - guint state); +void bus_engine_proxy_candidate_clicked + (BusEngineProxy *engine, + guint index, + guint button, + guint state); /** * bus_engine_proxy_enable: + * @engine: A #BusEngineProxy. * - * Call "Enable" method of an engine asynchronously. Do nothing if the engine is already enabled. + * Call "Enable" method of an engine asynchronously. Do nothing if the + * engine is already enabled. */ -void bus_engine_proxy_enable (BusEngineProxy *engine); +void bus_engine_proxy_enable (BusEngineProxy *engine); /** * bus_engine_proxy_disable: + * @engine: A #BusEngineProxy. * - * Call "Disable" method of an engine asynchronously. Do nothing if the engine is already disabled. + * Call "Disable" method of an engine asynchronously. Do nothing if + * the engine is already disabled. */ -void bus_engine_proxy_disable (BusEngineProxy *engine); +void bus_engine_proxy_disable (BusEngineProxy *engine); /** * bus_engine_proxy_property_activate: + * @engine: A #BusEngineProxy. + * @name: Property name. + * @state: Property state. * * Call "PropertyActivate" method of an engine asynchronously. */ -void bus_engine_proxy_property_activate (BusEngineProxy *engine, - const gchar *prop_name, - guint state); +void bus_engine_proxy_property_activate + (BusEngineProxy *engine, + const gchar *prop_name, + guint state); /** * bus_engine_proxy_property_show: + * @engine: A #BusEngineProxy. + * @prop_name: Property name. * * Call "PropertyShow" method of an engine asynchronously. */ -void bus_engine_proxy_property_show (BusEngineProxy *engine, - const gchar *prop_name); +void bus_engine_proxy_property_show + (BusEngineProxy *engine, + const gchar *prop_name); /** * bus_engine_proxy_property_hide: + * @engine: A #BusEngineProxy. + * @prop_name: Property name. * * Call "PropertyHide" method of an engine asynchronously. */ -void bus_engine_proxy_property_hide (BusEngineProxy *engine, - const gchar *prop_name); +void bus_engine_proxy_property_hide + (BusEngineProxy *engine, + const gchar *prop_name); /** * bus_engine_proxy_is_enabled: - * @returns: TRUE if the engine is enabled. + * @engine: A #BusEngineProxy. + * @returns: %TRUE if the engine is enabled. */ -gboolean bus_engine_proxy_is_enabled (BusEngineProxy *engine); +gboolean bus_engine_proxy_is_enabled (BusEngineProxy *engine); /** * bus_engine_proxy_set_surrounding_text: + * @engine: A #BusEngineProxy. + * @text: The surrounding text. + * @cursor_pos: The cursor position on surrounding text. + * @anchor_pos: The anchor position on selection area. * * Call "SetSurroundingText" method of an engine asynchronously. */ -void bus_engine_proxy_set_surrounding_text - (BusEngineProxy *engine, - IBusText *text, - guint cursor_pos, - guint anchor_pos); +void bus_engine_proxy_set_surrounding_text + (BusEngineProxy *engine, + IBusText *text, + guint cursor_pos, + guint anchor_pos); /** * bus_engine_proxy_process_hand_writing_event: + * @engine: A #BusEngineProxy. + * @coordinates: A #GVariant containing an array of coordinates. * - * Call "ProcessHandWritingEvent" method of an engine asynchronously. The type of the GVariant should be "(ad)". - * See ibus_input_context_process_hand_writing_event for details. + * Call "ProcessHandWritingEvent" method of an engine + * asynchronously. The type of the GVariant should be "(ad)". See + * ibus_input_context_process_hand_writing_event() for details. */ -void bus_engine_proxy_process_hand_writing_event - (BusEngineProxy *engine, - GVariant *coordinates); +void bus_engine_proxy_process_hand_writing_event + (BusEngineProxy *engine, + GVariant *coordinates); /** * bus_engine_proxy_cancel_hand_writing: + * @engine: A #BusEngineProxy. + * @n_strokes: The number of strokes to be removed. 0 means "remove all". * * Call "CancelHandWriting" method of an engine asynchronously. - * See ibus_input_context_cancel_hand_writing for details. + * See ibus_input_context_cancel_hand_writing() for details. + */ +void bus_engine_proxy_cancel_hand_writing + (BusEngineProxy *engine, + guint n_strokes); + +/** + * bus_engine_proxy_set_content_type: + * @engine: A #BusEngineProxy. + * @purpose: Primary purpose of the input context, as an #IBusInputPurpose. + * @hints: Hints that augment @purpose, as an #IBusInputHints. + * + * Call "SetContentType" method of an engine asynchronously. + * See ibus_input_context_set_content_type() for details. */ -void bus_engine_proxy_cancel_hand_writing - (BusEngineProxy *engine, - guint n_strokes); +void bus_engine_proxy_set_content_type + (BusEngineProxy *engine, + guint purpose, + guint hints); /** * bus_engine_proxy_get_properties: + * @engine: A #BusEngineProxy. + * @returns: An #IBusPropList. * - * Get an IBusPropList object associated with the engine. + * Get an #IBusPropList object associated with the engine. */ -IBusPropList *bus_engine_proxy_get_properties (BusEngineProxy *engine); +IBusPropList *bus_engine_proxy_get_properties + (BusEngineProxy *engine); G_END_DECLS #endif diff --git a/bus/inputcontext.c b/bus/inputcontext.c index d7ada6ef..a2d1d52c 100644 --- a/bus/inputcontext.c +++ b/bus/inputcontext.c @@ -1,8 +1,8 @@ /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ /* vim:set et sts=4: */ /* ibus - The Input Bus - * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com> - * Copyright (C) 2008-2010 Red Hat, Inc. + * Copyright (C) 2008-2013 Peng Huang <shawn.p.huang@gmail.com> + * Copyright (C) 2008-2013 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -89,6 +89,10 @@ struct _BusInputContext { /* incompleted set engine by desc request */ SetEngineByDescData *data; + + /* content-type (primary purpose and hints) */ + guint purpose; + guint hints; }; struct _BusInputContextClass { @@ -132,69 +136,83 @@ typedef struct _BusInputContextPrivate BusInputContextPrivate; static guint context_signals[LAST_SIGNAL] = { 0 }; /* functions prototype */ -static void bus_input_context_destroy (BusInputContext *context); +static void bus_input_context_destroy + (BusInputContext *context); static void bus_input_context_service_method_call - (IBusService *service, - GDBusConnection *connection, - const gchar *sender, - const gchar *object_path, - const gchar *interface_name, - const gchar *method_name, - GVariant *parameters, - GDBusMethodInvocation *invocation); -static void bus_input_context_unset_engine (BusInputContext *context); -static void bus_input_context_commit_text (BusInputContext *context, - IBusText *text); + (IBusService *service, + GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *method_name, + GVariant *parameters, + GDBusMethodInvocation *invocation); +static gboolean bus_input_context_service_set_property + (IBusService *service, + GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *property_name, + GVariant *value, + GError **error); +static void bus_input_context_unset_engine + (BusInputContext *context); +static void bus_input_context_commit_text + (BusInputContext *context, + IBusText *text); static void bus_input_context_update_preedit_text - (BusInputContext *context, - IBusText *text, - guint cursor_pos, - gboolean visible, - guint mode); + (BusInputContext *context, + IBusText *text, + guint cursor_pos, + gboolean visible, + guint mode); static void bus_input_context_show_preedit_text - (BusInputContext *context); + (BusInputContext *context); static void bus_input_context_hide_preedit_text - (BusInputContext *context); + (BusInputContext *context); static void bus_input_context_update_auxiliary_text - (BusInputContext *context, - IBusText *text, - gboolean visible); + (BusInputContext *context, + IBusText *text, + gboolean visible); static void bus_input_context_show_auxiliary_text - (BusInputContext *context); + (BusInputContext *context); static void bus_input_context_hide_auxiliary_text - (BusInputContext *context); + (BusInputContext *context); static void bus_input_context_update_lookup_table - (BusInputContext *context, - IBusLookupTable *table, - gboolean visible); + (BusInputContext *context, + IBusLookupTable *table, + gboolean visible); static void bus_input_context_show_lookup_table - (BusInputContext *context); + (BusInputContext *context); static void bus_input_context_hide_lookup_table - (BusInputContext *context); + (BusInputContext *context); static void bus_input_context_page_up_lookup_table - (BusInputContext *context); + (BusInputContext *context); static void bus_input_context_page_down_lookup_table - (BusInputContext *context); + (BusInputContext *context); static void bus_input_context_cursor_up_lookup_table - (BusInputContext *context); + (BusInputContext *context); static void bus_input_context_cursor_down_lookup_table - (BusInputContext *context); + (BusInputContext *context); static void bus_input_context_register_properties - (BusInputContext *context, - IBusPropList *props); + (BusInputContext *context, + IBusPropList *props); static void bus_input_context_update_property - (BusInputContext *context, - IBusProperty *prop); -static void _engine_destroy_cb (BusEngineProxy *factory, - BusInputContext *context); + (BusInputContext *context, + IBusProperty *prop); +static void _engine_destroy_cb (BusEngineProxy *factory, + BusInputContext *context); static IBusText *text_empty = NULL; static IBusLookupTable *lookup_table_empty = NULL; static IBusPropList *props_empty = NULL; -/* The interfaces available in this class, which consists of a list of methods this class implements and - * a list of signals this class may emit. Method calls to the interface that are not defined in this XML - * will be automatically rejected by the GDBus library (see src/ibusservice.c for details.) */ +/* The interfaces available in this class, which consists of a list of + * methods this class implements and a list of signals this class may + * emit. Method calls to the interface that are not defined in this + * XML will be automatically rejected by the GDBus library (see + * src/ibusservice.c for details.) */ static const gchar introspection_xml[] = "<node>" " <interface name='org.freedesktop.IBus.InputContext'>" @@ -277,6 +295,9 @@ static const gchar introspection_xml[] = " <signal name='UpdateProperty'>" " <arg type='v' name='prop' />" " </signal>" + + /* properties */ + " <property name='ContentType' type='(uu)' access='write' />" " </interface>" "</node>"; @@ -316,7 +337,10 @@ bus_input_context_class_init (BusInputContextClass *class) ibus_object_class->destroy = (IBusObjectDestroyFunc) bus_input_context_destroy; /* override the parent class's implementation. */ - IBUS_SERVICE_CLASS (class)->service_method_call = bus_input_context_service_method_call; + IBUS_SERVICE_CLASS (class)->service_method_call = + bus_input_context_service_method_call; + IBUS_SERVICE_CLASS (class)->service_set_property = + bus_input_context_service_set_property; /* register the xml so that bus_ibus_impl_service_method_call will be called on a method call defined in the xml (e.g. 'FocusIn'.) */ ibus_service_class_add_interfaces (IBUS_SERVICE_CLASS (class), introspection_xml); @@ -607,14 +631,9 @@ bus_input_context_destroy (BusInputContext *context) IBUS_OBJECT_CLASS (bus_input_context_parent_class)->destroy (IBUS_OBJECT (context)); } -/** - * bus_input_context_emit_signal: - * @signal_name: The D-Bus signal name to emit which is in the introspection_xml. - * - * Emit the D-Bus signal. - */ static gboolean -bus_input_context_emit_signal (BusInputContext *context, +bus_input_context_send_signal (BusInputContext *context, + const gchar *interface_name, const gchar *signal_name, GVariant *parameters, GError **error) @@ -623,7 +642,7 @@ bus_input_context_emit_signal (BusInputContext *context, return TRUE; GDBusMessage *message = g_dbus_message_new_signal (ibus_service_get_object_path ((IBusService *)context), - "org.freedesktop.IBus.InputContext", + interface_name, signal_name); g_dbus_message_set_sender (message, "org.freedesktop.IBus"); g_dbus_message_set_destination (message, bus_connection_get_unique_name (context->connection)); @@ -639,6 +658,58 @@ bus_input_context_emit_signal (BusInputContext *context, } /** + * bus_input_context_emit_signal: + * @signal_name: The D-Bus signal name to emit which is in the introspection_xml. + * + * Emit the D-Bus signal. + */ +static gboolean +bus_input_context_emit_signal (BusInputContext *context, + const gchar *signal_name, + GVariant *parameters, + GError **error) +{ + if (context->connection == NULL) + return TRUE; + + return bus_input_context_send_signal (context, + "org.freedesktop.IBus.InputContext", + signal_name, + parameters, + error); +} + +/** + * bus_input_context_property_changed: + * @context: a #BusInputContext + * @property_name: The D-Bus property name which has changed + * @value: The new value of the property + * + * Emit the D-Bus "PropertiesChanged" signal for a property. + * Returns: %TRUE on success, %FALSE on failure + */ +static gboolean +bus_input_context_property_changed (BusInputContext *context, + const gchar *property_name, + GVariant *value, + GError **error) +{ + if (context->connection == NULL) + return TRUE; + + GVariantBuilder *builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY); + g_variant_builder_add (builder, "{sv}", property_name, value); + return bus_input_context_send_signal (context, + "org.freedesktop.DBus.Properties", + "PropertiesChanged", + g_variant_new ("(sa{sv}as)", + "org.freedesktop.IBus", + builder, + NULL), + error); +} + +/** * _ic_process_key_event_reply_cb: * * A GAsyncReadyCallback function to be called when bus_engine_proxy_process_key_event() is finished. @@ -948,11 +1019,6 @@ _ic_get_engine (BusInputContext *context, g_variant_new ("(v)", ibus_serializable_serialize ((IBusSerializable *)desc))); } -/** - * bus_input_context_service_method_call: - * - * Handle a D-Bus method call whose destination and interface name are both "org.freedesktop.IBus.InputContext" - */ static void _ic_set_surrounding_text (BusInputContext *context, GVariant *parameters, @@ -985,6 +1051,11 @@ _ic_set_surrounding_text (BusInputContext *context, g_dbus_method_invocation_return_value (invocation, NULL); } +/** + * bus_input_context_service_method_call: + * + * Handle a D-Bus method call whose destination and interface name are both "org.freedesktop.IBus.InputContext" + */ static void bus_input_context_service_method_call (IBusService *service, GDBusConnection *connection, @@ -1024,7 +1095,7 @@ bus_input_context_service_method_call (IBusService *service, { "PropertyActivate", _ic_property_activate }, { "SetEngine", _ic_set_engine }, { "GetEngine", _ic_get_engine }, - { "SetSurroundingText", _ic_set_surrounding_text}, + { "SetSurroundingText", _ic_set_surrounding_text } }; gint i; @@ -1038,6 +1109,63 @@ bus_input_context_service_method_call (IBusService *service, g_return_if_reached (); } +static gboolean +bus_input_context_service_set_property (IBusService *service, + GDBusConnection *connection, + const gchar *sender, + const gchar *object_path, + const gchar *interface_name, + const gchar *property_name, + GVariant *value, + GError **error) +{ + if (g_strcmp0 (interface_name, IBUS_INTERFACE_INPUT_CONTEXT) != 0) { + return IBUS_SERVICE_CLASS (bus_input_context_parent_class)-> + service_set_property (service, + connection, + sender, + object_path, + interface_name, + property_name, + value, + error); + } + + if (g_strcmp0 (property_name, "ContentType") == 0) { + BusInputContext *context = (BusInputContext *) service; + guint purpose = 0; + guint hints = 0; + + g_variant_get (value, "(uu)", &purpose, &hints); + if (purpose != context->purpose || hints != context->hints) { + GError *error; + gboolean retval; + + context->purpose = purpose; + context->hints = hints; + + if (context->has_focus && context->engine) + bus_engine_proxy_set_content_type (context->engine, + purpose, + hints); + + error = NULL; + retval = bus_input_context_property_changed (context, + "ContentType", + value, + &error); + if (!retval) { + g_warning ("Failed to emit PropertiesChanged signal: %s", + error->message); + g_error_free (error); + } + } + return TRUE; + } + + g_return_val_if_reached (FALSE); +} + gboolean bus_input_context_has_focus (BusInputContext *context) { @@ -1066,6 +1194,7 @@ bus_input_context_focus_in (BusInputContext *context) bus_engine_proxy_enable (context->engine); bus_engine_proxy_set_capabilities (context->engine, context->capabilities); bus_engine_proxy_set_cursor_location (context->engine, context->x, context->y, context->w, context->h); + bus_engine_proxy_set_content_type (context->engine, context->purpose, context->hints); } if (context->capabilities & IBUS_CAP_FOCUS) { @@ -1953,6 +2082,7 @@ bus_input_context_enable (BusInputContext *context) bus_engine_proxy_enable (context->engine); bus_engine_proxy_set_capabilities (context->engine, context->capabilities); bus_engine_proxy_set_cursor_location (context->engine, context->x, context->y, context->w, context->h); + bus_engine_proxy_set_content_type (context->engine, context->purpose, context->hints); } void @@ -2057,6 +2187,7 @@ bus_input_context_set_engine (BusInputContext *context, bus_engine_proxy_enable (context->engine); bus_engine_proxy_set_capabilities (context->engine, context->capabilities); bus_engine_proxy_set_cursor_location (context->engine, context->x, context->y, context->w, context->h); + bus_engine_proxy_set_content_type (context->engine, context->purpose, context->hints); } } g_signal_emit (context, |