Blame bus/ibusimpl.c

Packit Service 1d8f1c
/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
Packit Service 1d8f1c
/* vim:set et sts=4: */
Packit Service 1d8f1c
/* ibus - The Input Bus
Packit Service 1d8f1c
 * Copyright (C) 2008-2013 Peng Huang <shawn.p.huang@gmail.com>
Packit Service 1d8f1c
 * Copyright (C) 2011-2018 Takao Fujiwara <takao.fujiwara1@gmail.com>
Packit Service 1d8f1c
 * Copyright (C) 2008-2018 Red Hat, Inc.
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * This library is free software; you can redistribute it and/or
Packit Service 1d8f1c
 * modify it under the terms of the GNU Lesser General Public
Packit Service 1d8f1c
 * License as published by the Free Software Foundation; either
Packit Service 1d8f1c
 * version 2.1 of the License, or (at your option) any later version.
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * This library is distributed in the hope that it will be useful,
Packit Service 1d8f1c
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 1d8f1c
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 1d8f1c
 * Lesser General Public License for more details.
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * You should have received a copy of the GNU Lesser General Public
Packit Service 1d8f1c
 * License along with this library; if not, write to the Free Software
Packit Service 1d8f1c
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
Packit Service 1d8f1c
 * USA
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
Packit Service 1d8f1c
#include "ibusimpl.h"
Packit Service 1d8f1c
Packit Service 1d8f1c
#include <locale.h>
Packit Service 1d8f1c
#include <signal.h>
Packit Service 1d8f1c
#include <strings.h>
Packit Service 1d8f1c
#include <sys/types.h>
Packit Service 1d8f1c
#include <sys/wait.h>
Packit Service 1d8f1c
#include <unistd.h>
Packit Service 1d8f1c
Packit Service 1d8f1c
#include "connection.h"
Packit Service 1d8f1c
#include "dbusimpl.h"
Packit Service 1d8f1c
#include "factoryproxy.h"
Packit Service 1d8f1c
#include "global.h"
Packit Service 1d8f1c
#include "inputcontext.h"
Packit Service 1d8f1c
#include "panelproxy.h"
Packit Service 1d8f1c
#include "server.h"
Packit Service 1d8f1c
#include "types.h"
Packit Service 1d8f1c
Packit Service 1d8f1c
struct _BusIBusImpl {
Packit Service 1d8f1c
    IBusService parent;
Packit Service 1d8f1c
    /* instance members */
Packit Service 1d8f1c
    GHashTable *factory_dict;
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* registered components */
Packit Service 1d8f1c
    GList *registered_components;
Packit Service 1d8f1c
    GList *contexts;
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* a fake input context for global engine support */
Packit Service 1d8f1c
    BusInputContext *fake_context;
Packit Service 1d8f1c
    
Packit Service 1d8f1c
    /* a list of engines that are started by a user (without the --ibus
Packit Service 1d8f1c
     * command line flag.) */
Packit Service 1d8f1c
    GList *register_engine_list;
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* if TRUE, ibus-daemon uses a keysym translated by the system
Packit Service 1d8f1c
     * (i.e. XKB) as-is. otherwise, ibus-daemon itself converts keycode
Packit Service 1d8f1c
     * into keysym. */
Packit Service 1d8f1c
    gboolean use_sys_layout;
Packit Service 1d8f1c
Packit Service 1d8f1c
    gboolean embed_preedit_text;
Packit Service 1d8f1c
Packit Service 1d8f1c
    IBusRegistry    *registry;
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* a list of BusComponent objects that are created from component XML
Packit Service 1d8f1c
     * files (or from the cache of them). */
Packit Service 1d8f1c
    GList *components;
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* a mapping from an engine name (e.g. 'pinyin') to the corresponding
Packit Service 1d8f1c
     * IBusEngineDesc object. */
Packit Service 1d8f1c
    GHashTable *engine_table;
Packit Service 1d8f1c
Packit Service 1d8f1c
    BusInputContext *focused_context;
Packit Service 1d8f1c
    BusPanelProxy   *panel;
Packit Service 1d8f1c
    BusPanelProxy   *emoji_extension;
Packit Service 1d8f1c
    gboolean         enable_emoji_extension;
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* a default keymap of ibus-daemon (usually "us") which is used only
Packit Service 1d8f1c
     * when use_sys_layout is FALSE. */
Packit Service 1d8f1c
    IBusKeymap      *keymap;
Packit Service 1d8f1c
Packit Service 1d8f1c
    gboolean use_global_engine;
Packit Service 1d8f1c
    gchar *global_engine_name;
Packit Service 1d8f1c
    gchar *global_previous_engine_name;
Packit Service 1d8f1c
    GVariant *extension_register_keys;
Packit Service 1d8f1c
};
Packit Service 1d8f1c
Packit Service 1d8f1c
struct _BusIBusImplClass {
Packit Service 1d8f1c
    IBusServiceClass parent;
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* class members */
Packit Service 1d8f1c
};
Packit Service 1d8f1c
Packit Service 1d8f1c
enum {
Packit Service 1d8f1c
    LAST_SIGNAL,
Packit Service 1d8f1c
};
Packit Service 1d8f1c
Packit Service 1d8f1c
enum {
Packit Service 1d8f1c
    PROP_0,
Packit Service 1d8f1c
};
Packit Service 1d8f1c
Packit Service 1d8f1c
/*
Packit Service 1d8f1c
static guint            _signals[LAST_SIGNAL] = { 0 };
Packit Service 1d8f1c
*/
Packit Service 1d8f1c
Packit Service 1d8f1c
/* functions prototype */
Packit Service 1d8f1c
static void     bus_ibus_impl_destroy   (BusIBusImpl        *ibus);
Packit Service 1d8f1c
static void     bus_ibus_impl_service_method_call
Packit Service 1d8f1c
                                        (IBusService        *service,
Packit Service 1d8f1c
                                         GDBusConnection    *connection,
Packit Service 1d8f1c
                                         const gchar        *sender,
Packit Service 1d8f1c
                                         const gchar        *object_path,
Packit Service 1d8f1c
                                         const gchar        *interface_name,
Packit Service 1d8f1c
                                         const gchar        *method_name,
Packit Service 1d8f1c
                                         GVariant           *parameters,
Packit Service 1d8f1c
                                         GDBusMethodInvocation
Packit Service 1d8f1c
                                                            *invocation);
Packit Service 1d8f1c
static GVariant *
Packit Service 1d8f1c
                bus_ibus_impl_service_get_property
Packit Service 1d8f1c
                                        (IBusService        *service,
Packit Service 1d8f1c
                                         GDBusConnection    *connection,
Packit Service 1d8f1c
                                         const gchar        *sender,
Packit Service 1d8f1c
                                         const gchar        *object_path,
Packit Service 1d8f1c
                                         const gchar        *interface_name,
Packit Service 1d8f1c
                                         const gchar        *property_name,
Packit Service 1d8f1c
                                         GError            **error);
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
                bus_ibus_impl_service_set_property
Packit Service 1d8f1c
                                        (IBusService        *service,
Packit Service 1d8f1c
                                         GDBusConnection    *connection,
Packit Service 1d8f1c
                                         const gchar        *sender,
Packit Service 1d8f1c
                                         const gchar        *object_path,
Packit Service 1d8f1c
                                         const gchar        *interface_name,
Packit Service 1d8f1c
                                         const gchar        *property_name,
Packit Service 1d8f1c
                                         GVariant           *value,
Packit Service 1d8f1c
                                         GError            **error);
Packit Service 1d8f1c
static void     bus_ibus_impl_registry_init
Packit Service 1d8f1c
                                        (BusIBusImpl        *ibus);
Packit Service 1d8f1c
static void     bus_ibus_impl_registry_changed
Packit Service 1d8f1c
                                        (BusIBusImpl        *ibus);
Packit Service 1d8f1c
static void     bus_ibus_impl_registry_destroy
Packit Service 1d8f1c
                                        (BusIBusImpl        *ibus);
Packit Service 1d8f1c
static void     bus_ibus_impl_component_name_owner_changed
Packit Service 1d8f1c
                                        (BusIBusImpl        *ibus,
Packit Service 1d8f1c
                                         const gchar        *name,
Packit Service 1d8f1c
                                         const gchar        *old_name,
Packit Service 1d8f1c
                                         const gchar        *new_name);
Packit Service 1d8f1c
static void     bus_ibus_impl_global_engine_changed
Packit Service 1d8f1c
                                        (BusIBusImpl        *ibus);
Packit Service 1d8f1c
static void     bus_ibus_impl_set_context_engine_from_desc
Packit Service 1d8f1c
                                        (BusIBusImpl        *ibus,
Packit Service 1d8f1c
                                         BusInputContext    *context,
Packit Service 1d8f1c
                                         IBusEngineDesc     *desc);
Packit Service 1d8f1c
static BusInputContext
Packit Service 1d8f1c
               *bus_ibus_impl_create_input_context
Packit Service 1d8f1c
                                        (BusIBusImpl        *ibus,
Packit Service 1d8f1c
                                         BusConnection      *connection,
Packit Service 1d8f1c
                                         const gchar        *client);
Packit Service 1d8f1c
static IBusEngineDesc
Packit Service 1d8f1c
               *bus_ibus_impl_get_engine_desc
Packit Service 1d8f1c
                                        (BusIBusImpl        *ibus,
Packit Service 1d8f1c
                                         const gchar        *engine_name);
Packit Service 1d8f1c
static void     bus_ibus_impl_set_focused_context
Packit Service 1d8f1c
                                        (BusIBusImpl        *ibus,
Packit Service 1d8f1c
                                         BusInputContext    *context);
Packit Service 1d8f1c
static void     bus_ibus_impl_property_changed
Packit Service 1d8f1c
                                        (BusIBusImpl        *service,
Packit Service 1d8f1c
                                         const gchar        *property_name,
Packit Service 1d8f1c
                                         GVariant           *value);
Packit Service 1d8f1c
/* some callback functions */
Packit Service 1d8f1c
static void     _context_engine_changed_cb
Packit Service 1d8f1c
                                        (BusInputContext    *context,
Packit Service 1d8f1c
                                         BusIBusImpl        *ibus);
Packit Service 1d8f1c
Packit Service 1d8f1c
/* The interfaces available in this class, which consists of a list of
Packit Service 1d8f1c
 * methods this class implements and a list of signals this class may emit.
Packit Service 1d8f1c
 * Method calls to the interface that are not defined in this XML will
Packit Service 1d8f1c
 * be automatically rejected by the GDBus library (see src/ibusservice.c
Packit Service 1d8f1c
 * for details.)
Packit Service 1d8f1c
 * Implement org.freedesktop.DBus.Properties
Packit Service 1d8f1c
 * http://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-properties */
Packit Service 1d8f1c
static const gchar introspection_xml[] =
Packit Service 1d8f1c
    "<node>\n"
Packit Service 1d8f1c
    "  <interface name='org.freedesktop.IBus'>\n"
Packit Service 1d8f1c
    "    <property name='Address' type='s' access='read' />\n"
Packit Service 1d8f1c
    "    <property name='CurrentInputContext' type='o' access='read' />\n"
Packit Service 1d8f1c
    "    <property name='Engines' type='av' access='read' />\n"
Packit Service 1d8f1c
    "    <property name='GlobalEngine' type='v' access='read' />\n"
Packit Service 1d8f1c
    "    <property name='PreloadEngines' type='as' access='write'>\n"
Packit Service 1d8f1c
    "      
Packit Service 1d8f1c
    "          name='org.freedesktop.DBus.Property.EmitsChangedSignal'\n"
Packit Service 1d8f1c
    "          value='true' />\n"
Packit Service 1d8f1c
    "    </property>\n"
Packit Service 1d8f1c
    "    <property name='EmbedPreeditText' type='b' access='readwrite'>\n"
Packit Service 1d8f1c
    "      
Packit Service 1d8f1c
    "          name='org.freedesktop.DBus.Property.EmitsChangedSignal'\n"
Packit Service 1d8f1c
    "          value='true' />\n"
Packit Service 1d8f1c
    "    </property>\n"
Packit Service 1d8f1c
    "    <method name='CreateInputContext'>\n"
Packit Service 1d8f1c
    "      <arg direction='in'  type='s' name='client_name' />\n"
Packit Service 1d8f1c
    "      <arg direction='out' type='o' name='object_path' />\n"
Packit Service 1d8f1c
    "    </method>\n"
Packit Service 1d8f1c
    "    <method name='RegisterComponent'>\n"
Packit Service 1d8f1c
    "      <arg direction='in'  type='v' name='component' />\n"
Packit Service 1d8f1c
    "    </method>\n"
Packit Service 1d8f1c
    "    <method name='GetEnginesByNames'>\n"
Packit Service 1d8f1c
    "      <arg direction='in'  type='as' name='names' />\n"
Packit Service 1d8f1c
    "      <arg direction='out' type='av' name='engines' />\n"
Packit Service 1d8f1c
    "    </method>\n"
Packit Service 1d8f1c
    "    <method name='Exit'>\n"
Packit Service 1d8f1c
    "      <arg direction='in'  type='b' name='restart' />\n"
Packit Service 1d8f1c
    "    </method>\n"
Packit Service 1d8f1c
    "    <method name='Ping'>\n"
Packit Service 1d8f1c
    "      <arg direction='in'  type='v' name='data' />\n"
Packit Service 1d8f1c
    "      <arg direction='out' type='v' name='data' />\n"
Packit Service 1d8f1c
    "    </method>\n"
Packit Service 1d8f1c
    "    <method name='SetGlobalEngine'>\n"
Packit Service 1d8f1c
    "      <arg direction='in'  type='s' name='engine_name' />\n"
Packit Service 1d8f1c
    "    </method>\n"
