gchar * ibus_message_to_string (IBusMessage *message) { g_assert (message != NULL); GString *string = g_string_new (""); IBusMessageIter iter; GType type; gint i = 0; g_string_append_printf (string, "message: %d\n" "\tdestination = %s\n" "\tpath = %s\n" "\tinterface = %s\n" "\tmember = %s\n", ibus_message_get_type (message), ibus_message_get_destination (message), ibus_message_get_path (message), ibus_message_get_interface (message), ibus_message_get_member (message)); ibus_message_iter_init (message, &iter); while ((type = ibus_message_iter_get_arg_type (&iter)) != G_TYPE_INVALID) { g_string_append_printf (string, "\t\targ%d is %s\n", i++, g_type_name (type)); ibus_message_iter_next (&iter); } return g_string_free (string, FALSE); }
/* dbus interface */ static IBusMessage * _dbus_no_implement (BusDBusImpl *dbus, IBusMessage *message, BusConnection *connection) { IBusMessage *reply_message; reply_message = ibus_message_new_error_printf (message, DBUS_ERROR_UNKNOWN_METHOD, "IBus does not support %s.", ibus_message_get_member (message)); return reply_message; }
void bus_dbus_impl_dispatch_message_by_rule (BusDBusImpl *dbus, IBusMessage *message, BusConnection *skip_connection) { g_assert (BUS_IS_DBUS_IMPL (dbus)); g_assert (message != NULL); g_assert (BUS_IS_CONNECTION (skip_connection) || skip_connection == NULL); GList *recipients = NULL; GList *link = NULL; static gint32 data_slot = -1; if (G_UNLIKELY (IBUS_OBJECT_DESTROYED (dbus))) { return; } if (data_slot == -1) { dbus_message_allocate_data_slot (&data_slot); } /* If this message has been dispatched by rule, it will be ignored. */ if (dbus_message_get_data (message, data_slot) != NULL) return; dbus_message_set_data (message, data_slot, (gpointer) TRUE, NULL); #if 0 if (g_strcmp0 (ibus_message_get_member (message), "ValueChanged") == 0) { g_debug ("Dispatch ValueChanged"); } #endif for (link = dbus->rules; link != NULL; link = link->next) { GList *list = bus_match_rule_get_recipients (BUS_MATCH_RULE (link->data), message); recipients = g_list_concat (recipients, list); } for (link = recipients; link != NULL; link = link->next) { BusConnection *connection = BUS_CONNECTION (link->data); if (connection != skip_connection) { ibus_connection_send (IBUS_CONNECTION (connection), message); } g_object_unref (connection); } g_list_free (recipients); }
static gboolean bus_engine_proxy_ibus_signal (IBusProxy *proxy, IBusMessage *message) { g_assert (BUS_IS_ENGINE_PROXY (proxy)); g_assert (message != NULL); g_assert (ibus_message_get_type (message) == DBUS_MESSAGE_TYPE_SIGNAL); const gchar *interface; const gchar *name; BusEngineProxy *engine; IBusError *error; gint i; static const struct { const gchar *member; const guint signal_id; } signals [] = { { "ShowPreeditText", SHOW_PREEDIT_TEXT }, { "HidePreeditText", HIDE_PREEDIT_TEXT }, { "ShowAuxiliaryText", SHOW_AUXILIARY_TEXT }, { "HideAuxiliaryText", HIDE_AUXILIARY_TEXT }, { "ShowLookupTable", SHOW_LOOKUP_TABLE }, { "HideLookupTable", HIDE_LOOKUP_TABLE }, { "PageUpLookupTable", PAGE_UP_LOOKUP_TABLE }, { "PageDownLookupTable", PAGE_DOWN_LOOKUP_TABLE }, { "CursorUpLookupTable", CURSOR_UP_LOOKUP_TABLE }, { "CursorDownLookupTable", CURSOR_DOWN_LOOKUP_TABLE }, }; engine = BUS_ENGINE_PROXY (proxy); interface = ibus_message_get_interface (message); name = ibus_message_get_member (message); if (interface != NULL && g_strcmp0 (interface, IBUS_INTERFACE_ENGINE) != 0) return FALSE; for (i = 0; i < G_N_ELEMENTS (signals); i++) { if (g_strcmp0 (name, signals[i].member) == 0) { g_signal_emit (engine, engine_signals[signals[i].signal_id], 0); goto handled; } } if (g_strcmp0 (name, "CommitText") == 0) { IBusText *text; gboolean retval; retval = ibus_message_get_args (message, &error, IBUS_TYPE_TEXT, &text, G_TYPE_INVALID); if (!retval) goto failed; g_signal_emit (engine, engine_signals[COMMIT_TEXT], 0, text); g_object_unref (text); } else if (g_strcmp0 (name, "ForwardKeyEvent") == 0) { guint32 keyval; guint32 keycode; guint32 states; gboolean retval; retval = ibus_message_get_args (message, &error, G_TYPE_UINT, &keyval, G_TYPE_UINT, &keycode, G_TYPE_UINT, &states, G_TYPE_INVALID); if (!retval) goto failed; g_signal_emit (engine, engine_signals[FORWARD_KEY_EVENT], 0, keyval, keycode, states); } else if (g_strcmp0 (name, "DeleteSurroundingText") == 0) { gint offset_from_cursor; guint nchars; gboolean retval; retval = ibus_message_get_args (message, &error, G_TYPE_INT, &offset_from_cursor, G_TYPE_UINT, &nchars, G_TYPE_INVALID); if (!retval) goto failed; g_signal_emit (engine, engine_signals[DELETE_SURROUNDING_TEXT], 0, offset_from_cursor, nchars); } else if (g_strcmp0 (name, "UpdatePreeditText") == 0) { IBusText *text; gint cursor_pos; gboolean visible; gboolean retval; guint mode; retval = ibus_message_get_args (message, &error, IBUS_TYPE_TEXT, &text, G_TYPE_UINT, &cursor_pos, G_TYPE_BOOLEAN, &visible, G_TYPE_UINT, &mode, G_TYPE_INVALID); if (!retval) goto failed; g_signal_emit (engine, engine_signals[UPDATE_PREEDIT_TEXT], 0, text, cursor_pos, visible, mode); if (g_object_is_floating (text)) g_object_unref (text); } else if (g_strcmp0 (name, "UpdateAuxiliaryText") == 0) { IBusText *text; gboolean visible; gboolean retval; retval = ibus_message_get_args (message, &error, IBUS_TYPE_TEXT, &text, G_TYPE_BOOLEAN, &visible, G_TYPE_INVALID); if (!retval) goto failed; g_signal_emit (engine, engine_signals[UPDATE_AUXILIARY_TEXT], 0, text, visible); if (g_object_is_floating (text)) g_object_unref (text); } else if (g_strcmp0 (name, "UpdateLookupTable") == 0) { IBusLookupTable *table; gboolean visible; gboolean retval; retval = ibus_message_get_args (message, &error, IBUS_TYPE_LOOKUP_TABLE, &table, G_TYPE_BOOLEAN, &visible, G_TYPE_INVALID); if (!retval) goto failed; g_signal_emit (engine, engine_signals[UPDATE_LOOKUP_TABLE], 0, table, visible); if (g_object_is_floating (table)) g_object_unref (table); } else if (g_strcmp0 (name, "RegisterProperties") == 0) { gboolean retval; IBusPropList *prop_list; retval = ibus_message_get_args (message, &error, IBUS_TYPE_PROP_LIST, &prop_list, G_TYPE_INVALID); if (!retval) { goto failed; } g_signal_emit (engine, engine_signals[REGISTER_PROPERTIES], 0, prop_list); if (g_object_is_floating (prop_list)) g_object_unref (prop_list); } else if (g_strcmp0 (name, "UpdateProperty") == 0) { IBusProperty *prop; gboolean retval; retval = ibus_message_get_args (message, &error, IBUS_TYPE_PROPERTY, &prop, G_TYPE_INVALID); if (!retval) goto failed; g_signal_emit (engine, engine_signals[UPDATE_PROPERTY], 0, prop); if (g_object_is_floating (prop)) g_object_unref (prop); } else return FALSE; handled: g_signal_stop_emission_by_name (engine, "ibus-signal"); return TRUE; failed: g_warning ("%s: %s", error->name, error->message); ibus_error_free (error); return FALSE; }
static gboolean _connection_ibus_message_cb (BusConnection *connection, IBusMessage *message, BusDBusImpl *dbus) { g_assert (BUS_IS_CONNECTION (connection)); g_assert (message != NULL); g_assert (BUS_IS_DBUS_IMPL (dbus)); const gchar *dest; if (G_UNLIKELY (IBUS_OBJECT_DESTROYED (dbus))) { return; } if (ibus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected")) { /* ignore signal from local interface */ return FALSE; } ibus_message_set_sender (message, bus_connection_get_unique_name (connection)); switch (ibus_message_get_type (message)) { #if 1 case DBUS_MESSAGE_TYPE_ERROR: g_debug ("From :%s to %s, Error: %s : %s", ibus_message_get_sender (message), ibus_message_get_destination (message), ibus_message_get_error_name (message), ibus_message_get_error_message (message)); break; #endif #if 0 case DBUS_MESSAGE_TYPE_SIGNAL: g_debug ("From :%s to %s, Signal: %s @ %s", ibus_message_get_sender (message), ibus_message_get_destination (message), ibus_message_get_member (message), ibus_message_get_path (message) ); break; #endif #if 0 case DBUS_MESSAGE_TYPE_METHOD_CALL: g_debug("From %s to %s, Method %s on %s", ibus_message_get_sender (message), ibus_message_get_destination (message), ibus_message_get_path (message), ibus_message_get_member (message)); break; #endif } dest = ibus_message_get_destination (message); if (dest == NULL || strcmp ((gchar *)dest, IBUS_SERVICE_IBUS) == 0 || strcmp ((gchar *)dest, DBUS_SERVICE_DBUS) == 0) { /* this message is sent to ibus-daemon */ switch (ibus_message_get_type (message)) { case DBUS_MESSAGE_TYPE_SIGNAL: case DBUS_MESSAGE_TYPE_METHOD_RETURN: case DBUS_MESSAGE_TYPE_ERROR: bus_dbus_impl_dispatch_message_by_rule (dbus, message, NULL); return FALSE; case DBUS_MESSAGE_TYPE_METHOD_CALL: { const gchar *path; IBusService *object; path = ibus_message_get_path (message); object = g_hash_table_lookup (dbus->objects, path); if (object == NULL || ibus_service_handle_message (object, (IBusConnection *) connection, message) == FALSE) { IBusMessage *error; error = ibus_message_new_error_printf (message, DBUS_ERROR_UNKNOWN_METHOD, "Unknown method %s on %s", ibus_message_get_member (message), path); ibus_connection_send ((IBusConnection *) connection, error); ibus_message_unref (error); } /* dispatch message */ bus_dbus_impl_dispatch_message_by_rule (dbus, message, NULL); } break; default: g_assert (FALSE); } } else { /* If the destination is not IBus or DBus, the message will be forwanded. */ bus_dbus_impl_dispatch_message (dbus, message); } g_signal_stop_emission_by_name (connection, "ibus-message"); return TRUE; }
static gboolean ibus_engine_ibus_message (IBusEngine *engine, IBusConnection *connection, IBusMessage *message) { g_assert (IBUS_IS_ENGINE (engine)); g_assert (IBUS_IS_CONNECTION (connection)); g_assert (message != NULL); g_assert (ibus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_CALL); IBusEnginePrivate *priv; priv = IBUS_ENGINE_GET_PRIVATE (engine); g_assert (priv->connection == connection); IBusMessage *reply = NULL; IBusError *error = NULL; gboolean retval; gint i; const gchar *interface; const gchar *name; static const struct { gchar *member; guint signal_id; } no_arg_methods[] = { { "FocusIn", FOCUS_IN }, { "FocusOut", FOCUS_OUT }, { "Reset", RESET }, { "Enable", ENABLE }, { "Disable", DISABLE }, { "PageUp", PAGE_UP }, { "PageDown", PAGE_DOWN }, { "CursorUp", CURSOR_UP }, { "CursorDown", CURSOR_DOWN }, }; interface = ibus_message_get_interface (message); name = ibus_message_get_member (message); if (interface != NULL && g_strcmp0 (interface, IBUS_INTERFACE_ENGINE) != 0) return IBUS_SERVICE_CLASS (ibus_engine_parent_class)->ibus_message ( (IBusService *) engine, connection, message); do { if (g_strcmp0 (name, "ProcessKeyEvent") == 0) { guint keyval, keycode, state; retval = ibus_message_get_args (message, &error, G_TYPE_UINT, &keyval, G_TYPE_UINT, &keycode, G_TYPE_UINT, &state, G_TYPE_INVALID); if (!retval) { reply = ibus_message_new_error_printf (message, DBUS_ERROR_INVALID_ARGS, "%s.%s: Can not match signature (uuu) of method", IBUS_INTERFACE_ENGINE, "ProcessKeyEvent"); ibus_error_free (error); } else { retval = FALSE; g_signal_emit (engine, engine_signals[PROCESS_KEY_EVENT], 0, keyval, keycode, state, &retval); reply = ibus_message_new_method_return (message); ibus_message_append_args (reply, G_TYPE_BOOLEAN, &retval, G_TYPE_INVALID); } break; } for (i = 0; i < G_N_ELEMENTS (no_arg_methods) && g_strcmp0 (name, no_arg_methods[i].member) != 0; i++); if (i < G_N_ELEMENTS (no_arg_methods)) { IBusMessageIter iter; ibus_message_iter_init (message, &iter); if (ibus_message_iter_has_next (&iter)) { reply = ibus_message_new_error_printf (message, DBUS_ERROR_INVALID_ARGS, "%s.%s: Method does not have arguments", IBUS_INTERFACE_ENGINE, no_arg_methods[i].member); } else { g_signal_emit (engine, engine_signals[no_arg_methods[i].signal_id], 0); reply = ibus_message_new_method_return (message); } break; } if (g_strcmp0 (name, "CandidateClicked") == 0) { guint index, button, state; retval = ibus_message_get_args (message, &error, G_TYPE_UINT, &index, G_TYPE_UINT, &button, G_TYPE_UINT, &state, G_TYPE_INVALID); if (!retval) { reply = ibus_message_new_error_printf (message, DBUS_ERROR_INVALID_ARGS, "%s.%s: Can not match signature (uuu) of method", IBUS_INTERFACE_ENGINE, "CandidateClicked"); ibus_error_free (error); } else { g_signal_emit (engine, engine_signals[CANDIDATE_CLICKED], 0, index, button, state); reply = ibus_message_new_method_return (message); } } else if (g_strcmp0 (name, "PropertyActivate") == 0) { gchar *name; guint state; retval = ibus_message_get_args (message, &error, G_TYPE_STRING, &name, G_TYPE_UINT, &state, G_TYPE_INVALID); if (!retval) { reply = ibus_message_new_error_printf (message, DBUS_ERROR_INVALID_ARGS, "%s.%s: Can not match signature (si) of method", IBUS_INTERFACE_ENGINE, "PropertyActivate"); ibus_error_free (error); } else { g_signal_emit (engine, engine_signals[PROPERTY_ACTIVATE], 0, name, state); reply = ibus_message_new_method_return (message); } } else if (g_strcmp0 (name, "PropertyShow") == 0) { gchar *name; retval = ibus_message_get_args (message, &error, G_TYPE_STRING, &name, G_TYPE_INVALID); if (!retval) { reply = ibus_message_new_error_printf (message, DBUS_ERROR_INVALID_ARGS, "%s.%s: Can not match signature (s) of method", IBUS_INTERFACE_ENGINE, "PropertyShow"); ibus_error_free (error); } else { g_signal_emit (engine, engine_signals[PROPERTY_SHOW], 0, name); reply = ibus_message_new_method_return (message); } } else if (g_strcmp0 (name, "PropertyHide") == 0) { gchar *name; retval = ibus_message_get_args (message, &error, G_TYPE_STRING, &name, G_TYPE_INVALID); if (!retval) { reply = ibus_message_new_error_printf (message, DBUS_ERROR_INVALID_ARGS, "%s.%s: Can not match signature (s) of method", IBUS_INTERFACE_ENGINE, "PropertyHide"); ibus_error_free (error); } else { g_signal_emit (engine, engine_signals[PROPERTY_HIDE], 0, name); reply = ibus_message_new_method_return (message); } } else if (g_strcmp0 (name, "SetCursorLocation") == 0) { gint x, y, w, h; retval = ibus_message_get_args (message, &error, G_TYPE_INT, &x, G_TYPE_INT, &y, G_TYPE_INT, &w, G_TYPE_INT, &h, G_TYPE_INVALID); if (!retval) { reply = ibus_message_new_error_printf (message, DBUS_ERROR_INVALID_ARGS, "%s.%s: Can not match signature (iiii) of method", IBUS_INTERFACE_ENGINE, "SetCursorLocation"); ibus_error_free (error); } else { engine->cursor_area.x = x; engine->cursor_area.y = y; engine->cursor_area.width = w; engine->cursor_area.height = h; g_signal_emit (engine, engine_signals[SET_CURSOR_LOCATION], 0, x, y, w, h); reply = ibus_message_new_method_return (message); } } else if (g_strcmp0 (name, "SetCapabilities") == 0) { guint caps; retval = ibus_message_get_args (message, &error, G_TYPE_UINT, &caps, G_TYPE_INVALID); if (!retval) { reply = ibus_message_new_error_printf (message, DBUS_ERROR_INVALID_ARGS, "%s.%s: Can not match signature (u) of method", IBUS_INTERFACE_ENGINE, "SetCapabilities"); ibus_error_free (error); } else { engine->client_capabilities = caps; g_signal_emit (engine, engine_signals[SET_CAPABILITIES], 0, caps); reply = ibus_message_new_method_return (message); } } else if (g_strcmp0 (name, "Destroy") == 0) { reply = ibus_message_new_method_return (message); ibus_connection_send (connection, reply); ibus_message_unref (reply); ibus_object_destroy ((IBusObject *) engine); return TRUE; } else { reply = ibus_message_new_error_printf (message, DBUS_ERROR_UNKNOWN_METHOD, "%s.%s", IBUS_INTERFACE_ENGINE, name); g_warn_if_reached (); } } while (0); ibus_connection_send (connection, reply); ibus_message_unref (reply); return TRUE; }
static gboolean ibus_input_context_ibus_signal (IBusProxy *proxy, IBusMessage *message) { g_assert (IBUS_IS_INPUT_CONTEXT (proxy)); g_assert (message != NULL); g_assert (ibus_message_get_type (message) == DBUS_MESSAGE_TYPE_SIGNAL); IBusInputContext *context; IBusError *error = NULL; gint i; const gchar *interface; const gchar *name; context = IBUS_INPUT_CONTEXT (proxy); static const struct { const gchar *member; guint signal_id; } signals [] = { { "Enabled", ENABLED }, { "Disabled", DISABLED }, { "ShowPreeditText", SHOW_PREEDIT_TEXT }, { "HidePreeditText", HIDE_PREEDIT_TEXT }, { "ShowAuxiliaryText", SHOW_AUXILIARY_TEXT }, { "HideAuxiliaryText", HIDE_AUXILIARY_TEXT }, { "ShowLookupTable", SHOW_LOOKUP_TABLE }, { "HideLookupTable", HIDE_LOOKUP_TABLE }, { "PageUpLookupTable", PAGE_UP_LOOKUP_TABLE }, { "PageDownLookupTable", PAGE_DOWN_LOOKUP_TABLE }, { "CursorUpLookupTable", CURSOR_UP_LOOKUP_TABLE }, { "CursorDownLookupTable", CURSOR_DOWN_LOOKUP_TABLE }, }; do { interface = ibus_message_get_interface (message); name = ibus_message_get_member (message); if (interface != NULL && g_strcmp0 (interface, IBUS_INTERFACE_INPUT_CONTEXT) != 0) { error = ibus_error_new_from_printf (DBUS_ERROR_FAILED, "Signal %s.%s is not handled", interface, name); break; } if (g_strcmp0 (name, "CommitText") == 0) { IBusText *text; gboolean retval; retval = ibus_message_get_args (message, &error, IBUS_TYPE_TEXT, &text, G_TYPE_INVALID); if (retval) { g_signal_emit (context, context_signals[COMMIT_TEXT], 0, text); if (g_object_is_floating (text)) g_object_unref (text); } break; } if (g_strcmp0 (name, "UpdatePreeditText") == 0) { IBusText *text; gint32 cursor_pos; gboolean visible; gboolean retval; retval = ibus_message_get_args (message, &error, IBUS_TYPE_TEXT, &text, G_TYPE_UINT, &cursor_pos, G_TYPE_BOOLEAN, &visible, G_TYPE_INVALID); if (retval) { g_signal_emit (context, context_signals[UPDATE_PREEDIT_TEXT], 0, text, cursor_pos, visible); if (g_object_is_floating (text)) g_object_unref (text); } break; } for (i = 0; i < G_N_ELEMENTS (signals) && g_strcmp0 (name, signals[i].member) != 0; i++); if (i < G_N_ELEMENTS (signals)) { g_signal_emit (context, context_signals[signals[i].signal_id], 0); break; } if (g_strcmp0 (name, "UpdateAuxiliaryText") == 0) { IBusText *text; gboolean visible; gboolean retval; retval = ibus_message_get_args (message, &error, IBUS_TYPE_TEXT, &text, G_TYPE_BOOLEAN, &visible, G_TYPE_INVALID); if (retval) { g_signal_emit (context, context_signals[UPDATE_AUXILIARY_TEXT], 0, text, visible); if (g_object_is_floating (text)) g_object_unref (text); } } else if (g_strcmp0 (name, "UpdateLookupTable") == 0) { IBusLookupTable *table; gboolean visible; gboolean retval; retval = ibus_message_get_args (message, &error, IBUS_TYPE_LOOKUP_TABLE, &table, G_TYPE_BOOLEAN, &visible, G_TYPE_INVALID); if (retval) { g_signal_emit (context, context_signals[UPDATE_LOOKUP_TABLE], 0, table, visible); if (g_object_is_floating (table)) g_object_unref (table); } } else if (g_strcmp0 (name, "RegisterProperties") == 0) { IBusPropList *prop_list; gboolean retval; retval = ibus_message_get_args (message, &error, IBUS_TYPE_PROP_LIST, &prop_list, G_TYPE_INVALID); if (retval) { g_signal_emit (context, context_signals[REGISTER_PROPERTIES], 0, prop_list); if (g_object_is_floating (prop_list)) g_object_unref (prop_list); } } else if (g_strcmp0 (name, "UpdateProperty") == 0) { IBusProperty *prop; gboolean retval; retval = ibus_message_get_args (message, &error, IBUS_TYPE_PROPERTY, &prop, G_TYPE_INVALID); if (retval) { g_signal_emit (context, context_signals[UPDATE_PROPERTY], 0, prop); if (g_object_is_floating (prop)) g_object_unref (prop); } } else if (g_strcmp0 (name, "ForwardKeyEvent") == 0) { guint32 keyval; guint32 keycode; guint32 state; gboolean retval; retval = ibus_message_get_args (message, &error, G_TYPE_UINT, &keyval, G_TYPE_UINT, &keycode, G_TYPE_UINT, &state, G_TYPE_INVALID); if (retval) { g_signal_emit (context, context_signals[FORWARD_KEY_EVENT], 0, keyval, keycode, state | IBUS_FORWARD_MASK); } } else if (g_strcmp0 (name, "DeleteSurroundingText") == 0) { gint offset_from_cursor; guint nchars; gboolean retval; retval = ibus_message_get_args (message, &error, G_TYPE_INT, &offset_from_cursor, G_TYPE_UINT, &nchars, G_TYPE_INVALID); if (retval) { g_signal_emit (context, context_signals[DELETE_SURROUNDING_TEXT], 0, offset_from_cursor, nchars); } } else { error = ibus_error_new_from_printf (DBUS_ERROR_FAILED, "Signal %s.%s is not handled", interface, name); break; } } while (0); if (error == NULL) { g_signal_stop_emission_by_name (context, "ibus-signal"); return TRUE; } /* some error happens */ g_warning ("%s: %s", error->name, error->message); ibus_error_free (error); return FALSE; }