Make the DBUS APIs async
This commit is contained in:
parent
78cda7aa74
commit
dd9e484336
106
glfw/dbus_glfw.c
vendored
106
glfw/dbus_glfw.c
vendored
@ -211,45 +211,93 @@ glfw_dbus_call_void_method(DBusConnection *conn, const char *node, const char *p
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GLFWbool
|
GLFWbool
|
||||||
call_method(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, va_list ap) {
|
glfw_dbus_get_args(DBusMessage *msg, const char *failmsg, ...) {
|
||||||
GLFWbool retval = GLFW_FALSE;
|
DBusError err;
|
||||||
|
dbus_error_init(&err);
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, failmsg);
|
||||||
|
int firstarg = va_arg(ap, int);
|
||||||
|
GLFWbool ret = dbus_message_get_args_valist(msg, &err, firstarg, ap) ? GLFW_TRUE : GLFW_FALSE;
|
||||||
|
va_end(ap);
|
||||||
|
if (!ret) report_error(&err, failmsg);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
if (conn) {
|
typedef struct {
|
||||||
DBusMessage *msg = dbus_message_new_method_call(node, path, interface, method);
|
dbus_pending_callback callback;
|
||||||
if (msg) {
|
void *user_data;
|
||||||
int firstarg = va_arg(ap, int);
|
} MethodResponse;
|
||||||
if ((firstarg == DBUS_TYPE_INVALID) || dbus_message_append_args_valist(msg, firstarg, ap)) {
|
|
||||||
DBusError err;
|
static const char*
|
||||||
dbus_error_init(&err);
|
format_message_error(DBusError *err) {
|
||||||
DBusMessage *reply = dbus_connection_send_with_reply_and_block(conn, msg, 300, &err);
|
static char buf[1024];
|
||||||
if (reply) {
|
snprintf(buf, sizeof(buf), "[%s] %s", err->name ? err->name : "", err->message);
|
||||||
firstarg = va_arg(ap, int);
|
return buf;
|
||||||
dbus_error_free(&err);
|
}
|
||||||
if ((firstarg == DBUS_TYPE_INVALID) || dbus_message_get_args_valist(reply, &err, firstarg, ap)) {
|
|
||||||
retval = GLFW_TRUE;
|
static void
|
||||||
} else {
|
method_reply_received(DBusPendingCall *pending, void *user_data) {
|
||||||
report_error(&err, "Failed to get reply args from DBUS method: %s on node: %s and interface: %s", method, node, interface);
|
MethodResponse *res = (MethodResponse*)user_data;
|
||||||
}
|
DBusMessage *msg = dbus_pending_call_steal_reply(pending);
|
||||||
dbus_message_unref(reply);
|
if (msg) {
|
||||||
} else {
|
DBusError err;
|
||||||
report_error(&err, "Failed to call DBUS method: %s on node: %s and interface: %s", method, node, interface);
|
dbus_error_init(&err);
|
||||||
}
|
if (dbus_set_error_from_message(&err, msg)) res->callback(NULL, format_message_error(&err), res->user_data);
|
||||||
}
|
else res->callback(msg, NULL, res->user_data);
|
||||||
dbus_message_unref(msg);
|
dbus_message_unref(msg);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLFWbool
|
||||||
|
call_method(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, dbus_pending_callback callback, void *user_data, va_list ap) {
|
||||||
|
if (!conn) return GLFW_FALSE;
|
||||||
|
DBusMessage *msg = dbus_message_new_method_call(node, path, interface, method);
|
||||||
|
if (!msg) return GLFW_FALSE;
|
||||||
|
GLFWbool retval = GLFW_FALSE;
|
||||||
|
MethodResponse *res = malloc(sizeof(MethodResponse));
|
||||||
|
if (!res) { dbus_message_unref(msg); return GLFW_FALSE; }
|
||||||
|
res->callback = callback;
|
||||||
|
res->user_data = user_data;
|
||||||
|
|
||||||
|
int firstarg = va_arg(ap, int);
|
||||||
|
if ((firstarg == DBUS_TYPE_INVALID) || dbus_message_append_args_valist(msg, firstarg, ap)) {
|
||||||
|
if (callback) {
|
||||||
|
DBusPendingCall *pending = NULL;
|
||||||
|
if (dbus_connection_send_with_reply(conn, msg, &pending, DBUS_TIMEOUT_USE_DEFAULT)) {
|
||||||
|
dbus_pending_call_set_notify(pending, method_reply_received, res, free);
|
||||||
|
} else {
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to call DBUS method: %s on node: %s and interface: %s out of memory", method, node, interface);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!dbus_connection_send(conn, msg, NULL)) {
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to call DBUS method: %s on node: %s and interface: %s out of memory", method, node, interface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to call DBUS method: %s on node: %s and interface: %s could not add arguments", method, node, interface);
|
||||||
|
}
|
||||||
|
dbus_message_unref(msg);
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWbool
|
GLFWbool
|
||||||
glfw_dbus_call_method(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...) {
|
glfw_dbus_call_method_with_reply(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, dbus_pending_callback callback, void* user_data, ...) {
|
||||||
|
GLFWbool retval;
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, user_data);
|
||||||
|
retval = call_method(conn, node, path, interface, method, callback, user_data, ap);
|
||||||
|
va_end(ap);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLFWbool
|
||||||
|
glfw_dbus_call_method_no_reply(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...) {
|
||||||
GLFWbool retval;
|
GLFWbool retval;
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, method);
|
va_start(ap, method);
|
||||||
retval = call_method(conn, node, path, interface, method, ap);
|
retval = call_method(conn, node, path, interface, method, NULL, NULL, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
7
glfw/dbus_glfw.h
vendored
7
glfw/dbus_glfw.h
vendored
@ -30,6 +30,8 @@
|
|||||||
#include <dbus/dbus.h>
|
#include <dbus/dbus.h>
|
||||||
#include "backend_utils.h"
|
#include "backend_utils.h"
|
||||||
|
|
||||||
|
typedef void(*dbus_pending_callback)(DBusMessage *msg, const char* err, void* data);
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
EventLoopData* eld;
|
EventLoopData* eld;
|
||||||
} _GLFWDBUSData;
|
} _GLFWDBUSData;
|
||||||
@ -41,5 +43,8 @@ DBusConnection* glfw_dbus_connect_to(const char *path, const char* err_msg);
|
|||||||
void glfw_dbus_close_connection(DBusConnection *conn);
|
void glfw_dbus_close_connection(DBusConnection *conn);
|
||||||
GLFWbool glfw_dbus_call_void_method(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...);
|
GLFWbool glfw_dbus_call_void_method(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...);
|
||||||
GLFWbool
|
GLFWbool
|
||||||
glfw_dbus_call_method(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...);
|
glfw_dbus_call_method_no_reply(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...);
|
||||||
|
GLFWbool
|
||||||
|
glfw_dbus_call_method_with_reply(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, dbus_pending_callback callback, void *user_data, ...);
|
||||||
void glfw_dbus_dispatch(DBusConnection *);
|
void glfw_dbus_dispatch(DBusConnection *);
|
||||||
|
GLFWbool glfw_dbus_get_args(DBusMessage *msg, const char *failmsg, ...);
|
||||||
|
|||||||
43
glfw/ibus_glfw.c
vendored
43
glfw/ibus_glfw.c
vendored
@ -153,11 +153,30 @@ read_ibus_address(_GLFWIBUSData *ibus) {
|
|||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
input_context_created(DBusMessage *msg, const char* errmsg, void *data) {
|
||||||
|
if (errmsg) {
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "IBUS: Failed to create input context with error: %s", errmsg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const char *path = NULL;
|
||||||
|
if (!glfw_dbus_get_args(msg, "Failed to get IBUS context path from reply", DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID)) return;
|
||||||
|
_GLFWIBUSData *ibus = (_GLFWIBUSData*)data;
|
||||||
|
free((void*)ibus->input_ctx_path);
|
||||||
|
ibus->input_ctx_path = strdup(path);
|
||||||
|
enum Capabilities caps = IBUS_CAP_FOCUS | IBUS_CAP_PREEDIT_TEXT;
|
||||||
|
if (!glfw_dbus_call_void_method(ibus->conn, IBUS_SERVICE, ibus->input_ctx_path, IBUS_INPUT_INTERFACE, "SetCapabilities", DBUS_TYPE_UINT32, &caps, DBUS_TYPE_INVALID)) return;
|
||||||
|
glfw_ibus_set_focused(ibus, GLFW_FALSE);
|
||||||
|
set_cursor_geometry(ibus, 0, 0, 0, 0);
|
||||||
|
debug("Connected to IBUS daemon for IME input management\n");
|
||||||
|
ibus->ok = GLFW_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
GLFWbool
|
GLFWbool
|
||||||
setup_connection(_GLFWIBUSData *ibus) {
|
setup_connection(_GLFWIBUSData *ibus) {
|
||||||
const char *path = NULL;
|
|
||||||
const char *client_name = "GLFW_Application";
|
const char *client_name = "GLFW_Application";
|
||||||
const char *address_file_name = get_ibus_address_file_name();
|
const char *address_file_name = get_ibus_address_file_name();
|
||||||
|
ibus->ok = GLFW_FALSE;
|
||||||
if (!address_file_name) return GLFW_FALSE;
|
if (!address_file_name) return GLFW_FALSE;
|
||||||
free((void*)ibus->address_file_name);
|
free((void*)ibus->address_file_name);
|
||||||
ibus->address_file_name = strdup(address_file_name);
|
ibus->address_file_name = strdup(address_file_name);
|
||||||
@ -169,25 +188,17 @@ setup_connection(_GLFWIBUSData *ibus) {
|
|||||||
debug("Connecting to IBUS daemon @ %s for IME input management\n", ibus->address);
|
debug("Connecting to IBUS daemon @ %s for IME input management\n", ibus->address);
|
||||||
ibus->conn = glfw_dbus_connect_to(ibus->address, "Failed to connect to the IBUS daemon, with error");
|
ibus->conn = glfw_dbus_connect_to(ibus->address, "Failed to connect to the IBUS daemon, with error");
|
||||||
if (!ibus->conn) return GLFW_FALSE;
|
if (!ibus->conn) return GLFW_FALSE;
|
||||||
if (!glfw_dbus_call_method(ibus->conn, IBUS_SERVICE, IBUS_PATH, IBUS_INTERFACE, "CreateInputContext",
|
free((void*)ibus->input_ctx_path); ibus->input_ctx_path = NULL;
|
||||||
DBUS_TYPE_STRING, &client_name, DBUS_TYPE_INVALID,
|
if (!glfw_dbus_call_method_with_reply(
|
||||||
DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID)) return GLFW_FALSE;
|
ibus->conn, IBUS_SERVICE, IBUS_PATH, IBUS_INTERFACE, "CreateInputContext", input_context_created, ibus,
|
||||||
free((void*)ibus->input_ctx_path);
|
DBUS_TYPE_STRING, &client_name, DBUS_TYPE_INVALID)) {
|
||||||
ibus->input_ctx_path = strdup(path);
|
return GLFW_FALSE;
|
||||||
enum Capabilities caps = IBUS_CAP_FOCUS | IBUS_CAP_PREEDIT_TEXT;
|
}
|
||||||
if (!glfw_dbus_call_void_method(ibus->conn, IBUS_SERVICE, ibus->input_ctx_path, IBUS_INPUT_INTERFACE, "SetCapabilities", DBUS_TYPE_UINT32, &caps, DBUS_TYPE_INVALID)) return GLFW_FALSE;
|
|
||||||
|
|
||||||
dbus_connection_flush(ibus->conn);
|
dbus_connection_flush(ibus->conn);
|
||||||
dbus_bus_add_match(ibus->conn, "type='signal',interface='org.freedesktop.IBus.InputContext'", NULL);
|
dbus_bus_add_match(ibus->conn, "type='signal',interface='org.freedesktop.IBus.InputContext'", NULL);
|
||||||
|
|
||||||
DBusObjectPathVTable ibus_vtable = {.message_function = message_handler};
|
DBusObjectPathVTable ibus_vtable = {.message_function = message_handler};
|
||||||
dbus_connection_try_register_object_path(ibus->conn, ibus->input_ctx_path, &ibus_vtable, ibus, NULL);
|
dbus_connection_try_register_object_path(ibus->conn, ibus->input_ctx_path, &ibus_vtable, ibus, NULL);
|
||||||
dbus_connection_flush(ibus->conn);
|
dbus_connection_flush(ibus->conn);
|
||||||
glfw_ibus_set_focused(ibus, GLFW_FALSE);
|
|
||||||
set_cursor_geometry(ibus, 0, 0, 0, 0);
|
|
||||||
debug("Connected to IBUS daemon for IME input management\n");
|
|
||||||
ibus->ok = GLFW_TRUE;
|
|
||||||
|
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,7 +262,7 @@ glfw_ibus_set_focused(_GLFWIBUSData *ibus, GLFWbool focused) {
|
|||||||
static void
|
static void
|
||||||
set_cursor_geometry(_GLFWIBUSData *ibus, int x, int y, int w, int h) {
|
set_cursor_geometry(_GLFWIBUSData *ibus, int x, int y, int w, int h) {
|
||||||
if (check_connection(ibus)) {
|
if (check_connection(ibus)) {
|
||||||
glfw_dbus_call_method(ibus->conn, IBUS_SERVICE, ibus->input_ctx_path, IBUS_INPUT_INTERFACE, "SetCursorLocation",
|
glfw_dbus_call_method_no_reply(ibus->conn, IBUS_SERVICE, ibus->input_ctx_path, IBUS_INPUT_INTERFACE, "SetCursorLocation",
|
||||||
DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y, DBUS_TYPE_INT32, &w, DBUS_TYPE_INT32, &h, DBUS_TYPE_INVALID);
|
DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y, DBUS_TYPE_INT32, &w, DBUS_TYPE_INT32, &h, DBUS_TYPE_INVALID);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user