Packit Service 1d8f1c
    "    <signal name='RegistryChanged'>\n"
Packit Service 1d8f1c
    "    </signal>\n"
Packit Service 1d8f1c
    "    <signal name='GlobalEngineChanged'>\n"
Packit Service 1d8f1c
    "      <arg type='s' name='engine_name' />\n"
Packit Service 1d8f1c
    "    </signal>\n"
Packit Service 1d8f1c
    "    <property name='ActiveEngines' type='av' access='read' />\n"
Packit Service 1d8f1c
    "    <method name='GetAddress'>\n"
Packit Service 1d8f1c
    "      <arg direction='out' type='s' name='address' />\n"
Packit Service 1d8f1c
    "      <annotation name='org.freedesktop.DBus.Deprecated' value='true'/>\n"
Packit Service 1d8f1c
    "    </method>\n"
Packit Service 1d8f1c
    "    <method name='CurrentInputContext'>\n"
Packit Service 1d8f1c
    "      <arg direction='out' type='o' name='object_path' />\n"
Packit Service 1d8f1c
    "      <annotation name='org.freedesktop.DBus.Deprecated' value='true'/>\n"
Packit Service 1d8f1c
    "    </method>\n"
Packit Service 1d8f1c
    "    <method name='ListEngines'>\n"
Packit Service 1d8f1c
    "      <arg direction='out' type='av' name='engines' />\n"
Packit Service 1d8f1c
    "      <annotation name='org.freedesktop.DBus.Deprecated' value='true'/>\n"
Packit Service 1d8f1c
    "    </method>\n"
Packit Service 1d8f1c
    "    <method name='ListActiveEngines'>\n"
Packit Service 1d8f1c
    "      <arg direction='out' type='av' name='engines' />\n"
Packit Service 1d8f1c
    "      <annotation name='org.freedesktop.DBus.Deprecated' value='true'/>\n"
Packit Service 1d8f1c
    "    </method>\n"
Packit Service 1d8f1c
    "    <method name='GetUseSysLayout'>\n"
Packit Service 1d8f1c
    "      <arg direction='out' type='b' name='enabled' />\n"
Packit Service 1d8f1c
    "      <annotation name='org.freedesktop.DBus.Deprecated' value='true'/>\n"
Packit Service 1d8f1c
    "    </method>\n"
Packit Service 1d8f1c
    "    <method name='GetUseGlobalEngine'>\n"
Packit Service 1d8f1c
    "      <arg direction='out' type='b' name='enabled' />\n"
Packit Service 1d8f1c
    "    </method>\n"
Packit Service 1d8f1c
    "    <method name='IsGlobalEngineEnabled'>\n"
Packit Service 1d8f1c
    "      <arg direction='out' type='b' name='enabled' />\n"
Packit Service 1d8f1c
    "      <annotation name='org.freedesktop.DBus.Deprecated' value='true'/>\n"
Packit Service 1d8f1c
    "    </method>\n"
Packit Service 1d8f1c
    "    <method name='GetGlobalEngine'>\n"
Packit Service 1d8f1c
    "      <arg direction='out' type='v' name='desc' />\n"
Packit Service 1d8f1c
    "      <annotation name='org.freedesktop.DBus.Deprecated' value='true'/>\n"
Packit Service 1d8f1c
    "    </method>\n"
Packit Service 1d8f1c
    "  </interface>\n"
Packit Service 1d8f1c
    "</node>\n";
Packit Service 1d8f1c
Packit Service 1d8f1c
Packit Service 1d8f1c
G_DEFINE_TYPE (BusIBusImpl, bus_ibus_impl, IBUS_TYPE_SERVICE)
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_ibus_impl_class_init (BusIBusImplClass *class)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    IBUS_OBJECT_CLASS (class)->destroy =
Packit Service 1d8f1c
            (IBusObjectDestroyFunc) bus_ibus_impl_destroy;
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* override the parent class's implementation. */
Packit Service 1d8f1c
    IBUS_SERVICE_CLASS (class)->service_method_call =
Packit Service 1d8f1c
            bus_ibus_impl_service_method_call;
Packit Service 1d8f1c
    IBUS_SERVICE_CLASS (class)->service_get_property =
Packit Service 1d8f1c
            bus_ibus_impl_service_get_property;
Packit Service 1d8f1c
    IBUS_SERVICE_CLASS (class)->service_set_property =
Packit Service 1d8f1c
            bus_ibus_impl_service_set_property;
Packit Service 1d8f1c
    /* register the xml so that bus_ibus_impl_service_method_call will be
Packit Service 1d8f1c
     * called on a method call defined in the xml (e.g. 'GetAddress'.) */
Packit Service 1d8f1c
    ibus_service_class_add_interfaces (IBUS_SERVICE_CLASS (class),
Packit Service 1d8f1c
                                       introspection_xml);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * _panel_destroy_cb:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * A callback function which is called when (1) the connection to the panel process is terminated,
