GDBus signal reaches after GDBus method returns



Do you have any ideas how to receive a GDBus signal before the GDBus method returns?
When I run the following program, the return of "KeyEvent" is always output faster than "CommitText" signal 
in the client program.
Or do you have any ideas to know if the returned GDBus method emitted a GDBus signal in the server side?

--------- start of server -----------------
#include <gio/gio.h>
#include <stdlib.h>

#define DBUS_NAME "org.test.GDBus.Example"
#define DBUS_PATH "/org/test/GDBus/Example"
#define DBUS_IFACE "org.test.GDBus.Example"

#define XML_TEMPLATE \
    "<node>"                                                         \
    "  <interface name= 'org.test.GDBus.Example'>"                   \
    "    <method name= 'X11KeyEvent'>"                               \
    "      <arg type= 'u' name= 'keysym' direction= 'in'/>"          \
    "      <arg type= 'b' name= 'processed' direction= 'out'/>"      \
    "    </method>"                                                  \
    "    <signal name='CommitText'>"                                 \
    "      <arg type='s' name='text' />"                             \
    "    </signal>"                                                  \
    "  </interface>"                                                 \
    "</node>"

static GDBusNodeInfo *introspection_data = NULL;

static void method_call_handler (GDBusConnection *connection,
                                 const gchar *sender,
                                 const gchar *object_path,
                                 const gchar *interface_name,
                                 const gchar *method_name,
                                 GVariant *parameters,
                                 GDBusMethodInvocation *invocation,
                                 gpointer user_data)
{
    if (g_strcmp0 (method_name, "X11KeyEvent") == 0) {
        guint32 keysym = 0;
        gchar buf[10];
        gboolean processed = FALSE;
        GError *error = NULL;

        g_variant_get (parameters, "(u)", &keysym);
        if (g_ascii_isalpha (keysym))
            processed = TRUE;
        if (keysym == '\n' || keysym == ' ') {
            buf[g_unichar_to_utf8 (0x21a9, buf)] = '\0';
            if (!g_dbus_connection_emit_signal (connection,
                                                sender,
                                                object_path,
                                                interface_name,
                                                "CommitText",
                                                g_variant_new ("(s)", buf),
                                                &error)) {
                g_warning ("Error in dbus signal: %s", error->message);
                g_clear_error (&error);
            }
        }

        g_dbus_method_invocation_return_value (
                invocation,
                g_variant_new("(b)", processed));
        g_print ("Got 0x%x\n", keysym);
        return;
    }
}

static const GDBusInterfaceVTable vtable =
{
    method_call_handler
};

static void bus_acquired_handler (GDBusConnection *connection,
                                  const gchar     *name,
                                  gpointer         user_data)
{
    guint registration_id = g_dbus_connection_register_object (
            connection,
            DBUS_PATH,
            introspection_data->interfaces[0],
            &vtable,
            NULL, NULL, NULL);
  g_assert (registration_id > 0);
}

int
main (int argc, char ** argv)
{
    guint id;
    GMainLoop *g_main_loop;
    introspection_data = g_dbus_node_info_new_for_xml (XML_TEMPLATE, NULL);

    id = g_bus_own_name (G_BUS_TYPE_SESSION,
                         DBUS_NAME,
                         G_BUS_NAME_OWNER_FLAGS_NONE,
                         bus_acquired_handler,
                         NULL,
                         NULL,
                         NULL,
                         NULL);

    g_main_loop = g_main_loop_new (NULL, FALSE);
    g_main_loop_run (g_main_loop);

    g_bus_unown_name (id);
    g_dbus_node_info_unref (introspection_data);
    return (0);
}

--------- end of server -----------------

--------- start of client -----------------
#include <gio/gio.h>

#include <stdio.h>
#include <stdlib.h>

#define DBUS_NAME "org.test.GDBus.Example"
#define DBUS_PATH "/org/test/GDBus/Example"
#define DBUS_IFACE "org.test.GDBus.Example"

static int elapsed;
static GMainLoop *loop;

static void
g_signal_cb (GDBusProxy *proxy,
             const gchar *sender_name,
             const gchar *signal_name,
             GVariant    *parameters)
{

    if (!g_strcmp0 (signal_name, "CommitText")) {
        const gchar *text = NULL;
        g_variant_get (parameters, "(&s)", &text);
        printf ("CommitText: %s\n", text);
        elapsed++;
        if (elapsed == 2 && loop) {
            g_main_loop_quit (loop);
            loop = NULL;
        }
        return;
    }
}

int
main (int argc, char ** argv)
{
    GDBusConnection *connection;
    GError *error = NULL;
    GDBusProxy *proxy;
    guint32 keysym = ' ';
    GVariant *result;

    connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
    g_assert_no_error (error);
    g_assert (connection != NULL);
    g_assert (!g_dbus_connection_is_closed (connection));

    error = NULL;
    proxy = g_dbus_proxy_new_sync (connection,
                                   G_DBUS_PROXY_FLAGS_NONE,
                                   NULL,
                                   DBUS_NAME,
                                   DBUS_PATH,
                                   DBUS_IFACE,
                                   NULL,
                                   &error);
    g_assert_no_error (error);

    g_signal_connect (proxy,
                      "g-signal",
                      G_CALLBACK (g_signal_cb),
                      NULL);
    error = NULL;
    result = g_dbus_proxy_call_sync (proxy,
                                     "X11KeyEvent",
                                     g_variant_new("(u)", keysym),
                                     G_DBUS_CALL_FLAGS_NONE,
                                     -1, NULL, &error);
    if (result != NULL) {
        gboolean processed = TRUE;
        g_variant_get (result, "(b)", &processed);
        if (!processed) {
            g_print ("KeyEvent: 0x%x\n", keysym);
        }
        g_variant_unref (result);
    } else {
        g_warning ("Got error: %s", error->message);
        g_clear_pointer (&error, g_error_free);
        g_assert_not_reached ();
    }
    elapsed++;

    if (elapsed < 2) {
        loop = g_main_loop_new (NULL, FALSE);
        g_main_loop_run (loop);
    }

    return 0;
}
--------- end of client -----------------


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]