xim: place popup from input context
This commit is contained in:
@@ -80,6 +80,8 @@ void xim_adapter_key_contract(struct ct*);
|
||||
void xim_adapter_release_lifecycle(struct ct*);
|
||||
void xim_adapter_free_waits_for_release(struct ct*);
|
||||
void xim_adapter_styles(struct ct*);
|
||||
void xim_adapter_placement(struct ct*);
|
||||
void xim_adapter_placement_updates(struct ct*);
|
||||
void xim_adapter_encoding_negotiation(struct ct*);
|
||||
void xim_adapter_callback_replacement(struct ct*);
|
||||
void xim_adapter_callback_unicode(struct ct*);
|
||||
|
||||
@@ -134,6 +134,8 @@ static const struct ct_test tests[] = {
|
||||
{ "xim/adapter-release-lifecycle", xim_adapter_release_lifecycle },
|
||||
{ "xim/adapter-free-waits-release", xim_adapter_free_waits_for_release },
|
||||
{ "xim/styles", xim_adapter_styles },
|
||||
{ "xim/placement", xim_adapter_placement },
|
||||
{ "xim/placement-updates", xim_adapter_placement_updates },
|
||||
{ "xim/encoding-negotiation", xim_adapter_encoding_negotiation },
|
||||
{ "xim/callback-replacement", xim_adapter_callback_replacement },
|
||||
{ "xim/callback-unicode", xim_adapter_callback_unicode },
|
||||
|
||||
@@ -1,20 +1,63 @@
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb-imdkit/imdkit.h>
|
||||
|
||||
typedef struct Icbinding Icbinding;
|
||||
struct Icbinding
|
||||
{
|
||||
xcb_im_input_context_t *ic;
|
||||
void *data;
|
||||
xcb_window_t clientwin;
|
||||
xcb_window_t focuswin;
|
||||
uint32_t preattrmask;
|
||||
xcb_im_preedit_attr_t preattr;
|
||||
};
|
||||
|
||||
static Icbinding icbindings[8];
|
||||
|
||||
static Icbinding*
|
||||
wirebinding(xcb_im_input_context_t *ic)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < 8; i++)
|
||||
if(icbindings[i].ic == ic)
|
||||
return &icbindings[i];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wirecommit(xcb_im_t*, xcb_im_input_context_t*, uint32_t,
|
||||
const char*, uint32_t, uint32_t);
|
||||
static void wirestart(xcb_im_t*, xcb_im_input_context_t*);
|
||||
static void wiredraw(xcb_im_t*, xcb_im_input_context_t*,
|
||||
xcb_im_preedit_draw_fr_t*);
|
||||
static void wiredone(xcb_im_t*, xcb_im_input_context_t*);
|
||||
static void* wiregetdata(xcb_im_input_context_t*);
|
||||
static xcb_get_geometry_cookie_t wiregeometry(xcb_connection_t*, xcb_drawable_t);
|
||||
static xcb_get_geometry_reply_t* wiregeometryreply(xcb_connection_t*,
|
||||
xcb_get_geometry_cookie_t, xcb_generic_error_t**);
|
||||
static xcb_translate_coordinates_cookie_t wiretranslate(xcb_connection_t*,
|
||||
xcb_window_t, xcb_window_t, int16_t, int16_t);
|
||||
static xcb_translate_coordinates_reply_t* wiretranslatereply(xcb_connection_t*,
|
||||
xcb_translate_coordinates_cookie_t, xcb_generic_error_t**);
|
||||
static int wireflush(xcb_connection_t*);
|
||||
|
||||
#define xcb_im_commit_string wirecommit
|
||||
#define xcb_im_preedit_start_callback wirestart
|
||||
#define xcb_im_preedit_draw_callback wiredraw
|
||||
#define xcb_im_preedit_done_callback wiredone
|
||||
#define xcb_im_input_context_get_data wiregetdata
|
||||
#define xcb_im_input_context_get_data(ic) \
|
||||
(wirebinding(ic) == nil ? nil : wirebinding(ic)->data)
|
||||
#define xcb_im_input_context_get_client_window(ic) \
|
||||
(wirebinding(ic) == nil ? XCB_NONE : wirebinding(ic)->clientwin)
|
||||
#define xcb_im_input_context_get_focus_window(ic) \
|
||||
(wirebinding(ic) == nil ? XCB_NONE : wirebinding(ic)->focuswin)
|
||||
#define xcb_im_input_context_get_preedit_attr_mask(ic) \
|
||||
(wirebinding(ic) == nil ? 0 : wirebinding(ic)->preattrmask)
|
||||
#define xcb_im_input_context_get_preedit_attr(ic) \
|
||||
(wirebinding(ic) == nil ? nil : &wirebinding(ic)->preattr)
|
||||
#define xcb_get_geometry wiregeometry
|
||||
#define xcb_get_geometry_reply wiregeometryreply
|
||||
#define xcb_translate_coordinates wiretranslate
|
||||
#define xcb_translate_coordinates_reply wiretranslatereply
|
||||
#define xcb_flush wireflush
|
||||
#include "xim/xim.c"
|
||||
#undef xcb_im_commit_string
|
||||
@@ -22,6 +65,14 @@ static int wireflush(xcb_connection_t*);
|
||||
#undef xcb_im_preedit_draw_callback
|
||||
#undef xcb_im_preedit_done_callback
|
||||
#undef xcb_im_input_context_get_data
|
||||
#undef xcb_im_input_context_get_client_window
|
||||
#undef xcb_im_input_context_get_focus_window
|
||||
#undef xcb_im_input_context_get_preedit_attr_mask
|
||||
#undef xcb_im_input_context_get_preedit_attr
|
||||
#undef xcb_get_geometry
|
||||
#undef xcb_get_geometry_reply
|
||||
#undef xcb_translate_coordinates
|
||||
#undef xcb_translate_coordinates_reply
|
||||
#undef xcb_flush
|
||||
#include "cutest/cutest.h"
|
||||
|
||||
@@ -51,17 +102,23 @@ struct Wirecall
|
||||
u32int feedback[Maxrunes];
|
||||
};
|
||||
|
||||
typedef struct Icbinding Icbinding;
|
||||
struct Icbinding
|
||||
typedef struct Wirewin Wirewin;
|
||||
struct Wirewin
|
||||
{
|
||||
xcb_im_input_context_t *ic;
|
||||
void *data;
|
||||
xcb_window_t win;
|
||||
int geometryok;
|
||||
int translateok;
|
||||
int samescreen;
|
||||
int rootx;
|
||||
int rooty;
|
||||
int height;
|
||||
};
|
||||
|
||||
static Wirecall wirecalls[Maxwire];
|
||||
static Icbinding icbindings[8];
|
||||
static Wirewin wirewins[8];
|
||||
static int nwirecalls;
|
||||
static int nflush;
|
||||
static int transx, transy;
|
||||
|
||||
static Wirecall*
|
||||
newwire(int op, xcb_im_input_context_t *ic)
|
||||
@@ -133,17 +190,80 @@ wiredone(xcb_im_t *im, xcb_im_input_context_t *ic)
|
||||
newwire(Wdone, ic);
|
||||
}
|
||||
|
||||
static void*
|
||||
wiregetdata(xcb_im_input_context_t *ic)
|
||||
static Wirewin*
|
||||
wirewindow(xcb_window_t win)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < nelem(icbindings); i++)
|
||||
if(icbindings[i].ic == ic)
|
||||
return icbindings[i].data;
|
||||
for(i = 0; i < nelem(wirewins); i++)
|
||||
if(wirewins[i].win == win)
|
||||
return &wirewins[i];
|
||||
return nil;
|
||||
}
|
||||
|
||||
static xcb_get_geometry_cookie_t
|
||||
wiregeometry(xcb_connection_t *c, xcb_drawable_t drawable)
|
||||
{
|
||||
xcb_get_geometry_cookie_t cookie;
|
||||
|
||||
USED(c);
|
||||
cookie.sequence = drawable;
|
||||
return cookie;
|
||||
}
|
||||
|
||||
static xcb_get_geometry_reply_t*
|
||||
wiregeometryreply(xcb_connection_t *c, xcb_get_geometry_cookie_t cookie,
|
||||
xcb_generic_error_t **error)
|
||||
{
|
||||
xcb_get_geometry_reply_t *reply;
|
||||
Wirewin *w;
|
||||
|
||||
USED(c);
|
||||
USED(error);
|
||||
w = wirewindow(cookie.sequence);
|
||||
if(w == nil || !w->geometryok)
|
||||
return nil;
|
||||
reply = calloc(1, sizeof *reply);
|
||||
if(reply != nil)
|
||||
reply->height = w->height;
|
||||
return reply;
|
||||
}
|
||||
|
||||
static xcb_translate_coordinates_cookie_t
|
||||
wiretranslate(xcb_connection_t *c, xcb_window_t src, xcb_window_t dst,
|
||||
int16_t x, int16_t y)
|
||||
{
|
||||
xcb_translate_coordinates_cookie_t cookie;
|
||||
|
||||
USED(c);
|
||||
USED(dst);
|
||||
cookie.sequence = src;
|
||||
transx = x;
|
||||
transy = y;
|
||||
return cookie;
|
||||
}
|
||||
|
||||
static xcb_translate_coordinates_reply_t*
|
||||
wiretranslatereply(xcb_connection_t *c,
|
||||
xcb_translate_coordinates_cookie_t cookie, xcb_generic_error_t **error)
|
||||
{
|
||||
xcb_translate_coordinates_reply_t *reply;
|
||||
Wirewin *w;
|
||||
|
||||
USED(c);
|
||||
USED(error);
|
||||
w = wirewindow(cookie.sequence);
|
||||
if(w == nil || !w->translateok)
|
||||
return nil;
|
||||
reply = calloc(1, sizeof *reply);
|
||||
if(reply != nil){
|
||||
reply->same_screen = w->samescreen;
|
||||
reply->dst_x = w->rootx + transx;
|
||||
reply->dst_y = w->rooty + transy;
|
||||
}
|
||||
return reply;
|
||||
}
|
||||
|
||||
static int
|
||||
wireflush(xcb_connection_t *c)
|
||||
{
|
||||
@@ -157,8 +277,10 @@ wireclear(void)
|
||||
{
|
||||
memset(wirecalls, 0, sizeof wirecalls);
|
||||
memset(icbindings, 0, sizeof icbindings);
|
||||
memset(wirewins, 0, sizeof wirewins);
|
||||
nwirecalls = 0;
|
||||
nflush = 0;
|
||||
transx = transy = 0;
|
||||
preowner = nil;
|
||||
}
|
||||
|
||||
@@ -169,6 +291,23 @@ wirebind(int n, xcb_im_input_context_t *ic, Ic *state)
|
||||
icbindings[n].data = state;
|
||||
}
|
||||
|
||||
static Wirewin*
|
||||
wirewin(int n, xcb_window_t win, int x, int y, int h)
|
||||
{
|
||||
Wirewin *w;
|
||||
|
||||
w = &wirewins[n];
|
||||
memset(w, 0, sizeof *w);
|
||||
w->win = win;
|
||||
w->geometryok = 1;
|
||||
w->translateok = 1;
|
||||
w->samescreen = 1;
|
||||
w->rootx = x;
|
||||
w->rooty = y;
|
||||
w->height = h;
|
||||
return w;
|
||||
}
|
||||
|
||||
void testengineinit(int);
|
||||
void testenginehandle(Keyreq*);
|
||||
void* testengineowner(void);
|
||||
@@ -506,6 +645,131 @@ xim_adapter_styles(struct ct *t)
|
||||
CT_EQ_INT(t, Cclientpreedit, state.cap);
|
||||
}
|
||||
|
||||
void
|
||||
xim_adapter_placement(struct ct *t)
|
||||
{
|
||||
static const struct {
|
||||
u32int style;
|
||||
u32int mask;
|
||||
int fgeo;
|
||||
int ftrans;
|
||||
int cgeo;
|
||||
int ctrans;
|
||||
int valid;
|
||||
int x;
|
||||
int y;
|
||||
} cases[] = {
|
||||
{XCB_IM_PreeditPosition | XCB_IM_StatusNothing,
|
||||
XCB_XIM_XNSpotLocation_MASK, 1, 1, 1, 1, 1, 103, 204},
|
||||
{XCB_IM_PreeditPosition | XCB_IM_StatusNothing,
|
||||
XCB_XIM_XNSpotLocation_MASK, 1, 0, 1, 1, 1, 303, 404},
|
||||
{XCB_IM_PreeditPosition | XCB_IM_StatusNothing,
|
||||
0, 1, 1, 1, 1, 1, 100, 230},
|
||||
{XCB_IM_PreeditNothing | XCB_IM_StatusNothing,
|
||||
XCB_XIM_XNSpotLocation_MASK, 1, 1, 1, 1, 1, 100, 230},
|
||||
{XCB_IM_PreeditPosition | XCB_IM_StatusNothing,
|
||||
0, 0, 1, 1, 1, 1, 300, 440},
|
||||
{XCB_IM_PreeditPosition | XCB_IM_StatusNothing,
|
||||
0, 0, 1, 0, 1, 0, 0, 0},
|
||||
};
|
||||
xcb_im_input_context_t *ic;
|
||||
Icbinding *b;
|
||||
Wirewin *focus, *client;
|
||||
Ic state;
|
||||
int i;
|
||||
|
||||
ic = (xcb_im_input_context_t*)(uintptr)70;
|
||||
for(i = 0; i < nelem(cases); i++){
|
||||
wireclear();
|
||||
memset(&state, 0, sizeof state);
|
||||
state.xic = ic;
|
||||
state.style = cases[i].style;
|
||||
state.caret.valid = 1;
|
||||
state.caret.x = state.caret.y = 9;
|
||||
wirebind(0, ic, &state);
|
||||
b = &icbindings[0];
|
||||
b->focuswin = 10;
|
||||
b->clientwin = 20;
|
||||
b->preattrmask = cases[i].mask;
|
||||
b->preattr.spot_location.x = 3;
|
||||
b->preattr.spot_location.y = 4;
|
||||
focus = wirewin(0, 10, 100, 200, 30);
|
||||
client = wirewin(1, 20, 300, 400, 40);
|
||||
focus->geometryok = cases[i].fgeo;
|
||||
focus->translateok = cases[i].ftrans;
|
||||
client->geometryok = cases[i].cgeo;
|
||||
client->translateok = cases[i].ctrans;
|
||||
refreshplace(&state);
|
||||
CT_EQ_UINT(t, 10, state.focuswin);
|
||||
CT_EQ_UINT(t, 20, state.clientwin);
|
||||
CT_EQ_INT(t, cases[i].style ==
|
||||
(XCB_IM_PreeditPosition | XCB_IM_StatusNothing) &&
|
||||
cases[i].mask != 0, state.hasspot);
|
||||
CT_EQ_INT(t, cases[i].valid, state.caret.valid);
|
||||
CT_EQ_INT(t, cases[i].x, state.caret.x);
|
||||
CT_EQ_INT(t, cases[i].y, state.caret.y);
|
||||
CT_EQ_INT(t, 0, state.caret.h);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
xim_adapter_placement_updates(struct ct *t)
|
||||
{
|
||||
xcb_im_packet_header_fr_t hdr;
|
||||
xcb_im_input_context_t *ic;
|
||||
Icbinding *b;
|
||||
Ximfix f;
|
||||
Keyreq req;
|
||||
Keyres res;
|
||||
Ic state;
|
||||
|
||||
ic = (xcb_im_input_context_t*)(uintptr)71;
|
||||
memset(&state, 0, sizeof state);
|
||||
if(!ximbegin(t, &f, LangJP))
|
||||
goto cleanup;
|
||||
wireclear();
|
||||
state.xic = ic;
|
||||
state.style = XCB_IM_PreeditPosition | XCB_IM_StatusNothing;
|
||||
wirebind(0, ic, &state);
|
||||
b = &icbindings[0];
|
||||
b->focuswin = 11;
|
||||
b->clientwin = 21;
|
||||
b->preattrmask = XCB_XIM_XNSpotLocation_MASK;
|
||||
b->preattr.spot_location.x = 5;
|
||||
b->preattr.spot_location.y = 6;
|
||||
wirewin(0, 11, 100, 200, 30);
|
||||
CT_CHECK(t, readattrs(&state));
|
||||
place(&state);
|
||||
CT_CHECK(t, !readattrs(&state));
|
||||
keypress(&state, 'x', 0, &res);
|
||||
req = nexttrace(t, &f, Keypress, &state);
|
||||
CT_CHECK(t, req.caret.valid);
|
||||
CT_EQ_INT(t, 105, req.caret.x);
|
||||
CT_EQ_INT(t, 206, req.caret.y);
|
||||
|
||||
b->preattr.spot_location.x = 15;
|
||||
b->preattr.spot_location.y = 16;
|
||||
memset(&hdr, 0, sizeof hdr);
|
||||
hdr.major_opcode = XCB_XIM_SET_IC_VALUES;
|
||||
callback(nil, nil, ic, &hdr, nil, nil, nil);
|
||||
req = nexttrace(t, &f, Keycaret, &state);
|
||||
CT_CHECK(t, req.caret.valid);
|
||||
CT_EQ_INT(t, 115, req.caret.x);
|
||||
CT_EQ_INT(t, 216, req.caret.y);
|
||||
CT_EQ_INT(t, 15, state.spot.x);
|
||||
CT_EQ_INT(t, 16, state.spot.y);
|
||||
CT_CHECK(t, !readattrs(&state));
|
||||
b->preattrmask = 0;
|
||||
wirewins[0].geometryok = 0;
|
||||
hdr.major_opcode = XCB_XIM_SET_IC_FOCUS;
|
||||
callback(nil, nil, ic, &hdr, nil, nil, nil);
|
||||
req = nexttrace(t, &f, Keycaret, &state);
|
||||
CT_CHECK(t, !req.caret.valid);
|
||||
cleanup:
|
||||
preowner = nil;
|
||||
ximend(&f);
|
||||
}
|
||||
|
||||
void
|
||||
xim_adapter_encoding_negotiation(struct ct *t)
|
||||
{
|
||||
|
||||
132
xim/xim.c
132
xim/xim.c
@@ -21,6 +21,11 @@ struct Ic
|
||||
int encoding;
|
||||
int prestarted;
|
||||
int nprerune;
|
||||
xcb_window_t clientwin;
|
||||
xcb_window_t focuswin;
|
||||
xcb_point_t spot;
|
||||
int hasspot;
|
||||
Caret caret;
|
||||
};
|
||||
|
||||
typedef struct Clientenc Clientenc;
|
||||
@@ -41,6 +46,7 @@ static xcb_im_t *xim;
|
||||
static xcb_keysym_t *kmap;
|
||||
static uint8_t minkc, maxkc;
|
||||
static uint8_t symsper;
|
||||
static xcb_window_t rootwin;
|
||||
static int opened;
|
||||
static Ic *ics;
|
||||
static Ic *preowner;
|
||||
@@ -181,6 +187,108 @@ getscreen(int scr)
|
||||
return nil;
|
||||
}
|
||||
|
||||
static int
|
||||
readattrs(Ic *state)
|
||||
{
|
||||
const xcb_im_preedit_attr_t *attr;
|
||||
xcb_window_t clientwin, focuswin;
|
||||
xcb_point_t spot;
|
||||
int changed, hasspot;
|
||||
|
||||
clientwin = xcb_im_input_context_get_client_window(state->xic);
|
||||
focuswin = xcb_im_input_context_get_focus_window(state->xic);
|
||||
spot = state->spot;
|
||||
hasspot = 0;
|
||||
if(state->style == (XCB_IM_PreeditPosition | XCB_IM_StatusNothing) &&
|
||||
(xcb_im_input_context_get_preedit_attr_mask(state->xic) &
|
||||
XCB_XIM_XNSpotLocation_MASK)){
|
||||
attr = xcb_im_input_context_get_preedit_attr(state->xic);
|
||||
if(attr != nil){
|
||||
spot = attr->spot_location;
|
||||
hasspot = 1;
|
||||
}
|
||||
}
|
||||
changed = clientwin != state->clientwin || focuswin != state->focuswin ||
|
||||
hasspot != state->hasspot || (hasspot &&
|
||||
(spot.x != state->spot.x || spot.y != state->spot.y));
|
||||
state->clientwin = clientwin;
|
||||
state->focuswin = focuswin;
|
||||
state->spot = spot;
|
||||
state->hasspot = hasspot;
|
||||
return changed;
|
||||
}
|
||||
|
||||
static int
|
||||
translate(xcb_window_t win, int x, int y, Caret *caret)
|
||||
{
|
||||
xcb_translate_coordinates_cookie_t cookie;
|
||||
xcb_translate_coordinates_reply_t *reply;
|
||||
|
||||
if(win == XCB_NONE)
|
||||
return 0;
|
||||
cookie = xcb_translate_coordinates(conn, win, rootwin, x, y);
|
||||
reply = xcb_translate_coordinates_reply(conn, cookie, nil);
|
||||
if(reply == nil || !reply->same_screen){
|
||||
free(reply);
|
||||
return 0;
|
||||
}
|
||||
caret->valid = 1;
|
||||
caret->x = reply->dst_x;
|
||||
caret->y = reply->dst_y;
|
||||
caret->h = 0;
|
||||
free(reply);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
placebottom(Ic *state, xcb_window_t win)
|
||||
{
|
||||
xcb_get_geometry_cookie_t gcookie;
|
||||
xcb_get_geometry_reply_t *geometry;
|
||||
int height;
|
||||
|
||||
if(win == XCB_NONE)
|
||||
return 0;
|
||||
gcookie = xcb_get_geometry(conn, win);
|
||||
geometry = xcb_get_geometry_reply(conn, gcookie, nil);
|
||||
if(geometry == nil)
|
||||
return 0;
|
||||
height = geometry->height;
|
||||
free(geometry);
|
||||
if(!translate(win, 0, 0, &state->caret))
|
||||
return 0;
|
||||
state->caret.y += height;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
place(Ic *state)
|
||||
{
|
||||
xcb_window_t win[2];
|
||||
int i, nwin;
|
||||
|
||||
memset(&state->caret, 0, sizeof state->caret);
|
||||
win[0] = state->focuswin;
|
||||
nwin = 1;
|
||||
if(state->clientwin != state->focuswin)
|
||||
win[nwin++] = state->clientwin;
|
||||
if(state->hasspot)
|
||||
for(i = 0; i < nwin; i++)
|
||||
if(translate(win[i], state->spot.x, state->spot.y,
|
||||
&state->caret))
|
||||
return;
|
||||
for(i = 0; i < nwin; i++)
|
||||
if(placebottom(state, win[i]))
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
refreshplace(Ic *state)
|
||||
{
|
||||
readattrs(state);
|
||||
place(state);
|
||||
}
|
||||
|
||||
static void
|
||||
commit(Ic *state, char *s, int nbyte)
|
||||
{
|
||||
@@ -281,6 +389,7 @@ sendrequest(Ic *state, int op, u32int key, u32int mod, Keyres *res)
|
||||
kr.op = op;
|
||||
kr.ks = key;
|
||||
kr.mod = mod & Mmask;
|
||||
kr.caret = state->caret;
|
||||
kr.reply = replyc;
|
||||
chansend(keyc, &kr);
|
||||
chanrecv(replyc, res);
|
||||
@@ -317,7 +426,7 @@ kpress(Ic *state, xcb_im_input_context_t *ic, xcb_key_press_event_t *ev)
|
||||
Keyres res;
|
||||
char buf[Maxutf];
|
||||
u32int key, rune;
|
||||
int n;
|
||||
int n, wasvalid;
|
||||
|
||||
key = kget(ev->detail, ev->state);
|
||||
rune = xkb_keysym_to_utf32(key);
|
||||
@@ -327,6 +436,15 @@ kpress(Ic *state, xcb_im_input_context_t *ic, xcb_key_press_event_t *ev)
|
||||
key = Kspec + (key - 0xff00);
|
||||
else
|
||||
key = rune;
|
||||
if(meaningful(key)){
|
||||
wasvalid = state->caret.valid;
|
||||
if(!state->engaged)
|
||||
refreshplace(state);
|
||||
else if(readattrs(state))
|
||||
place(state);
|
||||
if(state->engaged && wasvalid && !state->caret.valid)
|
||||
sendrequest(state, Keycaret, 0, 0, &res);
|
||||
}
|
||||
keypress(state, key, ev->state, &res);
|
||||
n = stoutf(&res.commit, buf, sizeof buf);
|
||||
commit(state, buf, n);
|
||||
@@ -387,6 +505,7 @@ iccreate(xcb_im_client_t *client, xcb_im_input_context_t *ic)
|
||||
state->client = client;
|
||||
state->encoding = getencoding(client);
|
||||
setstyle(state, xcb_im_input_context_get_input_style(ic));
|
||||
refreshplace(state);
|
||||
state->next = ics;
|
||||
ics = state;
|
||||
xcb_im_input_context_set_data(ic, state, icfree);
|
||||
@@ -432,6 +551,15 @@ callback(xcb_im_t *im, xcb_im_client_t *client, xcb_im_input_context_t *ic,
|
||||
if(ev != nil && (ev->response_type & ~0x80) == XCB_KEY_PRESS)
|
||||
kpress(state, ic, ev);
|
||||
break;
|
||||
case XCB_XIM_SET_IC_VALUES:
|
||||
case XCB_XIM_SET_IC_FOCUS:
|
||||
refreshplace(state);
|
||||
if(state->engaged){
|
||||
Keyres res;
|
||||
|
||||
sendrequest(state, Keycaret, 0, 0, &res);
|
||||
}
|
||||
break;
|
||||
case XCB_XIM_DESTROY_IC:
|
||||
case XCB_XIM_RESET_IC:
|
||||
case XCB_XIM_UNSET_IC_FOCUS:
|
||||
@@ -461,6 +589,7 @@ ximclose(void)
|
||||
free(state);
|
||||
}
|
||||
ics = nil;
|
||||
rootwin = XCB_NONE;
|
||||
free(kmap);
|
||||
kmap = nil;
|
||||
if(conn != nil){
|
||||
@@ -502,6 +631,7 @@ ximinit(void)
|
||||
ximlog("cannot find X screen");
|
||||
return -1;
|
||||
}
|
||||
rootwin = screen->root;
|
||||
if(kinit() < 0){
|
||||
ximlog("cannot read keyboard mapping");
|
||||
return -1;
|
||||
|
||||
Reference in New Issue
Block a user