Better XIM interaction by filtering modifiers (#2000)

This commit is contained in:
Amos Bird 2024-07-10 02:51:23 +08:00 committed by GitHub
parent 8b612f08cf
commit 8eb8ff3b6f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 41 additions and 8 deletions

View File

@ -36,6 +36,7 @@
#include <libgwater-xcb.h> #include <libgwater-xcb.h>
#include <xcb/xcb.h> #include <xcb/xcb.h>
#include <xcb/xcb_ewmh.h> #include <xcb/xcb_ewmh.h>
#include <xcb/xcb_keysyms.h>
#include <nkutils-bindings.h> #include <nkutils-bindings.h>
@ -49,6 +50,7 @@ struct _xcb_stuff {
#ifdef XCB_IMDKIT #ifdef XCB_IMDKIT
xcb_xic_t ic; xcb_xic_t ic;
xcb_xim_t *im; xcb_xim_t *im;
xcb_key_symbols_t *syms;
#endif #endif
xcb_ewmh_connection_t ewmh; xcb_ewmh_connection_t ewmh;
xcb_screen_t *screen; xcb_screen_t *screen;

View File

@ -79,6 +79,7 @@ deps += [
dependency('xcb-randr'), dependency('xcb-randr'),
dependency('xcb-cursor'), dependency('xcb-cursor'),
dependency('xcb-xinerama'), dependency('xcb-xinerama'),
dependency('xcb-keysyms'),
dependency('cairo-xcb'), dependency('cairo-xcb'),
dependency('libstartup-notification-1.0'), dependency('libstartup-notification-1.0'),
] ]

View File

@ -31,6 +31,7 @@
#include "config.h" #include "config.h"
#ifdef XCB_IMDKIT #ifdef XCB_IMDKIT
#include <xcb/xcb_keysyms.h>
#include <xcb-imdkit/encoding.h> #include <xcb-imdkit/encoding.h>
#endif #endif
#include <cairo-xcb.h> #include <cairo-xcb.h>
@ -90,6 +91,7 @@ struct _xcb_stuff xcb_int = {.connection = NULL,
.screen = NULL, .screen = NULL,
#ifdef XCB_IMDKIT #ifdef XCB_IMDKIT
.im = NULL, .im = NULL,
.syms = NULL,
#endif #endif
.screen_nbr = -1, .screen_nbr = -1,
.sndisplay = NULL, .sndisplay = NULL,
@ -1189,7 +1191,7 @@ static gboolean x11_button_to_nk_bindings_scroll(guint32 x11_button,
static void rofi_key_press_event_handler(xcb_key_press_event_t *xkpe, static void rofi_key_press_event_handler(xcb_key_press_event_t *xkpe,
RofiViewState *state) { RofiViewState *state) {
gchar *text; gchar *text;
g_log("IMDKit", G_LOG_LEVEL_DEBUG, "press handler"); g_log("IMDKit", G_LOG_LEVEL_DEBUG, "press handler %d", xkpe->detail);
xcb->last_timestamp = xkpe->time; xcb->last_timestamp = xkpe->time;
if (config.xserver_i300_workaround) { if (config.xserver_i300_workaround) {
@ -1208,6 +1210,7 @@ static void rofi_key_press_event_handler(xcb_key_press_event_t *xkpe,
static void rofi_key_release_event_handler(xcb_key_release_event_t *xkre, static void rofi_key_release_event_handler(xcb_key_release_event_t *xkre,
G_GNUC_UNUSED RofiViewState *state) { G_GNUC_UNUSED RofiViewState *state) {
g_log("IMDKit", G_LOG_LEVEL_DEBUG, "release handler %d", xkre->detail);
xcb->last_timestamp = xkre->time; xcb->last_timestamp = xkre->time;
nk_bindings_seat_handle_key(xcb->bindings_seat, NULL, xkre->detail, nk_bindings_seat_handle_key(xcb->bindings_seat, NULL, xkre->detail,
NK_BINDINGS_KEY_STATE_RELEASE); NK_BINDINGS_KEY_STATE_RELEASE);
@ -1372,8 +1375,14 @@ static void main_loop_x11_event_handler_view(xcb_generic_event_t *event) {
xcb_key_press_event_t *xkpe = (xcb_key_press_event_t *)event; xcb_key_press_event_t *xkpe = (xcb_key_press_event_t *)event;
#ifdef XCB_IMDKIT #ifdef XCB_IMDKIT
if (xcb->ic) { if (xcb->ic) {
g_log("IMDKit", G_LOG_LEVEL_DEBUG, "input xim"); xcb_keysym_t sym = xcb_key_press_lookup_keysym(xcb->syms, xkpe, 0);
xcb_xim_forward_event(xcb->im, xcb->ic, xkpe); if (xcb_is_modifier_key(sym)) {
rofi_key_press_event_handler(xkpe, state);
} else {
g_log("IMDKit", G_LOG_LEVEL_DEBUG, "press key %d to xim", xkpe->detail);
xcb_xim_forward_event(xcb->im, xcb->ic, xkpe);
return;
}
} else } else
#endif #endif
{ {
@ -1383,7 +1392,21 @@ static void main_loop_x11_event_handler_view(xcb_generic_event_t *event) {
} }
case XCB_KEY_RELEASE: { case XCB_KEY_RELEASE: {
xcb_key_release_event_t *xkre = (xcb_key_release_event_t *)event; xcb_key_release_event_t *xkre = (xcb_key_release_event_t *)event;
rofi_key_release_event_handler(xkre, state); #ifdef XCB_IMDKIT
if (xcb->ic) {
xcb_keysym_t sym = xcb_key_press_lookup_keysym(xcb->syms, xkre, 0);
if (xcb_is_modifier_key(sym)) {
rofi_key_press_event_handler(xkre, state);
} else {
g_log("IMDKit", G_LOG_LEVEL_DEBUG, "release key %d to xim", xkre->detail);
xcb_xim_forward_event(xcb->im, xcb->ic, xkre);
return;
}
} else
#endif
{
rofi_key_release_event_handler(xkre, state);
}
break; break;
} }
default: default:
@ -1401,7 +1424,15 @@ void x11_event_handler_fowarding(G_GNUC_UNUSED xcb_xim_t *im,
if (state == NULL) { if (state == NULL) {
return; return;
} }
rofi_key_press_event_handler(event, state);
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);
}
rofi_view_maybe_update(state);
} }
#endif #endif
@ -1422,9 +1453,7 @@ static gboolean main_loop_x11_event_handler(xcb_generic_event_t *ev,
} }
#ifdef XCB_IMDKIT #ifdef XCB_IMDKIT
if (xcb->im if (xcb->im && xcb_xim_filter_event(xcb->im, ev))
&& (ev->response_type & ~0x80) != XCB_KEY_PRESS
&& !xcb_xim_filter_event(xcb->im, ev))
return G_SOURCE_CONTINUE; return G_SOURCE_CONTINUE;
#endif #endif
@ -1659,6 +1688,7 @@ gboolean display_setup(GMainLoop *main_loop, NkBindings *bindings) {
xcb->connection = g_water_xcb_source_get_connection(xcb->source); xcb->connection = g_water_xcb_source_get_connection(xcb->source);
#ifdef XCB_IMDKIT #ifdef XCB_IMDKIT
xcb->im = xcb_xim_create(xcb->connection, xcb->screen_nbr, NULL); xcb->im = xcb_xim_create(xcb->connection, xcb->screen_nbr, NULL);
xcb->syms = xcb_key_symbols_alloc(xcb->connection);
#endif #endif
#ifdef XCB_IMDKIT #ifdef XCB_IMDKIT