first commit
This commit is contained in:
10
xim/xcb-imdkit/test/CMakeLists.txt
Normal file
10
xim/xcb-imdkit/test/CMakeLists.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
add_executable(test_server test_server.c)
|
||||
target_link_libraries(test_server XCB::XCB XCB::UTIL XCB::KEYSYMS xcb-imdkit)
|
||||
add_executable(test_client test_client.c)
|
||||
target_link_libraries(test_client XCB::XCB XCB::UTIL XCB::KEYSYMS xcb-imdkit)
|
||||
add_executable(client_demo client_demo.c)
|
||||
target_link_libraries(client_demo XCB::XCB XCB::UTIL XCB::KEYSYMS xcb-imdkit)
|
||||
|
||||
add_executable(test_encoding test_encoding.c)
|
||||
target_link_libraries(test_encoding xcb-imdkit)
|
||||
add_test(NAME test_encoding COMMAND test_encoding)
|
||||
139
xim/xcb-imdkit/test/client_demo.c
Normal file
139
xim/xcb-imdkit/test/client_demo.c
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Weng Xuetian <wengxt@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*
|
||||
*/
|
||||
#include "encoding.h"
|
||||
#include "imclient.h"
|
||||
#include "ximproto.h"
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/xcb_aux.h>
|
||||
#include <xcb/xproto.h>
|
||||
|
||||
xcb_window_t w;
|
||||
xcb_xic_t ic;
|
||||
|
||||
void forward_event(xcb_xim_t *im, xcb_xic_t ic, xcb_key_press_event_t *event,
|
||||
void *user_data) {
|
||||
fprintf(stderr, "Key %s Keycode %u, State %u\n",
|
||||
event->response_type == XCB_KEY_PRESS ? "press" : "release",
|
||||
event->detail, event->state);
|
||||
}
|
||||
|
||||
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) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void disconnected(xcb_xim_t *im, void *user_data) {
|
||||
fprintf(stderr, "Disconnected from input method server.\n");
|
||||
ic = 0;
|
||||
}
|
||||
|
||||
xcb_xim_im_callback callback = {
|
||||
.forward_event = forward_event,
|
||||
.commit_string = commit_string,
|
||||
.disconnected = disconnected,
|
||||
};
|
||||
|
||||
void logger(const char *fmt, ...) {
|
||||
va_list argp;
|
||||
va_start(argp, fmt);
|
||||
vprintf(fmt, argp);
|
||||
va_end(argp);
|
||||
}
|
||||
|
||||
void create_ic_callback(xcb_xim_t *im, xcb_xic_t new_ic, void *user_data) {
|
||||
ic = new_ic;
|
||||
if (ic) {
|
||||
fprintf(stderr, "icid:%u\n", ic);
|
||||
xcb_xim_set_ic_focus(im, ic);
|
||||
}
|
||||
}
|
||||
|
||||
void open_callback(xcb_xim_t *im, void *user_data) {
|
||||
uint32_t input_style = XCB_IM_PreeditPosition | XCB_IM_StatusArea;
|
||||
xcb_point_t spot;
|
||||
spot.x = 0;
|
||||
spot.y = 0;
|
||||
xcb_xim_nested_list nested =
|
||||
xcb_xim_create_nested_list(im, XCB_XIM_XNSpotLocation, &spot, NULL);
|
||||
xcb_xim_create_ic(im, create_ic_callback, NULL, XCB_XIM_XNInputStyle,
|
||||
&input_style, XCB_XIM_XNClientWindow, &w,
|
||||
XCB_XIM_XNFocusWindow, &w, XCB_XIM_XNPreeditAttributes,
|
||||
&nested, NULL);
|
||||
free(nested.data);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
// Init global state for compound text encoding.
|
||||
xcb_compound_text_init();
|
||||
|
||||
// Open connection to X server
|
||||
int screen_default_nbr;
|
||||
xcb_connection_t *connection = xcb_connect(NULL, &screen_default_nbr);
|
||||
xcb_screen_t *screen = xcb_aux_get_screen(connection, screen_default_nbr);
|
||||
|
||||
if (!screen) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
xcb_xim_t *im = xcb_xim_create(connection, screen_default_nbr, NULL);
|
||||
|
||||
xcb_xim_set_im_callback(im, &callback, NULL);
|
||||
xcb_xim_set_log_handler(im, logger);
|
||||
xcb_xim_set_use_compound_text(im, true);
|
||||
xcb_xim_set_use_utf8_string(im, true);
|
||||
|
||||
// Open connection to XIM server.
|
||||
xcb_xim_open(im, open_callback, true, NULL);
|
||||
|
||||
// Create a dummy window for testing.
|
||||
w = xcb_generate_id(connection);
|
||||
xcb_create_window(connection, XCB_COPY_FROM_PARENT, w, screen->root, 0, 0,
|
||||
100, 100, 1, XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
||||
screen->root_visual, 0, NULL);
|
||||
uint32_t mask = XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE |
|
||||
XCB_EVENT_MASK_FOCUS_CHANGE;
|
||||
xcb_change_window_attributes(connection, w, XCB_CW_EVENT_MASK, &mask);
|
||||
xcb_map_window(connection, w);
|
||||
xcb_flush(connection);
|
||||
|
||||
xcb_generic_event_t *event;
|
||||
while ((event = xcb_wait_for_event(connection))) {
|
||||
logger("event_type=%d\n", (event->response_type & ~0x80));
|
||||
if (!xcb_xim_filter_event(im, event)) {
|
||||
// Forward event to input method if IC is created.
|
||||
if (ic && (((event->response_type & ~0x80) == XCB_KEY_PRESS) ||
|
||||
((event->response_type & ~0x80) == XCB_KEY_RELEASE))) {
|
||||
xcb_xim_forward_event(im, ic, (xcb_key_press_event_t *)event);
|
||||
}
|
||||
}
|
||||
free(event);
|
||||
}
|
||||
|
||||
xcb_xim_close(im);
|
||||
xcb_xim_destroy(im);
|
||||
|
||||
xcb_disconnect(connection);
|
||||
|
||||
return 0;
|
||||
}
|
||||
170
xim/xcb-imdkit/test/test_client.c
Normal file
170
xim/xcb-imdkit/test/test_client.c
Normal file
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Weng Xuetian <wengxt@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*
|
||||
*/
|
||||
#include "imclient.h"
|
||||
#include "ximproto.h"
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/xcb_aux.h>
|
||||
#include <xcb/xproto.h>
|
||||
|
||||
xcb_connection_t *connection;
|
||||
xcb_window_t w;
|
||||
xcb_screen_t *screen;
|
||||
bool end = false;
|
||||
|
||||
void forward_event(xcb_xim_t *im, xcb_xic_t ic, xcb_key_press_event_t *event,
|
||||
void *user_data) {
|
||||
fprintf(stderr, "Key %s Keycode %u, State %u\n",
|
||||
event->response_type == XCB_KEY_PRESS ? "press" : "release",
|
||||
event->detail, event->state);
|
||||
}
|
||||
|
||||
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) {
|
||||
fprintf(stderr, "key commit: %.*s\n", length, str);
|
||||
}
|
||||
|
||||
xcb_xim_im_callback callback = {.forward_event = forward_event,
|
||||
.commit_string = commit_string};
|
||||
|
||||
void destroy_ic_callback(xcb_xim_t *im, xcb_xic_t ic, void *user_data) {
|
||||
fprintf(stderr, "ic %d destroyed\n", ic);
|
||||
// end = true;
|
||||
}
|
||||
|
||||
void get_ic_values_callback(xcb_xim_t *im, xcb_xic_t ic,
|
||||
xcb_im_get_ic_values_reply_fr_t *reply,
|
||||
void *user_data) {
|
||||
fprintf(stderr, "get ic %d done\n", ic);
|
||||
xcb_xim_destroy_ic(im, ic, destroy_ic_callback, NULL);
|
||||
xcb_key_press_event_t event;
|
||||
memset(&event, 0, sizeof(event));
|
||||
event.root = screen->root;
|
||||
event.detail = 65;
|
||||
event.state = 0x4;
|
||||
event.event = w;
|
||||
event.response_type = XCB_KEY_PRESS;
|
||||
xcb_xim_forward_event(im, ic, &event);
|
||||
event.detail = 38;
|
||||
event.state = 0;
|
||||
xcb_xim_forward_event(im, ic, &event);
|
||||
event.detail = 56;
|
||||
event.state = 0;
|
||||
xcb_xim_forward_event(im, ic, &event);
|
||||
event.detail = 38;
|
||||
event.state = 0;
|
||||
xcb_xim_forward_event(im, ic, &event);
|
||||
event.detail = 56;
|
||||
event.state = 0;
|
||||
xcb_xim_forward_event(im, ic, &event);
|
||||
event.detail = 38;
|
||||
event.state = 0;
|
||||
xcb_xim_forward_event(im, ic, &event);
|
||||
event.detail = 56;
|
||||
event.state = 0;
|
||||
xcb_xim_forward_event(im, ic, &event);
|
||||
event.detail = 38;
|
||||
event.state = 0;
|
||||
xcb_xim_forward_event(im, ic, &event);
|
||||
event.detail = 56;
|
||||
event.state = 0;
|
||||
xcb_xim_forward_event(im, ic, &event);
|
||||
}
|
||||
|
||||
void set_ic_values_callback(xcb_xim_t *im, xcb_xic_t ic, void *user_data) {
|
||||
fprintf(stderr, "set ic %d done\n", ic);
|
||||
xcb_xim_get_ic_values(im, ic, get_ic_values_callback, NULL,
|
||||
XCB_XIM_XNPreeditAttributes, NULL);
|
||||
}
|
||||
|
||||
void create_ic_callback(xcb_xim_t *im, xcb_xic_t ic, void *user_data) {
|
||||
if (ic) {
|
||||
fprintf(stderr, "icid:%u\n", ic);
|
||||
xcb_point_t spot;
|
||||
spot.x = 0;
|
||||
spot.y = 0;
|
||||
xcb_xim_nested_list nested =
|
||||
xcb_xim_create_nested_list(im, XCB_XIM_XNSpotLocation, &spot, NULL);
|
||||
xcb_xim_set_ic_values(im, ic, set_ic_values_callback, NULL,
|
||||
XCB_XIM_XNPreeditAttributes, &nested, NULL);
|
||||
free(nested.data);
|
||||
} else {
|
||||
fprintf(stderr, "failed.\n");
|
||||
}
|
||||
}
|
||||
|
||||
void get_im_values_callback(xcb_xim_t *im,
|
||||
xcb_im_get_im_values_reply_fr_t *reply,
|
||||
void *user_data) {
|
||||
w = xcb_generate_id(connection);
|
||||
xcb_create_window(connection, XCB_COPY_FROM_PARENT, w, screen->root, 0, 0,
|
||||
1, 1, 1, XCB_WINDOW_CLASS_INPUT_OUTPUT,
|
||||
screen->root_visual, 0, NULL);
|
||||
uint32_t input_style = XCB_IM_PreeditPosition | XCB_IM_StatusArea;
|
||||
xcb_point_t spot;
|
||||
spot.x = 0;
|
||||
spot.y = 0;
|
||||
xcb_xim_nested_list nested =
|
||||
xcb_xim_create_nested_list(im, XCB_XIM_XNSpotLocation, &spot, NULL);
|
||||
xcb_xim_create_ic(im, create_ic_callback, NULL, XCB_XIM_XNInputStyle,
|
||||
&input_style, XCB_XIM_XNClientWindow, &w,
|
||||
XCB_XIM_XNFocusWindow, &w, XCB_XIM_XNPreeditAttributes,
|
||||
&nested, NULL);
|
||||
free(nested.data);
|
||||
}
|
||||
|
||||
void open_callback(xcb_xim_t *im, void *user_data) {
|
||||
xcb_xim_get_im_values(im, get_im_values_callback, NULL,
|
||||
XCB_XIM_XNQueryInputStyle, NULL);
|
||||
}
|
||||
|
||||
void logger(const char *fmt, ...) {
|
||||
va_list argp;
|
||||
va_start(argp, fmt);
|
||||
vprintf(fmt, argp);
|
||||
va_end(argp);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
/* Open the connection to the X server */
|
||||
int screen_default_nbr;
|
||||
connection = xcb_connect(NULL, &screen_default_nbr);
|
||||
screen = xcb_aux_get_screen(connection, screen_default_nbr);
|
||||
|
||||
if (!screen) {
|
||||
return false;
|
||||
}
|
||||
xcb_xim_t *im =
|
||||
xcb_xim_create(connection, screen_default_nbr, "@im=test_server");
|
||||
|
||||
xcb_xim_set_im_callback(im, &callback, NULL);
|
||||
xcb_xim_set_log_handler(im, logger);
|
||||
assert(xcb_xim_open(im, open_callback, true, NULL));
|
||||
|
||||
xcb_generic_event_t *event;
|
||||
while ((event = xcb_wait_for_event(connection))) {
|
||||
xcb_xim_filter_event(im, event);
|
||||
free(event);
|
||||
if (end) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
xcb_xim_close(im);
|
||||
xcb_xim_destroy(im);
|
||||
|
||||
xcb_disconnect(connection);
|
||||
|
||||
return 0;
|
||||
}
|
||||
33
xim/xcb-imdkit/test/test_encoding.c
Normal file
33
xim/xcb-imdkit/test/test_encoding.c
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Weng Xuetian <wengxt@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*
|
||||
*/
|
||||
#include "encoding.h"
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define TEST_STRING "hello world!你好世界켐ㅇㄹ貴方元気?☺"
|
||||
|
||||
void test_conversion(const char *str) {
|
||||
|
||||
size_t len;
|
||||
char *result = xcb_utf8_to_compound_text(str, strlen(str), &len);
|
||||
|
||||
char *utf8_result = xcb_compound_text_to_utf8(result, len, NULL);
|
||||
|
||||
assert(strcmp(utf8_result, str) == 0);
|
||||
|
||||
free(result);
|
||||
free(utf8_result);
|
||||
}
|
||||
|
||||
int main() {
|
||||
xcb_compound_text_init();
|
||||
test_conversion(TEST_STRING);
|
||||
test_conversion("\xe2\x80\x93");
|
||||
|
||||
return 0;
|
||||
}
|
||||
113
xim/xcb-imdkit/test/test_server.c
Normal file
113
xim/xcb-imdkit/test/test_server.c
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Weng Xuetian <wengxt@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*
|
||||
*/
|
||||
#include "encoding.h"
|
||||
#include "imdkit.h"
|
||||
#include "ximproto.h"
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/xcb_aux.h>
|
||||
#include <xcb/xcb_keysyms.h>
|
||||
#include <xcb/xproto.h>
|
||||
|
||||
#define TEST_STRING "hello world你好世界켐ㅇㄹ貴方元気?☺"
|
||||
|
||||
bool end = false;
|
||||
|
||||
void callback(xcb_im_t *im, xcb_im_client_t *client, xcb_im_input_context_t *ic,
|
||||
const xcb_im_packet_header_fr_t *hdr, void *frame, void *arg,
|
||||
void *user_data) {
|
||||
if (hdr->major_opcode == XCB_XIM_DISCONNECT) {
|
||||
// end = true;
|
||||
}
|
||||
|
||||
if (hdr->major_opcode == XCB_XIM_FORWARD_EVENT) {
|
||||
xcb_key_press_event_t *event = arg;
|
||||
|
||||
xcb_key_symbols_t *key_symbols = user_data;
|
||||
xcb_keysym_t sym =
|
||||
xcb_key_symbols_get_keysym(key_symbols, event->detail, 0);
|
||||
if (sym == 't') {
|
||||
size_t len;
|
||||
char *result = xcb_utf8_to_compound_text(TEST_STRING,
|
||||
strlen(TEST_STRING), &len);
|
||||
xcb_im_commit_string(im, ic, XCB_XIM_LOOKUP_CHARS, result, len, 0);
|
||||
free(result);
|
||||
} else {
|
||||
xcb_im_forward_event(im, ic, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t style_array[] = {
|
||||
XCB_IM_PreeditPosition | XCB_IM_StatusArea, // OverTheSpot
|
||||
XCB_IM_PreeditPosition | XCB_IM_StatusNothing, // OverTheSpot
|
||||
XCB_IM_PreeditPosition | XCB_IM_StatusNone, // OverTheSpot
|
||||
XCB_IM_PreeditNothing | XCB_IM_StatusNothing, // Root
|
||||
XCB_IM_PreeditNothing | XCB_IM_StatusNone, // Root
|
||||
};
|
||||
static char *encoding_array[] = {
|
||||
"COMPOUND_TEXT",
|
||||
};
|
||||
|
||||
static xcb_im_encodings_t encodings = {1, encoding_array};
|
||||
|
||||
static xcb_im_styles_t styles = {5, style_array};
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
xcb_compound_text_init();
|
||||
/* Open the connection to the X server */
|
||||
|
||||
int screen_default_nbr;
|
||||
xcb_connection_t *connection = xcb_connect(NULL, &screen_default_nbr);
|
||||
xcb_screen_t *screen = xcb_aux_get_screen(connection, screen_default_nbr);
|
||||
xcb_key_symbols_t *key_symbols = xcb_key_symbols_alloc(connection);
|
||||
|
||||
if (!screen) {
|
||||
return false;
|
||||
}
|
||||
xcb_window_t root = screen->root;
|
||||
|
||||
xcb_window_t w = xcb_generate_id(connection);
|
||||
xcb_create_window(connection, XCB_COPY_FROM_PARENT, w, root, 0, 0, 1, 1, 1,
|
||||
XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, 0,
|
||||
NULL);
|
||||
xcb_im_trigger_keys_t keys;
|
||||
xcb_im_ximtriggerkey_fr_t key;
|
||||
key.keysym = ' ';
|
||||
key.modifier = 1 << 2;
|
||||
key.modifier_mask = 1 << 2;
|
||||
keys.nKeys = 1;
|
||||
keys.keys = &key;
|
||||
xcb_im_t *im = xcb_im_create(
|
||||
connection, screen_default_nbr, w, "test_server", XCB_IM_ALL_LOCALES,
|
||||
&styles, &keys, &keys, &encodings, 0, callback, key_symbols);
|
||||
assert(xcb_im_open_im(im));
|
||||
|
||||
printf("winid:%u\n", w);
|
||||
|
||||
xcb_generic_event_t *event;
|
||||
while ((event = xcb_wait_for_event(connection))) {
|
||||
xcb_im_filter_event(im, event);
|
||||
free(event);
|
||||
if (end) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
xcb_im_close_im(im);
|
||||
xcb_im_destroy(im);
|
||||
|
||||
xcb_key_symbols_free(key_symbols);
|
||||
xcb_disconnect(connection);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user