strans/xim/xcb-imdkit/src/clientprotocolhandler.c
2025-12-23 20:21:56 +09:00

856 lines
27 KiB
C

/*
* SPDX-FileCopyrightText: 2014 Weng Xuetian <wengxt@gmail.com>
*
* SPDX-License-Identifier: LGPL-2.1-only
*
*/
#include "clientprotocolhandler.h"
#include "common.h"
#include "imclient_p.h"
#include "parser.h"
#include "uthash.h"
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <xcb/xproto.h>
bool _xcb_xim_send_query_extension(xcb_xim_t *im) {
xcb_im_query_extension_fr_t frame;
xcb_im_str_fr_t extensions[ARRAY_SIZE(Default_Extension)];
frame.input_method_ID = im->connect_id;
frame.extensions_supported_by_the_IM_library.size =
ARRAY_SIZE(Default_Extension);
frame.extensions_supported_by_the_IM_library.items = extensions;
for (uint32_t i = 0; i < frame.extensions_supported_by_the_IM_library.size;
i++) {
extensions[i].length_of_string = strlen(Default_Extension[i].name);
extensions[i].string = (uint8_t *)Default_Extension[i].name;
}
bool fail;
_xcb_xim_send_frame(im, frame, fail);
if (!fail) {
im->open_state = XIM_OPEN_WAIT_EXTENSION_REPLY;
}
return !fail;
}
bool _xcb_xim_send_encoding_negotiation(xcb_xim_t *im) {
xcb_im_encoding_negotiation_fr_t frame;
xcb_im_str_fr_t encodings[2];
int idx = 0;
if (im->use_compound_text) {
encodings[idx].length_of_string = strlen("COMPOUND_TEXT");
encodings[idx].string = (uint8_t *)"COMPOUND_TEXT";
idx++;
}
if (im->use_utf8_string) {
encodings[idx].length_of_string = strlen("UTF8_STRING");
encodings[idx].string = (uint8_t *)"UTF8_STRING";
idx++;
}
frame.input_method_ID = im->connect_id;
frame.supported_list_of_encoding_in_IM_library.size = idx;
frame.supported_list_of_encoding_in_IM_library.items = encodings;
frame.list_of_encodings_supported_in_th.size = 0;
frame.list_of_encodings_supported_in_th.items = 0;
bool fail;
_xcb_xim_send_frame(im, frame, fail);
if (!fail) {
im->open_state = XIM_OPEN_WAIT_ENCODING_REPLY;
}
return !fail;
}
void _xcb_xim_handle_open_reply(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
if (im->open_state != XIM_OPEN_WAIT_OPEN_REPLY) {
return;
}
xcb_im_open_reply_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
im->connect_id = frame.input_method_ID;
// construct a name based attr table
for (uint32_t i = 0; i < frame.IM_attribute_supported.size; i++) {
xcb_im_ximattr_fr_t *subframe = &frame.IM_attribute_supported.items[i];
if (subframe->length_of_im_attribute == 0) {
continue;
}
xcb_xim_imattr_table_t *imattr = NULL;
HASH_FIND(hh, im->imattr, subframe->im_attribute,
subframe->length_of_im_attribute, imattr);
if (imattr) {
continue;
}
imattr = malloc(sizeof(xcb_xim_imattr_table_t));
imattr->attr.attribute_ID = subframe->attribute_ID;
imattr->attr.type_of_the_value = subframe->type_of_the_value;
imattr->attr.length_of_im_attribute = subframe->length_of_im_attribute;
imattr->attr.im_attribute =
malloc((imattr->attr.length_of_im_attribute + 1) * sizeof(uint8_t));
imattr->attr.im_attribute[imattr->attr.length_of_im_attribute] = 0;
memcpy(imattr->attr.im_attribute, subframe->im_attribute,
imattr->attr.length_of_im_attribute);
HASH_ADD_KEYPTR(hh, im->imattr, imattr->attr.im_attribute,
imattr->attr.length_of_im_attribute, imattr);
}
for (uint32_t i = 0; i < frame.IC_attribute_supported.size; i++) {
xcb_im_xicattr_fr_t *subframe = &frame.IC_attribute_supported.items[i];
if (subframe->length_of_ic_attribute == 0) {
continue;
}
xcb_xim_icattr_table_t *icattr = NULL;
HASH_FIND(hh, im->icattr, subframe->ic_attribute,
subframe->length_of_ic_attribute, icattr);
if (icattr) {
continue;
}
icattr = malloc(sizeof(xcb_xim_icattr_table_t));
icattr->attr.attribute_ID = subframe->attribute_ID;
icattr->attr.type_of_the_value = subframe->type_of_the_value;
icattr->attr.length_of_ic_attribute = subframe->length_of_ic_attribute;
icattr->attr.ic_attribute =
malloc((icattr->attr.length_of_ic_attribute + 1) * sizeof(uint8_t));
icattr->attr.ic_attribute[icattr->attr.length_of_ic_attribute] = 0;
memcpy(icattr->attr.ic_attribute, subframe->ic_attribute,
icattr->attr.length_of_ic_attribute);
HASH_ADD_KEYPTR(hh, im->icattr, icattr->attr.ic_attribute,
icattr->attr.length_of_ic_attribute, icattr);
}
xcb_im_open_reply_fr_free(&frame);
_xcb_xim_send_query_extension(im);
}
void _xcb_xim_handle_query_extension_reply(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
if (im->open_state != XIM_OPEN_WAIT_EXTENSION_REPLY) {
return;
}
xcb_im_query_extension_reply_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
do {
if (frame.input_method_ID != im->connect_id) {
break;
}
free(im->extensions);
im->extensions = NULL;
im->nExtensions = 0;
// There are some wrong implementation around that use a different wire
// format, thus do not hard fail on this.
if (fail) {
break;
}
im->extensions =
frame.list_of_extensions_supported_by_th.size
? calloc(frame.list_of_extensions_supported_by_th.size,
sizeof(xcb_xim_extension_t))
: NULL;
im->nExtensions = frame.list_of_extensions_supported_by_th.size;
for (uint32_t i = 0; i < frame.list_of_extensions_supported_by_th.size;
i++) {
im->extensions[i].major_code =
frame.list_of_extensions_supported_by_th.items[i]
.extension_major_opcode;
im->extensions[i].minor_code =
frame.list_of_extensions_supported_by_th.items[i]
.extension_minor_opcode;
}
} while (0);
_xcb_xim_send_encoding_negotiation(im);
if (!fail) {
xcb_im_query_extension_reply_fr_free(&frame);
}
}
void _xcb_xim_handle_encoding_negotiation_reply(
xcb_xim_t *im, const xcb_im_packet_header_fr_t *hdr, uint8_t *data) {
if (im->open_state != XIM_OPEN_WAIT_ENCODING_REPLY) {
return;
}
xcb_im_encoding_negotiation_reply_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
xcb_xim_encoding_t encodings[2] = {XCB_XIM_COMPOUND_TEXT,
XCB_XIM_COMPOUND_TEXT};
size_t nEncodings = 0;
if (im->use_compound_text) {
encodings[nEncodings++] = XCB_XIM_COMPOUND_TEXT;
}
if (im->use_utf8_string) {
encodings[nEncodings++] = XCB_XIM_UTF8_STRING;
}
// we only send compound
if (frame.input_method_ID != im->connect_id &&
frame.index_of_the_encoding_determined >= nEncodings) {
break;
}
im->open_state = XIM_OPEN_DONE;
im->encoding = encodings[frame.index_of_the_encoding_determined];
if (im->connect_state.callback) {
im->connect_state.callback(im, im->connect_state.user_data);
}
_xcb_change_event_mask(im->conn, im->accept_win,
XCB_EVENT_MASK_STRUCTURE_NOTIFY, false);
} while (0);
xcb_im_encoding_negotiation_reply_fr_free(&frame);
}
void _xcb_xim_handle_register_triggerkeys(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_register_triggerkeys_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
// we dont check (frame.input_method_ID != im->connect_id);
// here because this is send with open_reply
free(im->onKeys.keys);
free(im->offKeys.keys);
im->onKeys.keys = frame.on_keys_list.size
? calloc(frame.on_keys_list.size,
sizeof(xcb_im_ximtriggerkey_fr_t))
: NULL;
im->offKeys.keys = frame.off_keys_list.size
? calloc(frame.off_keys_list.size,
sizeof(xcb_im_ximtriggerkey_fr_t))
: NULL;
if ((frame.on_keys_list.size && !im->onKeys.keys) ||
(frame.off_keys_list.size && !im->offKeys.keys)) {
free(im->onKeys.keys);
free(im->offKeys.keys);
im->onKeys.keys = im->offKeys.keys = NULL;
im->onKeys.nKeys = im->offKeys.nKeys = 0;
break;
}
im->onKeys.nKeys = frame.on_keys_list.size;
im->offKeys.nKeys = frame.off_keys_list.size;
if (frame.on_keys_list.size) {
memcpy(im->onKeys.keys, frame.on_keys_list.items,
frame.on_keys_list.size * sizeof(xcb_im_ximtriggerkey_fr_t));
}
if (frame.off_keys_list.size) {
memcpy(im->offKeys.keys, frame.off_keys_list.items,
frame.off_keys_list.size *
sizeof(xcb_im_ximtriggerkey_fr_t));
}
} while (0);
xcb_im_register_triggerkeys_fr_free(&frame);
}
void _xcb_xim_handle_create_ic_reply(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_create_ic_reply_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (!im->current) {
break;
}
if (im->current->major_code != XCB_XIM_CREATE_IC &&
im->connect_id != frame.input_method_ID) {
break;
}
xcb_xim_request_queue_t *request = im->current;
im->current = NULL;
if (request->callback.create_ic) {
request->callback.create_ic(im, frame.input_context_ID,
request->user_data);
}
_xcb_xim_request_free(request);
} while (0);
xcb_im_create_ic_reply_fr_free(&frame);
}
void _xcb_xim_handle_destroy_ic_reply(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_destroy_ic_reply_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (!im->current) {
break;
}
if (im->current->major_code != XCB_XIM_DESTROY_IC &&
im->connect_id != frame.input_method_ID &&
im->current->frame.destroy_ic.input_context_ID !=
frame.input_context_ID) {
break;
}
xcb_xim_request_queue_t *request = im->current;
im->current = NULL;
if (request->callback.destroy_ic) {
request->callback.destroy_ic(im, frame.input_context_ID,
request->user_data);
}
_xcb_xim_request_free(request);
} while (0);
xcb_im_destroy_ic_reply_fr_free(&frame);
}
void _xcb_xim_handle_get_im_values_reply(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_get_im_values_reply_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (!im->current) {
break;
}
if (im->current->major_code != XCB_XIM_GET_IM_VALUES &&
im->connect_id != frame.input_method_ID) {
break;
}
xcb_xim_request_queue_t *request = im->current;
im->current = NULL;
if (request->callback.get_im_values) {
request->callback.get_im_values(im, &frame, request->user_data);
}
_xcb_xim_request_free(request);
} while (0);
xcb_im_get_im_values_reply_fr_free(&frame);
}
void _xcb_xim_handle_get_ic_values_reply(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_get_ic_values_reply_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (!im->current) {
break;
}
if (im->current->major_code != XCB_XIM_GET_IC_VALUES &&
im->connect_id != frame.input_method_ID &&
im->current->frame.get_ic_values.input_context_ID !=
frame.input_context_ID) {
break;
}
xcb_xim_request_queue_t *request = im->current;
im->current = NULL;
if (request->callback.get_ic_values) {
request->callback.get_ic_values(im, frame.input_context_ID, &frame,
request->user_data);
}
_xcb_xim_request_free(request);
} while (0);
xcb_im_get_ic_values_reply_fr_free(&frame);
}
void _xcb_xim_handle_set_ic_values_reply(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_set_ic_values_reply_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (!im->current) {
break;
}
if (im->current->major_code != XCB_XIM_SET_IC_VALUES &&
im->connect_id != frame.input_method_ID &&
im->current->frame.set_ic_values.input_context_ID !=
frame.input_context_ID) {
break;
}
xcb_xim_request_queue_t *request = im->current;
im->current = NULL;
if (request->callback.set_ic_values) {
request->callback.set_ic_values(im, frame.input_context_ID,
request->user_data);
}
_xcb_xim_request_free(request);
} while (0);
xcb_im_set_ic_values_reply_fr_free(&frame);
}
void _xcb_xim_handle_reset_ic_reply(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_reset_ic_reply_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (!im->current) {
break;
}
if (im->current->major_code != XCB_XIM_RESET_IC &&
im->connect_id != frame.input_method_ID &&
im->current->frame.reset_ic.input_context_ID !=
frame.input_context_ID) {
break;
}
xcb_xim_request_queue_t *request = im->current;
im->current = NULL;
if (request->callback.reset_ic) {
request->callback.reset_ic(im, frame.input_context_ID, &frame,
request->user_data);
}
_xcb_xim_request_free(request);
} while (0);
xcb_im_reset_ic_reply_fr_free(&frame);
}
void _xcb_xim_handle_forward_event(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_forward_event_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (XIM_MESSAGE_BYTES(hdr) < xcb_im_forward_event_fr_size(&frame) +
sizeof(xcb_key_press_event_t)) {
break;
}
if (im->connect_id != frame.input_method_ID) {
break;
}
xcb_key_press_event_t key_event;
data += xcb_im_forward_event_fr_size(&frame);
memcpy(&key_event, data, sizeof(xcb_key_press_event_t));
if (im->im_callback.forward_event) {
im->im_callback.forward_event(im, frame.input_context_ID,
&key_event, im->user_data);
}
if (frame.flag & XCB_XIM_SYNCHRONOUS) {
_xcb_xim_sync(im, frame.input_context_ID);
}
} while (0);
xcb_im_forward_event_fr_free(&frame);
}
void _xcb_xim_handle_commit(xcb_xim_t *im, const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
if (XIM_MESSAGE_BYTES(hdr) < 6) {
return;
}
uint8_t *pflag = data + 4;
uint16_t flag;
size_t len = XIM_MESSAGE_BYTES(hdr);
uint16_t_read(&flag, &pflag, &len, false);
if (flag & XCB_XIM_LOOKUP_KEYSYM) {
xcb_im_commit_both_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (im->connect_id != frame.input_method_ID) {
break;
}
if (im->im_callback.commit_string) {
im->im_callback.commit_string(
im, frame.input_context_ID, frame.flag,
(char *)frame.committed_string,
frame.byte_length_of_committed_string, &frame.keysym, 1,
im->user_data);
}
if (flag & XCB_XIM_SYNCHRONOUS) {
_xcb_xim_sync(im, frame.input_context_ID);
}
} while (0);
xcb_im_commit_both_fr_free(&frame);
} else if ((flag & XCB_XIM_LOOKUP_BOTH) == XCB_XIM_LOOKUP_CHARS) {
xcb_im_commit_chars_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (im->connect_id != frame.input_method_ID) {
break;
}
if (im->im_callback.commit_string) {
im->im_callback.commit_string(
im, frame.input_context_ID, frame.flag,
(char *)frame.committed_string,
frame.byte_length_of_committed_string, NULL, 0,
im->user_data);
}
if (flag & XCB_XIM_SYNCHRONOUS) {
_xcb_xim_sync(im, frame.input_context_ID);
}
} while (0);
xcb_im_commit_chars_fr_free(&frame);
}
}
void _xcb_xim_handle_close_reply(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
// why we need to wait server :?
}
void _xcb_xim_handle_geometry(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_geometry_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (im->connect_id != frame.input_method_ID) {
break;
}
if (im->im_callback.geometry) {
im->im_callback.geometry(im, frame.input_context_ID, im->user_data);
}
} while (0);
xcb_im_geometry_fr_free(&frame);
}
void _xcb_xim_handle_preedit_start(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_preedit_start_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (im->connect_id != frame.input_method_ID) {
break;
}
if (im->im_callback.preedit_start) {
im->im_callback.preedit_start(im, frame.input_context_ID,
im->user_data);
}
} while (0);
xcb_im_preedit_start_fr_free(&frame);
}
void _xcb_xim_handle_preedit_draw(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_preedit_draw_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (im->connect_id != frame.input_method_ID) {
break;
}
if (im->im_callback.preedit_draw) {
im->im_callback.preedit_draw(im, frame.input_context_ID, &frame,
im->user_data);
}
} while (0);
xcb_im_preedit_draw_fr_free(&frame);
}
void _xcb_xim_handle_preedit_caret(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_preedit_caret_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (im->connect_id != frame.input_method_ID) {
break;
}
if (im->im_callback.preedit_caret) {
im->im_callback.preedit_caret(im, frame.input_context_ID, &frame,
im->user_data);
}
} while (0);
xcb_im_preedit_caret_fr_free(&frame);
}
void _xcb_xim_handle_preedit_done(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_preedit_done_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (im->connect_id != frame.input_method_ID) {
break;
}
if (im->im_callback.preedit_done) {
im->im_callback.preedit_done(im, frame.input_context_ID,
im->user_data);
}
} while (0);
xcb_im_preedit_done_fr_free(&frame);
}
void _xcb_xim_handle_status_start(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_status_start_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (im->connect_id != frame.input_method_ID) {
break;
}
if (im->im_callback.status_start) {
im->im_callback.status_start(im, frame.input_context_ID,
im->user_data);
}
} while (0);
xcb_im_status_start_fr_free(&frame);
}
void _xcb_xim_handle_status_draw(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
if (XIM_MESSAGE_BYTES(hdr) < 8) {
return;
}
uint8_t *ptype = data + 4;
uint32_t type;
size_t len = XIM_MESSAGE_BYTES(hdr);
uint32_t_read(&type, &ptype, &len, false);
if (type == XCB_IM_TextType) {
xcb_im_status_draw_text_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (im->connect_id != frame.input_method_ID) {
break;
}
if (im->im_callback.status_draw_text) {
im->im_callback.status_draw_text(im, frame.input_context_ID,
&frame, im->user_data);
}
} while (0);
xcb_im_status_draw_text_fr_free(&frame);
} else if (type == XCB_IM_BitmapType) {
xcb_im_status_draw_bitmap_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (im->connect_id != frame.input_method_ID) {
break;
}
if (im->im_callback.status_draw_bitmap) {
im->im_callback.status_draw_bitmap(im, frame.input_context_ID,
&frame, im->user_data);
}
} while (0);
xcb_im_status_draw_bitmap_fr_free(&frame);
}
}
void _xcb_xim_handle_status_done(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_status_done_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (im->connect_id != frame.input_method_ID) {
break;
}
if (im->im_callback.status_done) {
im->im_callback.status_done(im, frame.input_context_ID,
im->user_data);
}
} while (0);
xcb_im_status_done_fr_free(&frame);
}
void _xcb_xim_handle_set_event_mask(xcb_xim_t *im,
const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_set_event_mask_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (im->connect_id != frame.input_method_ID) {
break;
}
if (im->im_callback.set_event_mask) {
im->im_callback.set_event_mask(
im, frame.input_context_ID, frame.forward_event_mask,
frame.synchronous_event_mask, im->user_data);
}
} while (0);
xcb_im_set_event_mask_fr_free(&frame);
}
void _xcb_xim_handle_sync(xcb_xim_t *im, const xcb_im_packet_header_fr_t *hdr,
uint8_t *data) {
xcb_im_sync_fr_t frame;
bool fail;
_xcb_xim_read_frame(frame, data, XIM_MESSAGE_BYTES(hdr), fail);
if (fail) {
return;
}
do {
if (im->connect_id != frame.input_method_ID) {
break;
}
_xcb_xim_sync(im, frame.input_context_ID);
} while (0);
xcb_im_sync_fr_free(&frame);
}
void _xcb_xim_handle_error(xcb_xim_t *im, uint8_t *data) {
if (im->open_state == XIM_OPEN_DONE) {
if (im->current) {
_xcb_xim_process_fail_callback(im, im->current);
_xcb_xim_request_free(im->current);
im->current = NULL;
}
} else {
if (im->open_state != XIM_OPEN_INVALID) {
im->open_state = XIM_OPEN_INVALID;
im->yield_recheck = true;
}
}
}