diff --git a/ibus.c b/ibus.c index ae04ed3..aa065bb 100644 --- a/ibus.c +++ b/ibus.c @@ -526,11 +526,16 @@ dropconncontexts(DBusConnection *conn) dropcontext(&contexts[i]); } +/* + * A key is proof of focus: some clients never send FocusIn, and the + * focus events of two applications can cross. + */ static int processkey(Ictx *ctx, u32int sym, u32int state, Keyres *res) { - if(state & Relmask || !ctx->focused || hidden(ctx)) + if(state & Relmask || hidden(ctx)) return 0; + ctx->focused = 1; sendrequest(ctx, Keypress, ipckeysym(sym, xkb_keysym_to_utf32(sym)), ipcmod(state), res); if(preowner != nil && preowner != ctx) diff --git a/tests/ibus_test.c b/tests/ibus_test.c index 8aa6bc5..ec4013b 100644 --- a/tests/ibus_test.c +++ b/tests/ibus_test.c @@ -281,25 +281,21 @@ ibus_context_lifecycle(struct ct *t) CT_EQ_PTR(t, b, findcontext(f.c2, "/context/one")); CT_EQ_PTR(t, nil, findcontext(f.c1, "/context/missing")); - memset(&res, 0, sizeof res); - CT_CHECK(t, !processkey(a, 'x', 0, &res)); - CT_CHECK(t, !res.eaten); - notrace(t, &f); - CT_EQ_PTR(t, nil, testengineowner()); - setcursor(a, -10, -20, 14); notrace(t, &f); CT_CHECK(t, a->caret.valid); - a->focused = 1; memset(&res, 0, sizeof res); CT_CHECK(t, !processkey(a, 'x', Relmask, &res)); CT_CHECK(t, !res.eaten); notrace(t, &f); + CT_CHECK(t, !a->focused); CT_EQ_PTR(t, nil, testengineowner()); + /* A key stands for the FocusIn a client may never send. */ memset(&res, 0, sizeof res); CT_CHECK(t, processkey(a, 'x', 0, &res)); req = nexttrace(t, &f, Keypress, a); + CT_CHECK(t, a->focused); CT_CHECK(t, !res.eaten); CT_CHECK(t, req.caret.valid); CT_EQ_INT(t, -10, req.caret.x); @@ -430,12 +426,8 @@ ibus_active_release_lifecycle(struct ct *t) reused = newcontext(f.c1, "/context/prune"); CT_EQ_PTR(t, ctx, reused); CT_EQ_PTR(t, nil, testengineowner()); - memset(&res, 0, sizeof res); - CT_CHECK(t, !processkey(reused, 'x', 0, &res)); - CT_CHECK(t, !res.eaten); - notrace(t, &f); - reused->focused = 1; contextkey(t, &f, reused, 'n', 0); + CT_CHECK(t, reused->focused); CT_EQ_PTR(t, reused, testengineowner()); dropconncontexts(f.c1); nexttrace(t, &f, Keyrelease, reused);