Fix remaining sync BUS calls

Also work on IBUS integration
This commit is contained in:
Kovid Goyal
2018-07-10 13:30:36 +05:30
parent 3b226618ad
commit 8675659fcb
5 changed files with 103 additions and 40 deletions

37
glfw/dbus_glfw.c vendored
View File

@@ -180,38 +180,6 @@ glfw_dbus_close_connection(DBusConnection *conn) {
dbus_connection_unref(conn);
}
static GLFWbool
call_void_method(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, va_list ap) {
GLFWbool retval = GLFW_FALSE;
if (conn) {
DBusMessage *msg = dbus_message_new_method_call(node, path, interface, method);
if (msg) {
int firstarg = va_arg(ap, int);
if ((firstarg == DBUS_TYPE_INVALID) || dbus_message_append_args_valist(msg, firstarg, ap)) {
if (dbus_connection_send(conn, msg, NULL)) {
dbus_connection_flush(conn);
retval = GLFW_TRUE;
}
}
dbus_message_unref(msg);
}
}
return retval;
}
GLFWbool
glfw_dbus_call_void_method(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...) {
GLFWbool retval;
va_list ap;
va_start(ap, method);
retval = call_void_method(conn, node, path, interface, method, ap);
va_end(ap);
return retval;
}
GLFWbool
glfw_dbus_get_args(DBusMessage *msg, const char *failmsg, ...) {
DBusError err;
@@ -267,11 +235,14 @@ call_method(DBusConnection *conn, const char *node, const char *path, const char
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);
retval = GLFW_TRUE;
} 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)) {
if (dbus_connection_send(conn, msg, NULL)) {
retval = GLFW_TRUE;
} else {
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to call DBUS method: %s on node: %s and interface: %s out of memory", method, node, interface);
}
}

1
glfw/dbus_glfw.h vendored
View File

@@ -41,7 +41,6 @@ GLFWbool glfw_dbus_init(_GLFWDBUSData *dbus, EventLoopData *eld);
void glfw_dbus_terminate(_GLFWDBUSData *dbus);
DBusConnection* glfw_dbus_connect_to(const char *path, const char* err_msg, const char* name);
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_method_no_reply(DBusConnection *conn, const char *node, const char *path, const char *interface, const char *method, ...);
GLFWbool

91
glfw/ibus_glfw.c vendored
View File

