summaryrefslogtreecommitdiff
path: root/test.c
blob: bacd4424a6d6864265c3ec0d79b8b5d2d0b41b72 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <locale.h>
#include <langinfo.h>
#include <assert.h>

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>

static Atom atom_wm_protocols;
static Atom atom_wm_delete;
static Atom atom_wm_state;
static Atom atom_wm_fullscreen;
static Display *dpy;
static Window win;
static GC gc;
static XIM im;
static XIC ic;

static void set_fullscreen()
{
	XEvent e = { 0 };
	e.type = ClientMessage;
	e.xclient.window = win;
	e.xclient.message_type = atom_wm_state;
	e.xclient.format = 32;
	e.xclient.data.l[0] = 1;
	e.xclient.data.l[1] = atom_wm_fullscreen;
	e.xclient.data.l[2] = 0;

	XSendEvent(dpy, DefaultRootWindow(dpy), False, SubstructureNotifyMask, &e);
}

static int preedit_start_cb(XIC ic, XPointer client_data, XPointer p)
{
	printf("start preedit\n");
	return -1;
}

static int preedit_stop_cb(XIC ic, XPointer client_data, XPointer p)
{
	printf("stop preedit\n");
	return 0;
}

static int preedit_draw_cb(XIC ic, XPointer client_data, XIMPreeditDrawCallbackStruct *s)
{
	printf("draw preedit %d'%s'\n", s->text->length, s->text->string.multi_byte);
	return 0;
}

int main(int argc, char ** argv)
{
	bool quit = false;
	setlocale(LC_ALL, "");
	XSetLocaleModifiers("@im=xmim");

	char *nl = nl_langinfo(CODESET);
	printf("codeset %s\n", nl);

	dpy = XOpenDisplay(NULL);
	assert(dpy);
	int scr = DefaultScreen(dpy);

	atom_wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", True);
	atom_wm_delete = XInternAtom(dpy, "WM_DELETE_WINDOW", True);
	atom_wm_state = XInternAtom(dpy, "_NET_WM_STATE", True);
	atom_wm_fullscreen = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", True);

	win = XCreateSimpleWindow(dpy, RootWindow(dpy, scr), 0, 0, 400, 400, 0,
	                          WhitePixel(dpy, scr), WhitePixel(dpy, scr));

	im = XOpenIM(dpy, NULL, NULL, NULL);
	assert(im);

	XIMStyles *xim_styles = NULL;
	if (XGetIMValues(im, XNQueryInputStyle, &xim_styles, NULL) == 0) {
		printf("styles: (%u)\n", xim_styles->count_styles);
		for (int i = 0; i < xim_styles->count_styles; i++) {
			const XIMStyle style = xim_styles->supported_styles[i];
			printf(" style %lu\n", style);
		}
	}

	XIMCallback preedit_start = { NULL, (XIMProc) preedit_start_cb };
	XIMCallback preedit_stop = { NULL, (XIMProc) preedit_stop_cb };
	XIMCallback preedit_draw = { NULL, (XIMProc) preedit_draw_cb };

	XVaNestedList preedit_list =
	        XVaCreateNestedList(0,
	                            XNPreeditStartCallback, &preedit_start,
	                            XNPreeditDoneCallback, &preedit_stop,
	                            XNPreeditDrawCallback, &preedit_draw,
	                            NULL);

	ic = XCreateIC(im,
	               XNInputStyle, XIMPreeditCallbacks | XIMStatusNothing,
	               XNClientWindow, win, XNFocusWindow, win,
	               XNPreeditAttributes, preedit_list,
	               NULL);
	assert(ic);

	XGCValues gc_values;
	gc = XCreateGC(dpy, win, 0, &gc_values);

	unsigned long im_event_mask;
	XGetICValues(ic, XNFilterEvents, &im_event_mask, NULL);
	printf("im event mask 0x%lx\n", im_event_mask);

	im_event_mask |= KeyPressMask | KeyReleaseMask | ButtonPressMask | FocusChangeMask | ClientMessage;
	XSelectInput(dpy, win, im_event_mask);
	XSetWMProtocols(dpy, win, &atom_wm_delete, 1);

	set_fullscreen();

	XMapWindow(dpy, win);

	while (!quit) {
		XEvent e;
		XNextEvent(dpy, &e);
		if (XFilterEvent(&e, None)) {
			continue;
		}
		switch (e.type) {
		case KeyPress: {
			printf("key press\n");
			KeySym keysym;
			Status status;
			int buflength;
			static int bufsize = 16;
			static char *buf;
			if (buf == NULL) {
				buf = malloc(bufsize + 1);
				assert(buf);
			}
			buflength = Xutf8LookupString(ic, &e.xkey, buf, bufsize, &keysym, &status);
			if (status == XBufferOverflow) {
				bufsize = buflength;
				buf = realloc(buf, bufsize + 1);
				assert(buf);
				buflength = Xutf8LookupString(ic, &e.xkey, buf, bufsize, &keysym, &status);
			}
			switch(status) {
			case XLookupKeySym:
				printf("keysim(0x%lx)\n", keysym);
				break;
			case XLookupBoth:
				printf("keysim(0x%lx)+", keysym);
				// Fallthrough
			case XLookupChars:
				buf[buflength] = '\0';
				printf("string(%d'%s')\n", buflength, buf);
				break;
			case XLookupNone:
				printf("none\n");
				break;
			default:
				printf("weirdo\n");
				break;
			}
		}	break;
		case KeyRelease:
			printf("key release\n");
			break;
		case ButtonPress:
			printf("button press\n");
			break;
		case FocusIn:
			printf("focus in\n");
			XSetICFocus(ic);
			break;
		case FocusOut:
			printf("focus out\n");
			XUnsetICFocus(ic);
			break;
		case ClientMessage:
			printf("client message\n");
			if (e.xclient.message_type == atom_wm_protocols) {
				if (e.xclient.data.l[0] == atom_wm_delete) {
					quit = true;
				}
			}
			break;
		default:
			printf("unknown event\n");
			break;
		}
	}

	XFreeGC(dpy, gc);
	XDestroyIC(ic);
	XCloseIM(im);
	XDestroyWindow(dpy, win);
	XFlush(dpy);
	XCloseDisplay(dpy);

	return EXIT_SUCCESS;
}