Blame portal/portal.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
rpm-build f3645b
 * Copyright (C) 2017-2019 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
#include <config.h>
Packit Service 1d8f1c
#include <fcntl.h>
Packit Service 1d8f1c
#include <glib.h>
Packit Service 1d8f1c
#include <gio/gio.h>
Packit Service 1d8f1c
#include <ibus.h>
Packit Service 1d8f1c
#include <locale.h>
Packit Service 1d8f1c
#include <pwd.h>
Packit Service 1d8f1c
#include <signal.h>
Packit Service 1d8f1c
#include <stdlib.h>
Packit Service 1d8f1c
#include <sys/types.h>
Packit Service 1d8f1c
#include <sys/stat.h>
Packit Service 1d8f1c
#include <unistd.h>
Packit Service 1d8f1c
Packit Service 1d8f1c
#include "ibus-portal-dbus.h"
Packit Service 1d8f1c
Packit Service 1d8f1c
typedef struct _IBusPortal IBusPortal;
Packit Service 1d8f1c
typedef struct _IBusPortalClass IBusPortalClass;
Packit Service 1d8f1c
typedef struct _IBusPortalContext IBusPortalContext;
Packit Service 1d8f1c
typedef struct _IBusPortalContextClass IBusPortalContextClass;
Packit Service 1d8f1c
Packit Service 1d8f1c
struct _IBusPortalContext
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    IBusDbusInputContextSkeleton parent_instance;
Packit Service 1d8f1c
    IBusInputContext *context;
Packit Service 1d8f1c
    guint id;
Packit Service 1d8f1c
    char *owner;
Packit Service 1d8f1c
    char *object_path;
Packit Service 1d8f1c
    IBusDbusService *service;
Packit Service 1d8f1c
};
Packit Service 1d8f1c
Packit Service 1d8f1c
struct _IBusPortalContextClass
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    IBusDbusInputContextSkeletonClass parent_class;
Packit Service 1d8f1c
};
Packit Service 1d8f1c
Packit Service 1d8f1c
struct _IBusPortal
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    IBusDbusPortalSkeleton parent_instance;
Packit Service 1d8f1c
Packit Service 1d8f1c
};
Packit Service 1d8f1c
Packit Service 1d8f1c
struct _IBusPortalClass
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    IBusDbusPortalSkeletonClass parent_class;
Packit Service 1d8f1c
};
Packit Service 1d8f1c
Packit Service 1d8f1c
enum
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    PROP_CONTENT_TYPE = 1,
rpm-build f3645b
    PROP_CLIENT_COMMIT_PREEDIT,
Packit Service 1d8f1c
    N_PROPERTIES
Packit Service 1d8f1c
};
Packit Service 1d8f1c
Packit Service 1d8f1c
static GMainLoop *loop = NULL;
Packit Service 1d8f1c
static IBusBus *ibus_bus;
Packit Service 1d8f1c
static IBusPortal *ibus_portal = NULL;
Packit Service 1d8f1c
static gboolean opt_verbose;
Packit Service 1d8f1c
static gboolean opt_replace;
Packit Service 1d8f1c
Packit Service 1d8f1c
static GList *all_contexts = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
static guint next_context_id;
Packit Service 1d8f1c
Packit Service 1d8f1c
GType ibus_portal_context_get_type (void) G_GNUC_CONST;
Packit Service 1d8f1c
static void ibus_portal_context_iface_init (IBusDbusInputContextIface *iface);
Packit Service 1d8f1c
Packit Service 1d8f1c
static void portal_context_g_signal (GDBusProxy        *proxy,
Packit Service 1d8f1c
                                     const gchar       *sender_name,
Packit Service 1d8f1c
                                     const gchar       *signal_name,
Packit Service 1d8f1c
                                     GVariant          *parameters,
Packit Service 1d8f1c
                                     IBusPortalContext *portal_context);
