diff --git a/ibus.c b/ibus.c index 88631d6..f1964c3 100644 --- a/ibus.c +++ b/ibus.c @@ -19,12 +19,6 @@ enum Ibussupermask = 1<<26, }; -typedef struct Watch Watch; -struct Watch -{ - DBusWatch *w; -}; - typedef struct Ictx Ictx; struct Ictx { @@ -34,7 +28,7 @@ struct Ictx Caret caret; }; -static Watch watches[Maxwatches]; +static DBusWatch *watches[Maxwatches]; static int nwatches; static DBusConnection *conns[Maxconns]; static int nconns; @@ -205,13 +199,13 @@ addwatch(DBusWatch *w, void *_) USED(_); for(i = 0; i < nwatches; i++) - if(watches[i].w == nil){ - watches[i].w = w; + if(watches[i] == nil){ + watches[i] = w; return TRUE; } if(nwatches >= Maxwatches) return FALSE; - watches[nwatches++].w = w; + watches[nwatches++] = w; return TRUE; } @@ -222,8 +216,8 @@ removewatch(DBusWatch *w, void *_) USED(_); for(i = 0; i < nwatches; i++) - if(watches[i].w == w){ - watches[i].w = nil; + if(watches[i] == w){ + watches[i] = nil; return; } } @@ -309,11 +303,10 @@ releasecontext(Ictx *ctx) { Keyres res; - if(replyc != nil) + if(ctx->focused) sendrequest(ctx, Keyrelease, 0, 0, &res); ctx->focused = 0; memset(&ctx->caret, 0, sizeof ctx->caret); - } static void @@ -752,17 +745,17 @@ ibusthread(void *_) for(;;){ n = 0; for(i = 0; i < nwatches && n < Maxwatches; i++){ - if(watches[i].w == nil) + if(watches[i] == nil) continue; - if(!dbus_watch_get_enabled(watches[i].w)) + if(!dbus_watch_get_enabled(watches[i])) continue; - pfds[n].fd = dbus_watch_get_unix_fd(watches[i].w); + pfds[n].fd = dbus_watch_get_unix_fd(watches[i]); pfds[n].events = 0; - f = dbus_watch_get_flags(watches[i].w); + f = dbus_watch_get_flags(watches[i]); if(f & DBUS_WATCH_READABLE) pfds[n].events |= POLLIN; if(f & DBUS_WATCH_WRITABLE) pfds[n].events |= POLLOUT; wi[n] = i; - polled[n] = watches[i].w; + polled[n] = watches[i]; n++; } rv = poll(pfds, n, 200); @@ -771,7 +764,7 @@ ibusthread(void *_) for(i = 0; i < n; i++){ if(pfds[i].revents == 0) continue; - if(watches[wi[i]].w != polled[i]) + if(watches[wi[i]] != polled[i]) continue; f = 0; if(pfds[i].revents & POLLIN) f |= DBUS_WATCH_READABLE; diff --git a/tests/Makefile b/tests/Makefile index 94354f5..568651e 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -3,12 +3,14 @@ LD = 9l CFLAGS = -std=c99 -Wall -Wextra -O2 -g -I.. -I../cutest FT_CFLAGS = $(shell pkg-config --cflags freetype2) FT_LIBS = $(shell pkg-config --libs freetype2) -LIBS = -lthread -lbio $(FT_LIBS) +IBUS_CFLAGS = $(shell pkg-config --cflags dbus-1 xkbcommon) +IBUS_LIBS = $(shell pkg-config --libs dbus-1 xkbcommon) +LIBS = -lthread -lbio $(FT_LIBS) $(IBUS_LIBS) PROG = unit_test TESTSRC = unit_test.c test_util.c str_test.c hash_test.c trie_test.c \ ko_test.c vi_test.c engine_test.c dict_test.c ipc_test.c \ - popup_test.c font_test.c + popup_test.c font_test.c ibus_test.c TESTOBJ = $(TESTSRC:.c=.o) PARENTSRC = str.c hash.c trie.c dict.c ko.c vi.c ipc.c popup_layout.c \ font.c @@ -25,6 +27,8 @@ $(PROG): $(OBJS) $(TESTOBJ): test.h ../dat.h ../fn.h ../ipc.h ../cutest/cutest.h engine_test.o: ../strans.c +ibus_test.o: CFLAGS += $(IBUS_CFLAGS) +ibus_test.o: ../ibus.c unit_font.o: CFLAGS += $(FT_CFLAGS) unit_%.o: ../%.c ../dat.h ../fn.h ../ipc.h diff --git a/tests/ibus_test.c b/tests/ibus_test.c new file mode 100644 index 0000000..482c856 --- /dev/null +++ b/tests/ibus_test.c @@ -0,0 +1,71 @@ +#include "../ibus.c" +#include "../cutest/cutest.h" + +void +ibus_context_lifecycle(struct ct *t) +{ + Channel *oldkeyc, *oldreplyc; + DBusConnection *c1, *c2; + Ictx *a, *b; + Keyreq req; + Keyres res; + + oldkeyc = keyc; + oldreplyc = replyc; + keyc = chancreate(sizeof(Keyreq), 2); + replyc = chancreate(sizeof(Keyres), 2); + memset(contexts, 0, sizeof contexts); + c1 = malloc(1); + c2 = malloc(1); + if(!CT_CHECK(t, c1 != nil && c2 != nil)) + goto cleanup; + a = newcontext(c1, "/context/one"); + b = newcontext(c2, "/context/one"); + if(!CT_CHECK(t, a != nil && b != nil && a != b)) + goto cleanup; + CT_EQ_PTR(t, a, findcontext(c1, "/context/one")); + CT_EQ_PTR(t, b, findcontext(c2, "/context/one")); + CT_EQ_PTR(t, nil, findcontext(c1, "/context/missing")); + + a->caret.valid = 1; + releasecontext(a); + CT_CHECK(t, channbrecv(keyc, &req) <= 0); + CT_CHECK(t, !a->caret.valid); + + a->focused = 1; + a->caret.valid = 1; + memset(&res, 0, sizeof res); + chansend(replyc, &res); + releasecontext(a); + if(CT_CHECK(t, channbrecv(keyc, &req) > 0)){ + CT_EQ_PTR(t, a, req.owner); + CT_EQ_INT(t, Keyrelease, req.op); + CT_EQ_PTR(t, replyc, req.reply); + } + CT_CHECK(t, !a->focused); + CT_CHECK(t, !a->caret.valid); + releasecontext(a); + CT_CHECK(t, channbrecv(keyc, &req) <= 0); + + dropcontext(a); + CT_CHECK(t, channbrecv(keyc, &req) <= 0); + CT_EQ_PTR(t, nil, findcontext(c1, "/context/one")); + CT_EQ_PTR(t, a, newcontext(c1, "/context/reused")); + + b->focused = 1; + chansend(replyc, &res); + dropcontext(b); + if(CT_CHECK(t, channbrecv(keyc, &req) > 0)){ + CT_EQ_PTR(t, b, req.owner); + CT_EQ_INT(t, Keyrelease, req.op); + } + CT_EQ_PTR(t, nil, findcontext(c2, "/context/one")); +cleanup: + memset(contexts, 0, sizeof contexts); + free(c1); + free(c2); + chanfree(keyc); + chanfree(replyc); + keyc = oldkeyc; + replyc = oldreplyc; +} diff --git a/tests/test.h b/tests/test.h index 195e81d..9aeee02 100644 --- a/tests/test.h +++ b/tests/test.h @@ -70,3 +70,4 @@ void ipc_response_empty_and_preedit(struct ct*); void ipc_response_max_and_drain(struct ct*); void ipc_response_fragmented_and_truncated(struct ct*); void ipc_broken_peer_send(struct ct*); +void ibus_context_lifecycle(struct ct*); diff --git a/tests/unit_test.c b/tests/unit_test.c index 9583dbf..ecae4df 100644 --- a/tests/unit_test.c +++ b/tests/unit_test.c @@ -124,6 +124,7 @@ static const struct ct_test tests[] = { { "ipc/response-max-drain", ipc_response_max_and_drain }, { "ipc/response-fragmented-truncated", ipc_response_fragmented_and_truncated }, { "ipc/broken-peer-send", ipc_broken_peer_send }, + { "ibus/context-lifecycle", ibus_context_lifecycle }, }; void