summaryrefslogtreecommitdiffstats
path: root/source/xcb.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/xcb.c')
-rw-r--r--source/xcb.c149
1 files changed, 130 insertions, 19 deletions
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;