Skip to content

Commit

Permalink
Add API to allow enforce encoding on client library and query encoding
Browse files Browse the repository at this point in the history
to be used.

Fix a bug in protocolhandler for encoding index, the index should be the
index on our side, instead of the client side.
  • Loading branch information
wengxt committed Mar 1, 2021
1 parent 7766db9 commit a16d25e
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 15 deletions.
33 changes: 27 additions & 6 deletions src/clientprotocolhandler.c
Expand Up @@ -37,12 +37,23 @@ bool _xcb_xim_send_query_extension(xcb_xim_t *im) {

bool _xcb_xim_send_encoding_negotiation(xcb_xim_t *im) {
xcb_im_encoding_negotiation_fr_t frame;
xcb_im_str_fr_t compound;
compound.length_of_string = strlen("COMPOUND_TEXT");
compound.string = (uint8_t *)"COMPOUND_TEXT";
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 = 1;
frame.supported_list_of_encoding_in_IM_library.items = &compound;
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;

Expand Down Expand Up @@ -185,13 +196,23 @@ void _xcb_xim_handle_encoding_negotiation_reply(
}

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 != 0) {
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);
Expand Down
15 changes: 14 additions & 1 deletion src/imclient.c
Expand Up @@ -497,7 +497,6 @@ xcb_xim_t *xcb_xim_create(xcb_connection_t *conn, int screen_id,
if (!imname) {
imname = getenv("XMODIFIERS");
}

im->conn = conn;
im->server_name = _xcb_xim_make_im_name(imname);
im->screen_id = screen_id;
Expand All @@ -509,13 +508,27 @@ xcb_xim_t *xcb_xim_create(xcb_connection_t *conn, int screen_id,
} else {
im->byte_order = 'B';
}

im->use_compound_text = true;
im->use_utf8_string = false;
im->encoding = XCB_XIM_COMPOUND_TEXT;
return im;
}

void xcb_xim_set_log_handler(xcb_xim_t *im, void (*logger)(const char *, ...)) {
im->logger = logger;
}

void xcb_xim_set_use_compound_text(xcb_xim_t *im, bool enable) {
im->use_compound_text = enable;
}

void xcb_xim_set_use_utf8_string(xcb_xim_t *im, bool enable) {
im->use_utf8_string = enable;
}

xcb_xim_encoding_t xcb_xim_get_encoding(xcb_xim_t *im) { return im->encoding; }

bool _xcb_xim_open(xcb_xim_t *im) {
im->connect_state.phase = XIM_CONNECT_FAIL;
im->open_state = XIM_OPEN_INVALID;
Expand Down
12 changes: 12 additions & 0 deletions src/imclient.h
Expand Up @@ -86,6 +86,11 @@ typedef enum _xcb_xim_trigger_key_type_t {
XCB_XIM_TRIGGER_OFF_KEY,
} xcb_xim_trigger_key_type_t;

typedef enum _xcb_xim_encoding_t {
XCB_XIM_COMPOUND_TEXT,
XCB_XIM_UTF8_STRING,
} xcb_xim_encoding_t;

typedef void (*xcb_xim_open_callback)(xcb_xim_t *im, void *user_data);
typedef void (*xcb_xim_create_ic_callback)(xcb_xim_t *im, xcb_xic_t ic,
void *user_data);
Expand All @@ -106,11 +111,18 @@ XCBIMDKIT_EXPORT xcb_xim_t *xcb_xim_create(xcb_connection_t *conn,
int screen_id, const char *imname);
XCBIMDKIT_EXPORT void
xcb_xim_set_log_handler(xcb_xim_t *im, void (*logger)(const char *, ...));
XCBIMDKIT_EXPORT void xcb_xim_set_use_compound_text(xcb_xim_t *im, bool enable);
XCBIMDKIT_EXPORT void xcb_xim_set_use_utf8_string(xcb_xim_t *im, bool enable);
XCBIMDKIT_EXPORT
xcb_xim_encoding_t xcb_xim_get_encoding(xcb_xim_t *im);
XCBIMDKIT_EXPORT void xcb_xim_destroy(xcb_xim_t *im);
XCBIMDKIT_EXPORT bool xcb_xim_open(xcb_xim_t *im,
xcb_xim_open_callback callback,
bool auto_connect, void *user_data);
XCBIMDKIT_EXPORT void
xcb_xim_set_im_callback(xcb_xim_t *im, const xcb_xim_im_callback *callbacks,
void *user_data);
XCBIMDKIT_EXPORT void
xcb_xim_set_im_callback(xcb_xim_t *im, const xcb_xim_im_callback *callbacks,
void *user_data);
XCBIMDKIT_EXPORT bool xcb_xim_filter_event(xcb_xim_t *im,
Expand Down
4 changes: 4 additions & 0 deletions src/imclient_p.h
Expand Up @@ -165,6 +165,10 @@ struct _xcb_xim_t {
xcb_window_t focus_window;

void (*logger)(const char *, ...);

bool use_compound_text;
bool use_utf8_string;
xcb_xim_encoding_t encoding;
};

#define _xcb_xim_read_frame(FRAME, DATA, LEN, FAIL) \
Expand Down
7 changes: 4 additions & 3 deletions src/protocolhandler.c
Expand Up @@ -161,6 +161,7 @@ void _xcb_im_handle_encoding_negotiation(xcb_im_t *im, xcb_im_client_t *client,
// no match then we use 0.
if (i == frame.supported_list_of_encoding_in_IM_library.size) {
i = 0;
j = 0;
}

xcb_im_encoding_negotiation_fr_free(&frame);
Expand All @@ -169,10 +170,10 @@ void _xcb_im_handle_encoding_negotiation(xcb_im_t *im, xcb_im_client_t *client,
reply_frame.index_of_the_encoding_determined = i;
reply_frame.category_of_the_encoding_determined = 0;

uint16_t index = j;

if (im->callback) {
im->callback(im, client, NULL, hdr, &frame,
&reply_frame.index_of_the_encoding_determined,
im->user_data);
im->callback(im, client, NULL, hdr, &frame, &index, im->user_data);
}

_xcb_im_send_frame(im, client, reply_frame, true);
Expand Down
16 changes: 11 additions & 5 deletions test/client_demo.c
Expand Up @@ -31,11 +31,15 @@ void forward_event(xcb_xim_t *im, xcb_xic_t ic, xcb_key_press_event_t *event,
void commit_string(xcb_xim_t *im, xcb_xic_t ic, uint32_t flag, char *str,
uint32_t length, uint32_t *keysym, size_t nKeySym,
void *user_data) {
size_t newLength = 0;
char *utf8 = xcb_compound_text_to_utf8(str, length, &newLength);
if (utf8) {
int l = newLength;
fprintf(stderr, "key commit: %.*s\n", l, utf8);
if (xcb_xim_get_encoding(im) == XCB_XIM_UTF8_STRING) {
fprintf(stderr, "key commit utf8: %.*s\n", length, str);
} else if (xcb_xim_get_encoding(im) == XCB_XIM_COMPOUND_TEXT) {
size_t newLength = 0;
char *utf8 = xcb_compound_text_to_utf8(str, length, &newLength);
if (utf8) {
int l = newLength;
fprintf(stderr, "key commit: %.*s\n", l, utf8);
}
}
}

Expand Down Expand Up @@ -88,6 +92,8 @@ int main(int argc, char *argv[]) {

xcb_xim_set_im_callback(im, &callback, NULL);
xcb_xim_set_log_handler(im, logger);
xcb_xim_set_use_compound_text(im, false);
xcb_xim_set_use_utf8_string(im, true);

// Open connection to XIM server.
xcb_xim_open(im, open_callback, true, NULL);
Expand Down

0 comments on commit a16d25e

Please sign in to comment.