FCITX_EXPORT_API void FcitxInstanceDestroyIC(FcitxInstance* instance, int frontendid, void* filter) { FcitxInputContext *rec, *last; UT_array* frontends = &instance->frontends; FcitxAddon** pfrontend = (FcitxAddon**) utarray_eltptr(frontends, frontendid); if (pfrontend == NULL) return; FcitxFrontend* frontend = (*pfrontend)->frontend; last = NULL; for (rec = instance->ic_list; rec != NULL; last = rec, rec = rec->next) { if (rec->frontendid == frontendid && frontend->CheckIC((*pfrontend)->addonInstance, rec, filter)) { if (last != NULL) last->next = rec->next; else instance->ic_list = rec->next; rec->next = instance->free_list; instance->free_list = rec; if (rec == FcitxInstanceGetCurrentIC(instance)) { FcitxUICloseInputWindow(instance); FcitxUIOnInputUnFocus(instance); FcitxInstanceSetCurrentIC(instance, NULL); } frontend->DestroyIC((*pfrontend)->addonInstance, rec); return; } } return; }
void FcitxInstanceCleanUpIC(FcitxInstance* instance) { FcitxInputContext *rec = instance->ic_list, *last = NULL, *todel; while (rec) { FcitxAddon **pfrontend = FcitxInstanceGetPFrontend(instance, rec->frontendid); FcitxFrontend *frontend = (*pfrontend)->frontend; pid_t pid = 0; if (frontend->GetPid) pid = frontend->GetPid((*pfrontend)->addonInstance, rec); if (pid && !fcitx_utils_pid_exists(pid)) { if (last != NULL) last->next = rec->next; else instance->ic_list = rec->next; todel = rec; rec = rec->next; todel->next = instance->free_list; instance->free_list = todel; frontend->DestroyIC((*pfrontend)->addonInstance, todel); FreeICData(instance, todel); if (todel == instance->CurrentIC) { instance->CurrentIC = NULL; FcitxUICloseInputWindow(instance); FcitxUIOnInputUnFocus(instance); FcitxInstanceSetCurrentIC(instance, NULL); } } else { last = rec; rec = rec->next; } } }
FCITX_EXPORT_API void FcitxInstanceCommitString(FcitxInstance* instance, FcitxInputContext* ic, const char* str) { if (str == NULL) return ; if (ic == NULL) return; char *pstr = FcitxInstanceProcessCommitFilter(instance, str); if (pstr != NULL) str = pstr; FcitxAddon **pfrontend = FcitxInstanceGetPFrontend(instance, ic->frontendid); if (pfrontend == NULL) return; FcitxFrontend* frontend = (*pfrontend)->frontend; frontend->CommitString((*pfrontend)->addonInstance, ic, str); FcitxInputState* input = instance->input; fcitx_utf8_strncpy(input->strLastCommit, str, MAX_USER_INPUT); input->strLastCommit[MAX_USER_INPUT] = '\0'; instance->iHZInputed += (int)(fcitx_utf8_strlen(str)); if (pstr) free(pstr); }
FCITX_EXPORT_API void FcitxInstanceSetWindowOffset(FcitxInstance* instance, FcitxInputContext *ic, int x, int y) { FcitxAddon **pfrontend = FcitxInstanceGetPFrontend(instance, ic->frontendid); if (pfrontend == NULL) return; FcitxFrontend* frontend = (*pfrontend)->frontend; if (frontend->SetWindowOffset) frontend->SetWindowOffset((*pfrontend)->addonInstance, ic, x, y); }
FCITX_EXPORT_API void FcitxInstanceEnd(FcitxInstance* instance) { FcitxInstanceSaveAllIM(instance); if (instance->uinormal && instance->uinormal->ui->Destroy) instance->uinormal->ui->Destroy(instance->uinormal->addonInstance); if (instance->uifallback && instance->uifallback->ui->Destroy) instance->uifallback->ui->Destroy(instance->uifallback->addonInstance); instance->uifallback = NULL; instance->ui = NULL; instance->uinormal = NULL; /* handle exit */ FcitxAddon** pimclass; FcitxAddon** pfrontend; FcitxFrontend* frontend; FcitxInputContext* rec = NULL; for (pimclass = (FcitxAddon**) utarray_front(&instance->imeclasses); pimclass != NULL; pimclass = (FcitxAddon**) utarray_next(&instance->imeclasses, pimclass) ) { if ((*pimclass)->imclass->Destroy) (*pimclass)->imclass->Destroy((*pimclass)->addonInstance); } for (rec = instance->ic_list; rec != NULL; rec = rec->next) { pfrontend = (FcitxAddon**) utarray_eltptr(&instance->frontends, rec->frontendid); frontend = (*pfrontend)->frontend; frontend->CloseIM((*pfrontend)->addonInstance, rec); } for (rec = instance->ic_list; rec != NULL; rec = rec->next) { pfrontend = (FcitxAddon**) utarray_eltptr(&instance->frontends, rec->frontendid); frontend = (*pfrontend)->frontend; frontend->DestroyIC((*pfrontend)->addonInstance, rec); } int frontendid = 0; for (pfrontend = (FcitxAddon**) utarray_front(&instance->frontends); pfrontend != NULL; pfrontend = (FcitxAddon**) utarray_next(&instance->frontends, pfrontend) ) { if (pfrontend == NULL) return; FcitxFrontend* frontend = (*pfrontend)->frontend; frontend->Destroy((*pfrontend)->addonInstance); frontendid++; } sem_post(instance->sem); }
FCITX_EXPORT_API void FcitxInstanceSetWindowOffset(FcitxInstance* instance, FcitxInputContext *ic, int x, int y) { UT_array* frontends = &instance->frontends; FcitxAddon** pfrontend = (FcitxAddon**) utarray_eltptr(frontends, ic->frontendid); if (pfrontend == NULL) return; FcitxFrontend* frontend = (*pfrontend)->frontend; if (frontend->SetWindowOffset) frontend->SetWindowOffset((*pfrontend)->addonInstance, ic, x, y); }
FCITX_EXPORT_API void FcitxInstanceGetWindowRect(FcitxInstance* instance, FcitxInputContext* ic, int* x, int* y, int* w, int* h) { if (ic == NULL) return; FcitxAddon **pfrontend = FcitxInstanceGetPFrontend(instance, ic->frontendid); if (pfrontend == NULL) return; FcitxFrontend* frontend = (*pfrontend)->frontend; if (frontend->GetWindowRect) { frontend->GetWindowRect((*pfrontend)->addonInstance, ic, x, y, w, h); } }
FCITX_EXPORT_API void FcitxInstanceDeleteSurroundingText(FcitxInstance* instance, FcitxInputContext* ic, int offset, unsigned int size) { if (ic == NULL) return; FcitxAddon **pfrontend = FcitxInstanceGetPFrontend(instance, ic->frontendid); if (pfrontend == NULL) return; FcitxFrontend* frontend = (*pfrontend)->frontend; if (frontend->DeleteSurroundingText) { frontend->DeleteSurroundingText((*pfrontend)->addonInstance, ic, offset, size); } }
FCITX_EXPORT_API void FcitxInstanceGetWindowPosition(FcitxInstance* instance, FcitxInputContext* ic, int* x, int* y) { if (ic == NULL) return; UT_array* frontends = &instance->frontends; FcitxAddon** pfrontend = (FcitxAddon**) utarray_eltptr(frontends, ic->frontendid); if (pfrontend == NULL) return; FcitxFrontend* frontend = (*pfrontend)->frontend; if (frontend->GetWindowPosition) frontend->GetWindowPosition((*pfrontend)->addonInstance, ic, x, y); }
FCITX_EXPORT_API FcitxInputContext* FcitxInstanceFindIC(FcitxInstance* instance, int frontendid, void *filter) { FcitxAddon **pfrontend = FcitxInstanceGetPFrontend(instance, frontendid); if (pfrontend == NULL) return NULL; FcitxFrontend* frontend = (*pfrontend)->frontend; FcitxInputContext *rec = instance->ic_list; while (rec != NULL) { if (rec->frontendid == frontendid && frontend->CheckIC((*pfrontend)->addonInstance, rec, filter)) return rec; rec = rec->next; } return NULL; }
FCITX_EXPORT_API void FcitxInstanceUpdateClientSideUI(FcitxInstance* instance, FcitxInputContext* ic) { if (ic == NULL) return; if (!(ic->contextCaps & CAPACITY_CLIENT_SIDE_UI)) return; FcitxAddon **pfrontend = FcitxInstanceGetPFrontend(instance, ic->frontendid); if (pfrontend == NULL) return; FcitxFrontend* frontend = (*pfrontend)->frontend; if (frontend->UpdateClientSideUI) frontend->UpdateClientSideUI((*pfrontend)->addonInstance, ic); }
FCITX_EXPORT_API void FcitxInstanceUpdatePreedit(FcitxInstance* instance, FcitxInputContext* ic) { if (!instance->profile->bUsePreedit) return; if (ic == NULL) return; if (!(ic->contextCaps & CAPACITY_PREEDIT)) return; FcitxAddon **pfrontend = FcitxInstanceGetPFrontend(instance, ic->frontendid); if (pfrontend == NULL) return; FcitxFrontend* frontend = (*pfrontend)->frontend; frontend->UpdatePreedit((*pfrontend)->addonInstance, ic); }
FCITX_EXPORT_API void FcitxInstanceSetICStateFromSameApplication(FcitxInstance* instance, int frontendid, FcitxInputContext *ic) { FcitxAddon **pfrontend = FcitxInstanceGetPFrontend(instance, frontendid); if (pfrontend == NULL) return; FcitxFrontend* frontend = (*pfrontend)->frontend; if (!frontend->CheckICFromSameApplication) return; FcitxInputContext *rec = instance->ic_list; while (rec != NULL) { if (rec->frontendid == frontendid && frontend->CheckICFromSameApplication((*pfrontend)->addonInstance, rec, ic)) { ic->state = rec->state; break; } rec = rec->next; } }
FCITX_EXPORT_API boolean FcitxInstanceGetSurroundingText(FcitxInstance* instance, FcitxInputContext* ic, char** str, unsigned int* cursor, unsigned int* anchor) { if (ic == NULL) return false; if (!(ic->contextCaps & CAPACITY_SURROUNDING_TEXT)) return false; FcitxAddon **pfrontend = FcitxInstanceGetPFrontend(instance, ic->frontendid); if (pfrontend == NULL) return false; FcitxFrontend* frontend = (*pfrontend)->frontend; if (frontend->GetSurroundingPreedit) { return frontend->GetSurroundingPreedit((*pfrontend)->addonInstance, ic, str, cursor, anchor); } return false; }
FCITX_EXPORT_API void FcitxInstanceGetWindowPosition(FcitxInstance* instance, FcitxInputContext* ic, int* x, int* y) { if (ic == NULL) return; FcitxAddon **pfrontend = FcitxInstanceGetPFrontend(instance, ic->frontendid); if (pfrontend == NULL) return; FcitxFrontend* frontend = (*pfrontend)->frontend; int rx, ry, rw, rh; if (frontend->GetWindowRect) { frontend->GetWindowRect((*pfrontend)->addonInstance, ic, &rx, &ry, &rw, &rh); *x = rx; *y = ry + rh; } }
FCITX_EXPORT_API FcitxInputContext* FcitxInstanceCreateIC(FcitxInstance* instance, int frontendid, void * priv) { /* clean up invalid ic here */ FcitxInstanceCleanUpIC(instance); FcitxAddon **pfrontend = FcitxInstanceGetPFrontend(instance, frontendid); if (pfrontend == NULL) return NULL; FcitxFrontend* frontend = (*pfrontend)->frontend; FcitxInputContext *rec; if (instance->free_list != NULL) { rec = instance->free_list; instance->free_list = instance->free_list->next; } else rec = malloc(sizeof(FcitxInputContext2)); memset(rec, 0, sizeof(FcitxInputContext2)); rec->frontendid = frontendid; rec->offset_x = -1; rec->offset_y = -1; NewICData(instance, rec); switch (instance->config->shareState) { case ShareState_All: rec->state = instance->globalState; break; case ShareState_None: case ShareState_PerProgram: rec->state = instance->config->defaultIMState; break; default: break; } frontend->CreateIC((*pfrontend)->addonInstance, rec, priv); rec->next = instance->ic_list; instance->ic_list = rec; return rec; }
FCITX_EXPORT_API FcitxInputContext* FcitxInstanceCreateIC(FcitxInstance* instance, int frontendid, void * priv) { UT_array* frontends = &instance->frontends; FcitxAddon** pfrontend = (FcitxAddon**) utarray_eltptr(frontends, frontendid); if (pfrontend == NULL) return NULL; FcitxFrontend* frontend = (*pfrontend)->frontend; FcitxInputContext *rec; if (instance->free_list != NULL) { rec = instance->free_list; instance->free_list = instance->free_list->next; } else rec = malloc(sizeof(FcitxInputContext)); memset(rec, 0, sizeof(FcitxInputContext)); rec->frontendid = frontendid; rec->offset_x = -1; rec->offset_y = -1; switch (instance->config->shareState) { case ShareState_All: rec->state = instance->globalState; break; case ShareState_None: case ShareState_PerProgram: rec->state = instance->config->defaultIMState; break; default: break; } frontend->CreateIC((*pfrontend)->addonInstance, rec, priv); rec->next = instance->ic_list; instance->ic_list = rec; return rec; }
FCITX_EXPORT_API void FcitxInstanceCommitString(FcitxInstance* instance, FcitxInputContext* ic, char* str) { if (str == NULL) return ; if (ic == NULL) return; UT_array* frontends = &instance->frontends; char *pstr = FcitxInstanceProcessCommitFilter(instance, str); if (pstr != NULL) str = pstr; FcitxAddon** pfrontend = (FcitxAddon**) utarray_eltptr(frontends, ic->frontendid); if (pfrontend == NULL) return; FcitxFrontend* frontend = (*pfrontend)->frontend; frontend->CommitString((*pfrontend)->addonInstance, ic, str); if (pstr) free(pstr); }
FCITX_EXPORT_API void FcitxInstanceEnd(FcitxInstance* instance) { /* avoid duplicate destroy */ if (instance->destroy) return; if (!instance->initialized) { if (!instance->loadingFatalError) { if (!instance->quietQuit) FcitxLog(ERROR, "Exiting."); instance->loadingFatalError = true; sem_post(instance->sem); } return; } instance->destroy = true; FcitxProfileSave(instance->profile); FcitxInstanceSaveAllIM(instance); if (instance->uinormal && instance->uinormal->ui->Destroy) instance->uinormal->ui->Destroy(instance->uinormal->addonInstance); if (instance->uifallback && instance->uifallback->ui->Destroy) instance->uifallback->ui->Destroy(instance->uifallback->addonInstance); instance->uifallback = NULL; instance->ui = NULL; instance->uinormal = NULL; /* handle exit */ FcitxAddon** pimclass; FcitxAddon** pfrontend; FcitxFrontend* frontend; FcitxInputContext* rec = NULL; for (pimclass = (FcitxAddon**) utarray_front(&instance->imeclasses); pimclass != NULL; pimclass = (FcitxAddon**) utarray_next(&instance->imeclasses, pimclass) ) { if ((*pimclass)->imclass->Destroy) (*pimclass)->imclass->Destroy((*pimclass)->addonInstance); } for (rec = instance->ic_list; rec != NULL; rec = rec->next) { pfrontend = (FcitxAddon**) utarray_eltptr(&instance->frontends, rec->frontendid); frontend = (*pfrontend)->frontend; frontend->CloseIM((*pfrontend)->addonInstance, rec); } for (rec = instance->ic_list; rec != NULL; rec = rec->next) { pfrontend = (FcitxAddon**) utarray_eltptr(&instance->frontends, rec->frontendid); frontend = (*pfrontend)->frontend; frontend->DestroyIC((*pfrontend)->addonInstance, rec); } for (pfrontend = (FcitxAddon**) utarray_front(&instance->frontends); pfrontend != NULL; pfrontend = (FcitxAddon**) utarray_next(&instance->frontends, pfrontend) ) { if (pfrontend == NULL) continue; FcitxFrontend* frontend = (*pfrontend)->frontend; frontend->Destroy((*pfrontend)->addonInstance); } FcitxAddon** pmodule; for (pmodule = (FcitxAddon**) utarray_front(&instance->modules); pmodule != NULL; pmodule = (FcitxAddon**) utarray_next(&instance->modules, pmodule) ) { if (pmodule == NULL) return; FcitxModule* module = (*pmodule)->module; if (module->Destroy) module->Destroy((*pmodule)->addonInstance); } sem_post(instance->sem); /* don't return to main loop, wait for exit */ int countDown = 5; while(countDown--) { sleep(1000); } exit(0); }
FCITX_EXPORT_API boolean FcitxInstanceLoadFrontend(FcitxInstance* instance) { UT_array* addons = &instance->addons; UT_array* frontends = &instance->frontends; FcitxAddon *addon; int frontendindex = 0; utarray_clear(frontends); for (addon = (FcitxAddon *) utarray_front(addons); addon != NULL; addon = (FcitxAddon *) utarray_next(addons, addon)) { if (addon->bEnabled && addon->category == AC_FRONTEND) { char *modulePath; switch (addon->type) { case AT_SHAREDLIBRARY: { FILE *fp = FcitxXDGGetLibFile(addon->library, "r", &modulePath); void *handle; FcitxFrontend* frontend; if (!fp) break; fclose(fp); handle = dlopen(modulePath, RTLD_LAZY | RTLD_GLOBAL); if (!handle) { FcitxLog(ERROR, _("Frontend: open %s fail %s") , modulePath , dlerror()); break; } if (!CheckABIVersion(handle)) { FcitxLog(ERROR, "%s ABI Version Error", addon->name); dlclose(handle); break; } frontend = dlsym(handle, "frontend"); if (!frontend || !frontend->Create) { FcitxLog(ERROR, _("Frontend: bad frontend")); dlclose(handle); break; } if ((addon->addonInstance = frontend->Create(instance, frontendindex)) == NULL) { dlclose(handle); break; } addon->frontend = frontend; frontendindex ++; utarray_push_back(frontends, &addon); } break; default: break; } free(modulePath); } } if (utarray_len(&instance->frontends) <= 0) { FcitxLog(ERROR, _("No available frontend")); return false; } return true; }
FCITX_EXPORT_API void FcitxInstanceRealEnd(FcitxInstance* instance) { FcitxProfileSave(instance->profile); FcitxInstanceSaveAllIM(instance); if (instance->uinormal && instance->uinormal->ui->Destroy) instance->uinormal->ui->Destroy(instance->uinormal->addonInstance); if (instance->uifallback && instance->uifallback->ui->Destroy) instance->uifallback->ui->Destroy(instance->uifallback->addonInstance); instance->uifallback = NULL; instance->ui = NULL; instance->uinormal = NULL; /* handle exit */ FcitxAddon** pimclass; FcitxAddon** pfrontend; FcitxFrontend* frontend; FcitxInputContext* rec = NULL; for (pimclass = (FcitxAddon**)utarray_front(&instance->imeclasses); pimclass != NULL; pimclass = (FcitxAddon**)utarray_next(&instance->imeclasses, pimclass) ) { if ((*pimclass)->imclass->Destroy) (*pimclass)->imclass->Destroy((*pimclass)->addonInstance); } for (rec = instance->ic_list; rec != NULL; rec = rec->next) { pfrontend = (FcitxAddon**)utarray_eltptr(&instance->frontends, (unsigned int)rec->frontendid); frontend = (*pfrontend)->frontend; frontend->CloseIM((*pfrontend)->addonInstance, rec); } for (rec = instance->ic_list; rec != NULL; rec = rec->next) { pfrontend = (FcitxAddon**)utarray_eltptr(&instance->frontends, (unsigned int)rec->frontendid); frontend = (*pfrontend)->frontend; frontend->DestroyIC((*pfrontend)->addonInstance, rec); } for (pfrontend = (FcitxAddon**)utarray_front(&instance->frontends); pfrontend != NULL; pfrontend = (FcitxAddon**)utarray_next(&instance->frontends, pfrontend) ) { if (pfrontend == NULL) continue; FcitxFrontend* frontend = (*pfrontend)->frontend; frontend->Destroy((*pfrontend)->addonInstance); } FcitxAddon** pmodule; for (pmodule = (FcitxAddon**) utarray_front(&instance->modules); pmodule != NULL; pmodule = (FcitxAddon**) utarray_next(&instance->modules, pmodule)) { if (pmodule == NULL) return; FcitxModule* module = (*pmodule)->module; if (module->Destroy) module->Destroy((*pmodule)->addonInstance); } sem_post(instance->sem); }