diff --git a/ibus.c b/ibus.c index e39cb73..a8c7693 100644 --- a/ibus.c +++ b/ibus.c @@ -854,6 +854,10 @@ onmsg(DBusConnection *c, DBusMessage *m, void*) if(strcmp(member, "GetAll") == 0) return handlepropertygetall(c, m); } + /* libibus destroys a context through its Service base interface. */ + if(strcmp(iface, "org.freedesktop.IBus.Service") == 0 && + strcmp(member, "Destroy") == 0) + iface = "org.freedesktop.IBus.InputContext"; if(strcmp(iface, "org.freedesktop.IBus.InputContext") == 0){ ctx = findcontext(c, path); if(ctx == nil) diff --git a/tests/ibus_live_test.c b/tests/ibus_live_test.c index fd1572e..5ba2fad 100644 --- a/tests/ibus_live_test.c +++ b/tests/ibus_live_test.c @@ -39,6 +39,31 @@ invalidcall(DBusConnection *conn, char *path, char *member) return ok; } +/* libibus destroys through the Service interface; the path must go away. */ +static int +destroyed(DBusConnection *conn, char *path) +{ + DBusMessage *m, *reply; + const char *name; + int ok; + + m = dbus_message_new_method_call("org.freedesktop.IBus", path, + "org.freedesktop.IBus.Service", "Destroy"); + reply = callret(conn, m, "Service.Destroy"); + if(reply == NULL) + return 0; + dbus_message_unref(reply); + reply = sendcall(conn, contextcall(path, "FocusIn"), "FocusIn"); + if(reply == NULL) + return 0; + name = dbus_message_get_error_name(reply); + ok = name != NULL && strcmp(name, DBUS_ERROR_UNKNOWN_OBJECT) == 0; + if(!ok) + fail("context survived Service.Destroy"); + dbus_message_unref(reply); + return ok; +} + static int overflowrejected(char *address) { @@ -115,6 +140,7 @@ runcontract(char *address) createcontext(conn, path, sizeof path, "contract context"); for(i = 0; ok && i < (int)(sizeof bad / sizeof bad[0]); i++) ok = invalidcall(conn, path, bad[i]); + ok = ok && destroyed(conn, path); closebus(&conn); return ok; }