summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorduarm <mathdu@protonmail.com>2022-11-08 15:18:45 -0300
committerGitHub <noreply@github.com>2022-11-08 19:18:45 +0100
commit6d02648d3a2ab9ee9751db8783f00b14071f57b4 (patch)
treee556dc9fe0d8a0368def8a2bd46fe4544d36fbe3
parent579902deff5c23cf690fc76bb9bcdca4f511b0df (diff)
input method (#1735)
* input method draft * restoring relese event * using unused macro, removing debug code, handling disconnection * review fixes, new update_im_window_pos method * initializing variables correctly * initializing im pos queue correctly * ime window positioning * add widget_get_y_pos() position * [Build] Update makefile with imdkit * [CI] Add imdkit as dependency. * [XCB] rofi_view_paste don't throw warning, print debug. * [XCB] rofi_view_paste lower 'failed to convert selection' * [Build] Add minimum version check to imdkit * new macro XCB_IMDKIT_1_0_3_LOWER * [Build] Try to support old version of imdkit in meson/makefile. * [Build] Fix typo in meson.build * [XIM] Don't set use compound/set use utf8 when on old version. * [Build] Allow building without imdkit. * [Doc] Add imdkit to dependency list. Co-authored-by: Dave Davenport <qball@gmpclient.org>
-rw-r--r--.github/actions/setup/action.yml1
-rw-r--r--INSTALL.md1
-rw-r--r--Makefile.am2
-rw-r--r--configure.ac6
-rw-r--r--include/view.h10
-rw-r--r--include/xcb-internal.h5
-rw-r--r--include/xcb.h12
-rw-r--r--meson.build20
-rw-r--r--source/rofi.c7
-rw-r--r--source/view.c116
-rw-r--r--source/xcb.c149
11 files changed, 308 insertions, 21 deletions
diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml
index 0f641a5f..14973be3 100644
--- a/.github/actions/setup/action.yml
+++ b/.github/actions/setup/action.yml
@@ -29,6 +29,7 @@ runs:
libxcb-xkb-dev \
libxcb-xrm-dev \
libxcb-cursor-dev \
+ libxcb-imdkit-dev \
libxkbcommon-dev \
libxkbcommon-dev \
libxkbcommon-x11-dev \
diff --git a/INSTALL.md b/INSTALL.md
index f62ffbfc..dd7a5401 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -39,6 +39,7 @@ You can also use [Meson](https://mesonbuild.com/) as an alternative.
* xcb-util
* xcb-util-wm (sometimes split as libxcb-ewmh and libxcb-icccm)
* xcb-util-cursor
+* xcb-imdkit (optional, 1.0.3 or up preferred)
On debian based systems, the developer packages are in the form of: `<package>-dev` on rpm based
`<package>-devel`.
diff --git a/Makefile.am b/Makefile.am
index 24e5526a..4e316e74 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -145,6 +145,7 @@ rofi_CFLAGS=\
$(libsn_CFLAGS)\
$(cairo_CFLAGS)\
$(gdkpixbuf_CFLAGS)\
+ $(imdclient_CFLAGS)\
-DMANPAGE_PATH="\"$(mandir)/\""\
-I$(top_srcdir)/include/\
-I$(top_builddir)/lexer/\
@@ -165,6 +166,7 @@ rofi_LDADD=\
$(pango_LIBS)\
$(cairo_LIBS)\
$(gdkpixbuf_LIBS)\
+ $(imdclient_LIBS)\
$(LIBS)
##
diff --git a/configure.ac b/configure.ac
index de043d48..cdef673d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -145,7 +145,11 @@ NK_INIT([bindings xdg-theme])
PKG_CHECK_MODULES([glib], [glib-2.0 >= ${glib_min_version} gio-unix-2.0 gmodule-2.0])
AC_DEFINE_UNQUOTED([GLIB_VERSION_MIN_REQUIRED], [(G_ENCODE_VERSION(${glib_min_major},${glib_min_minor}))], [The lower GLib version supported])
AC_DEFINE_UNQUOTED([GLIB_VERSION_MAX_ALLOWED], [(G_ENCODE_VERSION(${glib_min_major},${glib_min_minor}))], [The highest GLib version supported])
-GW_CHECK_XCB([xcb-aux xcb-xkb xkbcommon xkbcommon-x11 xcb-ewmh xcb-icccm xcb-cursor xcb-randr xcb-xinerama])
+GW_CHECK_XCB([xcb-aux xcb-xkb xkbcommon xkbcommon-x11 xcb-ewmh xcb-icccm xcb-cursor xcb-randr xcb-xinerama ])
+PKG_CHECK_MODULES([imdclient], [xcb-imdkit <= 1.0.2 ],
+ [AC_DEFINE([XCB_IMDKIT_1_0_3_LOWER], [1], [Indicate lower version of imdclient])
+ AC_DEFINE([XCB_IMDKIT],[1], [IMD Kit missing])],
+ [PKG_CHECK_MODULES([imdclient], [xcb-imdkit >= 1.0.3],[AC_DEFINE([XCB_IMDKIT],[1], [IMD Kit missing])],[HAVE_IMDKIT=0])])
PKG_CHECK_MODULES([pango], [pango pangocairo])
PKG_CHECK_MODULES([cairo], [cairo cairo-xcb])
PKG_CHECK_MODULES([libsn], [libstartup-notification-1.0 ])
diff --git a/include/view.h b/include/view.h
index 8fbe0159..9ca8bfbf 100644
--- a/include/view.h
+++ b/include/view.h
@@ -341,5 +341,15 @@ void rofi_view_set_window_title(const char *title);
* set ellipsize mode to start.
*/
void rofi_view_ellipsize_start(RofiViewState *state);
+
+/**
+ * @param new_x New XIM window x pos
+ * @param new_y New XIM window y pos
+ *
+ * Updates the XIM window position to new_x and new_y, relative to the
+ * main_window
+ */
+gboolean rofi_set_im_window_pos(int new_x, int new_y);
+
/** @} */
#endif
diff --git a/include/xcb-internal.h b/include/xcb-internal.h
index f2d78ca1..c83ef585 100644
--- a/include/xcb-internal.h
+++ b/include/xcb-internal.h
@@ -32,6 +32,7 @@
#include <glib.h>
#include <libsn/sn.h>
+#include "xcb.h"
#include <libgwater-xcb.h>
#include <xcb/xcb.h>
#include <xcb/xcb_ewmh.h>
@@ -45,6 +46,10 @@ struct _xcb_stuff {
GMainLoop *main_loop;
GWaterXcbSource *source;
xcb_connection_t *connection;
+#ifdef XCB_IMDKIT
+ xcb_xic_t ic;
+ xcb_xim_t *im;
+#endif
xcb_ewmh_connection_t ewmh;
xcb_screen_t *screen;
int screen_nbr;
diff --git a/include/xcb.h b/include/xcb.h
index afc9c5ec..2b847645 100644
--- a/include/xcb.h
+++ b/include/xcb.h
@@ -29,6 +29,10 @@
#define ROFI_XCB_H
#include <cairo.h>
+#include <config.h>
+#ifdef XCB_IMDKIT
+#include <xcb-imdkit/imclient.h>
+#endif
#include <xcb/xcb.h>
/**
@@ -220,6 +224,7 @@ extern WindowManagerQuirk current_window_manager;
* @returns NULL if window was not found, or unmapped, otherwise returns a
* cairo_surface.
*/
+
cairo_surface_t *x11_helper_get_screenshot_surface_window(xcb_window_t window,
int size);
@@ -233,4 +238,11 @@ cairo_surface_t *x11_helper_get_screenshot_surface_window(xcb_window_t window,
void cairo_image_surface_blur(cairo_surface_t *surface, double radius,
double deviation);
+#ifdef XCB_IMDKIT
+/**
+ * IME Forwarding
+ */
+void x11_event_handler_fowarding(xcb_xim_t *im, xcb_xic_t ic,
+ xcb_key_press_event_t *event, void *user_data);
+#endif
#endif
diff --git a/meson.build b/meson.build
index 98a56f10..2c8d476a 100644
--- a/meson.build
+++ b/meson.build
@@ -74,9 +74,27 @@ deps += [
dependency('libstartup-notification-1.0'),
]
-check = dependency('check', version: '>= 0.11.0', required: get_option('check'))
+imdkit_new = dependency('xcb-imdkit', version: '>= 1.0.3', required: false)
+imdkit_old = dependency('xcb-imdkit', version: '<= 1.0.2', required: false)
+
+check = dependency('check', version: '>= 0.11.0', required: get_option('check'))
header_conf = configuration_data()
+
+if imdkit_new.found()
+ deps += imdkit_new
+ header_conf.set('XCB_IMDKIT_1_0_3_LOWER', false)
+ header_conf.set('XCB_IMDKIT', true)
+elif imdkit_old.found()
+ deps+= imdkit_old
+ header_conf.set('XCB_IMDKIT_1_0_3_LOWER', true)
+ header_conf.set('XCB_IMDKIT', true)
+else
+ header_conf.set('XCB_IMDKIT_1_0_3_LOWER', false)
+ header_conf.set('XCB_IMDKIT', false)
+endif
+
+
header_conf.set_quoted('PACKAGE_NAME', meson.project_name())
header_conf.set_quoted('PACKAGE_VERSION', meson.project_version())
header_conf.set_quoted('VERSION', meson.project_version())
diff --git a/source/rofi.c b/source/rofi.c
index 0bf4be81..d8d6a1f1 100644
--- a/source/rofi.c
+++ b/source/rofi.c
@@ -380,6 +380,13 @@ static void help(G_GNUC_UNUSED int argc, char **argv) {
printf("\t• asan %sdisabled%s\n", is_term ? color_red : "",
is_term ? color_reset : "");
#endif
+#ifdef XCB_IMDKIT
+ printf("\t• imdkit %senabled%s\n", is_term ? color_green : "",
+ is_term ? color_reset : "");
+#else
+ printf("\t• imdkit %sdisabled%s\n", is_term ? color_red : "",
+ is_term ? color_reset : "");
+#endif
printf("\n");
printf("For more information see: %sman rofi%s\n", is_term ? color_bold : "",
is_term ? color_reset : "");
diff --git a/source/view.c b/source/view.c
index cfa96438..1c432891 100644
--- a/source/view.c
+++ b/source/view.c
@@ -38,6 +38,9 @@
#include <string.h>
#include <time.h>
#include <unistd.h>
+#ifdef XCB_IMDKIT
+#include <xcb-imdkit/encoding.h>
+#endif
#include <xcb/xcb_ewmh.h>
#include <xcb/xcb_icccm.h>
#include <xcb/xkb.h>
@@ -79,6 +82,20 @@ void rofi_view_update(RofiViewState *state, gboolean qr);
static int rofi_view_calculate_height(RofiViewState *state);
+#ifdef XCB_IMDKIT
+static void xim_commit_string(xcb_xim_t *im, G_GNUC_UNUSED xcb_xic_t ic,
+ G_GNUC_UNUSED uint32_t flag, char *str,
+ uint32_t length, G_GNUC_UNUSED uint32_t *keysym,
+ G_GNUC_UNUSED size_t nKeySym,
+ G_GNUC_UNUSED void *user_data);
+static void xim_disconnected(G_GNUC_UNUSED xcb_xim_t *im,
+ G_GNUC_UNUSED void *user_data);
+xcb_xim_im_callback xim_callback = {.forward_event =
+ x11_event_handler_fowarding,
+ .commit_string = xim_commit_string,
+ .disconnected = xim_disconnected};
+#endif
+
/** Thread pool used for filtering */
GThreadPool *tpool = NULL;
@@ -784,6 +801,86 @@ rofi_view_setup_fake_transparency(widget *win,
TICK_N("Fake transparency");
}
}
+
+#ifdef XCB_IMDKIT
+static void xim_commit_string(xcb_xim_t *im, G_GNUC_UNUSED xcb_xic_t ic,
+ G_GNUC_UNUSED uint32_t flag, char *str,
+ uint32_t length, G_GNUC_UNUSED uint32_t *keysym,
+ G_GNUC_UNUSED size_t nKeySym,
+ G_GNUC_UNUSED void *user_data) {
+ RofiViewState *state = rofi_view_get_active();
+ if (state == NULL) {
+ return;
+ }
+
+#ifndef XCB_IMDKIT_1_0_3_LOWER
+ if (xcb_xim_get_encoding(im) == XCB_XIM_UTF8_STRING) {
+ rofi_view_handle_text(state, str);
+ } else if (xcb_xim_get_encoding(im) == XCB_XIM_COMPOUND_TEXT) {
+ size_t newLength = 0;
+ char *utf8 = xcb_compound_text_to_utf8(str, length, &newLength);
+ if (utf8) {
+ rofi_view_handle_text(state, utf8);
+ }
+ }
+#else
+ size_t newLength = 0;
+ char *utf8 = xcb_compound_text_to_utf8(str, length, &newLength);
+ if (utf8) {
+ rofi_view_handle_text(state, utf8);
+ }
+#endif
+}
+
+static void xim_disconnected(G_GNUC_UNUSED xcb_xim_t *im,
+ G_GNUC_UNUSED void *user_data) {
+ xcb->ic = 0;
+}
+
+static void create_ic_callback(xcb_xim_t *im, xcb_xic_t new_ic,
+ G_GNUC_UNUSED void *user_data) {
+ xcb->ic = new_ic;
+ if (xcb->ic) {
+ xcb_xim_set_ic_focus(im, xcb->ic);
+ }
+}
+
+gboolean rofi_set_im_window_pos(int new_x, int new_y) {
+ if (!xcb->ic)
+ return false;
+
+ static xcb_point_t spot = {.x = 0, .y = 0};
+ if (spot.x != new_x || spot.y != new_y) {
+ spot.x = new_x;
+ spot.y = new_y;
+ xcb_xim_nested_list nested = xcb_xim_create_nested_list(
+ xcb->im, XCB_XIM_XNSpotLocation, &spot, NULL);
+ xcb_xim_set_ic_values(xcb->im, xcb->ic, NULL, NULL, XCB_XIM_XNClientWindow,
+ &CacheState.main_window, XCB_XIM_XNFocusWindow,
+ &CacheState.main_window, XCB_XIM_XNPreeditAttributes,
+ &nested, NULL);
+ free(nested.data);
+ }
+ return true;
+}
+static void open_xim_callback(xcb_xim_t *im, G_GNUC_UNUSED void *user_data) {
+ RofiViewState *state = rofi_view_get_active();
+ uint32_t input_style = XCB_IM_PreeditPosition | XCB_IM_StatusArea;
+ xcb_point_t spot;
+ spot.x += widget_get_x_pos(&state->text->widget) +
+ textbox_get_cursor_x_pos(state->text);
+ spot.y += widget_get_y_pos(&state->text->widget) +
+ widget_get_height(&state->text->widget);
+ xcb_xim_nested_list nested =
+ xcb_xim_create_nested_list(im, XCB_XIM_XNSpotLocation, &spot, NULL);
+ xcb_xim_create_ic(
+ im, create_ic_callback, NULL, XCB_XIM_XNInputStyle, &input_style,
+ XCB_XIM_XNClientWindow, &CacheState.main_window, XCB_XIM_XNFocusWindow,
+ &CacheState.main_window, XCB_XIM_XNPreeditAttributes, &nested, NULL);
+ free(nested.data);
+}
+#endif
+
void __create_window(MenuFlags menu_flags) {
uint32_t selmask = XCB_CW_BACK_PIXMAP | XCB_CW_BORDER_PIXEL |
XCB_CW_BIT_GRAVITY | XCB_CW_BACKING_STORE |
@@ -799,6 +896,15 @@ void __create_window(MenuFlags menu_flags) {
XCB_GRAVITY_STATIC, XCB_BACKING_STORE_NOT_USEFUL,
xcb_event_masks, map};
+#ifdef XCB_IMDKIT
+ xcb_xim_set_im_callback(xcb->im, &xim_callback, NULL);
+#endif
+
+// Open connection to XIM server.
+#ifdef XCB_IMDKIT
+ xcb_xim_open(xcb->im, open_xim_callback, true, NULL);
+#endif
+
xcb_window_t box_window = xcb_generate_id(xcb->connection);
xcb_void_cookie_t cc = xcb_create_window_checked(
xcb->connection, depth->depth, box_window, xcb_stuff_get_root_window(), 0,
@@ -810,6 +916,7 @@ void __create_window(MenuFlags menu_flags) {
g_error("xcb_create_window() failed error=0x%x\n", error->error_code);
exit(EXIT_FAILURE);
}
+
TICK_N("xcb create window");
CacheState.gc = xcb_generate_id(xcb->connection);
xcb_create_gc(xcb->connection, CacheState.gc, box_window, 0, 0);
@@ -1107,6 +1214,7 @@ static void update_callback(textbox *t, icon *ico, unsigned int index,
textbox_set_pango_attributes(t, list);
pango_attr_list_unref(list);
}
+
g_list_free(add_list);
g_free(text);
} else {
@@ -1149,6 +1257,14 @@ void rofi_view_update(RofiViewState *state, gboolean qr) {
cairo_set_operator(d, CAIRO_OPERATOR_OVER);
widget_draw(WIDGET(state->main_window), d);
+#ifdef XCB_IMDKIT
+ int x = widget_get_x_pos(&state->text->widget) +
+ textbox_get_cursor_x_pos(state->text);
+ int y = widget_get_y_pos(&state->text->widget) +
+ widget_get_height(&state->text->widget);
+ rofi_set_im_window_pos(x, y);
+#endif
+
TICK_N("widgets");
cairo_surface_flush(CacheState.edit_surf);
if (qr) {
diff --git a/source/xcb.c b/source/xcb.c
index e7959b04..db9e344a 100644
--- a/source/xcb.c
+++ b/source/xcb.c
@@ -30,6 +30,9 @@
#define G_LOG_DOMAIN "X11Helper"
#include "config.h"
+#ifdef XCB_IMDKIT
+#include <xcb-imdkit/encoding.h>
+#endif
#include <cairo-xcb.h>
#include <cairo.h>
#include <glib.h>
@@ -62,6 +65,7 @@
#include "xcb-internal.h"
#include "xcb.h"
#include <libsn/sn.h>
+#include <stdbool.h>
#include "mode.h"
#include "modes/window.h"
@@ -84,6 +88,9 @@ WindowManagerQuirk current_window_manager = WM_EWHM;
*/
struct _xcb_stuff xcb_int = {.connection = NULL,
.screen = NULL,
+#ifdef XCB_IMDKIT
+ .im = NULL,
+#endif
.screen_nbr = -1,
.sndisplay = NULL,
.sncontext = NULL,
@@ -1061,6 +1068,35 @@ int monitor_active(workarea *mon) {
return FALSE;
}
+static bool get_atom_name(xcb_connection_t *conn, xcb_atom_t atom, char **out) {
+ xcb_get_atom_name_cookie_t cookie;
+ xcb_get_atom_name_reply_t *reply;
+ int length;
+ char *name;
+
+ if (atom == 0) {
+ *out = NULL;
+ return true;
+ }
+
+ cookie = xcb_get_atom_name(conn, atom);
+ reply = xcb_get_atom_name_reply(conn, cookie, NULL);
+ if (!reply)
+ return false;
+
+ length = xcb_get_atom_name_name_length(reply);
+ name = xcb_get_atom_name_name(reply);
+
+ (*out) = g_strndup(name, length);
+ if (!(*out)) {
+ free(reply);
+ return false;
+ }
+
+ free(reply);
+ return true;
+}
+
/**
* @param state Internal state of the menu.
* @param xse X selection event.
@@ -1070,7 +1106,7 @@ int monitor_active(workarea *mon) {
static void rofi_view_paste(RofiViewState *state,
xcb_selection_notify_event_t *xse) {
if (xse->property == XCB_ATOM_NONE) {
- g_warning("Failed to convert selection");
+ g_debug("Failed to convert selection");
} else if (xse->property == xcb->ewmh.UTF8_STRING) {
gchar *text = window_get_text_prop(xse->requestor, xcb->ewmh.UTF8_STRING);
if (text != NULL && text[0] != '\0') {
@@ -1085,7 +1121,13 @@ static void rofi_view_paste(RofiViewState *state,
}
g_free(text);
} else {
- g_warning("Failed");
+ char *out = NULL;
+ if (get_atom_name(xcb->connection, xse->property, &out)) {
+ g_debug("rofi_view_paste: Got unknown atom: %s", out);
+ g_free(out);
+ } else {
+ g_debug("rofi_view_paste: Got unknown, unnamed: %s", out);
+ }
}
}
@@ -1142,6 +1184,32 @@ static gboolean x11_button_to_nk_bindings_scroll(guint32 x11_button,
return TRUE;
}
+static void rofi_key_press_event_handler(xcb_key_press_event_t *xkpe,
+ RofiViewState *state) {
+ gchar *text;
+
+ xcb->last_timestamp = xkpe->time;
+ if (config.xserver_i300_workaround) {
+ text = nk_bindings_seat_handle_key_with_modmask(
+ xcb->bindings_seat, NULL, xkpe->state, xkpe->detail,
+ NK_BINDINGS_KEY_STATE_PRESS);
+ } else {
+ text = nk_bindings_seat_handle_key(xcb->bindings_seat, NULL, xkpe->detail,
+ NK_BINDINGS_KEY_STATE_PRESS);
+ }
+ if (text != NULL) {
+ rofi_view_handle_text(state, text);
+ g_free(text);
+ }
+}
+
+static void rofi_key_release_event_handler(xcb_key_release_event_t *xkre,
+ G_GNUC_UNUSED RofiViewState *state) {
+ xcb->last_timestamp = xkre->time;
+ nk_bindings_seat_handle_key(xcb->bindings_seat, NULL, xkre->detail,
+ NK_BINDINGS_KEY_STATE_RELEASE);
+}
+
/**
* Process X11 events in the main-loop (gui-thread) of the application.
*/
@@ -1301,28 +1369,26 @@ static void main_loop_x11_event_handler_view(xcb_generic_event_t *event) {
}
case XCB_KEY_PRESS: {
xcb_key_press_event_t *xkpe = (xcb_key_press_event_t *)event;
- gchar *text;
-
- xcb->last_timestamp = xkpe->time;
- if (config.xserver_i300_workaround) {
- text = nk_bindings_seat_handle_key_with_modmask(
- xcb->bindings_seat, NULL, xkpe->state, xkpe->detail,
- NK_BINDINGS_KEY_STATE_PRESS);
- } else {
- text = nk_bindings_seat_handle_key(xcb->bindings_seat, NULL, xkpe->detail,
- NK_BINDINGS_KEY_STATE_PRESS);
- }
- if (text != NULL) {
- rofi_view_handle_text(state, text);
- g_free(text);
+#ifdef XCB_IMDKIT
+ if (xcb->ic) {
+ xcb_xim_forward_event(xcb->im, xcb->ic, xkpe);
+ } else
+#endif
+ {
+ rofi_key_press_event_handler(xkpe, state);
}
break;
}
case XCB_KEY_RELEASE: {
xcb_key_release_event_t *xkre = (xcb_key_release_event_t *)event;
- xcb->last_timestamp = xkre->time;
- nk_bindings_seat_handle_key(xcb->bindings_seat, NULL, xkre->detail,
- NK_BINDINGS_KEY_STATE_RELEASE);
+#ifdef XCB_IMDKIT
+ if (xcb->ic) {
+ xcb_xim_forward_event(xcb->im, xcb->ic, xkre);
+ } else
+#endif
+ {
+ rofi_key_release_event_handler(xkre, state);
+ }
break;
}
default:
@@ -1331,6 +1397,25 @@ static void main_loop_x11_event_handler_view(xcb_generic_event_t *event) {
rofi_view_maybe_update(state);
}
+#ifdef XCB_IMDKIT
+void x11_event_handler_fowarding(G_GNUC_UNUSED xcb_xim_t *im,
+ G_GNUC_UNUSED xcb_xic_t ic,
+ xcb_key_press_event_t *event,
+ G_GNUC_UNUSED void *user_data) {
+ RofiViewState *state = rofi_view_get_active();
+ if (state == NULL) {
+ return;
+ }
+ uint8_t type = event->response_type & ~0x80;
+ if (type == XCB_KEY_PRESS) {
+ rofi_key_press_event_handler(event, state);
+ } else if (type == XCB_KEY_RELEASE) {
+ xcb_key_release_event_t *xkre = (xcb_key_release_event_t *)event;
+ rofi_key_release_event_handler(xkre, state);
+ }
+}
+#endif
+
static gboolean main_loop_x11_event_handler(xcb_generic_event_t *ev,
G_GNUC_UNUSED gpointer user_data) {
if (ev == NULL) {
@@ -1346,6 +1431,13 @@ static gboolean main_loop_x11_event_handler(xcb_generic_event_t *ev,
// status);
return G_SOURCE_CONTINUE;
}
+
+#ifdef XCB_IMDKIT
+ if (xcb->im && xcb_xim_filter_event(xcb->im, ev)) {
+ return G_SOURCE_CONTINUE;
+ }
+#endif
+
uint8_t type = ev->response_type & ~0x80;
if (type == xcb->xkb.first_event) {
switch (ev->pad0) {
@@ -1375,6 +1467,7 @@ static gboolean main_loop_x11_event_handler(xcb_generic_event_t *ev,
if (xcb->sndisplay != NULL) {
sn_xcb_display_process_event(xcb->sndisplay, ev);
}
+
main_loop_x11_event_handler_view(ev);
return G_SOURCE_CONTINUE;
}
@@ -1542,6 +1635,9 @@ gboolean display_setup(GMainLoop *main_loop, NkBindings *bindings) {
find_arg_str("-display", &display_str);
xcb->main_loop = main_loop;
+#ifdef XCB_IMDKIT
+ xcb_compound_text_init();
+#endif
xcb->source = g_water_xcb_source_new(g_main_loop_get_context(xcb->main_loop),
display_str, &xcb->screen_nbr,
main_loop_x11_event_handler, NULL, NULL);
@@ -1550,6 +1646,16 @@ gboolean display_setup(GMainLoop *main_loop, NkBindings *bindings) {
return FALSE;
}
xcb->connection = g_water_xcb_source_get_connection(xcb->source);
+#ifdef XCB_IMDKIT
+ xcb->im = xcb_xim_create(xcb->connection, xcb->screen_nbr, NULL);
+#endif
+
+#ifdef XCB_IMDKIT
+#ifndef XCB_IMDKIT_1_0_3_LOWER
+ xcb_xim_set_use_compound_text(xcb->im, true);
+ xcb_xim_set_use_utf8_string(xcb->im, true);
+#endif
+#endif
TICK_N("Open Display");
@@ -1819,6 +1925,11 @@ void display_cleanup(void) {
xcb_ewmh_connection_wipe(&(xcb->ewmh));
xcb_flush(xcb->connection);
xcb_aux_sync(xcb->connection);
+#ifdef XCB_IMDKIT
+ xcb_xim_close(xcb->im);
+ xcb_xim_destroy(xcb->im);
+ xcb->im = NULL;
+#endif
g_water_xcb_source_free(xcb->source);
xcb->source = NULL;
xcb->connection = NULL;