@@ -164,8 +164,12 @@ input_context_created(DBusMessage *msg, const char* errmsg, void *data) {
_GLFWIBUSData *ibus = (_GLFWIBUSData*)data;
free((void*)ibus->input_ctx_path);
ibus->input_ctx_path = strdup(path);
if (!ibus->input_ctx_path) return;
dbus_bus_add_match(ibus->conn, "type='signal',interface='org.freedesktop.IBus.InputContext'", NULL);
DBusObjectPathVTable ibus_vtable = {.message_function = message_handler};
dbus_connection_try_register_object_path(ibus->conn, ibus->input_ctx_path, &ibus_vtable, ibus, NULL);
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;
if (!glfw_dbus_call_method_no_reply(ibus->conn, IBUS_SERVICE, ibus->input_ctx_path, IBUS_INPUT_INTERFACE, "SetCapabilities", DBUS_TYPE_UINT32, &caps, DBUS_TYPE_INVALID)) return;
ibus->ok = GLFW_TRUE;
glfw_ibus_set_focused(ibus, GLFW_FALSE);
set_cursor_geometry(ibus, 0, 0, 0, 0);
@@ -195,10 +199,6 @@ setup_connection(_GLFWIBUSData *ibus) {
return GLFW_FALSE;
}
dbus_connection_flush(ibus->conn);
dbus_bus_add_match(ibus->conn, "type='signal',interface='org.freedesktop.IBus.InputContext'", NULL);
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_flush(ibus->conn);
return GLFW_TRUE;
}
@@ -250,7 +250,7 @@ glfw_ibus_dispatch(_GLFWIBUSData *ibus) {
static void
simple_message(_GLFWIBUSData *ibus, const char *method) {
if (check_connection(ibus)) {
glfw_dbus_call_void_method(ibus->conn, IBUS_SERVICE, ibus->input_ctx_path, IBUS_INPUT_INTERFACE, method, DBUS_TYPE_INVALID);
glfw_dbus_call_method_no_reply(ibus->conn, IBUS_SERVICE, ibus->input_ctx_path, IBUS_INPUT_INTERFACE, method, DBUS_TYPE_INVALID);
}
}
@@ -266,3 +266,82 @@ set_cursor_geometry(_GLFWIBUSData *ibus, int x, int y, int w, int h) {
DBUS_TYPE_INT32, &x, DBUS_TYPE_INT32, &y, DBUS_TYPE_INT32, &w, DBUS_TYPE_INT32, &h, DBUS_TYPE_INVALID);
}
}
typedef enum
{
IBUS_SHIFT_MASK = 1 << 0,
IBUS_LOCK_MASK = 1 << 1,
IBUS_CONTROL_MASK = 1 << 2,
IBUS_MOD1_MASK = 1 << 3,
IBUS_MOD2_MASK = 1 << 4,
IBUS_MOD3_MASK = 1 << 5,
IBUS_MOD4_MASK = 1 << 6,
IBUS_MOD5_MASK = 1 << 7,
IBUS_BUTTON1_MASK = 1 << 8,
IBUS_BUTTON2_MASK = 1 << 9,
IBUS_BUTTON3_MASK = 1 << 10,
IBUS_BUTTON4_MASK = 1 << 11,
IBUS_BUTTON5_MASK = 1 << 12,
/* The next few modifiers are used by XKB, so we skip to the end.
* Bits 15 - 23 are currently unused. Bit 29 is used internally.
*/
/* ibus mask */
IBUS_HANDLED_MASK = 1 << 24,
IBUS_FORWARD_MASK = 1 << 25,
IBUS_IGNORED_MASK = IBUS_FORWARD_MASK,
IBUS_SUPER_MASK = 1 << 26,
IBUS_HYPER_MASK = 1 << 27,
IBUS_META_MASK = 1 << 28,
IBUS_RELEASE_MASK = 1 << 30,
IBUS_MODIFIER_MASK = 0x5f001fff
} IBusModifierType;
static inline uint32_t
ibus_key_state(unsigned int glfw_modifiers, int action) {
uint32_t ans = action == GLFW_RELEASE ? IBUS_RELEASE_MASK : 0;
#define M(g, i) if(glfw_modifiers & GLFW_MOD_##g) ans |= i
M(SHIFT, IBUS_SHIFT_MASK);
M(CAPS_LOCK, IBUS_LOCK_MASK);
M(CONTROL, IBUS_CONTROL_MASK);
M(ALT, IBUS_MOD1_MASK);
M(NUM_LOCK, IBUS_MOD2_MASK);
M(SUPER, IBUS_MOD4_MASK);
#undef M
return ans;
}
void
key_event_processed(DBusMessage *msg, const char* errmsg, void *data) {
if (errmsg) {
_glfwInputError(GLFW_PLATFORM_ERROR, "IBUS: Failed to process key with error: %s", errmsg);
return;
}
uint32_t handled;
if (!glfw_dbus_get_args(msg, "Failed to get IBUS handled key from reply", DBUS_TYPE_BOOLEAN, &handled, DBUS_TYPE_INVALID)) return;
KeyEvent *ev = (KeyEvent*)data;
free(ev);
}
GLFWbool
process_key(const KeyEvent *ev_) {
if (!check_connection(ev_->ibus)) return GLFW_FALSE;
KeyEvent *ev = malloc(sizeof(KeyEvent));
if (!ev) return GLFW_FALSE;
memcpy(ev, ev_, sizeof(KeyEvent));
uint32_t state = ibus_key_state(ev->glfw_modifiers, ev->action);
if (!glfw_dbus_call_method_with_reply(
ev->ibus->conn, IBUS_SERVICE, ev->ibus->input_ctx_path, IBUS_INPUT_INTERFACE, "ProcessKeyEvent",
key_event_processed, ev,
DBUS_TYPE_UINT32, &ev->keysym, DBUS_TYPE_UINT32, &ev->keycode, DBUS_TYPE_UINT32,
&state, DBUS_TYPE_INVALID)) {
free(ev);
return GLFW_FALSE;
}
return GLFW_TRUE;
}

10
glfw/ibus_glfw.h vendored
View File

@@ -28,6 +28,7 @@
#pragma once
#include "dbus_glfw.h"
#include <xkbcommon/xkbcommon.h>
typedef struct {
GLFWbool ok, inited;
@@ -36,7 +37,16 @@ typedef struct {
const char *input_ctx_path, *address_file_name, *address;
} _GLFWIBUSData;
typedef struct {
xkb_keycode_t keycode;
xkb_keysym_t keysym;
unsigned int glfw_modifiers;
int action;
_GLFWIBUSData *ibus;
} KeyEvent;
void glfw_connect_to_ibus(_GLFWIBUSData *ibus);
void glfw_ibus_terminate(_GLFWIBUSData *ibus);
void glfw_ibus_set_focused(_GLFWIBUSData *ibus, GLFWbool focused);
void glfw_ibus_dispatch(_GLFWIBUSData *ibus);
GLFWbool process_key(const KeyEvent *ev_);

4
glfw/xkb_glfw.c vendored
View File

@@ -408,6 +408,7 @@ format_xkb_mods(_GLFWXKBData *xkb, const char* name, xkb_mod_mask_t mods) {
void
glfw_xkb_handle_key_event(_GLFWwindow *window, _GLFWXKBData *xkb, xkb_keycode_t scancode, int action) {
const xkb_keysym_t *syms, *clean_syms, *default_syms;
static KeyEvent ev;
xkb_keysym_t glfw_sym;
xkb_keycode_t code_for_sym = scancode;
#ifdef _GLFW_WAYLAND
@@ -425,6 +426,9 @@ glfw_xkb_handle_key_event(_GLFWwindow *window, _GLFWXKBData *xkb, xkb_keycode_t
}
glfw_sym = clean_syms[0];
debug("clean_sym: %s ", glfw_xkb_keysym_name(clean_syms[0]));
ev.action = action; ev.glfw_modifiers = xkb->modifiers; ev.keycode = scancode; ev.keysym = glfw_sym;
ev.ibus = &xkb->ibus;
process_key(&ev);
if (action == GLFW_PRESS || action == GLFW_REPEAT) {
const char *text_type = "composed_text";
glfw_sym = compose_symbol(xkb, syms[0]);