Add Ctrl+space customization.
[platform/upstream/ibus.git] / src / ibusproxy.c
1 /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
2 /* vim:set et sts=4: */
3 /* ibus - The Input Bus
4  * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
5  * Copyright (C) 2008-2010 Red Hat, Inc.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #include "ibusproxy.h"
24 #include "ibusmarshalers.h"
25 #include "ibusinternal.h"
26 #include "ibusobject.h"
27
28 #define IBUS_PROXY_GET_PRIVATE(o)  \
29    (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_PROXY, IBusProxyPrivate))
30
31 enum {
32     DESTROY,
33     LAST_SIGNAL,
34 };
35
36 static guint            proxy_signals[LAST_SIGNAL] = { 0 };
37
38 /* functions prototype */
39 static void      ibus_proxy_dispose         (GObject            *object);
40 static void      ibus_proxy_real_destroy    (IBusProxy          *proxy);
41
42 static void      ibus_proxy_connection_closed_cb
43                                             (GDBusConnection    *connection,
44                                              gboolean            remote_peer_vanished,
45                                              GError             *error,
46                                              IBusProxy          *proxy);
47 static void      initable_iface_init        (GInitableIface     *initable_iface);
48 static void      async_initable_iface_init  (GAsyncInitableIface
49                                                                 *async_initable_iface);
50 G_DEFINE_TYPE_WITH_CODE (IBusProxy, ibus_proxy, G_TYPE_DBUS_PROXY,
51                          G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init)
52                          G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init)
53                          );
54
55 static void
56 ibus_proxy_class_init (IBusProxyClass *class)
57 {
58     GObjectClass *gobject_class = G_OBJECT_CLASS (class);
59
60     gobject_class->dispose = ibus_proxy_dispose;
61
62     class->destroy = ibus_proxy_real_destroy;
63
64     /* install signals */
65     /**
66      * IBusProxy::destroy:
67      * @object: An IBusProxy.
68      *
69      * Destroy and free an IBusProxy
70      *
71      * See also:  ibus_proxy_destroy().
72      *
73      * <note><para>Argument @user_data is ignored in this function.</para></note>
74      */
75     proxy_signals[DESTROY] =
76         g_signal_new (I_("destroy"),
77             G_TYPE_FROM_CLASS (gobject_class),
78             G_SIGNAL_RUN_LAST,
79             G_STRUCT_OFFSET (IBusProxyClass, destroy),
80             NULL, NULL,
81             _ibus_marshal_VOID__VOID,
82             G_TYPE_NONE, 0);
83 }
84
85 static void
86 ibus_proxy_init (IBusProxy *proxy)
87 {
88     proxy->own = TRUE;
89 }
90
91 /**
92  * ibus_proxy_dispose:
93  *
94  * Override GObject's dispose function.
95  */
96 static void
97 ibus_proxy_dispose (GObject *object)
98 {
99     if (! (IBUS_PROXY_FLAGS (object) & IBUS_IN_DESTRUCTION)) {
100         IBUS_PROXY_SET_FLAGS (object, IBUS_IN_DESTRUCTION);
101         if (! (IBUS_PROXY_FLAGS (object) & IBUS_DESTROYED)) {
102             g_signal_emit (object, proxy_signals[DESTROY], 0);
103             IBUS_PROXY_SET_FLAGS (object, IBUS_DESTROYED);
104         }
105         IBUS_PROXY_UNSET_FLAGS (object, IBUS_IN_DESTRUCTION);
106     }
107
108     G_OBJECT_CLASS(ibus_proxy_parent_class)->dispose (object);
109 }
110
111 /**
112  * ibus_proxy_real_destroy:
113  *
114  * Handle "destroy" signal which is emitted by ibus_proxy_dispose.
115  */
116 static void
117 ibus_proxy_real_destroy (IBusProxy *proxy)
118 {
119     GDBusConnection *connection = g_dbus_proxy_get_connection ((GDBusProxy *) proxy);
120     g_assert (connection != NULL);
121     if (!g_dbus_connection_is_closed (connection) && proxy->own) {
122         g_dbus_proxy_call ((GDBusProxy *)proxy,
123                            "org.freedesktop.IBus.Service.Destroy",
124                            NULL,
125                            G_DBUS_CALL_FLAGS_NONE,
126                            -1, NULL, NULL, NULL);
127     }
128     g_signal_handlers_disconnect_by_func (connection,
129                                           (GCallback) ibus_proxy_connection_closed_cb,
130                                           proxy);
131 }
132
133 static void
134 ibus_proxy_connection_closed_cb (GDBusConnection *connection,
135                                  gboolean         remote_peer_vanished,
136                                  GError          *error,
137                                  IBusProxy       *proxy)
138 {
139     ibus_proxy_destroy (proxy);
140 }
141
142 void
143 ibus_proxy_destroy (IBusProxy *proxy)
144 {
145     g_assert (IBUS_IS_PROXY (proxy));
146
147     if (! (IBUS_PROXY_FLAGS (proxy) & IBUS_IN_DESTRUCTION)) {
148         g_object_run_dispose (G_OBJECT (proxy));
149     }
150 }
151
152 static gboolean
153 ibus_proxy_init_finish (IBusProxy  *proxy,
154                         GError    **error)
155 {
156     g_assert (IBUS_IS_PROXY (proxy));
157     g_assert (error == NULL || *error == NULL);
158
159     GDBusConnection *connection =
160             g_dbus_proxy_get_connection ((GDBusProxy *)proxy);
161
162     if (connection == NULL || g_dbus_connection_is_closed (connection)) {
163         /*
164          * When proxy is created asynchronously, the connection may be closed
165          * before proxy is ready. In this case, we need override interfaces
166          * GInitable and GAsyncInitable to report the error.
167          */
168         if (error != NULL)
169             *error = g_error_new (G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
170                     "Connection is closed.");
171         return FALSE;
172     }
173
174     g_signal_connect (connection, "closed",
175             G_CALLBACK (ibus_proxy_connection_closed_cb), proxy);
176
177     return TRUE;
178 }
179
180
181 static GInitableIface *initable_iface_parent = NULL;
182
183 static gboolean
184 initable_init (GInitable     *initable,
185                GCancellable  *cancellable,
186                GError       **error)
187 {
188     if (!initable_iface_parent->init (initable, cancellable, error))
189         return FALSE;
190     return ibus_proxy_init_finish ((IBusProxy *)initable, error);
191 }
192
193 static void
194 initable_iface_init (GInitableIface *initable_iface)
195 {
196     initable_iface_parent = g_type_interface_peek_parent (initable_iface);
197     initable_iface->init = initable_init;
198 }
199
200 static GAsyncInitableIface *async_initable_iface_parent = NULL;
201
202 static void
203 async_initable_init_async (GAsyncInitable      *initable,
204                            gint                 io_priority,
205                            GCancellable        *cancellable,
206                            GAsyncReadyCallback  callback,
207                            gpointer             user_data)
208 {
209     async_initable_iface_parent->init_async (initable,
210             io_priority, cancellable, callback, user_data);
211 }
212
213 static gboolean
214 async_initable_init_finish (GAsyncInitable  *initable,
215                             GAsyncResult    *res,
216                             GError         **error)
217 {
218     if (!async_initable_iface_parent->init_finish (initable, res, error))
219         return FALSE;
220     return ibus_proxy_init_finish ((IBusProxy *)initable, error);
221 }
222
223 static void
224 async_initable_iface_init (GAsyncInitableIface *async_initable_iface)
225 {
226     async_initable_iface_parent = g_type_interface_peek_parent (async_initable_iface);
227     async_initable_iface->init_async = async_initable_init_async;
228     async_initable_iface->init_finish = async_initable_init_finish;
229 }