FCITX_EXPORT_API FcitxInstance* FcitxInstanceCreateWithFD(sem_t *sem, int argc, char* argv[], int fd) { FcitxInstance* instance = fcitx_utils_malloc0(sizeof(FcitxInstance)); FcitxAddonsInit(&instance->addons); FcitxInstanceInitIM(instance); FcitxFrontendsInit(&instance->frontends); InitFcitxModules(&instance->modules); InitFcitxModules(&instance->eventmodules); utarray_init(&instance->uistats, &stat_icd); utarray_init(&instance->uicompstats, &compstat_icd); utarray_init(&instance->uimenus, &menup_icd); utarray_init(&instance->timeout, &timeout_icd); utarray_init(&instance->icdata, &icdata_icd); instance->input = FcitxInputStateCreate(); instance->sem = sem; instance->config = fcitx_utils_malloc0(sizeof(FcitxGlobalConfig)); instance->profile = fcitx_utils_malloc0(sizeof(FcitxProfile)); instance->globalIMName = strdup(""); if (fd > 0) { fcntl(fd, F_SETFL, O_NONBLOCK); instance->fd = fd; } if (!FcitxGlobalConfigLoad(instance->config)) goto error_exit; FcitxCandidateWordSetPageSize(instance->input->candList, instance->config->iMaxCandWord); if (!ProcessOption(instance, argc, argv)) goto error_exit; instance->timeStart = time(NULL); instance->globalState = instance->config->defaultIMState; instance->totaltime = 0; FcitxInitThread(instance); if (!FcitxProfileLoad(instance->profile, instance)) goto error_exit; if (FcitxAddonGetConfigDesc() == NULL) goto error_exit; if (GetIMConfigDesc() == NULL) goto error_exit; FcitxAddonsLoad(&instance->addons); FcitxInstanceFillAddonOwner(instance, NULL); FcitxInstanceResolveAddonDependency(instance); FcitxInstanceInitBuiltInHotkey(instance); FcitxInstanceInitBuiltContext(instance); FcitxModuleLoad(instance); if (instance->loadingFatalError) return instance; if (!FcitxInstanceLoadAllIM(instance)) { FcitxInstanceEnd(instance); return instance; } FcitxInstanceInitIMMenu(instance); FcitxUIRegisterMenu(instance, &instance->imMenu); FcitxUIRegisterStatus(instance, instance, "remind", instance->profile->bUseRemind ? _("Use remind") : _("No remind"), _("Toggle Remind"), ToggleRemindState, GetRemindEnabled); FcitxUISetStatusVisable(instance, "remind", false); FcitxUILoad(instance); instance->iIMIndex = FcitxInstanceGetIMIndexByName(instance, instance->profile->imName); FcitxInstanceSwitchIMByIndex(instance, instance->iIMIndex); if (!FcitxInstanceLoadFrontend(instance)) { FcitxInstanceEnd(instance); return instance; } /* make in order to use block X, query is not good here */ pthread_create(&instance->pid, NULL, RunInstance, instance); return instance; error_exit: FcitxInstanceEnd(instance); return instance; }
void _fcitx_main_window_add_addon_page(FcitxMainWindow* self) { FcitxAddon* addon; utarray_new(self->addons, &addonicd); FcitxAddonsLoad(self->addons); GtkWidget* vbox = gtk_vbox_new(FALSE, 0); GtkListStore *store; store = gtk_list_store_new(N_COLUMNS, G_TYPE_POINTER); GtkWidget* swin = gtk_scrolled_window_new(NULL, NULL); gtk_box_pack_start(GTK_BOX(vbox), swin, TRUE, TRUE, 0); g_object_set(swin, "hscrollbar-policy", GTK_POLICY_NEVER, NULL); self->addonview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); g_object_set(self->addonview, "headers-visible", FALSE, NULL); gtk_container_add(GTK_CONTAINER(swin), self->addonview); GtkCellRenderer *renderer; GtkTreeViewColumn *column; renderer = gtk_cell_renderer_toggle_new(); column = gtk_tree_view_column_new_with_attributes("Enable", renderer, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(self->addonview), column); gtk_cell_layout_set_cell_data_func(GTK_CELL_LAYOUT(column), renderer, _fcitx_main_window_enabled_data_func, self->addonview, NULL); g_signal_connect(G_OBJECT(renderer), "toggled", G_CALLBACK(_fcitx_main_window_toggled_cb), GTK_TREE_MODEL(store)); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes("Name", renderer, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(self->addonview), column); gtk_cell_layout_set_cell_data_func(GTK_CELL_LAYOUT(column), renderer, _fcitx_main_window_name_data_func, self->addonview, NULL); gtk_tree_view_set_model(GTK_TREE_VIEW(self->addonview), GTK_TREE_MODEL(store)); g_object_unref(store); for (addon = (FcitxAddon *) utarray_front(self->addons); addon != NULL; addon = (FcitxAddon *) utarray_next(self->addons, addon)) { GtkTreeIter iter; store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(self->addonview))); gtk_list_store_append(store, &iter); gtk_list_store_set(store, &iter, LIST_ADDON, addon, -1); } GtkWidget* hbuttonbox = gtk_hbutton_box_new(); gtk_box_pack_start(GTK_BOX(vbox), hbuttonbox, FALSE, TRUE, 0); self->button = gtk_button_new_with_label(_("Configure")); gtk_widget_set_sensitive(self->button, FALSE); gtk_button_set_image(GTK_BUTTON(self->button), gtk_image_new_from_stock(GTK_STOCK_PREFERENCES, GTK_ICON_SIZE_BUTTON)); gtk_box_pack_start(GTK_BOX(hbuttonbox), self->button, TRUE, TRUE, 0); g_signal_connect(G_OBJECT(self->button), "clicked", G_CALLBACK(_fcitx_main_window_configure_button_clicked), self); GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(self->addonview)); gtk_tree_selection_set_mode(selection, GTK_SELECTION_SINGLE); g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(_fcitx_main_window_addon_selection_changed), self); g_signal_connect(G_OBJECT(self->addonview), "row-activated", G_CALLBACK(_fcitx_main_window_addon_row_activated), self); self->addonpage = _fcitx_main_window_add_page(self, _("Addon"), vbox, GTK_STOCK_ADD); }
void _fcitx_main_window_add_addon_page(FcitxMainWindow* self) { /* load addon */ FcitxAddon* addon; utarray_new(self->addons, &addonicd); FcitxAddonsLoad(self->addons); GtkWidget* vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); /* advance check box */ self->advancecheckbox = gtk_check_button_new_with_label(_("Advance")); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(self->advancecheckbox), FALSE); g_signal_connect(G_OBJECT(self->advancecheckbox), "toggled", G_CALLBACK(_fcitx_main_window_checkbox_changed), self); /* filter entry */ self->filterentry = gtk_entry_new(); gtk_entry_set_icon_from_stock (GTK_ENTRY (self->filterentry), GTK_ENTRY_ICON_SECONDARY, GTK_STOCK_CLEAR); g_object_set(G_OBJECT(self->filterentry), "margin", 5, NULL); #if GTK_CHECK_VERSION(3,2,0) gtk_entry_set_placeholder_text(GTK_ENTRY (self->filterentry), _("Search Addon")); #endif g_signal_connect(G_OBJECT(self->filterentry), "icon-press", G_CALLBACK (icon_press_cb), NULL); gtk_box_pack_start(GTK_BOX(vbox), self->filterentry, FALSE, TRUE, 5); /* list view */ self->addonstore = gtk_list_store_new(N_COLUMNS, G_TYPE_POINTER); for (addon = (FcitxAddon *) utarray_front(self->addons); addon != NULL; addon = (FcitxAddon *) utarray_next(self->addons, addon)) { GtkTreeIter iter; gtk_list_store_append(self->addonstore, &iter); gtk_list_store_set(self->addonstore, &iter, LIST_ADDON, addon, -1); } self->filtermodel = gtk_tree_model_filter_new(GTK_TREE_MODEL(self->addonstore), NULL); gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(self->filtermodel), (GtkTreeModelFilterVisibleFunc) _filter_addon_func, self, NULL); self->addonview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(self->filtermodel)); /* add column check box */ self->togglecell = gtk_cell_renderer_toggle_new(); gtk_cell_renderer_toggle_set_activatable(GTK_CELL_RENDERER_TOGGLE(self->togglecell), FALSE); self->checkboxcolumn = gtk_tree_view_column_new_with_attributes("Enable", self->togglecell, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(self->addonview), self->checkboxcolumn); gtk_cell_layout_set_cell_data_func(GTK_CELL_LAYOUT(self->checkboxcolumn), self->togglecell, _fcitx_main_window_enabled_data_func, NULL, NULL); gtk_cell_renderer_toggle_set_activatable(GTK_CELL_RENDERER_TOGGLE(self->togglecell), FALSE); /* add column text */ GtkCellRenderer* renderer = gtk_cell_renderer_text_new(); GtkTreeViewColumn* column = gtk_tree_view_column_new_with_attributes("Name", renderer, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(self->addonview), column); gtk_cell_layout_set_cell_data_func(GTK_CELL_LAYOUT(column), renderer, _fcitx_main_window_name_data_func, NULL, NULL); /* add addon list to vbox */ GtkWidget* swin = gtk_scrolled_window_new(NULL, NULL); g_object_set(swin, "hscrollbar-policy", GTK_POLICY_NEVER, NULL); g_object_set(self->addonview, "headers-visible", FALSE, NULL); gtk_container_add(GTK_CONTAINER(swin), self->addonview); gtk_box_pack_start(GTK_BOX(vbox), swin, TRUE, TRUE, 0); g_object_set(G_OBJECT(swin), "margin-left", 5, "margin-right", 5, "shadow-type", GTK_SHADOW_IN, NULL); g_signal_connect(G_OBJECT(self->togglecell), "toggled", G_CALLBACK(_fcitx_main_window_toggled_cb), GTK_TREE_MODEL(self->addonstore)); gtk_box_pack_start(GTK_BOX(vbox), self->advancecheckbox, FALSE, TRUE, 0); g_object_set(G_OBJECT(self->advancecheckbox), "margin-left", 5, "margin-right", 5, NULL); /* configure button */ GtkWidget* hbuttonbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL); gtk_box_pack_start(GTK_BOX(vbox), hbuttonbox, FALSE, TRUE, 0); g_object_set(G_OBJECT(hbuttonbox), "margin", 5, NULL); self->button = gtk_button_new_with_label(_("Configure")); gtk_widget_set_sensitive(self->button, FALSE); gtk_button_set_image(GTK_BUTTON(self->button), gtk_image_new_from_stock(GTK_STOCK_PREFERENCES, GTK_ICON_SIZE_BUTTON)); gtk_box_pack_start(GTK_BOX(hbuttonbox), self->button, TRUE, TRUE, 0); g_signal_connect(G_OBJECT(self->button), "clicked", G_CALLBACK(_fcitx_main_window_configure_button_clicked), self); GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(self->addonview)); gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE); g_signal_connect(G_OBJECT(selection), "changed", G_CALLBACK(_fcitx_main_window_addon_selection_changed), self); g_signal_connect(G_OBJECT(self->filterentry), "changed", G_CALLBACK(_fcitx_main_window_filtertext_changed), self); gtk_tree_model_filter_refilter(GTK_TREE_MODEL_FILTER(self->filtermodel)); _fcitx_main_window_add_page(self, _("Addon"), vbox, GTK_STOCK_ADD); }
void* RunInstance(void* arg) { FcitxInstance* instance = (FcitxInstance*) arg; FcitxAddonsInit(&instance->addons); FcitxInstanceInitIM(instance); FcitxInstanceInitNoPreeditApps(instance); FcitxFrontendsInit(&instance->frontends); InitFcitxModules(&instance->modules); InitFcitxModules(&instance->eventmodules); utarray_init(&instance->uistats, &stat_icd); utarray_init(&instance->uicompstats, &compstat_icd); utarray_init(&instance->uimenus, fcitx_ptr_icd); utarray_init(&instance->timeout, &timeout_icd); utarray_init(&instance->icdata, &icdata_icd); instance->input = FcitxInputStateCreate(); instance->config = fcitx_utils_malloc0(sizeof(FcitxGlobalConfig)); instance->profile = fcitx_utils_malloc0(sizeof(FcitxProfile)); instance->globalIMName = strdup(""); if (instance->fd >= 0) { fcntl(instance->fd, F_SETFL, O_NONBLOCK); } else { instance->fd = -1; } if (!FcitxGlobalConfigLoad(instance->config)) goto error_exit; FcitxCandidateWordSetPageSize(instance->input->candList, instance->config->iMaxCandWord); int overrideDelay = instance->overrideDelay; if (overrideDelay < 0) overrideDelay = instance->config->iDelayStart; if (overrideDelay > 0) sleep(overrideDelay); instance->timeStart = time(NULL); instance->globalState = instance->config->defaultIMState; instance->totaltime = 0; FcitxInitThread(instance); if (!FcitxProfileLoad(instance->profile, instance)) goto error_exit; if (FcitxAddonGetConfigDesc() == NULL) goto error_exit; if (GetIMConfigDesc() == NULL) goto error_exit; FcitxAddonsLoad(&instance->addons); FcitxInstanceFillAddonOwner(instance, NULL); FcitxInstanceResolveAddonDependency(instance); FcitxInstanceInitBuiltInHotkey(instance); FcitxInstanceInitBuiltContext(instance); FcitxModuleLoad(instance); if (instance->loadingFatalError) return NULL; if (!FcitxInstanceLoadAllIM(instance)) { goto error_exit; } FcitxInstanceInitIMMenu(instance); FcitxUIRegisterMenu(instance, &instance->imMenu); FcitxUIRegisterStatus(instance, instance, "remind", instance->profile->bUseRemind ? _("Use remind") : _("No remind"), _("Toggle Remind"), ToggleRemindState, GetRemindEnabled); FcitxUISetStatusVisable(instance, "remind", false); FcitxUILoad(instance); instance->iIMIndex = FcitxInstanceGetIMIndexByName(instance, instance->profile->imName); if (instance->iIMIndex < 0) { instance->iIMIndex = 0; } FcitxInstanceSwitchIMByIndex(instance, instance->iIMIndex); if (!FcitxInstanceLoadFrontend(instance)) { goto error_exit; } /* fcitx is running in a standalone thread or not */ if (instance->sem) { sem_post(&instance->notifySem); sem_wait(&instance->startUpSem); } else { instance->initialized = true; } uint64_t curtime = 0; while (1) { FcitxAddon** pmodule; uint8_t signo = 0; if (instance->fd >= 0) { while (read(instance->fd, &signo, sizeof(char)) > 0) { if (signo == SIGINT || signo == SIGTERM || signo == SIGQUIT || signo == SIGXCPU) FcitxInstanceEnd(instance); else if (signo == SIGHUP) FcitxInstanceRestart(instance); else if (signo == SIGUSR1) FcitxInstanceReloadConfig(instance); } } do { instance->eventflag &= (~FEF_PROCESS_EVENT_MASK); for (pmodule = (FcitxAddon**) utarray_front(&instance->eventmodules); pmodule != NULL; pmodule = (FcitxAddon**) utarray_next(&instance->eventmodules, pmodule)) { FcitxModule* module = (*pmodule)->module; module->ProcessEvent((*pmodule)->addonInstance); } struct timeval current_time; gettimeofday(¤t_time, NULL); curtime = (current_time.tv_sec * 1000LL) + (current_time.tv_usec / 1000LL); unsigned int idx = 0; while(idx < utarray_len(&instance->timeout)) { TimeoutItem* ti = (TimeoutItem*) utarray_eltptr(&instance->timeout, idx); uint64_t id = ti->idx; if (ti->time + ti->milli <= curtime) { ti->callback(ti->arg); ti = (TimeoutItem*) utarray_eltptr(&instance->timeout, idx); /* faster remove */ if (ti && ti->idx == id) utarray_remove_quick(&instance->timeout, idx); else { FcitxInstanceRemoveTimeoutById(instance, id); idx = 0; } } else { idx++; } } if (instance->eventflag & FEF_UI_MOVE) FcitxUIMoveInputWindowReal(instance); if (instance->eventflag & FEF_UI_UPDATE) FcitxUIUpdateInputWindowReal(instance); } while ((instance->eventflag & FEF_PROCESS_EVENT_MASK) != FEF_NONE); setjmp(FcitxRecover); if (instance->destroy || instance->restart) { FcitxInstanceRealEnd(instance); break; } if (instance->eventflag & FEF_RELOAD_ADDON) { instance->eventflag &= ~(FEF_RELOAD_ADDON); FcitxInstanceReloadAddon(instance); } FD_ZERO(&instance->rfds); FD_ZERO(&instance->wfds); FD_ZERO(&instance->efds); instance->maxfd = 0; if (instance->fd > 0) { instance->maxfd = instance->fd; FD_SET(instance->fd, &instance->rfds); } for (pmodule = (FcitxAddon**) utarray_front(&instance->eventmodules); pmodule != NULL; pmodule = (FcitxAddon**) utarray_next(&instance->eventmodules, pmodule)) { FcitxModule* module = (*pmodule)->module; module->SetFD((*pmodule)->addonInstance); } if (instance->maxfd == 0) break; struct timeval tval; struct timeval* ptval = NULL; if (utarray_len(&instance->timeout) != 0) { unsigned long int min_time = LONG_MAX; TimeoutItem* ti; for (ti = (TimeoutItem*)utarray_front(&instance->timeout);ti; ti = (TimeoutItem*)utarray_next(&instance->timeout, ti)) { if (ti->time + ti->milli - curtime < min_time) { min_time = ti->time + ti->milli - curtime; } } tval.tv_usec = (min_time % 1000) * 1000; tval.tv_sec = min_time / 1000; ptval = &tval; } select(instance->maxfd + 1, &instance->rfds, &instance->wfds, &instance->efds, ptval); } if (instance->restart) { fcitx_utils_restart_in_place(); } return NULL; error_exit: sem_post(&instance->startUpSem); FcitxInstanceEnd(instance); return NULL; }
FCITX_EXPORT_API FcitxInstance* FcitxInstanceCreate(sem_t *sem, int argc, char* argv[]) { FcitxInstance* instance = fcitx_utils_malloc0(sizeof(FcitxInstance)); FcitxAddonsInit(&instance->addons); FcitxInstanceInitIM(instance); FcitxFrontendsInit(&instance->frontends); InitFcitxModules(&instance->eventmodules); utarray_init(&instance->uistats, &stat_icd); utarray_init(&instance->uimenus, &menup_icd); instance->input = FcitxInputStateCreate(); instance->sem = sem; instance->config = fcitx_utils_malloc0(sizeof(FcitxGlobalConfig)); instance->profile = fcitx_utils_malloc0(sizeof(FcitxProfile)); if (!FcitxGlobalConfigLoad(instance->config)) goto error_exit; FcitxCandidateWordSetPageSize(instance->input->candList, instance->config->iMaxCandWord); if (!ProcessOption(instance, argc, argv)) goto error_exit; instance->timeStart = time(NULL); instance->globalState = instance->config->defaultIMState; instance->totaltime = 0; FcitxInitThread(instance); if (!FcitxProfileLoad(instance->profile, instance)) goto error_exit; if (FcitxAddonGetConfigDesc() == NULL) goto error_exit; if (GetIMConfigDesc() == NULL) goto error_exit; FcitxAddonsLoad(&instance->addons); /* FIXME: a walkaround for not have instance in function FcitxModuleInvokeFunction */ FcitxAddon* addon; for (addon = (FcitxAddon *) utarray_front(&instance->addons); addon != NULL; addon = (FcitxAddon *) utarray_next(&instance->addons, addon)) { addon->owner = instance; } FcitxInstanceResolveAddonDependency(instance); FcitxInstanceInitBuiltInHotkey(instance); FcitxInstanceInitBuiltContext(instance); FcitxModuleLoad(instance); if (!FcitxInstanceLoadAllIM(instance)) { FcitxInstanceEnd(instance); return instance; } FcitxInstanceInitIMMenu(instance); FcitxUIRegisterMenu(instance, &instance->imMenu); FcitxUIRegisterStatus(instance, instance, "remind", _("Remind"), _("Remind"), ToggleRemindState, GetRemindEnabled); FcitxUILoad(instance); instance->iIMIndex = FcitxInstanceGetIMIndexByName(instance, instance->profile->imName); FcitxInstanceSwitchIM(instance, instance->iIMIndex); instance->lastIMIndex = instance->iIMIndex; if (!FcitxInstanceLoadFrontend(instance)) { FcitxInstanceEnd(instance); return instance; } if (instance->config->bFirstRun) { instance->config->bFirstRun = false; FcitxGlobalConfigSave(instance->config); const char *imname = "fcitx"; char *strTemp; asprintf(&strTemp, "@im=%s", imname); if ((getenv("XMODIFIERS") != NULL && CHECK_ENV("XMODIFIERS", strTemp, true)) || (CHECK_ENV("GTK_IM_MODULE", "xim", false) && CHECK_ENV("GTK_IM_MODULE", "fcitx", false)) || (CHECK_ENV("QT_IM_MODULE", "xim", false) && CHECK_ENV("QT_IM_MODULE", "fcitx", false))) { char *msg[12]; msg[0] = _("Please check your environment varibles."); msg[1] = _("You can use tools provided by your distribution."); msg[2] = _("Or You may need to set environment varibles below to make fcitx work correctly."); msg[3] = "export XMODIFIERS=\"@im=fcitx\""; msg[4] = "export QT_IM_MODULE=xim"; msg[5] = "export GTK_IM_MODULE=xim"; msg[6] = _("Or (Depends on you install im module or not)"); msg[7] = "export XMODIFIERS=\"@im=fcitx\""; msg[8] = "export QT_IM_MODULE=fcitx"; msg[9] = "export GTK_IM_MODULE=fcitx"; msg[10] = _("If you use login manager like gdm or kdm, put those lines in your ~/.xprofile."); msg[11] = _("If you use ~/.xinitrc and startx, put those lines in ~/.xinitrc."); FcitxUIDisplayMessage(instance, _("Setting Hint"), msg, 12); } free(strTemp); } /* make in order to use block X, query is not good here */ pthread_create(&instance->pid, NULL, RunInstance, instance); return instance; error_exit: FcitxInstanceEnd(instance); return instance; }