Packit Service 1d8f1c
Packit Service 1d8f1c
G_DEFINE_TYPE_WITH_CODE (IBusPortalContext,
Packit Service 1d8f1c
                         ibus_portal_context,
Packit Service 1d8f1c
                         IBUS_DBUS_TYPE_INPUT_CONTEXT_SKELETON,
Packit Service 1d8f1c
                         G_IMPLEMENT_INTERFACE (IBUS_DBUS_TYPE_INPUT_CONTEXT,
Packit Service 1d8f1c
                                 ibus_portal_context_iface_init));
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_forward_method_cb (GObject *source_object,
Packit Service 1d8f1c
                    GAsyncResult *res,
Packit Service 1d8f1c
                    gpointer user_data)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GDBusMethodInvocation *invocation = user_data;
Packit Service 1d8f1c
    GError *error = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    GVariant *variant = g_dbus_proxy_call_finish ((GDBusProxy *) source_object,
Packit Service 1d8f1c
                                                  res, &error);
Packit Service 1d8f1c
    if (variant == NULL) {
Packit Service 1d8f1c
        g_dbus_method_invocation_return_gerror (invocation, error);
Packit Service 1d8f1c
        g_error_free (error);
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_dbus_method_invocation_return_value (invocation, variant);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
_forward_method (IBusDbusInputContext  *object,
Packit Service 1d8f1c
                 GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    IBusPortalContext *portal_context = (IBusPortalContext *)object;
Packit Service 1d8f1c
    GDBusMessage *message = g_dbus_method_invocation_get_message (invocation);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_dbus_proxy_call (G_DBUS_PROXY (portal_context->context),
Packit Service 1d8f1c
                       g_dbus_method_invocation_get_method_name (invocation),
Packit Service 1d8f1c
                       g_dbus_message_get_body (message),
Packit Service 1d8f1c
                       G_DBUS_CALL_FLAGS_NONE,
Packit Service 1d8f1c
                       -1,
Packit Service 1d8f1c
                       NULL, /* cancellable */
Packit Service 1d8f1c
                       _forward_method_cb, invocation);
Packit Service 1d8f1c
    return TRUE;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
ibus_dbus_context_cancel_hand_writing (IBusDbusInputContext  *object,
Packit Service 1d8f1c
                                       GDBusMethodInvocation *invocation,
Packit Service 1d8f1c
                                       guint                  arg_n_strokes)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    return _forward_method (object, invocation);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
ibus_dbus_context_focus_in (IBusDbusInputContext  *object,
Packit Service 1d8f1c
                            GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    return _forward_method (object, invocation);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
ibus_dbus_context_focus_out (IBusDbusInputContext  *object,
Packit Service 1d8f1c
                             GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    return _forward_method (object, invocation);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
ibus_dbus_context_get_engine (IBusDbusInputContext  *object,
Packit Service 1d8f1c
                              GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    return _forward_method (object, invocation);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
ibus_dbus_context_process_hand_writing_event (IBusDbusInputContext  *object,
Packit Service 1d8f1c
                                              GDBusMethodInvocation *invocation,
Packit Service 1d8f1c
                                              GVariant
Packit Service 1d8f1c
                                                               *arg_coordinates)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    return _forward_method (object, invocation);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
ibus_dbus_context_process_key_event (IBusDbusInputContext  *object,
Packit Service 1d8f1c
                                     GDBusMethodInvocation *invocation,
Packit Service 1d8f1c
                                     guint                  arg_keyval,
Packit Service 1d8f1c
                                     guint                  arg_keycode,
Packit Service 1d8f1c
                                     guint                  arg_state)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    return _forward_method (object, invocation);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
ibus_dbus_context_property_activate (IBusDbusInputContext  *object,
Packit Service 1d8f1c
                                     GDBusMethodInvocation *invocation,
Packit Service 1d8f1c
                                     const gchar           *arg_name,
Packit Service 1d8f1c
                                     guint                  arg_state)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    return _forward_method (object, invocation);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
ibus_dbus_context_reset (IBusDbusInputContext  *object,
Packit Service 1d8f1c
                         GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    return _forward_method (object, invocation);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
ibus_dbus_context_set_capabilities (IBusDbusInputContext  *object,
Packit Service 1d8f1c
                                    GDBusMethodInvocation *invocation,
Packit Service 1d8f1c
                                    guint                  arg_caps)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    return _forward_method (object, invocation);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
ibus_dbus_context_set_cursor_location (IBusDbusInputContext  *object,
Packit Service 1d8f1c
                                       GDBusMethodInvocation *invocation,
Packit Service 1d8f1c
                                       gint                   arg_x,
Packit Service 1d8f1c
                                       gint                   arg_y,
Packit Service 1d8f1c
                                       gint                   arg_w,
Packit Service 1d8f1c
                                       gint                   arg_h)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    return _forward_method (object, invocation);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
ibus_dbus_context_set_cursor_location_relative (IBusDbusInputContext  *object,
Packit Service 1d8f1c
                                                GDBusMethodInvocation
Packit Service 1d8f1c
                                                                    *invocation,
Packit Service 1d8f1c
                                                gint                   arg_x,
Packit Service 1d8f1c
                                                gint                   arg_y,
Packit Service 1d8f1c
                                                gint                   arg_w,
Packit Service 1d8f1c
                                                gint                   arg_h)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    return _forward_method (object, invocation);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
ibus_dbus_context_set_engine (IBusDbusInputContext  *object,
Packit Service 1d8f1c
                              GDBusMethodInvocation *invocation,
Packit Service 1d8f1c
                              const gchar           *arg_name)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    return _forward_method (object, invocation);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
ibus_dbus_context_set_surrounding_text (IBusDbusInputContext  *object,
Packit Service 1d8f1c
                                        GDBusMethodInvocation *invocation,
Packit Service 1d8f1c
                                        GVariant              *arg_text,
Packit Service 1d8f1c
                                        guint                  arg_cursor_pos,
Packit Service 1d8f1c
                                        guint                  arg_anchor_pos)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    return _forward_method (object, invocation);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
ibus_portal_context_iface_init (IBusDbusInputContextIface *iface)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    iface->handle_cancel_hand_writing = ibus_dbus_context_cancel_hand_writing;
Packit Service 1d8f1c
    iface->handle_focus_in = ibus_dbus_context_focus_in;
Packit Service 1d8f1c
    iface->handle_focus_out = ibus_dbus_context_focus_out;
Packit Service 1d8f1c
    iface->handle_get_engine = ibus_dbus_context_get_engine;
Packit Service 1d8f1c
    iface->handle_process_hand_writing_event =
Packit Service 1d8f1c
            ibus_dbus_context_process_hand_writing_event;
Packit Service 1d8f1c
    iface->handle_process_key_event = ibus_dbus_context_process_key_event;
Packit Service 1d8f1c
    iface->handle_property_activate = ibus_dbus_context_property_activate;
Packit Service 1d8f1c
    iface->handle_reset = ibus_dbus_context_reset;
Packit Service 1d8f1c
    iface->handle_set_capabilities = ibus_dbus_context_set_capabilities;
Packit Service 1d8f1c
    iface->handle_set_cursor_location = ibus_dbus_context_set_cursor_location;
Packit Service 1d8f1c
    iface->handle_set_cursor_location_relative =
Packit Service 1d8f1c
            ibus_dbus_context_set_cursor_location_relative;
Packit Service 1d8f1c
    iface->handle_set_engine = ibus_dbus_context_set_engine;
Packit Service 1d8f1c
    iface->handle_set_surrounding_text = ibus_dbus_context_set_surrounding_text;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
ibus_portal_context_init (IBusPortalContext *portal_context)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
ibus_portal_context_finalize (GObject *object)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    IBusPortalContext *portal_context = (IBusPortalContext *)object;
Packit Service 1d8f1c
Packit Service 1d8f1c
    all_contexts = g_list_remove (all_contexts, portal_context);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_dbus_interface_skeleton_unexport (
Packit Service 1d8f1c
            G_DBUS_INTERFACE_SKELETON (portal_context->service));
Packit Service 1d8f1c
    g_dbus_interface_skeleton_unexport (
Packit Service 1d8f1c
            G_DBUS_INTERFACE_SKELETON (portal_context));
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_free (portal_context->owner);
Packit Service 1d8f1c
    g_free (portal_context->object_path);
Packit Service 1d8f1c
    g_object_unref (portal_context->service);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_signal_handlers_disconnect_by_func (
Packit Service 1d8f1c
            portal_context->context,
Packit Service 1d8f1c
            G_CALLBACK(portal_context_g_signal),
Packit Service 1d8f1c
            portal_context);
Packit Service 1d8f1c
    g_object_unref (portal_context->context);
Packit Service 1d8f1c
Packit Service 1d8f1c
    G_OBJECT_CLASS (ibus_portal_context_parent_class)->finalize (object);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
ibus_portal_context_set_property (IBusPortalContext *portal_context,
Packit Service 1d8f1c
                                  guint              prop_id,
Packit Service 1d8f1c
                                  const GValue      *value,
Packit Service 1d8f1c
                                  GParamSpec        *pspec)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    switch (prop_id) {
Packit Service 1d8f1c
    case PROP_CONTENT_TYPE:
Packit Service 1d8f1c
        g_dbus_proxy_call (G_DBUS_PROXY (portal_context->context),
Packit Service 1d8f1c
                           "org.freedesktop.DBus.Properties.Set",
Packit Service 1d8f1c
                           g_variant_new ("(ssv)",
Packit Service 1d8f1c
                                          IBUS_INTERFACE_INPUT_CONTEXT,
Packit Service 1d8f1c
                                          "ContentType",
Packit Service 1d8f1c
                                          g_value_get_variant (value)),
Packit Service 1d8f1c
                           G_DBUS_CALL_FLAGS_NONE,
Packit Service 1d8f1c
                           -1,
Packit Service 1d8f1c
                           NULL, /* cancellable */
Packit Service 1d8f1c
                           NULL, /* callback */
Packit Service 1d8f1c
                           NULL  /* user_data */
Packit Service 1d8f1c
                           );
Packit Service 1d8f1c
        break;
rpm-build f3645b
    case PROP_CLIENT_COMMIT_PREEDIT:
rpm-build f3645b
        g_dbus_proxy_call (G_DBUS_PROXY (portal_context->context),
rpm-build f3645b
                           "org.freedesktop.DBus.Properties.Set",
rpm-build f3645b
                           g_variant_new ("(ssv)",
rpm-build f3645b
                                          IBUS_INTERFACE_INPUT_CONTEXT,
rpm-build f3645b
                                          "ClientCommitPreedit",
rpm-build f3645b
                                          g_value_get_variant (value)),
rpm-build f3645b
                           G_DBUS_CALL_FLAGS_NONE,
rpm-build f3645b
                           -1,
rpm-build f3645b
                           NULL, /* cancellable */
rpm-build f3645b
                           NULL, /* callback */
rpm-build f3645b
                           NULL  /* user_data */
rpm-build f3645b
                           );
rpm-build f3645b
        break;
Packit Service 1d8f1c
    default:
Packit Service 1d8f1c
        G_OBJECT_WARN_INVALID_PROPERTY_ID (portal_context, prop_id, pspec);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
ibus_portal_context_get_property (IBusPortalContext *portal_context,
Packit Service 1d8f1c
                                  guint              prop_id,
Packit Service 1d8f1c
                                  GValue            *value,
Packit Service 1d8f1c
                                  GParamSpec        *pspec)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    switch (prop_id) {
Packit Service 1d8f1c
    case PROP_CONTENT_TYPE:
rpm-build f3645b
    case PROP_CLIENT_COMMIT_PREEDIT:
Packit Service 1d8f1c
        g_warning ("No support for setting content type");
Packit Service 1d8f1c
        break;
Packit Service 1d8f1c
    default:
Packit Service 1d8f1c
        G_OBJECT_WARN_INVALID_PROPERTY_ID (portal_context, prop_id, pspec);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
ibus_portal_context_g_authorize_method (GDBusInterfaceSkeleton *interface,
Packit Service 1d8f1c
                                        GDBusMethodInvocation  *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    IBusPortalContext *portal_context = (IBusPortalContext *)interface;
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (g_strcmp0 (g_dbus_method_invocation_get_sender (invocation),
Packit Service 1d8f1c
                   portal_context->owner) == 0) {
Packit Service 1d8f1c
        return TRUE;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
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
                                           "Access denied");
Packit Service 1d8f1c
    return FALSE;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
ibus_portal_context_class_init (IBusPortalContextClass *klass)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GObjectClass *gobject_class;
Packit Service 1d8f1c
    GDBusInterfaceSkeletonClass *skeleton_class;
Packit Service 1d8f1c
Packit Service 1d8f1c
    gobject_class = G_OBJECT_CLASS (klass);
Packit Service 1d8f1c
    gobject_class->finalize  = ibus_portal_context_finalize;
Packit Service 1d8f1c
    gobject_class->set_property  =
Packit Service 1d8f1c
            (GObjectSetPropertyFunc) ibus_portal_context_set_property;
Packit Service 1d8f1c
    gobject_class->get_property  =
Packit Service 1d8f1c
            (GObjectGetPropertyFunc) ibus_portal_context_get_property;
Packit Service 1d8f1c
Packit Service 1d8f1c
    skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS(klass);
Packit Service 1d8f1c
    skeleton_class->g_authorize_method = ibus_portal_context_g_authorize_method;
Packit Service 1d8f1c
Packit Service 1d8f1c
    ibus_dbus_input_context_override_properties (gobject_class,
Packit Service 1d8f1c
                                                 PROP_CONTENT_TYPE);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
portal_context_g_signal (GDBusProxy        *proxy,
Packit Service 1d8f1c
                         const gchar       *sender_name,
Packit Service 1d8f1c
                         const gchar       *signal_name,
Packit Service 1d8f1c
                         GVariant          *parameters,
Packit Service 1d8f1c
                         IBusPortalContext *portal_context)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GError *error = NULL;
Packit Service 1d8f1c
    GDBusConnection *connection;
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (g_strcmp0 (sender_name, IBUS_SERVICE_IBUS) != 0)
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
Packit Service 1d8f1c
    connection = g_dbus_interface_skeleton_get_connection (
Packit Service 1d8f1c
            G_DBUS_INTERFACE_SKELETON (portal_context));
Packit Service 1d8f1c
    if (!g_dbus_connection_emit_signal (connection,
Packit Service 1d8f1c
                                        portal_context->owner,
Packit Service 1d8f1c
                                        portal_context->object_path,
Packit Service 1d8f1c
                                        IBUS_INTERFACE_INPUT_CONTEXT,
Packit Service 1d8f1c
                                        signal_name,
Packit Service 1d8f1c
                                        parameters,
Packit Service 1d8f1c
                                        &error)) {
Packit Service 1d8f1c
        g_warning ("Unable to emit signal %s: %s", signal_name, error->message);
Packit Service 1d8f1c
        g_error_free (error);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_signal_stop_emission_by_name (proxy, "g-signal");
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
ibus_portal_context_handle_destroy (IBusDbusService       *object,
Packit Service 1d8f1c
                                    GDBusMethodInvocation *invocation,
Packit Service 1d8f1c
                                    IBusPortalContext     *portal_context)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_object_unref (portal_context);
Packit Service 1d8f1c
    return FALSE;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static IBusPortalContext *
Packit Service 1d8f1c
ibus_portal_context_new (IBusInputContext *context,
Packit Service 1d8f1c
                         GDBusConnection  *connection,
Packit Service 1d8f1c
                         const char       *owner,
Packit Service 1d8f1c
                         GError          **error)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    IBusPortalContext *portal_context =
Packit Service 1d8f1c
            g_object_new (ibus_portal_context_get_type (), NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_signal_connect (context,
Packit Service 1d8f1c
                      "g-signal",
Packit Service 1d8f1c
                      G_CALLBACK(portal_context_g_signal),
Packit Service 1d8f1c
                      portal_context);
Packit Service 1d8f1c
Packit Service 1d8f1c
    portal_context->id = ++next_context_id;
Packit Service 1d8f1c
    portal_context->context = g_object_ref (context);
Packit Service 1d8f1c
    portal_context->owner = g_strdup (owner);
Packit Service 1d8f1c
    portal_context->object_path =
Packit Service 1d8f1c
            g_strdup_printf (IBUS_PATH_INPUT_CONTEXT, portal_context->id);
Packit Service 1d8f1c
    portal_context->service = ibus_dbus_service_skeleton_new ();
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_signal_connect (portal_context->service,
Packit Service 1d8f1c
                      "handle-destroy",
Packit Service 1d8f1c
                      G_CALLBACK (ibus_portal_context_handle_destroy),
Packit Service 1d8f1c
                      portal_context);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (!g_dbus_interface_skeleton_export (
Packit Service 1d8f1c
                G_DBUS_INTERFACE_SKELETON (portal_context->service),
Packit Service 1d8f1c
                connection, portal_context->object_path,
Packit Service 1d8f1c
                error) ||
Packit Service 1d8f1c
        !g_dbus_interface_skeleton_export (
Packit Service 1d8f1c
                G_DBUS_INTERFACE_SKELETON (portal_context),
Packit Service 1d8f1c
                connection, portal_context->object_path,
Packit Service 1d8f1c
                error)) {
Packit Service 1d8f1c
        g_object_unref (portal_context);
Packit Service 1d8f1c
        return NULL;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    all_contexts = g_list_prepend (all_contexts, portal_context);
Packit Service 1d8f1c
Packit Service 1d8f1c
    return portal_context;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
GType ibus_portal_get_type (void) G_GNUC_CONST;
Packit Service 1d8f1c
static void ibus_portal_iface_init (IBusDbusPortalIface *iface);
Packit Service 1d8f1c
Packit Service 1d8f1c
G_DEFINE_TYPE_WITH_CODE (IBusPortal, ibus_portal,
Packit Service 1d8f1c
                         IBUS_DBUS_TYPE_PORTAL_SKELETON,
Packit Service 1d8f1c
                         G_IMPLEMENT_INTERFACE (IBUS_DBUS_TYPE_PORTAL,
Packit Service 1d8f1c
                                                ibus_portal_iface_init));
Packit Service 1d8f1c
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
create_input_context_done (IBusBus               *bus,
Packit Service 1d8f1c
                           GAsyncResult          *res,
Packit Service 1d8f1c
                           GDBusMethodInvocation *invocation)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GError *error = NULL;
Packit Service 1d8f1c
    IBusInputContext *context;
Packit Service 1d8f1c
    IBusPortalContext *portal_context;
Packit Service 1d8f1c
Packit Service 1d8f1c
    context = ibus_bus_create_input_context_async_finish (ibus_bus,
Packit Service 1d8f1c
                                                          res,
Packit Service 1d8f1c
                                                          &error);
Packit Service 1d8f1c
    if (context == NULL) {
Packit Service 1d8f1c
        g_dbus_method_invocation_return_gerror (invocation, error);
Packit Service 1d8f1c
        g_error_free (error);
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    portal_context = ibus_portal_context_new (
Packit Service 1d8f1c
            context,
Packit Service 1d8f1c
            g_dbus_method_invocation_get_connection (invocation),
Packit Service 1d8f1c
            g_dbus_method_invocation_get_sender (invocation),
Packit Service 1d8f1c
            &error);
Packit Service 1d8f1c
    g_object_unref (context);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (portal_context == NULL) {
Packit Service 1d8f1c
        g_dbus_method_invocation_return_gerror (invocation, error);
Packit Service 1d8f1c
        g_error_free (error);
Packit Service 1d8f1c
        g_object_unref (portal_context);
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    ibus_dbus_portal_complete_create_input_context (
Packit Service 1d8f1c
            IBUS_DBUS_PORTAL(ibus_portal),
Packit Service 1d8f1c
            invocation, portal_context->object_path);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static gboolean
Packit Service 1d8f1c
ibus_portal_handle_create_input_context (IBusDbusPortal        *object,
Packit Service 1d8f1c
                                         GDBusMethodInvocation *invocation,
Packit Service 1d8f1c
                                         const gchar           *arg_client_name)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    ibus_bus_create_input_context_async (
Packit Service 1d8f1c
            ibus_bus,
Packit Service 1d8f1c
            arg_client_name, -1,
Packit Service 1d8f1c
            NULL,
Packit Service 1d8f1c
            (GAsyncReadyCallback)create_input_context_done,
Packit Service 1d8f1c
            invocation);
Packit Service 1d8f1c
    return TRUE;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
ibus_portal_iface_init (IBusDbusPortalIface *iface)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    iface->handle_create_input_context =
Packit Service 1d8f1c
            ibus_portal_handle_create_input_context;
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
ibus_portal_init (IBusPortal *portal)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
ibus_portal_class_init (IBusPortalClass *klass)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
show_version_and_quit (void)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_print ("%s - Version %s\n", g_get_application_name (), VERSION);
Packit Service 1d8f1c
    exit (EXIT_SUCCESS);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static const GOptionEntry entries[] =
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    { "version",   'V', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK,
Packit Service 1d8f1c
      show_version_and_quit, "Show the application's version.", NULL },
Packit Service 1d8f1c
    { "verbose",   'v', 0, G_OPTION_ARG_NONE, 
Packit Service 1d8f1c
      &opt_verbose,   "verbose.", NULL },
Packit Service 1d8f1c
    { "replace",   'r', 0, G_OPTION_ARG_NONE,
Packit Service 1d8f1c
      &opt_replace,   "Replace.", NULL },
Packit Service 1d8f1c
    { NULL },
Packit Service 1d8f1c
};
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
on_bus_acquired (GDBusConnection *connection,
Packit Service 1d8f1c
                 const gchar     *name,
Packit Service 1d8f1c
                 gpointer         user_data)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GError *error = NULL;
Packit Service 1d8f1c
Packit Service 1d8f1c
    ibus_portal = g_object_new (ibus_portal_get_type (), NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    if (!g_dbus_interface_skeleton_export (
Packit Service 1d8f1c
                G_DBUS_INTERFACE_SKELETON (ibus_portal),
Packit Service 1d8f1c
                connection,
Packit Service 1d8f1c
                IBUS_PATH_IBUS,
Packit Service 1d8f1c
                &error)) {
Packit Service 1d8f1c
        g_warning ("Error exporting portal: %s", error->message);
Packit Service 1d8f1c
        g_error_free (error);
Packit Service 1d8f1c
        return;
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
on_name_acquired (GDBusConnection *connection,
Packit Service 1d8f1c
                  const gchar     *name,
Packit Service 1d8f1c
                  gpointer         user_data)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
on_name_lost (GDBusConnection *connection,
Packit Service 1d8f1c
              const gchar     *name,
Packit Service 1d8f1c
              gpointer         user_data)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_main_loop_quit (loop);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
name_owner_changed (GDBusConnection *connection,
Packit Service 1d8f1c
                    const gchar     *sender_name,
Packit Service 1d8f1c
                    const gchar     *object_path,
Packit Service 1d8f1c
                    const gchar     *interface_name,
Packit Service 1d8f1c
                    const gchar     *signal_name,
Packit Service 1d8f1c
                    GVariant        *parameters,
Packit Service 1d8f1c
                    gpointer         user_data)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
  const char *name, *from, *to;
Packit Service 1d8f1c
Packit Service 1d8f1c
  g_variant_get (parameters, "(sss)", &name, &from, &to);
Packit Service 1d8f1c
Packit Service 1d8f1c
  if (name[0] == ':' &&
Packit Service 1d8f1c
      g_strcmp0 (name, from) == 0 &&
Packit Service 1d8f1c
      g_strcmp0 (to, "") == 0)
Packit Service 1d8f1c
    {
Packit Service 1d8f1c
        GList *l, *next;
Packit Service 1d8f1c
        /* Client disconnected, free any input contexts it may have */
Packit Service 1d8f1c
        for (l = all_contexts; l != NULL; l = next) {
Packit Service 1d8f1c
            IBusPortalContext *portal_context = l->data;
Packit Service 1d8f1c
            next = l->next;
Packit Service 1d8f1c
Packit Service 1d8f1c
            if (g_strcmp0 (portal_context->owner, name) == 0) {
Packit Service 1d8f1c
                g_object_unref (portal_context);
Packit Service 1d8f1c
            }
Packit Service 1d8f1c
        }
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
static void
Packit Service 1d8f1c
_bus_disconnected_cb (IBusBus            *ibusbus)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    g_main_loop_quit (loop);
Packit Service 1d8f1c
}
Packit Service 1d8f1c
Packit Service 1d8f1c
gint
Packit Service 1d8f1c
main (gint argc, gchar **argv)
Packit Service 1d8f1c
{
Packit Service 1d8f1c
    GDBusConnection *session_bus = NULL;
Packit Service 1d8f1c
    guint owner_id;
Packit Service 1d8f1c
Packit Service 1d8f1c
    setlocale (LC_ALL, "");
Packit Service 1d8f1c
Packit Service 1d8f1c
    GOptionContext *context = g_option_context_new ("- ibus daemon");
Packit Service 1d8f1c
    g_option_context_add_main_entries (context, entries, "ibus-daemon");
Packit Service 1d8f1c
Packit Service 1d8f1c
    GError *error = NULL;
Packit Service 1d8f1c
    if (!g_option_context_parse (context, &argc, &argv, &error)) {
Packit Service 1d8f1c
        g_printerr ("Option parsing failed: %s\n", error->message);
Packit Service 1d8f1c
        g_error_free (error);
Packit Service 1d8f1c
        exit (-1);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    /* Avoid even loading gvfs to avoid accidental confusion */
Packit Service 1d8f1c
    g_setenv ("GIO_USE_VFS", "local", TRUE);
Packit Service 1d8f1c
Packit Service 1d8f1c
    ibus_init ();
Packit Service 1d8f1c
Packit Service 1d8f1c
    ibus_set_log_handler (opt_verbose);
Packit Service 1d8f1c
Packit Service 1d8f1c
    ibus_bus = ibus_bus_new ();
Packit Service 1d8f1c
    if (!ibus_bus_is_connected (ibus_bus)) {
Packit Service 1d8f1c
        g_printerr ("Not connected to the ibus bus\n");
Packit Service 1d8f1c
        exit (1);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_signal_connect (ibus_bus, "disconnected",
Packit Service 1d8f1c
                      G_CALLBACK (_bus_disconnected_cb), NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    loop = g_main_loop_new (NULL, FALSE);
Packit Service 1d8f1c
Packit Service 1d8f1c
    session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
Packit Service 1d8f1c
    if (session_bus == NULL) {
Packit Service 1d8f1c
        g_printerr ("No session bus: %s", error->message);
Packit Service 1d8f1c
        exit (-1);
Packit Service 1d8f1c
    }
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_dbus_connection_signal_subscribe (session_bus,
Packit Service 1d8f1c
                                        "org.freedesktop.DBus",
Packit Service 1d8f1c
                                        "org.freedesktop.DBus",
Packit Service 1d8f1c
                                        "NameOwnerChanged",
Packit Service 1d8f1c
                                        "/org/freedesktop/DBus",
Packit Service 1d8f1c
                                        NULL,
Packit Service 1d8f1c
                                        G_DBUS_SIGNAL_FLAGS_NONE,
Packit Service 1d8f1c
                                        name_owner_changed,
Packit Service 1d8f1c
                                        NULL, NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
Packit Service 1d8f1c
                               IBUS_SERVICE_PORTAL,
Packit Service 1d8f1c
                               G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
Packit Service 1d8f1c
                               (opt_replace ? G_BUS_NAME_OWNER_FLAGS_REPLACE
Packit Service 1d8f1c
                                            : 0),
Packit Service 1d8f1c
                               on_bus_acquired,
Packit Service 1d8f1c
                               on_name_acquired,
Packit Service 1d8f1c
                               on_name_lost,
Packit Service 1d8f1c
                               NULL,
Packit Service 1d8f1c
                               NULL);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_main_loop_run (loop);
Packit Service 1d8f1c
Packit Service 1d8f1c
    g_bus_unown_name (owner_id);
Packit Service 1d8f1c
    g_main_loop_unref (loop);
Packit Service 1d8f1c
Packit Service 1d8f1c
    return 0;
Packit Service 1d8f1c
}