spiegel-keyman/linux/ibus-keyman/src/KeymanSystemServiceClient.cpp
2023-09-21 10:25:48 +02:00

106 lines
2.9 KiB
C++

#include <cassert>
#include <systemd/sd-bus.h>
#include "KeymanSystemServiceClient.h"
#define KEYMAN_BUS_NAME "com.keyman.SystemService1"
#define KEYMAN_INTERFACE_NAME "com.keyman.SystemService1.System"
#define KEYMAN_OBJECT_PATH "/com/keyman/SystemService1/System"
extern gboolean testing;
class KeymanSystemServiceClient {
private:
sd_bus_error *error = NULL;
sd_bus_message *msg = NULL;
sd_bus *bus = NULL;
public:
KeymanSystemServiceClient();
~KeymanSystemServiceClient();
void SetCapsLockIndicator(guint32 capsLock);
gint32 GetCapsLockIndicator();
};
KeymanSystemServiceClient::KeymanSystemServiceClient() {
int result;
if (testing) {
result = sd_bus_open_user(&bus);
} else {
result = sd_bus_default_system(&bus);
}
if (result < 0) {
g_error("%s: Can't get connection: %s", __FUNCTION__, strerror(-result));
}
}
KeymanSystemServiceClient::~KeymanSystemServiceClient() {
if (error) { sd_bus_error_free(error); }
if (msg) { sd_bus_message_unref(msg); }
if (bus) { sd_bus_unref(bus); }
}
void KeymanSystemServiceClient::SetCapsLockIndicator(guint32 capsLock) {
// If Set/GetCapsLockIndicator is called more than once and previously
// failed, we will leak `error`.
assert(error == NULL);
if (!bus) {
// we already reported the error, so just return
return;
}
if (capsLock > 1) {
g_error("%s: Invalid value '%d' for parameter capsLock", __FUNCTION__, capsLock);
return;
}
int result = sd_bus_call_method(bus, KEYMAN_BUS_NAME, KEYMAN_OBJECT_PATH,
KEYMAN_INTERFACE_NAME, "SetCapsLockIndicator", error, &msg, "b", capsLock);
if (result < 0) {
g_error("%s: Failed to call method SetCapsLockIndicator: %s. %s. %s.",
__FUNCTION__, strerror(-result), error ? error->name : "-", error ? error->message : "-");
return;
}
}
gint32 KeymanSystemServiceClient::GetCapsLockIndicator() {
// If Set/GetCapsLockIndicator is called more than once and previously
// failed, we will leak `error`.
assert(error == NULL);
if (!bus) {
// we already reported the error, so just return
return -1;
}
int result = sd_bus_call_method(bus, KEYMAN_BUS_NAME, KEYMAN_OBJECT_PATH,
KEYMAN_INTERFACE_NAME, "GetCapsLockIndicator", error, &msg, "");
if (result < 0) {
g_error("%s: Failed to call method GetCapsLockIndicator: %s. %s. %s.",
__FUNCTION__, strerror(-result), error ? error->name : "-", error ? error->message : "-");
return -1;
}
guint32 capsLock = 0;
result = sd_bus_message_read(msg, "b", &capsLock);
if (result < 0) {
g_error("%s: Failed to parse response message: %s",
__FUNCTION__, strerror(-result));
return -1;
}
return capsLock;
}
void set_capslock_indicator(
guint32 capsLock
) {
KeymanSystemServiceClient client;
client.SetCapsLockIndicator(capsLock);
}
gint32 get_capslock_indicator() {
KeymanSystemServiceClient client;
return client.GetCapsLockIndicator();
}