Repository: libsdl-org/SDL
File: src/core/linux/SDL_dbus.c (C)

Code before:
bool SDL_DBus_CallVoidMethodOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...)
{
    bool result;
    va_list ap;
    va_start(ap, method);
    result = SDL_DBus_CallVoidMethodInternal(conn, node, path, interface, method, ap);
    va_end(ap);
    return result;
}

bool SDL_DBus_CallVoidMethod(const char *node, const char *path, const char *interface, const char *method, ...)
{
    bool result;
    va_list ap;
    va_start(ap, method);
    result = SDL_DBus_CallVoidMethodInternal(dbus.session_conn, node, path, interface, method, ap);
    va_end(ap);
    return result;
}

bool SDL_DBus_QueryPropertyOnConnection(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *property, int expectedtype, void *result)
{
    bool retval = false;

    // Make sure we're not looking up strings here, otherwise we'd have to save and return the reply
    SDL_assert(expectedtype != DBUS_TYPE_STRING && expectedtype != DBUS_TYPE_OBJECT_PATH);

    if (conn) {
        DBusMessage *msg = dbus.message_new_method_call(node, path, "org.freedesktop.DBus.Properties", "Get");
        if (msg) {
            if (dbus.message_append_args(msg, DBUS_TYPE_STRING, &interface, DBUS_TYPE_STRING, &property, DBUS_TYPE_INVALID)) {
                retval = SDL_DBus_CallWithBasicReply(conn, msg, NULL, expectedtype, result);
            }
            dbus.message_unref(msg);
        }
    }

    return retval;
}

bool SDL_DBus_QueryProperty(const char *node, const char *path, const char *interface, const char *property, int expectedtype, void *result)
{
    return SDL_DBus_QueryPropertyOnConnection(dbus.session_conn, node, path, interface, property, expectedtype, result);
}

void SDL_DBus_ScreensaverTickle(void)
{
    if (screensaver_cookie == 0 && !inhibit_handle) { // no need to tickle if we're inhibiting.
        // org.gnome.ScreenSaver is the legacy interface, but it'll either do nothing or just be a second harmless tickle on newer systems, so we leave it for now.
        SDL_DBus_CallVoidMethod("org.gnome.ScreenSaver", "/org/gnome/ScreenSaver", "org.gnome.ScreenSaver", "SimulateUserActivity", DBUS_TYPE_INVALID);
        SDL_DBus_CallVoidMethod("org.freedesktop.ScreenSaver", "/org/freedesktop/ScreenSaver", "org.freedesktop.ScreenSaver", "SimulateUserActivity", DBUS_TYPE_INVALID);

Review comment (suggestion):
Strictly speaking `DBUS_TYPE_SIGNATURE` is also stringlike, although I doubt you'll ever use it with this method.

libdbus does have functions to classify types. The types that are safe to read out of a message without copying or holding a reference to the message are exactly the "fixed types", for which `dbus_type_is_fixed(t)` returns nonzero. It has existed since at least 1.0.2 which is probably far back enough into retrocomputing.

String properties are quite common, so instead of documenting it as unsafe to call for strings (someone well-meaning will disobey that instruction sooner or later), I'd be inclined to add the `DBusMessage **` to it anyway, and you can just use NULL where you don't need it, ideally with an assertion:

```
SDL_assert(save_reply != NULL || dbus.type_is_fixed(expectedtype));
```

Code after:
        }

        if (dbus.message_iter_get_arg_type(&actual_iter) == expectedtype) {
            dbus.message_iter_get_basic(&actual_iter, result);
            retval = true;
        }

        if (save_reply) {
            *save_reply = reply;
        } else {
            dbus.message_unref(reply);
        }
    }

    return retval;
}

bool SDL_DBus_QueryPropertyOnConnection(DBusConnection *conn, DBusMessage **save_reply, const char *node, const char *path, const char *interface, const char *property, int expectedtype, void *result)
{
    bool retval = false;

    if (conn) {
        DBusMessage *msg = dbus.message_new_method_call(node, path, "org.freedesktop.DBus.Properties", "Get");
        if (msg) {
            if (dbus.message_append_args(msg, DBUS_TYPE_STRING, &interface, DBUS_TYPE_STRING, &property, DBUS_TYPE_INVALID)) {
                retval = SDL_DBus_CallWithBasicReply(conn, save_reply, msg, expectedtype, result);
            }
            dbus.message_unref(msg);
        }
    }

    return retval;
}

bool SDL_DBus_QueryProperty(DBusMessage **save_reply, const char *node, const char *path, const char *interface, const char *property, int expectedtype, void *result)
{
    return SDL_DBus_QueryPropertyOnConnection(dbus.session_conn, save_reply, node, path, interface, property, expectedtype, result);
}

void SDL_DBus_FreeReply(DBusMessage **saved_reply)
{
    DBusMessage *reply = *saved_reply;
    if (reply) {
        dbus.message_unref(reply);
        *saved_reply = NULL;
    }
}

void SDL_DBus_ScreensaverTickle(void)
{
    if (screensaver_cookie == 0 && !inhibit_handle) { // no need to tickle if we're inhibiting.