diff options
Diffstat (limited to 'source/xcb.c')
-rw-r--r-- | source/xcb.c | 149 |
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; |