Packit Service 1d8f1c
 * or (2) ibus_proxy_destroy (ibus->panel); is called. See src/ibusproxy.c for details.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_panel_destroy_cb (BusPanelProxy *panel,
Packit Service 1d8f1c
                   BusIBusImpl   *ibus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_assert (BUS_IS_PANEL_PROXY (panel));
Packit Service 1d8f1c
    g_assert (BUS_IS_IBUS_IMPL (ibus));
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (ibus->panel == panel)
Packit Service 1d8f1c
        ibus->panel = NULL;
Packit Service 1d8f1c
    else if (ibus->emoji_extension == panel)
Packit Service 1d8f1c
        ibus->emoji_extension = NULL;
Packit Service 1d8f1c
    else
Packit Service 1d8f1c
        g_return_if_reached ();
Packit Service 1d8f1c
    g_object_unref (panel);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_ibus_impl_set_panel_extension_mode (BusIBusImpl        *ibus,
Packit Service 1d8f1c
                                        IBusExtensionEvent *event)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    gboolean is_extension = FALSE;
Packit Service 1d8f1c
    g_return_if_fail (BUS_IS_IBUS_IMPL (ibus));
Packit Service 1d8f1c
    g_return_if_fail (IBUS_IS_EXTENSION_EVENT (event));
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (!ibus->emoji_extension) {
Packit Service 1d8f1c
        g_warning ("Panel extension is not running.");
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_return_if_fail (BUS_IS_PANEL_PROXY (ibus->emoji_extension));
Packit Service 1d8f1c
Packit Service 1d8f1c
    ibus->enable_emoji_extension = ibus_extension_event_is_enabled (event);
Packit Service 1d8f1c
    is_extension = ibus_extension_event_is_extension (event);
Packit Service 1d8f1c
    if (ibus->focused_context != NULL) {
Packit Service 1d8f1c
        if (ibus->enable_emoji_extension) {
Packit Service 1d8f1c
            bus_input_context_set_emoji_extension (ibus->focused_context,
Packit Service 1d8f1c
                                                   ibus->emoji_extension);
Packit Service 1d8f1c
        } else {
Packit Service 1d8f1c
            bus_input_context_set_emoji_extension (ibus->focused_context, NULL);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        if (is_extension)
Packit Service 1d8f1c
            bus_input_context_panel_extension_received (ibus->focused_context,
Packit Service 1d8f1c
                                                        event);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    if (is_extension)
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* Use the DBus method because it seems any DBus signal,
Packit Service 1d8f1c
     * g_dbus_message_new_signal(), cannot be reached to the server. */
Packit Service 1d8f1c
    bus_panel_proxy_panel_extension_received (ibus->emoji_extension,
Packit Service 1d8f1c
                                              event);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_ibus_impl_set_panel_extension_keys (BusIBusImpl *ibus,
Packit Service 1d8f1c
                                        GVariant    *parameters)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    BusEngineProxy *engine = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_return_if_fail (BUS_IS_IBUS_IMPL (ibus));
Packit Service 1d8f1c
    g_return_if_fail (parameters);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (!ibus->emoji_extension) {
Packit Service 1d8f1c
        g_warning ("Panel extension is not running.");
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (ibus->extension_register_keys)
Packit Service 1d8f1c
        g_variant_unref (ibus->extension_register_keys);
Packit Service 1d8f1c
    ibus->extension_register_keys = g_variant_ref_sink (parameters);
Packit Service 1d8f1c
    if (ibus->focused_context != NULL) {
Packit Service 1d8f1c
            engine = bus_input_context_get_engine (ibus->focused_context);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    if (!engine)
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    bus_engine_proxy_panel_extension_register_keys (engine, parameters);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_panel_panel_extension_cb (BusPanelProxy      *panel,
Packit Service 1d8f1c
                           IBusExtensionEvent *event,
Packit Service 1d8f1c
                           BusIBusImpl        *ibus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    bus_ibus_impl_set_panel_extension_mode (ibus, event);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_panel_panel_extension_register_keys_cb (BusInputContext *context,
Packit Service 1d8f1c
                                         GVariant        *parameters,
Packit Service 1d8f1c
                                         BusIBusImpl     *ibus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    bus_ibus_impl_set_panel_extension_keys (ibus, parameters);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_panel_update_preedit_text_received_cb (BusPanelProxy *panel,
Packit Service 1d8f1c
                                        IBusText      *text,
Packit Service 1d8f1c
                                        guint          cursor_pos,
Packit Service 1d8f1c
                                        gboolean       visible,
Packit Service 1d8f1c
                                        BusIBusImpl   *ibus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_return_if_fail (BUS_IS_IBUS_IMPL (ibus));
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (!ibus->focused_context)
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    bus_input_context_update_preedit_text (ibus->focused_context,
Packit Service 1d8f1c
        text, cursor_pos, visible, IBUS_ENGINE_PREEDIT_CLEAR, FALSE);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_panel_update_lookup_table_received_cb (BusPanelProxy   *panel,
Packit Service 1d8f1c
                                        IBusLookupTable *table,
Packit Service 1d8f1c
                                        gboolean         visible,
Packit Service 1d8f1c
                                        BusIBusImpl     *ibus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_return_if_fail (BUS_IS_IBUS_IMPL (ibus));
Packit Service 1d8f1c
    g_return_if_fail (IBUS_IS_LOOKUP_TABLE (table));
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (!ibus->focused_context)
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    /* Call bus_input_context_update_lookup_table() instead of
Packit Service 1d8f1c
     * bus_panel_proxy_update_lookup_table() for panel extensions because
Packit Service 1d8f1c
     * bus_input_context_page_up() can call bus_panel_proxy_page_up_received().
Packit Service 1d8f1c
     */
Packit Service 1d8f1c
    bus_input_context_update_lookup_table (
Packit Service 1d8f1c
            ibus->focused_context, table, visible, TRUE);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_panel_update_auxiliary_text_received_cb (BusPanelProxy *panel,
Packit Service 1d8f1c
                                          IBusText      *text,
Packit Service 1d8f1c
                                          gboolean       visible,
Packit Service 1d8f1c
                                          BusIBusImpl   *ibus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_return_if_fail (BUS_IS_IBUS_IMPL (ibus));
Packit Service 1d8f1c
    g_return_if_fail (IBUS_IS_TEXT (text));
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (!ibus->panel)
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    bus_panel_proxy_update_auxiliary_text (
Packit Service 1d8f1c
            ibus->panel, text, visible);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_registry_changed_cb (IBusRegistry *registry,
Packit Service 1d8f1c
                      BusIBusImpl  *ibus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    bus_ibus_impl_registry_changed (ibus);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/*
Packit Service 1d8f1c
 * _dbus_name_owner_changed_cb:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * A callback function to be called when the name-owner-changed signal is sent to the dbus object.
Packit Service 1d8f1c
 * This usually means a client (e.g. a panel/config/engine process or an application) is connected/disconnected to/from the bus.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_dbus_name_owner_changed_cb (BusDBusImpl   *dbus,
Packit Service 1d8f1c
                             BusConnection *orig_connection,
Packit Service 1d8f1c
                             const gchar   *name,
Packit Service 1d8f1c
                             const gchar   *old_name,
Packit Service 1d8f1c
                             const gchar   *new_name,
Packit Service 1d8f1c
                             BusIBusImpl   *ibus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    PanelType panel_type = PANEL_TYPE_NONE;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_assert (BUS_IS_DBUS_IMPL (dbus));
Packit Service 1d8f1c
    g_assert (name != NULL);
Packit Service 1d8f1c
    g_assert (old_name != NULL);
Packit Service 1d8f1c
    g_assert (new_name != NULL);
Packit Service 1d8f1c
    g_assert (BUS_IS_IBUS_IMPL (ibus));
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (!g_strcmp0 (name, IBUS_SERVICE_PANEL))
Packit Service 1d8f1c
        panel_type = PANEL_TYPE_PANEL;
Packit Service 1d8f1c
    else if (!g_strcmp0 (name, IBUS_SERVICE_PANEL_EXTENSION_EMOJI))
Packit Service 1d8f1c
        panel_type = PANEL_TYPE_EXTENSION_EMOJI;
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (panel_type != PANEL_TYPE_NONE) {
Packit Service 1d8f1c
        if (g_strcmp0 (new_name, "") != 0) {
Packit Service 1d8f1c
            /* a Panel process is started. */
Packit Service 1d8f1c
            BusConnection *connection;
Packit Service 1d8f1c
            BusInputContext *context = NULL;
Packit Service 1d8f1c
            BusPanelProxy   **panel = (panel_type == PANEL_TYPE_PANEL) ?
Packit Service 1d8f1c
                                      &ibus->panel : &ibus->emoji_extension;
Packit Service 1d8f1c
Packit Service 1d8f1c
            if (*panel != NULL) {
Packit Service 1d8f1c
                ibus_proxy_destroy ((IBusProxy *)(*panel));
Packit Service 1d8f1c
                /* panel should be NULL after destroy. See _panel_destroy_cb
Packit Service 1d8f1c
                 * for details. */
Packit Service 1d8f1c
                g_assert (*panel == NULL);
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
Packit Service 1d8f1c
            connection = bus_dbus_impl_get_connection_by_name (BUS_DEFAULT_DBUS, new_name);
Packit Service 1d8f1c
            g_return_if_fail (connection != NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
            *panel = bus_panel_proxy_new (connection, panel_type);
Packit Service 1d8f1c
            if (panel_type == PANEL_TYPE_EXTENSION_EMOJI)
Packit Service 1d8f1c
                ibus->enable_emoji_extension = FALSE;
Packit Service 1d8f1c
Packit Service 1d8f1c
            g_signal_connect (*panel,
Packit Service 1d8f1c
                              "destroy",
Packit Service 1d8f1c
                              G_CALLBACK (_panel_destroy_cb),
Packit Service 1d8f1c
                              ibus);
Packit Service 1d8f1c
            g_signal_connect (*panel,
Packit Service 1d8f1c
                              "panel-extension",
Packit Service 1d8f1c
                              G_CALLBACK (_panel_panel_extension_cb),
Packit Service 1d8f1c
                              ibus);
Packit Service 1d8f1c
            g_signal_connect (*panel,
Packit Service 1d8f1c
                              "panel-extension-register-keys",
Packit Service 1d8f1c
                              G_CALLBACK (
Packit Service 1d8f1c
                                      _panel_panel_extension_register_keys_cb),
Packit Service 1d8f1c
                              ibus);
Packit Service 1d8f1c
            g_signal_connect (
Packit Service 1d8f1c
                    *panel,
Packit Service 1d8f1c
                    "update-preedit-text-received",
Packit Service 1d8f1c
                    G_CALLBACK (_panel_update_preedit_text_received_cb),
Packit Service 1d8f1c
                    ibus);
Packit Service 1d8f1c
            g_signal_connect (
Packit Service 1d8f1c
                    *panel,
Packit Service 1d8f1c
                    "update-lookup-table-received",
Packit Service 1d8f1c
                    G_CALLBACK (_panel_update_lookup_table_received_cb),
Packit Service 1d8f1c
                    ibus);
Packit Service 1d8f1c
            g_signal_connect (
Packit Service 1d8f1c
                    *panel,
Packit Service 1d8f1c
                    "update-auxiliary-text-received",
Packit Service 1d8f1c
                    G_CALLBACK (_panel_update_auxiliary_text_received_cb),
Packit Service 1d8f1c
                    ibus);
Packit Service 1d8f1c
Packit Service 1d8f1c
            if (ibus->focused_context != NULL) {
Packit Service 1d8f1c
                context = ibus->focused_context;
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
            else if (ibus->use_global_engine) {
Packit Service 1d8f1c
                context = ibus->fake_context;
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
Packit Service 1d8f1c
            if (context != NULL) {
Packit Service 1d8f1c
                BusEngineProxy *engine;
Packit Service 1d8f1c
Packit Service 1d8f1c
                bus_panel_proxy_focus_in (*panel, context);
Packit Service 1d8f1c
Packit Service 1d8f1c
                engine = bus_input_context_get_engine (context);
Packit Service 1d8f1c
                if (engine != NULL) {
Packit Service 1d8f1c
                    IBusPropList *prop_list =
Packit Service 1d8f1c
                        bus_engine_proxy_get_properties (engine);
Packit Service 1d8f1c
                    bus_panel_proxy_register_properties (*panel, prop_list);
Packit Service 1d8f1c
                }
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    bus_ibus_impl_component_name_owner_changed (ibus, name, old_name, new_name);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * bus_ibus_impl_init:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * The constructor of BusIBusImpl. Initialize all member variables of a BusIBusImpl object.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_ibus_impl_init (BusIBusImpl *ibus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    ibus->factory_dict = g_hash_table_new_full (
Packit Service 1d8f1c
                            g_str_hash,
Packit Service 1d8f1c
                            g_str_equal,
Packit Service 1d8f1c
                            NULL,
Packit Service 1d8f1c
                            (GDestroyNotify) g_object_unref);
Packit Service 1d8f1c
Packit Service 1d8f1c
    ibus->fake_context = bus_input_context_new (NULL, "fake");
Packit Service 1d8f1c
    g_object_ref_sink (ibus->fake_context);
Packit Service 1d8f1c
    bus_dbus_impl_register_object (BUS_DEFAULT_DBUS,
Packit Service 1d8f1c
                                   (IBusService *) ibus->fake_context);
Packit Service 1d8f1c
    bus_input_context_set_capabilities (ibus->fake_context,
Packit Service 1d8f1c
                                        IBUS_CAP_PREEDIT_TEXT |
Packit Service 1d8f1c
                                        IBUS_CAP_FOCUS |
Packit Service 1d8f1c
                                        IBUS_CAP_SURROUNDING_TEXT);
Packit Service 1d8f1c
    g_signal_connect (ibus->fake_context,
Packit Service 1d8f1c
                      "engine-changed",
Packit Service 1d8f1c
                      G_CALLBACK (_context_engine_changed_cb),
Packit Service 1d8f1c
                      ibus);
Packit Service 1d8f1c
    bus_input_context_focus_in (ibus->fake_context);
Packit Service 1d8f1c
Packit Service 1d8f1c
    ibus->register_engine_list = NULL;
Packit Service 1d8f1c
    ibus->contexts = NULL;
Packit Service 1d8f1c
    ibus->focused_context = NULL;
Packit Service 1d8f1c
    ibus->panel = NULL;
Packit Service 1d8f1c
    ibus->emoji_extension = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    ibus->keymap = ibus_keymap_get ("us");
Packit Service 1d8f1c
Packit Service 1d8f1c
    ibus->use_sys_layout = TRUE;
Packit Service 1d8f1c
    ibus->embed_preedit_text = TRUE;
Packit Service 1d8f1c
    ibus->use_global_engine = TRUE;
Packit Service 1d8f1c
    ibus->global_engine_name = NULL;
Packit Service 1d8f1c
    ibus->global_previous_engine_name = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* focus the fake_context, if use_global_engine is enabled. */
Packit Service 1d8f1c
    if (ibus->use_global_engine)
Packit Service 1d8f1c
        bus_ibus_impl_set_focused_context (ibus, ibus->fake_context);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_signal_connect (BUS_DEFAULT_DBUS,
Packit Service 1d8f1c
                      "name-owner-changed",
Packit Service 1d8f1c
                      G_CALLBACK (_dbus_name_owner_changed_cb),
Packit Service 1d8f1c
                      ibus);
Packit Service 1d8f1c
Packit Service 1d8f1c
    bus_ibus_impl_registry_init (ibus);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * bus_ibus_impl_destroy:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * The destructor of BusIBusImpl.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_ibus_impl_destroy (BusIBusImpl *ibus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    pid_t pid;
Packit Service 1d8f1c
    glong timeout;
Packit Service 1d8f1c
    gint status;
Packit Service 1d8f1c
    gboolean flag;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_list_foreach (ibus->components, (GFunc) bus_component_stop, NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    pid = 0;
Packit Service 1d8f1c
    timeout = 0;
Packit Service 1d8f1c
    flag = FALSE;
Packit Service 1d8f1c
    while (1) {
Packit Service 1d8f1c
        while ((pid = waitpid (0, &status, WNOHANG)) > 0);
Packit Service 1d8f1c
Packit Service 1d8f1c
        if (pid == -1) { /* all children finished */
Packit Service 1d8f1c
            break;
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        if (pid == 0) { /* no child status changed */
Packit Service 1d8f1c
            g_usleep (1000);
Packit Service 1d8f1c
            timeout += 1000;
Packit Service 1d8f1c
            if (timeout >= G_USEC_PER_SEC) {
Packit Service 1d8f1c
                if (flag == FALSE) {
Packit Service 1d8f1c
                    gpointer old;
Packit Service 1d8f1c
                    old = signal (SIGTERM, SIG_IGN);
Packit Service 1d8f1c
                    /* send TERM signal to the whole process group (i.e. engines, panel, and config daemon.) */
Packit Service 1d8f1c
                    kill (-getpid (), SIGTERM);
Packit Service 1d8f1c
                    signal (SIGTERM, old);
Packit Service 1d8f1c
                    flag = TRUE;
Packit Service 1d8f1c
                }
Packit Service 1d8f1c
                else {
Packit Service 1d8f1c
                    g_warning ("Not every child processes exited!");
Packit Service 1d8f1c
                    break;
Packit Service 1d8f1c
                }
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_list_free_full (ibus->register_engine_list, g_object_unref);
Packit Service 1d8f1c
    ibus->register_engine_list = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (ibus->factory_dict != NULL) {
Packit Service 1d8f1c
        g_hash_table_destroy (ibus->factory_dict);
Packit Service 1d8f1c
        ibus->factory_dict = NULL;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (ibus->keymap != NULL) {
Packit Service 1d8f1c
        g_object_unref (ibus->keymap);
Packit Service 1d8f1c
        ibus->keymap = NULL;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_free (ibus->global_engine_name);
Packit Service 1d8f1c
    ibus->global_engine_name = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_free (ibus->global_previous_engine_name);
Packit Service 1d8f1c
    ibus->global_previous_engine_name = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (ibus->fake_context) {
Packit Service 1d8f1c
        g_object_unref (ibus->fake_context);
Packit Service 1d8f1c
        ibus->fake_context = NULL;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    bus_ibus_impl_registry_destroy (ibus);
Packit Service 1d8f1c
Packit Service 1d8f1c
    IBUS_OBJECT_CLASS (bus_ibus_impl_parent_class)->destroy (IBUS_OBJECT (ibus));
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * _ibus_get_address:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Implement the "Address" method call of the org.freedesktop.IBus interface.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static GVariant *
Packit Service 1d8f1c
_ibus_get_address (BusIBusImpl     *ibus,
Packit Service 1d8f1c
                   GDBusConnection *connection,
Packit Service 1d8f1c
                   GError         **error)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    if (error) {
Packit Service 1d8f1c
        *error = NULL;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    return g_variant_new_string (bus_server_get_address ());
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_ibus_get_address_depre (BusIBusImpl           *ibus,
Packit Service 1d8f1c
                         GVariant              *parameters,
Packit Service 1d8f1c
                         GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GDBusConnection *connection =
Packit Service 1d8f1c
            g_dbus_method_invocation_get_connection (invocation);
Packit Service 1d8f1c
    GError *error = NULL;
Packit Service 1d8f1c
    GVariant *variant = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_warning ("org.freedesktop.IBus.GetAddress() is deprecated!");
Packit Service 1d8f1c
Packit Service 1d8f1c
    variant = _ibus_get_address (ibus, connection, &error);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_dbus_method_invocation_return_value (invocation,
Packit Service 1d8f1c
            g_variant_new ("(s)", g_variant_get_string (variant, NULL)));
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_variant_unref (variant);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static IBusEngineDesc *
Packit Service 1d8f1c
_find_engine_desc_by_name (BusIBusImpl *ibus,
Packit Service 1d8f1c
                           const gchar *engine_name)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    IBusEngineDesc *desc = NULL;
Packit Service 1d8f1c
    GList *p;
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* find engine in registered engine list */
Packit Service 1d8f1c
    for (p = ibus->register_engine_list; p != NULL; p = p->next) {
Packit Service 1d8f1c
        desc = (IBusEngineDesc *) p->data;
Packit Service 1d8f1c
        if (g_strcmp0 (ibus_engine_desc_get_name (desc), engine_name) == 0)
Packit Service 1d8f1c
            return desc;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    return NULL;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * _context_request_engine_cb:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * A callback function to be called when the "request-engine" signal is sent to the context.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static IBusEngineDesc *
Packit Service 1d8f1c
_context_request_engine_cb (BusInputContext *context,
Packit Service 1d8f1c
                            const gchar     *engine_name,
Packit Service 1d8f1c
                            BusIBusImpl     *ibus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    if (engine_name == NULL || engine_name[0] == '\0')
Packit Service 1d8f1c
        engine_name = DEFAULT_ENGINE;
Packit Service 1d8f1c
Packit Service 1d8f1c
    return bus_ibus_impl_get_engine_desc (ibus, engine_name);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * bus_ibus_impl_get_engine_desc:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Get the IBusEngineDesc by engine_name. If the engine_name is NULL, return
Packit Service 1d8f1c
 * a default engine desc.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static IBusEngineDesc *
Packit Service 1d8f1c
bus_ibus_impl_get_engine_desc (BusIBusImpl *ibus,
Packit Service 1d8f1c
                               const gchar *engine_name)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_return_val_if_fail (engine_name != NULL, NULL);
Packit Service 1d8f1c
    g_return_val_if_fail (engine_name[0] != '\0', NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    IBusEngineDesc *desc = _find_engine_desc_by_name (ibus, engine_name);
Packit Service 1d8f1c
    if (desc == NULL) {
Packit Service 1d8f1c
        desc = (IBusEngineDesc *) g_hash_table_lookup (ibus->engine_table,
Packit Service 1d8f1c
                                                       engine_name);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    return desc;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_ibus_impl_set_context_engine_from_desc (BusIBusImpl     *ibus,
Packit Service 1d8f1c
                                            BusInputContext *context,
Packit Service 1d8f1c
                                            IBusEngineDesc  *desc)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    bus_input_context_set_engine_by_desc (context,
Packit Service 1d8f1c
                                          desc,
Packit Service 1d8f1c
                                          g_gdbus_timeout, /* timeout in msec. */
Packit Service 1d8f1c
                                          NULL, /* we do not cancel the call. */
Packit Service 1d8f1c
                                          NULL, /* use the default callback function. */
Packit Service 1d8f1c
                                          NULL);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_context_panel_extension_cb (BusInputContext    *context,
Packit Service 1d8f1c
                             IBusExtensionEvent *event,
Packit Service 1d8f1c
                             BusIBusImpl        *ibus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    bus_ibus_impl_set_panel_extension_mode (ibus, event);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
const static struct {
Packit Service 1d8f1c
    const gchar *name;
Packit Service 1d8f1c
    GCallback    callback;
Packit Service 1d8f1c
} context_signals [] = {
Packit Service 1d8f1c
    { "panel-extension",             G_CALLBACK (_context_panel_extension_cb) }
Packit Service 1d8f1c
};
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * bus_ibus_impl_set_focused_context:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Set the current focused context.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_ibus_impl_set_focused_context (BusIBusImpl     *ibus,
Packit Service 1d8f1c
                                   BusInputContext *context)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    gint i;
Packit Service 1d8f1c
    BusEngineProxy *engine = NULL;
Packit Service 1d8f1c
    guint purpose = 0;
Packit Service 1d8f1c
    guint hints = 0;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_assert (BUS_IS_IBUS_IMPL (ibus));
Packit Service 1d8f1c
    g_assert (context == NULL || BUS_IS_INPUT_CONTEXT (context));
Packit Service 1d8f1c
    g_assert (context == NULL || bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS);
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* Do noting if it is focused context. */
Packit Service 1d8f1c
    if (ibus->focused_context == context) {
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (ibus->focused_context) {
Packit Service 1d8f1c
        if (ibus->use_global_engine) {
Packit Service 1d8f1c
            /* dettach engine from the focused context */
Packit Service 1d8f1c
            engine = bus_input_context_get_engine (ibus->focused_context);
Packit Service 1d8f1c
            if (engine) {
Packit Service 1d8f1c
                g_object_ref (engine);
Packit Service 1d8f1c
                bus_input_context_set_engine (ibus->focused_context, NULL);
Packit Service 1d8f1c
                bus_input_context_set_emoji_extension (ibus->focused_context,
Packit Service 1d8f1c
                                                       NULL);
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
Packit Service 1d8f1c
        if (ibus->panel != NULL)
Packit Service 1d8f1c
            bus_panel_proxy_focus_out (ibus->panel, ibus->focused_context);
Packit Service 1d8f1c
        if (ibus->emoji_extension != NULL) {
Packit Service 1d8f1c
            bus_panel_proxy_focus_out (ibus->emoji_extension,
Packit Service 1d8f1c
                                       ibus->focused_context);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        bus_input_context_set_emoji_extension (ibus->focused_context, NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
        bus_input_context_get_content_type (ibus->focused_context,
Packit Service 1d8f1c
                                            &purpose, &hints);
Packit Service 1d8f1c
        for (i = 0; i < G_N_ELEMENTS(context_signals); i++) {
Packit Service 1d8f1c
            g_signal_handlers_disconnect_by_func (ibus->focused_context,
Packit Service 1d8f1c
                    context_signals[i].callback, ibus);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        g_object_unref (ibus->focused_context);
Packit Service 1d8f1c
        ibus->focused_context = NULL;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (context == NULL && ibus->use_global_engine) {
Packit Service 1d8f1c
        context = ibus->fake_context;
Packit Service 1d8f1c
        if (context)
Packit Service 1d8f1c
            bus_input_context_set_content_type (context, purpose, hints);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (context) {
Packit Service 1d8f1c
        ibus->focused_context = (BusInputContext *) g_object_ref (context);
Packit Service 1d8f1c
        /* attach engine to the focused context */
Packit Service 1d8f1c
        if (engine != NULL) {
Packit Service 1d8f1c
            bus_input_context_set_engine (context, engine);
Packit Service 1d8f1c
            bus_input_context_enable (context);
Packit Service 1d8f1c
            if (ibus->enable_emoji_extension) {
Packit Service 1d8f1c
                bus_input_context_set_emoji_extension (context,
Packit Service 1d8f1c
                                                       ibus->emoji_extension);
Packit Service 1d8f1c
            } else {
Packit Service 1d8f1c
                bus_input_context_set_emoji_extension (context, NULL);
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        for (i = 0; i < G_N_ELEMENTS(context_signals); i++) {
Packit Service 1d8f1c
            g_signal_connect (ibus->focused_context,
Packit Service 1d8f1c
                              context_signals[i].name,
Packit Service 1d8f1c
                              context_signals[i].callback,
Packit Service 1d8f1c
                              ibus);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
Packit Service 1d8f1c
        if (ibus->panel != NULL)
Packit Service 1d8f1c
            bus_panel_proxy_focus_in (ibus->panel, context);
Packit Service 1d8f1c
        if (ibus->emoji_extension != NULL)
Packit Service 1d8f1c
            bus_panel_proxy_focus_in (ibus->emoji_extension, context);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (engine != NULL)
Packit Service 1d8f1c
        g_object_unref (engine);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_ibus_impl_set_global_engine (BusIBusImpl    *ibus,
Packit Service 1d8f1c
                                 BusEngineProxy *engine)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    if (!ibus->use_global_engine)
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (ibus->focused_context) {
Packit Service 1d8f1c
        bus_input_context_set_engine (ibus->focused_context, engine);
Packit Service 1d8f1c
        if (ibus->enable_emoji_extension) {
Packit Service 1d8f1c
            bus_input_context_set_emoji_extension (ibus->focused_context,
Packit Service 1d8f1c
                                                   ibus->emoji_extension);
Packit Service 1d8f1c
        } else {
Packit Service 1d8f1c
            bus_input_context_set_emoji_extension (ibus->focused_context, NULL);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
    } else if (ibus->fake_context) {
Packit Service 1d8f1c
        bus_input_context_set_engine (ibus->fake_context, engine);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_ibus_impl_set_global_engine_by_name (BusIBusImpl *ibus,
Packit Service 1d8f1c
                                         const gchar *name)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    if (!ibus->use_global_engine)
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
Packit Service 1d8f1c
    BusInputContext *context =
Packit Service 1d8f1c
            ibus->focused_context != NULL ? ibus->focused_context : ibus->fake_context;
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (context == NULL) {
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (g_strcmp0 (name, ibus->global_engine_name) == 0) {
Packit Service 1d8f1c
        /* If the user requested the same global engine, then we just enable the
Packit Service 1d8f1c
         * original one. */
Packit Service 1d8f1c
        bus_input_context_enable (context);
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* If there is a focused input context, then we just change the engine of
Packit Service 1d8f1c
     * the focused context, which will then change the global engine
Packit Service 1d8f1c
     * automatically. Otherwise, we need to change the global engine directly.
Packit Service 1d8f1c
     */
Packit Service 1d8f1c
    IBusEngineDesc *desc = NULL;
Packit Service 1d8f1c
    desc = bus_ibus_impl_get_engine_desc (ibus, name);
Packit Service 1d8f1c
    if (desc != NULL) {
Packit Service 1d8f1c
        bus_ibus_impl_set_context_engine_from_desc (ibus,
Packit Service 1d8f1c
                                                    context,
Packit Service 1d8f1c
                                                    desc);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/* When preload_engines and register_engiens are changed, this function
Packit Service 1d8f1c
 * will check the global engine. If necessay, it will change the global engine.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_ibus_impl_check_global_engine (BusIBusImpl *ibus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GList *engine_list = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* do nothing */
Packit Service 1d8f1c
    if (!ibus->use_global_engine)
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* The current global engine is not removed, so do nothing. */
Packit Service 1d8f1c
    if (ibus->global_engine_name != NULL &&
Packit Service 1d8f1c
        _find_engine_desc_by_name (ibus, ibus->global_engine_name)) {
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* If the previous engine is available, then just switch to it. */
Packit Service 1d8f1c
    if (ibus->global_previous_engine_name != NULL &&
Packit Service 1d8f1c
        _find_engine_desc_by_name (ibus, ibus->global_previous_engine_name)) {
Packit Service 1d8f1c
        bus_ibus_impl_set_global_engine_by_name (
Packit Service 1d8f1c
            ibus, ibus->global_previous_engine_name);
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* Just switch to the fist engine in the list. */
Packit Service 1d8f1c
    engine_list = ibus->register_engine_list;
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (engine_list) {
Packit Service 1d8f1c
        IBusEngineDesc *engine_desc = (IBusEngineDesc *)engine_list->data;
Packit Service 1d8f1c
        bus_ibus_impl_set_global_engine_by_name (ibus,
Packit Service 1d8f1c
                        ibus_engine_desc_get_name (engine_desc));
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* No engine available? Just disable global engine. */
Packit Service 1d8f1c
    bus_ibus_impl_set_global_engine (ibus, NULL);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * _context_engine_changed_cb:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * A callback function to be called when the "engine-changed" signal is sent to the context.
Packit Service 1d8f1c
 * Update global engine as well if necessary.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_context_engine_changed_cb (BusInputContext *context,
Packit Service 1d8f1c
                            BusIBusImpl     *ibus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    if (!ibus->use_global_engine)
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
Packit Service 1d8f1c
    if ((context == ibus->focused_context) ||
Packit Service 1d8f1c
        (ibus->focused_context == NULL && context == ibus->fake_context)) {
Packit Service 1d8f1c
        BusEngineProxy *engine = bus_input_context_get_engine (context);
Packit Service 1d8f1c
        if (engine != NULL) {
Packit Service 1d8f1c
            /* only set global engine if engine is not NULL */
Packit Service 1d8f1c
            const gchar *name = ibus_engine_desc_get_name (bus_engine_proxy_get_desc (engine));
Packit Service 1d8f1c
            if (g_strcmp0 (name, ibus->global_engine_name) == 0)
Packit Service 1d8f1c
                return;
Packit Service 1d8f1c
            g_free (ibus->global_previous_engine_name);
Packit Service 1d8f1c
            ibus->global_previous_engine_name = ibus->global_engine_name;
Packit Service 1d8f1c
            ibus->global_engine_name = g_strdup (name);
Packit Service 1d8f1c
            bus_ibus_impl_global_engine_changed (ibus);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * _context_focus_in_cb:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * A callback function to be called when the "focus-in" signal is sent to the context.
Packit Service 1d8f1c
 * If necessary, enables the global engine on the context and update ibus->focused_context.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_context_focus_in_cb (BusInputContext *context,
Packit Service 1d8f1c
                      BusIBusImpl     *ibus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_assert (BUS_IS_IBUS_IMPL (ibus));
Packit Service 1d8f1c
    g_assert (BUS_IS_INPUT_CONTEXT (context));
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* Do nothing if context does not support focus.
Packit Service 1d8f1c
     * The global engine shoule be detached from the focused context. */
Packit Service 1d8f1c
    if ((bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS) == 0) {
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    bus_ibus_impl_set_focused_context (ibus, context);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * _context_focus_out_cb:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * A callback function to be called when the "focus-out" signal is sent to the context.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_context_focus_out_cb (BusInputContext    *context,
Packit Service 1d8f1c
                       BusIBusImpl        *ibus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_assert (BUS_IS_IBUS_IMPL (ibus));
Packit Service 1d8f1c
    g_assert (BUS_IS_INPUT_CONTEXT (context));
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* Do noting if context does not support focus.
Packit Service 1d8f1c
     * Actually, the context should emit focus signals, if it does not support focus */
Packit Service 1d8f1c
    if ((bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS) == 0) {
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* Do noting if it is not focused context. */
Packit Service 1d8f1c
    if (ibus->focused_context != context) {
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    bus_ibus_impl_set_focused_context (ibus, NULL);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * _context_destroy_cb:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * A callback function to be called when the "destroy" signal is sent to the
Packit Service 1d8f1c
 * context.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_context_destroy_cb (BusInputContext    *context,
Packit Service 1d8f1c
                     BusIBusImpl        *ibus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_assert (BUS_IS_IBUS_IMPL (ibus));
Packit Service 1d8f1c
    g_assert (BUS_IS_INPUT_CONTEXT (context));
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (context == ibus->focused_context)
Packit Service 1d8f1c
        bus_ibus_impl_set_focused_context (ibus, NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (ibus->panel &&
Packit Service 1d8f1c
        bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS) {
Packit Service 1d8f1c
        bus_panel_proxy_destroy_context (ibus->panel, context);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    if (ibus->emoji_extension &&
Packit Service 1d8f1c
        bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS) {
Packit Service 1d8f1c
        bus_panel_proxy_destroy_context (ibus->emoji_extension, context);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    ibus->contexts = g_list_remove (ibus->contexts, context);
Packit Service 1d8f1c
    g_object_unref (context);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * bus_ibus_impl_create_input_context:
Packit Service 1d8f1c
 * @client: A name of a client. e.g. "gtk-im"
Packit Service 1d8f1c
 * @returns: A BusInputContext object.
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Create a new BusInputContext object for the client.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static BusInputContext *
Packit Service 1d8f1c
bus_ibus_impl_create_input_context (BusIBusImpl   *ibus,
Packit Service 1d8f1c
                                    BusConnection *connection,
Packit Service 1d8f1c
                                    const gchar   *client)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    BusInputContext *context = bus_input_context_new (connection, client);
Packit Service 1d8f1c
    g_object_ref_sink (context);
Packit Service 1d8f1c
    ibus->contexts = g_list_append (ibus->contexts, context);
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* Installs glib signal handlers so that the ibus object could be notified when e.g. an IBus.InputContext D-Bus method is called. */
Packit Service 1d8f1c
    static const struct {
Packit Service 1d8f1c
        gchar *name;
Packit Service 1d8f1c
        GCallback callback;
Packit Service 1d8f1c
    } signals [] = {
Packit Service 1d8f1c
        { "request-engine", G_CALLBACK (_context_request_engine_cb) },
Packit Service 1d8f1c
        { "engine-changed", G_CALLBACK (_context_engine_changed_cb) },
Packit Service 1d8f1c
        { "focus-in",       G_CALLBACK (_context_focus_in_cb) },
Packit Service 1d8f1c
        { "focus-out",      G_CALLBACK (_context_focus_out_cb) },
Packit Service 1d8f1c
        { "destroy",        G_CALLBACK (_context_destroy_cb) },
Packit Service 1d8f1c
    };
Packit Service 1d8f1c
Packit Service 1d8f1c
    gint i;
Packit Service 1d8f1c
    for (i = 0; i < G_N_ELEMENTS (signals); i++) {
Packit Service 1d8f1c
        g_signal_connect (context,
Packit Service 1d8f1c
                          signals[i].name,
Packit Service 1d8f1c
                          signals[i].callback,
Packit Service 1d8f1c
                          ibus);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    bus_input_context_enable (context);
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* register the context object so that the object could handle IBus.InputContext method calls. */
Packit Service 1d8f1c
    bus_dbus_impl_register_object (BUS_DEFAULT_DBUS,
Packit Service 1d8f1c
                                   (IBusService *) context);
Packit Service 1d8f1c
    g_object_ref (context);
Packit Service 1d8f1c
    return context;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * _ibus_create_input_context:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Implement the "CreateInputContext" method call of the org.freedesktop.IBus interface.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_ibus_create_input_context (BusIBusImpl           *ibus,
Packit Service 1d8f1c
                            GVariant              *parameters,
Packit Service 1d8f1c
                            GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    const gchar *client_name = NULL;  // e.g. "gtk-im"
Packit Service 1d8f1c
    g_variant_get (parameters, "(&s)", &client_name);
Packit Service 1d8f1c
Packit Service 1d8f1c
    BusConnection *connection =
Packit Service 1d8f1c
            bus_connection_lookup (g_dbus_method_invocation_get_connection (invocation));
Packit Service 1d8f1c
    BusInputContext *context =
Packit Service 1d8f1c
            bus_ibus_impl_create_input_context (ibus,
Packit Service 1d8f1c
                                                connection,
Packit Service 1d8f1c
                                                client_name);
Packit Service 1d8f1c
    if (context) {
Packit Service 1d8f1c
        const gchar *path = ibus_service_get_object_path ((IBusService *) context);
Packit Service 1d8f1c
        /* the format-string 'o' is for a D-Bus object path. */
Packit Service 1d8f1c
        g_dbus_method_invocation_return_value (invocation, g_variant_new ("(o)", path));
Packit Service 1d8f1c
        g_object_unref (context);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    else {
Packit Service 1d8f1c
        g_dbus_method_invocation_return_error (invocation,
Packit Service 1d8f1c
                                               G_DBUS_ERROR,
Packit Service 1d8f1c
                                               G_DBUS_ERROR_FAILED,
Packit Service 1d8f1c
                                               "Create input context failed!");
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * _ibus_get_current_input_context:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Implement the "CurrentInputContext" method call of the
Packit Service 1d8f1c
 * org.freedesktop.IBus interface.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static GVariant *
Packit Service 1d8f1c
_ibus_get_current_input_context (BusIBusImpl     *ibus,
Packit Service 1d8f1c
                                 GDBusConnection *connection,
Packit Service 1d8f1c
                                 GError         **error)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    if (error) {
Packit Service 1d8f1c
        *error = NULL;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (!ibus->focused_context)
Packit Service 1d8f1c
    {
Packit Service 1d8f1c
        g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
Packit Service 1d8f1c
                     "No focused input context");
Packit Service 1d8f1c
        return NULL;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    else {
Packit Service 1d8f1c
        const gchar *path = ibus_service_get_object_path (
Packit Service 1d8f1c
                (IBusService *) ibus->focused_context);
Packit Service 1d8f1c
        /* the format-string 'o' is for a D-Bus object path. */
Packit Service 1d8f1c
        return g_variant_new_object_path (path);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_ibus_current_input_context_depre (BusIBusImpl           *ibus,
Packit Service 1d8f1c
                                   GVariant              *parameters,
Packit Service 1d8f1c
                                   GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GDBusConnection *connection =
Packit Service 1d8f1c
            g_dbus_method_invocation_get_connection (invocation);
Packit Service 1d8f1c
    GVariant *variant = NULL;
Packit Service 1d8f1c
    GError *error = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_warning ("org.freedesktop.IBus.CurrentInputContext() is deprecated!");
Packit Service 1d8f1c
Packit Service 1d8f1c
    variant = _ibus_get_current_input_context (ibus, connection, &error);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (variant == NULL) {
Packit Service 1d8f1c
        g_dbus_method_invocation_return_error (
Packit Service 1d8f1c
                invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
Packit Service 1d8f1c
                "%s", error->message);
Packit Service 1d8f1c
        g_error_free (error);
Packit Service 1d8f1c
    } else {
Packit Service 1d8f1c
        const gchar *path = g_variant_get_string (variant, NULL);
Packit Service 1d8f1c
        g_dbus_method_invocation_return_value (invocation,
Packit Service 1d8f1c
                                               g_variant_new ("(o)", path));
Packit Service 1d8f1c
        g_variant_unref (variant);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_component_destroy_cb (BusComponent *component,
Packit Service 1d8f1c
                       BusIBusImpl  *ibus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_assert (BUS_IS_IBUS_IMPL (ibus));
Packit Service 1d8f1c
    g_assert (BUS_IS_COMPONENT (component));
Packit Service 1d8f1c
Packit Service 1d8f1c
    ibus->registered_components = g_list_remove (ibus->registered_components, component);
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* remove engines from engine_list */
Packit Service 1d8f1c
    GList *engines = bus_component_get_engines (component);
Packit Service 1d8f1c
    GList *p;
Packit Service 1d8f1c
    for (p = engines; p != NULL; p = p->next) {
Packit Service 1d8f1c
        if (g_list_find (ibus->register_engine_list, p->data)) {
Packit Service 1d8f1c
            ibus->register_engine_list = g_list_remove (ibus->register_engine_list, p->data);
Packit Service 1d8f1c
            g_object_unref (p->data);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    g_list_free (engines);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_object_unref (component);
Packit Service 1d8f1c
Packit Service 1d8f1c
    bus_ibus_impl_check_global_engine (ibus);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * _ibus_register_component:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Implement the "RegisterComponent" method call of the
Packit Service 1d8f1c
 * org.freedesktop.IBus interface.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_ibus_register_component (BusIBusImpl           *ibus,
Packit Service 1d8f1c
                          GVariant              *parameters,
Packit Service 1d8f1c
                          GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GVariant *variant = g_variant_get_child_value (parameters, 0);
Packit Service 1d8f1c
    IBusComponent *component =
Packit Service 1d8f1c
            (IBusComponent *) ibus_serializable_deserialize (variant);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (!IBUS_IS_COMPONENT (component)) {
Packit Service 1d8f1c
        if (component)
Packit Service 1d8f1c
            g_object_unref (component);
Packit Service 1d8f1c
        g_dbus_method_invocation_return_error (
Packit Service 1d8f1c
                invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
Packit Service 1d8f1c
                "The first argument should be an IBusComponent.");
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    BusConnection *connection = bus_connection_lookup (
Packit Service 1d8f1c
            g_dbus_method_invocation_get_connection (invocation));
Packit Service 1d8f1c
    BusFactoryProxy *factory = bus_factory_proxy_new (connection);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (factory == NULL) {
Packit Service 1d8f1c
        g_object_unref (component);
Packit Service 1d8f1c
        g_dbus_method_invocation_return_error (
Packit Service 1d8f1c
                invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
Packit Service 1d8f1c
                "Create factory failed.");
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_object_ref_sink (component);
Packit Service 1d8f1c
Packit Service 1d8f1c
    BusComponent *buscomp = bus_component_new (component, factory);
Packit Service 1d8f1c
    bus_component_set_destroy_with_factory (buscomp, TRUE);
Packit Service 1d8f1c
    g_object_unref (component);
Packit Service 1d8f1c
    g_object_unref (factory);
Packit Service 1d8f1c
Packit Service 1d8f1c
    ibus->registered_components = g_list_append (ibus->registered_components,
Packit Service 1d8f1c
                                                g_object_ref_sink (buscomp));
Packit Service 1d8f1c
    GList *engines = bus_component_get_engines (buscomp);
Packit Service 1d8f1c
    g_list_foreach (engines, (GFunc) g_object_ref, NULL);
Packit Service 1d8f1c
    ibus->register_engine_list = g_list_concat (ibus->register_engine_list,
Packit Service 1d8f1c
                                               engines);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_signal_connect (buscomp,
Packit Service 1d8f1c
                      "destroy",
Packit Service 1d8f1c
                      G_CALLBACK (_component_destroy_cb),
Packit Service 1d8f1c
                      ibus);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_dbus_method_invocation_return_value (invocation, NULL);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * _ibus_get_engines:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Implement the "Engines" method call of the org.freedesktop.IBus interface.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static GVariant *
Packit Service 1d8f1c
_ibus_get_engines (BusIBusImpl     *ibus,
Packit Service 1d8f1c
                   GDBusConnection *connection,
Packit Service 1d8f1c
                   GError         **error)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GVariantBuilder builder;
Packit Service 1d8f1c
    GList *engines = NULL;
Packit Service 1d8f1c
    GList *p;
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (error) {
Packit Service 1d8f1c
        *error = NULL;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
Packit Service 1d8f1c
Packit Service 1d8f1c
    engines = g_hash_table_get_values (ibus->engine_table);
Packit Service 1d8f1c
Packit Service 1d8f1c
    for (p = engines; p != NULL; p = p->next) {
Packit Service 1d8f1c
        g_variant_builder_add (
Packit Service 1d8f1c
                &builder, "v",
Packit Service 1d8f1c
                ibus_serializable_serialize ((IBusSerializable *) p->data));
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_list_free (engines);
Packit Service 1d8f1c
Packit Service 1d8f1c
    return g_variant_builder_end (&builder);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_ibus_list_engines_depre (BusIBusImpl           *ibus,
Packit Service 1d8f1c
                          GVariant              *parameters,
Packit Service 1d8f1c
                          GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GDBusConnection *connection =
Packit Service 1d8f1c
            g_dbus_method_invocation_get_connection (invocation);
Packit Service 1d8f1c
    GError *error = NULL;
Packit Service 1d8f1c
    GVariant *variant = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_warning ("org.freedesktop.IBus.ListEngines() is deprecated!");
Packit Service 1d8f1c
Packit Service 1d8f1c
    variant = _ibus_get_engines (ibus, connection, &error);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_dbus_method_invocation_return_value (invocation,
Packit Service 1d8f1c
                                           g_variant_new ("(@av)", variant));
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * _ibus_get_engines_by_names:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Implement the "GetEnginesByNames" method call of the org.freedesktop.IBus interface.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_ibus_get_engines_by_names (BusIBusImpl           *ibus,
Packit Service 1d8f1c
                            GVariant              *parameters,
Packit Service 1d8f1c
                            GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    const gchar **names = NULL;
Packit Service 1d8f1c
    g_variant_get (parameters, "(^a&s)", &names);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_assert (names != NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    gint i = 0;
Packit Service 1d8f1c
    GVariantBuilder builder;
Packit Service 1d8f1c
    g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
Packit Service 1d8f1c
    while (names[i] != NULL) {
Packit Service 1d8f1c
        IBusEngineDesc *desc = (IBusEngineDesc *) g_hash_table_lookup (
Packit Service 1d8f1c
                ibus->engine_table, names[i++]);
Packit Service 1d8f1c
        if (desc == NULL)
Packit Service 1d8f1c
            continue;
Packit Service 1d8f1c
        g_variant_builder_add (
Packit Service 1d8f1c
                &builder,
Packit Service 1d8f1c
                "v",
Packit Service 1d8f1c
                ibus_serializable_serialize ((IBusSerializable *)desc));
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    g_dbus_method_invocation_return_value (invocation, g_variant_new ("(av)", &builder));
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * _ibus_get_active_engines:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Implement the "ActiveEngines" method call of the
Packit Service 1d8f1c
 * org.freedesktop.IBus interface.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static GVariant *
Packit Service 1d8f1c
_ibus_get_active_engines (BusIBusImpl     *ibus,
Packit Service 1d8f1c
                          GDBusConnection *connection,
Packit Service 1d8f1c
                          GError         **error)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GVariantBuilder builder;
Packit Service 1d8f1c
    GList *p;
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (error) {
Packit Service 1d8f1c
        *error = NULL;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_variant_builder_init (&builder, G_VARIANT_TYPE ("av"));
Packit Service 1d8f1c
Packit Service 1d8f1c
    for (p = ibus->register_engine_list; p != NULL; p = p->next) {
Packit Service 1d8f1c
        g_variant_builder_add (
Packit Service 1d8f1c
                &builder, "v",
Packit Service 1d8f1c
                ibus_serializable_serialize ((IBusSerializable *) p->data));
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    return g_variant_builder_end (&builder);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_ibus_list_active_engines_depre (BusIBusImpl           *ibus,
Packit Service 1d8f1c
                                 GVariant              *parameters,
Packit Service 1d8f1c
                                 GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GDBusConnection *connection =
Packit Service 1d8f1c
            g_dbus_method_invocation_get_connection (invocation);
Packit Service 1d8f1c
    GError *error = NULL;
Packit Service 1d8f1c
    GVariant *variant = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_warning ("org.freedesktop.IBus.ListActiveEngines() is deprecated!");
Packit Service 1d8f1c
Packit Service 1d8f1c
    variant = _ibus_get_active_engines (ibus, connection, &error);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_dbus_method_invocation_return_value (invocation,
Packit Service 1d8f1c
                                           g_variant_new ("(@av)", variant));
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * _ibus_exit:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Implement the "Exit" method call of the org.freedesktop.IBus interface.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_ibus_exit (BusIBusImpl           *ibus,
Packit Service 1d8f1c
            GVariant              *parameters,
Packit Service 1d8f1c
            GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    gboolean restart = FALSE;
Packit Service 1d8f1c
    g_variant_get (parameters, "(b)", &restart);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_dbus_method_invocation_return_value (invocation, NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* Make sure the reply has been sent out before exit */
Packit Service 1d8f1c
    g_dbus_connection_flush_sync (
Packit Service 1d8f1c
            g_dbus_method_invocation_get_connection (invocation),
Packit Service 1d8f1c
            NULL,
Packit Service 1d8f1c
            NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    bus_server_quit (restart);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * _ibus_ping:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Implement the "Ping" method call of the org.freedesktop.IBus interface.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_ibus_ping (BusIBusImpl           *ibus,
Packit Service 1d8f1c
            GVariant              *parameters,
Packit Service 1d8f1c
            GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_dbus_method_invocation_return_value (invocation, parameters);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * _ibus_get_use_sys_layout:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Implement the "UseSysLayout" method call of the
Packit Service 1d8f1c
 * org.freedesktop.IBus interface.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static GVariant *
Packit Service 1d8f1c
_ibus_get_use_sys_layout (BusIBusImpl     *ibus,
Packit Service 1d8f1c
                          GDBusConnection *connection,
Packit Service 1d8f1c
                          GError         **error)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    if (error) {
Packit Service 1d8f1c
        *error = NULL;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    return g_variant_new_boolean (ibus->use_sys_layout);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_ibus_get_use_sys_layout_depre (BusIBusImpl           *ibus,
Packit Service 1d8f1c
                                GVariant              *parameters,
Packit Service 1d8f1c
                                GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GDBusConnection *connection =
Packit Service 1d8f1c
            g_dbus_method_invocation_get_connection (invocation);
Packit Service 1d8f1c
    GError *error = NULL;
Packit Service 1d8f1c
    GVariant *variant = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_warning ("org.freedesktop.IBus.GetUseSysLayout() is deprecated!");
Packit Service 1d8f1c
Packit Service 1d8f1c
    variant = _ibus_get_use_sys_layout (ibus, connection, &error);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_dbus_method_invocation_return_value (invocation,
Packit Service 1d8f1c
            g_variant_new ("(b)", g_variant_get_boolean (variant)));
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_variant_unref (variant);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * _ibus_get_use_global_engine:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Implement the "UseGlobalEngine" method call of the
Packit Service 1d8f1c
 * org.freedesktop.IBus interface.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static GVariant *
Packit Service 1d8f1c
_ibus_get_use_global_engine (BusIBusImpl     *ibus,
Packit Service 1d8f1c
                             GDBusConnection *connection,
Packit Service 1d8f1c
                             GError         **error)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    if (error) {
Packit Service 1d8f1c
        *error = NULL;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    return g_variant_new_boolean (ibus->use_global_engine);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_ibus_get_use_global_engine_depre (BusIBusImpl           *ibus,
Packit Service 1d8f1c
                                   GVariant              *parameters,
Packit Service 1d8f1c
                                   GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GDBusConnection *connection =
Packit Service 1d8f1c
            g_dbus_method_invocation_get_connection (invocation);
Packit Service 1d8f1c
    GError *error = NULL;
Packit Service 1d8f1c
    GVariant *variant = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_warning ("org.freedesktop.IBus.GetUseGlobalEngine() is deprecated!");
Packit Service 1d8f1c
Packit Service 1d8f1c
    variant = _ibus_get_use_global_engine (ibus, connection, &error);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_dbus_method_invocation_return_value (invocation,
Packit Service 1d8f1c
            g_variant_new ("(b)", g_variant_get_boolean (variant)));
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_variant_unref (variant);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * _ibus_get_global_engine:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Implement the "GlobalEngine" method call of the
Packit Service 1d8f1c
 * org.freedesktop.IBus interface.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static GVariant *
Packit Service 1d8f1c
_ibus_get_global_engine (BusIBusImpl     *ibus,
Packit Service 1d8f1c
                         GDBusConnection *connection,
Packit Service 1d8f1c
                         GError         **error)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    IBusEngineDesc *desc = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (error) {
Packit Service 1d8f1c
        *error = NULL;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    do {
Packit Service 1d8f1c
        if (!ibus->use_global_engine)
Packit Service 1d8f1c
            break;
Packit Service 1d8f1c
        BusInputContext *context = ibus->focused_context;
Packit Service 1d8f1c
        if (context == NULL)
Packit Service 1d8f1c
            context = ibus->fake_context;
Packit Service 1d8f1c
Packit Service 1d8f1c
        desc = bus_input_context_get_engine_desc (context);
Packit Service 1d8f1c
Packit Service 1d8f1c
        if (desc == NULL)
Packit Service 1d8f1c
            break;
Packit Service 1d8f1c
Packit Service 1d8f1c
        GVariant *variant = ibus_serializable_serialize (
Packit Service 1d8f1c
                (IBusSerializable *) desc);
Packit Service 1d8f1c
        // Set type "v" for introspection_xml.
Packit Service 1d8f1c
        return g_variant_new_variant (variant);
Packit Service 1d8f1c
    } while (0);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_set_error (error,
Packit Service 1d8f1c
                 G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
Packit Service 1d8f1c
                 "No global engine.");
Packit Service 1d8f1c
    return NULL;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_ibus_get_global_engine_depre (BusIBusImpl           *ibus,
Packit Service 1d8f1c
                               GVariant              *parameters,
Packit Service 1d8f1c
                               GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GDBusConnection *connection =
Packit Service 1d8f1c
            g_dbus_method_invocation_get_connection (invocation);
Packit Service 1d8f1c
    GError *error = NULL;
Packit Service 1d8f1c
    GVariant *variant = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_warning ("org.freedesktop.IBus.GetGlobalEngine() is deprecated!");
Packit Service 1d8f1c
Packit Service 1d8f1c
    variant = _ibus_get_global_engine (ibus, connection, &error);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (variant == NULL) {
Packit Service 1d8f1c
        g_dbus_method_invocation_return_error (
Packit Service 1d8f1c
                invocation,
Packit Service 1d8f1c
                G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
Packit Service 1d8f1c
                "%s", error->message);
Packit Service 1d8f1c
        g_error_free (error);
Packit Service 1d8f1c
    } else {
Packit Service 1d8f1c
        GVariant *retval = g_variant_get_variant (variant);
Packit Service 1d8f1c
        g_dbus_method_invocation_return_value (invocation,
Packit Service 1d8f1c
                g_variant_new ("(v)", retval));
Packit Service 1d8f1c
        g_variant_unref (variant);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
struct _SetGlobalEngineData {
Packit Service 1d8f1c
    BusIBusImpl *ibus;
Packit Service 1d8f1c
    GDBusMethodInvocation *invocation;
Packit Service 1d8f1c
};
Packit Service 1d8f1c
typedef struct _SetGlobalEngineData SetGlobalEngineData;
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_ibus_set_global_engine_ready_cb (BusInputContext       *context,
Packit Service 1d8f1c
                                  GAsyncResult          *res,
Packit Service 1d8f1c
                                  SetGlobalEngineData   *data)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    BusIBusImpl *ibus = data->ibus;
Packit Service 1d8f1c
Packit Service 1d8f1c
    GError *error = NULL;
Packit Service 1d8f1c
    if (!bus_input_context_set_engine_by_desc_finish (context, res, &error)) {
Packit Service 1d8f1c
        g_dbus_method_invocation_return_error (data->invocation,
Packit Service 1d8f1c
                                               G_DBUS_ERROR,
Packit Service 1d8f1c
                                               G_DBUS_ERROR_FAILED,
Packit Service 1d8f1c
                                               "Set global engine failed: %s",
Packit Service 1d8f1c
                                               error->message);
Packit Service 1d8f1c
        g_error_free (error);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    else {
Packit Service 1d8f1c
        g_dbus_method_invocation_return_value (data->invocation, NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
        BusEngineProxy *engine = bus_input_context_get_engine (context);
Packit Service 1d8f1c
        if (ibus->use_global_engine && (context != ibus->focused_context)) {
Packit Service 1d8f1c
            /* context and ibus->focused_context don't match. This means that
Packit Service 1d8f1c
             * the focus is moved before _ibus_set_global_engine() asynchronous
Packit Service 1d8f1c
             * call finishes. In this case, the engine for the context currently
Packit Service 1d8f1c
             * being focused hasn't been updated. Update the engine here so that
Packit Service 1d8f1c
             * subsequent _ibus_get_global_engine() call could return a
Packit Service 1d8f1c
             * consistent engine name. */
Packit Service 1d8f1c
            if (engine && ibus->focused_context != NULL) {
Packit Service 1d8f1c
                g_object_ref (engine);
Packit Service 1d8f1c
                bus_input_context_set_engine (context, NULL);
Packit Service 1d8f1c
                bus_input_context_set_emoji_extension (context, NULL);
Packit Service 1d8f1c
                bus_input_context_set_engine (ibus->focused_context, engine);
Packit Service 1d8f1c
                if (ibus->enable_emoji_extension) {
Packit Service 1d8f1c
                    bus_input_context_set_emoji_extension (
Packit Service 1d8f1c
                            ibus->focused_context,
Packit Service 1d8f1c
                            ibus->emoji_extension);
Packit Service 1d8f1c
                } else {
Packit Service 1d8f1c
                    bus_input_context_set_emoji_extension (
Packit Service 1d8f1c
                            ibus->focused_context,
Packit Service 1d8f1c
                            NULL);
Packit Service 1d8f1c
                }
Packit Service 1d8f1c
                g_object_unref (engine);
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        if (engine && ibus->extension_register_keys) {
Packit Service 1d8f1c
            bus_engine_proxy_panel_extension_register_keys (
Packit Service 1d8f1c
                    engine,
Packit Service 1d8f1c
                    ibus->extension_register_keys);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_object_unref (ibus);
Packit Service 1d8f1c
    g_slice_free (SetGlobalEngineData, data);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * _ibus_set_global_engine:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Implement the "SetGlobalEngine" method call of the
Packit Service 1d8f1c
 * org.freedesktop.IBus interface.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_ibus_set_global_engine (BusIBusImpl           *ibus,
Packit Service 1d8f1c
                         GVariant              *parameters,
Packit Service 1d8f1c
                         GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    if (!ibus->use_global_engine) {
Packit Service 1d8f1c
        g_dbus_method_invocation_return_error (invocation,
Packit Service 1d8f1c
                        G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
Packit Service 1d8f1c
                        "Global engine feature is disabled.");
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    BusInputContext *context = ibus->focused_context;
Packit Service 1d8f1c
    if (context == NULL)
Packit Service 1d8f1c
        context = ibus->fake_context;
Packit Service 1d8f1c
Packit Service 1d8f1c
    const gchar *engine_name = NULL;
Packit Service 1d8f1c
    g_variant_get (parameters, "(&s)", &engine_name);
Packit Service 1d8f1c
Packit Service 1d8f1c
    IBusEngineDesc *desc = bus_ibus_impl_get_engine_desc(ibus, engine_name);
Packit Service 1d8f1c
    if (desc == NULL) {
Packit Service 1d8f1c
        g_dbus_method_invocation_return_error (invocation,
Packit Service 1d8f1c
                                               G_DBUS_ERROR,
Packit Service 1d8f1c
                                               G_DBUS_ERROR_FAILED,
Packit Service 1d8f1c
                                               "Cannot find engine %s.",
Packit Service 1d8f1c
                                               engine_name);
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    SetGlobalEngineData *data = g_slice_new0 (SetGlobalEngineData);
Packit Service 1d8f1c
    data->ibus = g_object_ref (ibus);
Packit Service 1d8f1c
    data->invocation = invocation;
Packit Service 1d8f1c
    bus_input_context_set_engine_by_desc (context,
Packit Service 1d8f1c
                                          desc,
Packit Service 1d8f1c
                                          g_gdbus_timeout, /* timeout in msec. */
Packit Service 1d8f1c
                                          NULL, /* we do not cancel the call. */
Packit Service 1d8f1c
                                          (GAsyncReadyCallback) _ibus_set_global_engine_ready_cb,
Packit Service 1d8f1c
                                          data);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * _ibus_get_global_engine_enabled:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Implement the "GlobalEngineEnabled" method call of the
Packit Service 1d8f1c
 * org.freedesktop.IBus interface.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static GVariant *
Packit Service 1d8f1c
_ibus_get_global_engine_enabled (BusIBusImpl     *ibus,
Packit Service 1d8f1c
                                 GDBusConnection *connection,
Packit Service 1d8f1c
                                 GError         **error)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    gboolean enabled = FALSE;
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (error) {
Packit Service 1d8f1c
        *error = NULL;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    do {
Packit Service 1d8f1c
        if (!ibus->use_global_engine)
Packit Service 1d8f1c
            break;
Packit Service 1d8f1c
Packit Service 1d8f1c
        BusInputContext *context = ibus->focused_context;
Packit Service 1d8f1c
        if (context == NULL)
Packit Service 1d8f1c
            context = ibus->fake_context;
Packit Service 1d8f1c
        if (context == NULL)
Packit Service 1d8f1c
            break;
Packit Service 1d8f1c
Packit Service 1d8f1c
        enabled = TRUE;
Packit Service 1d8f1c
    } while (0);
Packit Service 1d8f1c
Packit Service 1d8f1c
    return g_variant_new_boolean (enabled);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_ibus_is_global_engine_enabled_depre (BusIBusImpl           *ibus,
Packit Service 1d8f1c
                                      GVariant              *parameters,
Packit Service 1d8f1c
                                      GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GDBusConnection *connection =
Packit Service 1d8f1c
            g_dbus_method_invocation_get_connection (invocation);
Packit Service 1d8f1c
    GError *error = NULL;
Packit Service 1d8f1c
    GVariant *variant = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_warning ("org.freedesktop.IBus.IsGlobalEngineEnabled() is deprecated!");
Packit Service 1d8f1c
Packit Service 1d8f1c
    variant = _ibus_get_global_engine_enabled (ibus, connection, &error);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_dbus_method_invocation_return_value (invocation,
Packit Service 1d8f1c
            g_variant_new ("(b)", g_variant_get_boolean (variant)));
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_variant_unref (variant);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * _ibus_set_preload_engines:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Implement the "PreloadEngines" method call of the
Packit Service 1d8f1c
 * org.freedesktop.IBus interface.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
_ibus_set_preload_engines (BusIBusImpl     *ibus,
Packit Service 1d8f1c
                           GDBusConnection *connection,
Packit Service 1d8f1c
                           GVariant        *value,
Packit Service 1d8f1c
                           GError         **error)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    int i, j;
Packit Service 1d8f1c
    const gchar **names = NULL;
Packit Service 1d8f1c
    IBusEngineDesc *desc = NULL;
Packit Service 1d8f1c
    BusComponent *component = NULL;
Packit Service 1d8f1c
    BusFactoryProxy *factory = NULL;
Packit Service 1d8f1c
    GPtrArray *array = g_ptr_array_new ();
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (error) {
Packit Service 1d8f1c
        *error = NULL;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_variant_get (value, "^a&s", &names);
Packit Service 1d8f1c
Packit Service 1d8f1c
    for (i = 0; names[i] != NULL; i++) {
Packit Service 1d8f1c
        gboolean has_component = FALSE;
Packit Service 1d8f1c
Packit Service 1d8f1c
        desc = bus_ibus_impl_get_engine_desc(ibus, names[i]);
Packit Service 1d8f1c
Packit Service 1d8f1c
        if (desc == NULL) {
Packit Service 1d8f1c
            g_set_error (error,
Packit Service 1d8f1c
                         G_DBUS_ERROR,
Packit Service 1d8f1c
                         G_DBUS_ERROR_FAILED,
Packit Service 1d8f1c
                         "Cannot find engine %s.",
Packit Service 1d8f1c
                         names[i]);
Packit Service 1d8f1c
            g_ptr_array_free (array, FALSE);
Packit Service 1d8f1c
            return FALSE;
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
Packit Service 1d8f1c
        component = bus_component_from_engine_desc (desc);
Packit Service 1d8f1c
        factory = bus_component_get_factory (component);
Packit Service 1d8f1c
Packit Service 1d8f1c
        if (factory != NULL) {
Packit Service 1d8f1c
            continue;
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
Packit Service 1d8f1c
        for (j = 0; j < array->len; j++) {
Packit Service 1d8f1c
            if (component == (BusComponent *) g_ptr_array_index (array, j)) {
Packit Service 1d8f1c
                has_component = TRUE;
Packit Service 1d8f1c
                break;
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
Packit Service 1d8f1c
        if (!has_component) {
Packit Service 1d8f1c
            g_ptr_array_add (array, component);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    for (j = 0; j < array->len; j++) {
Packit Service 1d8f1c
        bus_component_start ((BusComponent *) g_ptr_array_index (array, j),
Packit Service 1d8f1c
                             g_verbose);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_ptr_array_free (array, FALSE);
Packit Service 1d8f1c
Packit Service 1d8f1c
    bus_ibus_impl_property_changed (ibus, "PreloadEngines", value);
Packit Service 1d8f1c
Packit Service 1d8f1c
    return TRUE;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * _ibus_get_embed_preedit_text:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Implement the "EmbedPreeditText" method call of
Packit Service 1d8f1c
 * the org.freedesktop.IBus interface.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static GVariant *
Packit Service 1d8f1c
_ibus_get_embed_preedit_text (BusIBusImpl     *ibus,
Packit Service 1d8f1c
                              GDBusConnection *connection,
Packit Service 1d8f1c
                              GError         **error)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    if (error) {
Packit Service 1d8f1c
        *error = NULL;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    return g_variant_new_boolean (ibus->embed_preedit_text);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * _ibus_set_embed_preedit_text:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Implement the "EmbedPreeditText" method call of
Packit Service 1d8f1c
 * the org.freedesktop.IBus interface.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
_ibus_set_embed_preedit_text (BusIBusImpl     *ibus,
Packit Service 1d8f1c
                              GDBusConnection *connection,
Packit Service 1d8f1c
                              GVariant        *value,
Packit Service 1d8f1c
                              GError         **error)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    if (error) {
Packit Service 1d8f1c
        *error = NULL;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    gboolean embed_preedit_text = g_variant_get_boolean (value);
Packit Service 1d8f1c
    if (embed_preedit_text != ibus->embed_preedit_text) {
Packit Service 1d8f1c
        ibus->embed_preedit_text = embed_preedit_text;
Packit Service 1d8f1c
        bus_ibus_impl_property_changed (ibus, "EmbedPreeditText", value);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    return TRUE;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * bus_ibus_impl_service_method_call:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Handle a D-Bus method call whose destination and interface name are
Packit Service 1d8f1c
 * both "org.freedesktop.IBus"
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_ibus_impl_service_method_call (IBusService           *service,
Packit Service 1d8f1c
                                   GDBusConnection       *connection,
Packit Service 1d8f1c
                                   const gchar           *sender,
Packit Service 1d8f1c
                                   const gchar           *object_path,
Packit Service 1d8f1c
                                   const gchar           *interface_name,
Packit Service 1d8f1c
                                   const gchar           *method_name,
Packit Service 1d8f1c
                                   GVariant              *parameters,
Packit Service 1d8f1c
                                   GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    if (g_strcmp0 (interface_name, IBUS_INTERFACE_IBUS) != 0) {
Packit Service 1d8f1c
        IBUS_SERVICE_CLASS (bus_ibus_impl_parent_class)->service_method_call (
Packit Service 1d8f1c
                        service, connection, sender, object_path,
Packit Service 1d8f1c
                        interface_name, method_name,
Packit Service 1d8f1c
                        parameters, invocation);
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* all methods in the xml definition above should be listed here. */
Packit Service 1d8f1c
    static const struct {
Packit Service 1d8f1c
        const gchar *method_name;
Packit Service 1d8f1c
        void (* method_callback) (BusIBusImpl *,
Packit Service 1d8f1c
                                  GVariant *,
Packit Service 1d8f1c
                                  GDBusMethodInvocation *);
Packit Service 1d8f1c
    } methods [] =  {
Packit Service 1d8f1c
        /* IBus interface */
Packit Service 1d8f1c
        { "CreateInputContext",    _ibus_create_input_context },
Packit Service 1d8f1c
        { "RegisterComponent",     _ibus_register_component },
Packit Service 1d8f1c
        { "GetEnginesByNames",     _ibus_get_engines_by_names },
Packit Service 1d8f1c
        { "Exit",                  _ibus_exit },
Packit Service 1d8f1c
        { "Ping",                  _ibus_ping },
Packit Service 1d8f1c
        { "SetGlobalEngine",       _ibus_set_global_engine },
Packit Service 1d8f1c
        /* Start of deprecated methods */
Packit Service 1d8f1c
        { "GetAddress",            _ibus_get_address_depre },
Packit Service 1d8f1c
        { "CurrentInputContext",   _ibus_current_input_context_depre },
Packit Service 1d8f1c
        { "ListEngines",           _ibus_list_engines_depre },
Packit Service 1d8f1c
        { "ListActiveEngines",     _ibus_list_active_engines_depre },
Packit Service 1d8f1c
        { "GetUseSysLayout",       _ibus_get_use_sys_layout_depre },
Packit Service 1d8f1c
        { "GetUseGlobalEngine",    _ibus_get_use_global_engine_depre },
Packit Service 1d8f1c
        { "GetGlobalEngine",       _ibus_get_global_engine_depre },
Packit Service 1d8f1c
        { "IsGlobalEngineEnabled", _ibus_is_global_engine_enabled_depre },
Packit Service 1d8f1c
        /* End of deprecated methods */
Packit Service 1d8f1c
    };
Packit Service 1d8f1c
Packit Service 1d8f1c
    gint i;
Packit Service 1d8f1c
    for (i = 0; i < G_N_ELEMENTS (methods); i++) {
Packit Service 1d8f1c
        if (g_strcmp0 (methods[i].method_name, method_name) == 0) {
Packit Service 1d8f1c
            methods[i].method_callback ((BusIBusImpl *) service,
Packit Service 1d8f1c
                                        parameters,
Packit Service 1d8f1c
                                        invocation);
Packit Service 1d8f1c
            return;
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_warning ("service_method_call received an unknown method: %s",
Packit Service 1d8f1c
               method_name ? method_name : "(null)");
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * bus_ibus_impl_service_get_property:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Handle org.freedesktop.DBus.Properties.Get
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static GVariant *
Packit Service 1d8f1c
bus_ibus_impl_service_get_property (IBusService     *service,
Packit Service 1d8f1c
                                    GDBusConnection *connection,
Packit Service 1d8f1c
                                    const gchar     *sender,
Packit Service 1d8f1c
                                    const gchar     *object_path,
Packit Service 1d8f1c
                                    const gchar     *interface_name,
Packit Service 1d8f1c
                                    const gchar     *property_name,
Packit Service 1d8f1c
                                    GError         **error)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    gint i;
Packit Service 1d8f1c
Packit Service 1d8f1c
    static const struct {
Packit Service 1d8f1c
        const gchar *method_name;
Packit Service 1d8f1c
        GVariant * (* method_callback) (BusIBusImpl *,
Packit Service 1d8f1c
                                        GDBusConnection *,
Packit Service 1d8f1c
                                        GError **);
Packit Service 1d8f1c
    } methods [] =  {
Packit Service 1d8f1c
        { "Address",               _ibus_get_address },
Packit Service 1d8f1c
        { "CurrentInputContext",   _ibus_get_current_input_context },
Packit Service 1d8f1c
        { "Engines",               _ibus_get_engines },
Packit Service 1d8f1c
        { "ActiveEngines",         _ibus_get_active_engines },
Packit Service 1d8f1c
        { "GlobalEngine",          _ibus_get_global_engine },
Packit Service 1d8f1c
        { "EmbedPreeditText",      _ibus_get_embed_preedit_text },
Packit Service 1d8f1c
    };
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (g_strcmp0 (interface_name, IBUS_INTERFACE_IBUS) != 0) {
Packit Service 1d8f1c
        return IBUS_SERVICE_CLASS (
Packit Service 1d8f1c
                bus_ibus_impl_parent_class)->service_get_property (
Packit Service 1d8f1c
                        service, connection, sender, object_path,
Packit Service 1d8f1c
                        interface_name, property_name,
Packit Service 1d8f1c
                        error);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    for (i = 0; i < G_N_ELEMENTS (methods); i++) {
Packit Service 1d8f1c
        if (g_strcmp0 (methods[i].method_name, property_name) == 0) {
Packit Service 1d8f1c
            return methods[i].method_callback ((BusIBusImpl *) service,
Packit Service 1d8f1c
                                               connection,
Packit Service 1d8f1c
                                               error);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_warning ("service_get_property received an unknown property: %s",
Packit Service 1d8f1c
               property_name ? property_name : "(null)");
Packit Service 1d8f1c
    return NULL;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * bus_ibus_impl_service_set_property:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Handle org.freedesktop.DBus.Properties.Set
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
bus_ibus_impl_service_set_property (IBusService     *service,
Packit Service 1d8f1c
                                    GDBusConnection *connection,
Packit Service 1d8f1c
                                    const gchar     *sender,
Packit Service 1d8f1c
                                    const gchar     *object_path,
Packit Service 1d8f1c
                                    const gchar     *interface_name,
Packit Service 1d8f1c
                                    const gchar     *property_name,
Packit Service 1d8f1c
                                    GVariant        *value,
Packit Service 1d8f1c
                                    GError         **error)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    gint i;
Packit Service 1d8f1c
Packit Service 1d8f1c
    static const struct {
Packit Service 1d8f1c
        const gchar *method_name;
Packit Service 1d8f1c
        gboolean (* method_callback) (BusIBusImpl *,
Packit Service 1d8f1c
                                      GDBusConnection *,
Packit Service 1d8f1c
                                      GVariant *,
Packit Service 1d8f1c
                                      GError **);
Packit Service 1d8f1c
    } methods [] =  {
Packit Service 1d8f1c
        { "PreloadEngines",        _ibus_set_preload_engines },
Packit Service 1d8f1c
        { "EmbedPreeditText",      _ibus_set_embed_preedit_text },
Packit Service 1d8f1c
    };
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (g_strcmp0 (interface_name, IBUS_INTERFACE_IBUS) != 0) {
Packit Service 1d8f1c
        return IBUS_SERVICE_CLASS (
Packit Service 1d8f1c
                bus_ibus_impl_parent_class)->service_set_property (
Packit Service 1d8f1c
                        service, connection, sender, object_path,
Packit Service 1d8f1c
                        interface_name, property_name,
Packit Service 1d8f1c
                        value, error);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    for (i = 0; i < G_N_ELEMENTS (methods); i++) {
Packit Service 1d8f1c
        if (g_strcmp0 (methods[i].method_name, property_name) == 0) {
Packit Service 1d8f1c
            return methods[i].method_callback ((BusIBusImpl *) service,
Packit Service 1d8f1c
                                               connection,
Packit Service 1d8f1c
                                               value,
Packit Service 1d8f1c
                                               error);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_warning ("service_set_property received an unknown property: %s",
Packit Service 1d8f1c
               property_name ? property_name : "(null)");
Packit Service 1d8f1c
    return FALSE;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
BusIBusImpl *
Packit Service 1d8f1c
bus_ibus_impl_get_default (void)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    static BusIBusImpl *ibus = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (ibus == NULL) {
Packit Service 1d8f1c
        ibus = (BusIBusImpl *) g_object_new (BUS_TYPE_IBUS_IMPL,
Packit Service 1d8f1c
                                             "object-path", IBUS_PATH_IBUS,
Packit Service 1d8f1c
                                             NULL);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    return ibus;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
BusFactoryProxy *
Packit Service 1d8f1c
bus_ibus_impl_lookup_factory (BusIBusImpl *ibus,
Packit Service 1d8f1c
                              const gchar *path)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_assert (BUS_IS_IBUS_IMPL (ibus));
Packit Service 1d8f1c
Packit Service 1d8f1c
    BusFactoryProxy *factory;
Packit Service 1d8f1c
Packit Service 1d8f1c
    factory = (BusFactoryProxy *) g_hash_table_lookup (ibus->factory_dict, path);
Packit Service 1d8f1c
Packit Service 1d8f1c
    return factory;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
IBusKeymap *
Packit Service 1d8f1c
bus_ibus_impl_get_keymap (BusIBusImpl *ibus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_assert (BUS_IS_IBUS_IMPL (ibus));
Packit Service 1d8f1c
Packit Service 1d8f1c
    return ibus->keymap;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * bus_ibus_impl_registry_init:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Initialize IBusRegistry.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_ibus_impl_registry_init (BusIBusImpl *ibus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GList *p;
Packit Service 1d8f1c
    GList *components;
Packit Service 1d8f1c
    IBusRegistry *registry = ibus_registry_new ();
Packit Service 1d8f1c
Packit Service 1d8f1c
    ibus->registry = NULL;
Packit Service 1d8f1c
    ibus->components = NULL;
Packit Service 1d8f1c
    ibus->engine_table = g_hash_table_new (g_str_hash, g_str_equal);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (g_strcmp0 (g_cache, "none") == 0) {
Packit Service 1d8f1c
        /* Only load registry, but not read and write cache. */
Packit Service 1d8f1c
        ibus_registry_load (registry);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    else if (g_strcmp0 (g_cache, "refresh") == 0) {
Packit Service 1d8f1c
        /* Load registry and overwrite the cache. */
Packit Service 1d8f1c
        ibus_registry_load (registry);
Packit Service 1d8f1c
        ibus_registry_save_cache (registry, TRUE);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    else if (g_strcmp0 (g_cache, "auto") == 0) {
Packit Service 1d8f1c
        /* Load registry from cache. If the cache does not exist or
Packit Service 1d8f1c
         * it is outdated, then generate it.
Packit Service 1d8f1c
         */
Packit Service 1d8f1c
        if (ibus_registry_load_cache (registry, FALSE) == FALSE ||
Packit Service 1d8f1c
            ibus_registry_check_modification (registry)) {
Packit Service 1d8f1c
Packit Service 1d8f1c
            ibus_object_destroy (IBUS_OBJECT (registry));
Packit Service 1d8f1c
            registry = ibus_registry_new ();
Packit Service 1d8f1c
Packit Service 1d8f1c
            if (ibus_registry_load_cache (registry, TRUE) == FALSE ||
Packit Service 1d8f1c
                ibus_registry_check_modification (registry)) {
Packit Service 1d8f1c
Packit Service 1d8f1c
                ibus_object_destroy (IBUS_OBJECT (registry));
Packit Service 1d8f1c
                registry = ibus_registry_new ();
Packit Service 1d8f1c
                ibus_registry_load (registry);
Packit Service 1d8f1c
                ibus_registry_save_cache (registry, TRUE);
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    ibus->registry = registry;
Packit Service 1d8f1c
    components = ibus_registry_get_components (registry);
Packit Service 1d8f1c
Packit Service 1d8f1c
    for (p = components; p != NULL; p = p->next) {
Packit Service 1d8f1c
        IBusComponent *component = (IBusComponent *) p->data;
Packit Service 1d8f1c
        BusComponent *buscomp = bus_component_new (component,
Packit Service 1d8f1c
                                                   NULL /* factory */);
Packit Service 1d8f1c
        GList *engines = NULL;
Packit Service 1d8f1c
        GList *p1;
Packit Service 1d8f1c
Packit Service 1d8f1c
        g_object_ref_sink (buscomp);
Packit Service 1d8f1c
        ibus->components = g_list_append (ibus->components, buscomp);
Packit Service 1d8f1c
Packit Service 1d8f1c
        engines = bus_component_get_engines (buscomp);
Packit Service 1d8f1c
        for (p1 = engines; p1 != NULL; p1 = p1->next) {
Packit Service 1d8f1c
            IBusEngineDesc *desc = (IBusEngineDesc *) p1->data;
Packit Service 1d8f1c
            const gchar *name = ibus_engine_desc_get_name (desc);
Packit Service 1d8f1c
            if (g_hash_table_lookup (ibus->engine_table, name) == NULL) {
Packit Service 1d8f1c
                g_hash_table_insert (ibus->engine_table,
Packit Service 1d8f1c
                                     (gpointer) name,
Packit Service 1d8f1c
                                     desc);
Packit Service 1d8f1c
            } else {
Packit Service 1d8f1c
                g_message ("Engine %s is already registered by other component",
Packit Service 1d8f1c
                           name);
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
        g_list_free (engines);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_list_free (components);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_signal_connect (ibus->registry,
Packit Service 1d8f1c
                      "changed",
Packit Service 1d8f1c
                      G_CALLBACK (_registry_changed_cb),
Packit Service 1d8f1c
                      ibus);
Packit Service 1d8f1c
    ibus_registry_start_monitor_changes (ibus->registry);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_ibus_impl_registry_destroy (BusIBusImpl *ibus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_list_free_full (ibus->components, g_object_unref);
Packit Service 1d8f1c
    ibus->components = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_clear_pointer (&ibus->engine_table, g_hash_table_destroy);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_clear_pointer (&ibus->registry, ibus_object_destroy);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (ibus->extension_register_keys)
Packit Service 1d8f1c
        g_clear_pointer (&ibus->extension_register_keys, g_variant_unref);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gint
Packit Service 1d8f1c
_component_is_name_cb (BusComponent *component,
Packit Service 1d8f1c
                       const gchar  *name)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_assert (BUS_IS_COMPONENT (component));
Packit Service 1d8f1c
    g_assert (name);
Packit Service 1d8f1c
Packit Service 1d8f1c
    return g_strcmp0 (bus_component_get_name (component), name);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_ibus_impl_component_name_owner_changed (BusIBusImpl *ibus,
Packit Service 1d8f1c
                                            const gchar *name,
Packit Service 1d8f1c
                                            const gchar *old_name,
Packit Service 1d8f1c
                                            const gchar *new_name)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    BusComponent *component;
Packit Service 1d8f1c
    BusFactoryProxy *factory;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_assert (BUS_IS_IBUS_IMPL (ibus));
Packit Service 1d8f1c
    g_assert (name);
Packit Service 1d8f1c
    g_assert (old_name);
Packit Service 1d8f1c
    g_assert (new_name);
Packit Service 1d8f1c
Packit Service 1d8f1c
    component = bus_ibus_impl_lookup_component_by_name (ibus, name);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (component == NULL) {
Packit Service 1d8f1c
        /* name is a unique name, or a well-known name we don't know. */
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (g_strcmp0 (old_name, "") != 0) {
Packit Service 1d8f1c
        /* the component is stopped. */
Packit Service 1d8f1c
        factory = bus_component_get_factory (component);
Packit Service 1d8f1c
Packit Service 1d8f1c
        if (factory != NULL) {
Packit Service 1d8f1c
            ibus_proxy_destroy ((IBusProxy *) factory);
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (g_strcmp0 (new_name, "") != 0) {
Packit Service 1d8f1c
        /* the component is started. */
Packit Service 1d8f1c
        BusConnection *connection =
Packit Service 1d8f1c
                bus_dbus_impl_get_connection_by_name (BUS_DEFAULT_DBUS,
Packit Service 1d8f1c
                                                      new_name);
Packit Service 1d8f1c
        if (connection == NULL)
Packit Service 1d8f1c
            return;
Packit Service 1d8f1c
Packit Service 1d8f1c
        factory = bus_factory_proxy_new (connection);
Packit Service 1d8f1c
        if (factory == NULL)
Packit Service 1d8f1c
            return;
Packit Service 1d8f1c
        bus_component_set_factory (component, factory);
Packit Service 1d8f1c
        g_object_unref (factory);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
BusComponent *
Packit Service 1d8f1c
bus_ibus_impl_lookup_component_by_name (BusIBusImpl *ibus,
Packit Service 1d8f1c
                                        const gchar *name)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GList *p;
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_assert (BUS_IS_IBUS_IMPL (ibus));
Packit Service 1d8f1c
    g_assert (name);
Packit Service 1d8f1c
Packit Service 1d8f1c
    p = g_list_find_custom (ibus->components,
Packit Service 1d8f1c
                            name,
Packit Service 1d8f1c
                            (GCompareFunc) _component_is_name_cb);
Packit Service 1d8f1c
    if (p) {
Packit Service 1d8f1c
        return (BusComponent *) p->data;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
    else {
Packit Service 1d8f1c
        return NULL;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * bus_ibus_impl_property_changed
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Send a "PropertiesChanged" D-Bus signal for a property to buses
Packit Service 1d8f1c
 * (connections) that are listening to the signal.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_ibus_impl_property_changed (BusIBusImpl *service,
Packit Service 1d8f1c
                                const gchar *property_name,
Packit Service 1d8f1c
                                GVariant    *value)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GDBusMessage *message =
Packit Service 1d8f1c
        g_dbus_message_new_signal ("/org/freedesktop/IBus",
Packit Service 1d8f1c
                                   "org.freedesktop.DBus.Properties",
Packit Service 1d8f1c
                                   "PropertiesChanged");
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* set a non-zero serial to make libdbus happy */
Packit Service 1d8f1c
    g_dbus_message_set_serial (message, 1);
Packit Service 1d8f1c
    g_dbus_message_set_sender (message, "org.freedesktop.IBus");
Packit Service 1d8f1c
Packit Service 1d8f1c
    GVariantBuilder *builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
Packit Service 1d8f1c
    g_variant_builder_add (builder, "{sv}", property_name, value);
Packit Service 1d8f1c
    g_dbus_message_set_body (message,
Packit Service 1d8f1c
                             g_variant_new ("(sa{sv}as)",
Packit Service 1d8f1c
                                            "org.freedesktop.IBus",
Packit Service 1d8f1c
                                            builder,
Packit Service 1d8f1c
                                            NULL));
Packit Service 1d8f1c
    g_variant_builder_unref (builder);
Packit Service 1d8f1c
Packit Service 1d8f1c
    bus_dbus_impl_dispatch_message_by_rule (BUS_DEFAULT_DBUS, message, NULL);
Packit Service 1d8f1c
    g_object_unref (message);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
/**
Packit Service 1d8f1c
 * bus_ibus_impl_emit_signal:
Packit Service 1d8f1c
 *
Packit Service 1d8f1c
 * Send a D-Bus signal to buses (connections) that are listening to the signal.
Packit Service 1d8f1c
 */
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_ibus_impl_emit_signal (BusIBusImpl *ibus,
Packit Service 1d8f1c
                           const gchar *signal_name,
Packit Service 1d8f1c
                           GVariant    *parameters)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GDBusMessage *message = g_dbus_message_new_signal ("/org/freedesktop/IBus",
Packit Service 1d8f1c
                                                       "org.freedesktop.IBus",
Packit Service 1d8f1c
                                                       signal_name);
Packit Service 1d8f1c
    /* set a non-zero serial to make libdbus happy */
Packit Service 1d8f1c
    g_dbus_message_set_serial (message, 1);
Packit Service 1d8f1c
    g_dbus_message_set_sender (message, "org.freedesktop.IBus");
Packit Service 1d8f1c
    if (parameters)
Packit Service 1d8f1c
        g_dbus_message_set_body (message, parameters);
Packit Service 1d8f1c
    bus_dbus_impl_dispatch_message_by_rule (BUS_DEFAULT_DBUS, message, NULL);
Packit Service 1d8f1c
    g_object_unref (message);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_ibus_impl_registry_changed (BusIBusImpl *ibus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    bus_ibus_impl_emit_signal (ibus, "RegistryChanged", NULL);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
bus_ibus_impl_global_engine_changed (BusIBusImpl *ibus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    const gchar *name = ibus->global_engine_name ? ibus->global_engine_name : "";
Packit Service 1d8f1c
    bus_ibus_impl_emit_signal (ibus, "GlobalEngineChanged",
Packit Service 1d8f1c
                               g_variant_new ("(s)", name));
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
gboolean
Packit Service 1d8f1c
bus_ibus_impl_is_use_sys_layout (BusIBusImpl *ibus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_assert (BUS_IS_IBUS_IMPL (ibus));
Packit Service 1d8f1c
Packit Service 1d8f1c
    return ibus->use_sys_layout;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
gboolean
Packit Service 1d8f1c
bus_ibus_impl_is_embed_preedit_text (BusIBusImpl *ibus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_assert (BUS_IS_IBUS_IMPL (ibus));
Packit Service 1d8f1c
Packit Service 1d8f1c
    return ibus->embed_preedit_text;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
BusInputContext *
Packit Service 1d8f1c
bus_ibus_impl_get_focused_input_context (BusIBusImpl *ibus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_assert (BUS_IS_IBUS_IMPL (ibus));
Packit Service 1d8f1c
Packit Service 1d8f1c
    return ibus->focused_context;
Packit Service 1d8f1c
}