diff --git a/src/common.h b/src/common.h index e6033bd..bd344c3 100644 --- a/src/common.h +++ b/src/common.h @@ -23,7 +23,7 @@ #define ARRAY_SIZE(X) (sizeof(X) / sizeof(X[0])) -#define XIM_MESSAGE_BYTES(hdr) ((hdr)->length * 4) +#define XIM_MESSAGE_BYTES(hdr) ((hdr)->length * 4u) /* * categories in XIM_SERVERS diff --git a/src/imclient.c b/src/imclient.c index 934cbb6..35cc76b 100644 --- a/src/imclient.c +++ b/src/imclient.c @@ -792,6 +792,7 @@ bool _xcb_xim_filter_property_changed(xcb_xim_t *im, bool xcb_xim_filter_event(xcb_xim_t *im, xcb_generic_event_t *event) { im->yield_recheck = false; + im->event_sequence = event->full_sequence; bool result = _xcb_xim_preconnect_im(im, event) || _xcb_xim_filter_event(im, event) || _xcb_xim_filter_destroy_window(im, event) || @@ -1485,7 +1486,11 @@ bool xcb_xim_unset_ic_focus(xcb_xim_t *im, xcb_xic_t ic) { return !fail; } -bool xcb_xim_forward_event(xcb_xim_t *im, xcb_xic_t ic, +bool xcb_xim_forward_event(xcb_xim_t *im, xcb_xic_t ic, xcb_key_press_event_t *event) { + return xcb_xim_forward_event_full(im, ic, (im->event_sequence >> 16), event); +} + +bool xcb_xim_forward_event_full(xcb_xim_t *im, xcb_xic_t ic, uint16_t sequence, xcb_key_press_event_t *event) { xcb_xim_request_queue_t *queue = _xcb_xim_new_request(im, XCB_XIM_FORWARD_EVENT, 0, NULL, NULL); @@ -1496,7 +1501,7 @@ bool xcb_xim_forward_event(xcb_xim_t *im, xcb_xic_t ic, frame.input_method_ID = im->connect_id; frame.input_context_ID = ic; frame.flag = XCB_XIM_SYNCHRONOUS; - frame.sequence_number = event->sequence; + frame.sequence_number = sequence; const size_t length = xcb_im_forward_event_fr_size(&frame) + sizeof(xcb_key_press_event_t); diff --git a/src/imclient.h b/src/imclient.h index f0298d5..55e3afa 100644 --- a/src/imclient.h +++ b/src/imclient.h @@ -162,6 +162,9 @@ XCBIMDKIT_EXPORT bool xcb_xim_set_ic_focus(xcb_xim_t *im, xcb_xic_t ic); XCBIMDKIT_EXPORT bool xcb_xim_unset_ic_focus(xcb_xim_t *im, xcb_xic_t ic); XCBIMDKIT_EXPORT bool xcb_xim_forward_event(xcb_xim_t *im, xcb_xic_t ic, xcb_key_press_event_t *event); +XCBIMDKIT_EXPORT bool xcb_xim_forward_event_full(xcb_xim_t *im, xcb_xic_t ic, + uint16_t sequence, + xcb_key_press_event_t *event); XCBIMDKIT_EXPORT bool xcb_xim_reset_ic(xcb_xim_t *im, xcb_xic_t ic, xcb_xim_reset_ic_callback callback, void *user_data); diff --git a/src/imclient_p.h b/src/imclient_p.h index b63e6a2..0d90719 100644 --- a/src/imclient_p.h +++ b/src/imclient_p.h @@ -171,13 +171,15 @@ struct _xcb_xim_t { bool use_compound_text; bool use_utf8_string; xcb_xim_encoding_t encoding; + + uint32_t event_sequence; }; #define _xcb_xim_read_frame(FRAME, DATA, LEN, FAIL) \ do { \ FAIL = false; \ uint8_t *_data = DATA; \ - size_t len = (LEN); \ + size_t len = (size_t)(LEN); \ frame_read_func(FRAME)(&FRAME, &_data, &len, false); \ if (!_data) { \ frame_free_func(FRAME)(&FRAME); \ diff --git a/src/imdkit.c b/src/imdkit.c index 1184fb8..3044984 100644 --- a/src/imdkit.c +++ b/src/imdkit.c @@ -836,11 +836,17 @@ void xcb_im_destroy(xcb_im_t *im) { void xcb_im_forward_event(xcb_im_t *im, xcb_im_input_context_t *ic, xcb_key_press_event_t *event) { + xcb_im_forward_event_full(im, ic, ic->forward_event_sequence, event); +} + +void xcb_im_forward_event_full(xcb_im_t *im, xcb_im_input_context_t *ic, + uint16_t sequence, + xcb_key_press_event_t *event) { xcb_im_client_t *client = ic->client; xcb_im_forward_event_fr_t frame; frame.input_method_ID = ic->client->connect_id; frame.input_context_ID = ic->id; - frame.sequence_number = event->sequence; + frame.sequence_number = sequence; if (im->use_sync_mode) { frame.flag = XCB_XIM_SYNCHRONOUS; client->sync = true; diff --git a/src/imdkit.h b/src/imdkit.h index a300411..ae85ba4 100644 --- a/src/imdkit.h +++ b/src/imdkit.h @@ -197,6 +197,21 @@ XCBIMDKIT_EXPORT void xcb_im_forward_event(xcb_im_t *im, xcb_im_input_context_t *ic, xcb_key_press_event_t *event); +/** + * Send a key event to the client. + * + * @param im XIM server + * @param ic Input context. + * @param sequence sequence number, when re-inject, should be the value from + * forward_event + * @param event key event. + * @see xcb_im_forward_event_fr_t. + */ +XCBIMDKIT_EXPORT void xcb_im_forward_event_full(xcb_im_t *im, + xcb_im_input_context_t *ic, + uint16_t sequence, + xcb_key_press_event_t *event); + /** * Commit a string to the client. * diff --git a/src/imdkit_p.h b/src/imdkit_p.h index 98f6e10..2349fb5 100644 --- a/src/imdkit_p.h +++ b/src/imdkit_p.h @@ -134,6 +134,7 @@ struct _xcb_im_input_context_t { UT_hash_handle hh; void *data; xcb_im_free_function free_data_function; + uint16_t forward_event_sequence; }; struct _xcb_im_client_t { diff --git a/src/protocolhandler.c b/src/protocolhandler.c index 5d66876..69783f9 100644 --- a/src/protocolhandler.c +++ b/src/protocolhandler.c @@ -725,6 +725,7 @@ void _xcb_im_handle_forward_event(xcb_im_t *im, xcb_im_client_t *client, if (!ic) { break; } + ic->forward_event_sequence = frame.sequence_number; if (client->sync) { _xcb_im_add_queue(im, client, ic->id, hdr, &frame, data); } else {