FCITX_EXPORT_API void FcitxUISwitchToFallback(struct _FcitxInstance* instance) { if (!instance->fallbackuiName || instance->ui != instance->uinormal) return; if (!instance->uifallback) { // load fallback ui FcitxAddon* fallbackAddon = FcitxAddonsGetAddonByName(&instance->addons, instance->fallbackuiName); if (!fallbackAddon || !fallbackAddon->bEnabled || !FcitxUILoadInternal(instance, fallbackAddon)) { // reset fallbackuiName, never load it again and again free(instance->fallbackuiName); instance->fallbackuiName = NULL; return; } instance->uifallback = fallbackAddon; if (instance->uifallback->ui->Suspend) instance->uifallback->ui->Suspend(instance->uifallback->addonInstance); } if (instance->uinormal->ui->Suspend) instance->uinormal->ui->Suspend(instance->uinormal->addonInstance); if (instance->uifallback->ui->Resume) instance->uifallback->ui->Resume(instance->uifallback->addonInstance); instance->ui = instance->uifallback; }
void* LuaCreate(FcitxInstance* instance) { LuaModule *luamodule = LuaModuleAlloc(instance); if (luamodule == NULL) { FcitxLog(ERROR, "LuaModule alloc failed"); goto err; } LoadLuaConfig(luamodule); FcitxIMEventHook hook = {.arg = luamodule, .func = LuaUpdateCandidateWordHookCallback}; FcitxInstanceRegisterUpdateCandidateWordHook(instance, hook); FcitxAddon* luaAddon = FcitxAddonsGetAddonByName( FcitxInstanceGetAddons(instance), FCITX_LUA_NAME); AddFunction(luaAddon, LuaCallCommand); return luamodule; err: if (luamodule) { LuaModuleFree(luamodule); } return NULL; }
void* ChttransCreate(FcitxInstance* instance) { FcitxChttrans* transState = fcitx_utils_malloc0(sizeof(FcitxChttrans)); FcitxAddon* transAddon = FcitxAddonsGetAddonByName(FcitxInstanceGetAddons(instance), FCITX_CHTTRANS_NAME); transState->owner = instance; if (!LoadChttransConfig(transState)) { free(transState); return NULL; } FcitxHotkeyHook hk; hk.arg = transState; hk.hotkey = transState->hkToggle; hk.hotkeyhandle = HotkeyToggleChttransState; FcitxStringFilterHook shk; shk.arg = transState; shk.func = ChttransOutputFilter; FcitxInstanceRegisterHotkeyFilter(instance, hk); FcitxInstanceRegisterOutputFilter(instance, shk); FcitxInstanceRegisterCommitFilter(instance, shk); FcitxUIRegisterStatus(instance, transState, "chttrans", transState->enabled ? _("Convert to Traditional Chinese") : _("Convert to Simplified Chinese"), _("Toggle Simp/Trad Chinese Conversion"), ToggleChttransState, GetChttransEnabled); FcitxInstanceWatchContext(instance, CONTEXT_IM_LANGUAGE, ChttransLanguageChanged, transState); AddFunction(transAddon, ChttransS2T); AddFunction(transAddon, ChttransT2S); return transState; }
void * QuickPhraseCreate(FcitxInstance *instance) { QuickPhraseState *qpstate = fcitx_utils_malloc0(sizeof(QuickPhraseState)); qpstate->owner = instance; qpstate->enabled = false; if (!LoadQuickPhraseConfig(&qpstate->config)) { free(qpstate); return NULL; } LoadQuickPhrase(qpstate); FcitxKeyFilterHook hk; hk.arg = qpstate; hk.func = QuickPhrasePostFilter; FcitxInstanceRegisterPostInputFilter(instance, hk); hk.func = QuickPhrasePreFilter; FcitxInstanceRegisterPreInputFilter(instance, hk); FcitxIMEventHook resethk; resethk.arg = qpstate; resethk.func = QuickPhraseReset; FcitxInstanceRegisterResetInputHook(instance, resethk); FcitxInstanceRegisterWatchableContext(instance, CONTEXT_DISABLE_QUICKPHRASE, FCT_Boolean, FCF_ResetOnInputMethodChange); FcitxAddon* addon = FcitxAddonsGetAddonByName( FcitxInstanceGetAddons(instance), FCITX_QUICKPHRASE_NAME); FcitxModuleAddFunction(addon, QuickPhraseLaunch); return qpstate; }
void* LightUICreate(FcitxInstance* instance) { FcitxModuleFunctionArg arg; FcitxLightUI* lightui = fcitx_utils_malloc0(sizeof(FcitxLightUI)); FcitxAddon* lightuiaddon = FcitxAddonsGetAddonByName(FcitxInstanceGetAddons(instance), FCITX_LIGHT_UI_NAME); lightui->owner = instance; if (!LoadLightUIConfig(lightui)) { free(lightui); return NULL; } lightui->dpy = InvokeFunction(instance, FCITX_X11, GETDISPLAY, arg); if (lightui->dpy == NULL) { free(lightui); return NULL; } lightui->isfallback = FcitxUIIsFallback(instance, lightuiaddon); lightui->iScreen = DefaultScreen(lightui->dpy); CreateFont(lightui); lightui->protocolAtom = XInternAtom (lightui->dpy, "WM_PROTOCOLS", False); lightui->killAtom = XInternAtom (lightui->dpy, "WM_DELETE_WINDOW", False); /* Main Menu Initial */ FcitxMenuInit(&lightui->mainMenu); FcitxUIMenu **menupp; UT_array* uimenus = FcitxInstanceGetUIMenus(instance); for (menupp = (FcitxUIMenu **) utarray_front(uimenus); menupp != NULL; menupp = (FcitxUIMenu **) utarray_next(uimenus, menupp) ) { FcitxUIMenu * menup = *menupp; if (!menup->isSubMenu) FcitxMenuAddMenuItem(&lightui->mainMenu, menup->name, MENUTYPE_SUBMENU, menup); } FcitxMenuAddMenuItem(&lightui->mainMenu, NULL, MENUTYPE_DIVLINE, NULL); FcitxMenuAddMenuItem(&lightui->mainMenu, _("Configure"), MENUTYPE_SIMPLE, NULL); FcitxMenuAddMenuItem(&lightui->mainMenu, _("Exit"), MENUTYPE_SIMPLE, NULL); lightui->mainMenu.MenuAction = MainMenuAction; lightui->mainMenu.priv = lightui; lightui->mainMenu.mark = -1; lightui->inputWindow = CreateInputWindow(lightui); lightui->mainWindow = CreateMainWindow(lightui); lightui->trayWindow = CreateTrayWindow(lightui); lightui->mainMenuWindow = CreateMainMenuWindow(lightui); FcitxIMEventHook resethk; resethk.arg = lightui; resethk.func = LightUIInputReset; FcitxInstanceRegisterResetInputHook(instance, resethk); return lightui; }
void* PuncCreate(FcitxInstance* instance) { FcitxPuncState* puncState = fcitx_utils_malloc0(sizeof(FcitxPuncState)); FcitxAddon* puncaddon = FcitxAddonsGetAddonByName(FcitxInstanceGetAddons(instance), FCITX_PUNC_NAME); puncState->owner = instance; LoadPuncDict(puncState); FcitxKeyFilterHook hk; hk.arg = puncState; hk.func = ProcessPunc; FcitxInstanceRegisterPostInputFilter(instance, hk); hk.func = PuncPreFilter; FcitxInstanceRegisterPreInputFilter(instance, hk); puncState->cLastIsAutoConvert = '\0'; puncState->bLastIsNumber = false; FcitxHotkeyHook hotkey; hotkey.hotkey = FcitxInstanceGetGlobalConfig(instance)->hkPunc; hotkey.hotkeyhandle = TogglePuncStateWithHotkey; hotkey.arg = puncState; FcitxInstanceRegisterHotkeyFilter(instance, hotkey); FcitxIMEventHook hook; hook.arg = puncState; hook.func = ResetPunc; FcitxInstanceRegisterResetInputHook(instance, hook); hook.func = ResetPuncWhichStatus; FcitxInstanceRegisterInputUnFocusHook(instance, hook); FcitxInstanceWatchContext(instance, CONTEXT_IM_LANGUAGE, PuncLanguageChanged, puncState); FcitxProfile* profile = FcitxInstanceGetProfile(instance); FcitxUIRegisterStatus(instance, puncState, "punc", profile->bUseWidePunc ? _("Full width punct") : _("Latin punct"), _("Toggle Full Width Punctuation"), TogglePuncState, GetPuncState); puncState->slot = FcitxInstanceAllocDataForIC(instance, PuncWhichAlloc, PuncWhichCopy, PuncWhichFree, puncState); FcitxModuleAddFunction(puncaddon, PuncGetPunc); FcitxModuleAddFunction(puncaddon, PuncGetPunc2); return puncState; }
FCITX_EXPORT_API void FcitxUILoad(FcitxInstance* instance) { UT_array* addons = &instance->addons; FcitxAddon *addon; for (addon = (FcitxAddon *) utarray_front(addons); addon != NULL; addon = (FcitxAddon *) utarray_next(addons, addon)) { if (addon->bEnabled && addon->category == AC_UI) { if (FcitxUILoadInternal(instance, addon)) instance->uinormal = addon; if (instance->uinormal != NULL) break; } } instance->ui = instance->uinormal; if (instance->ui == NULL) FcitxLog(ERROR, "no usable user interface."); else { do { FcitxAddon* fallbackAddon = FcitxAddonsGetAddonByName(&instance->addons, addon->uifallback); if (fallbackAddon == NULL) break; if (!fallbackAddon->bEnabled) break; if (FcitxUILoadInternal(instance, fallbackAddon)) { instance->uifallback = fallbackAddon; if (instance->uifallback->ui->Suspend) instance->uifallback->ui->Suspend(instance->uifallback->addonInstance); } } while (0); } }
// Creates the IME component void* FcitxTabletImeCreate(FcitxInstance* instance) { // Steal the user data from the event addon, since it's more long lived FcitxTablet* ud = FcitxAddonsGetAddonByName(FcitxInstanceGetAddons(instance), FCITX_TABLET_NAME)->addonInstance; FcitxInstanceRegisterIM( instance, ud, //userdata "tablet", "Tablet", "tablet", NULL, FcitxTabletReset, FcitxTabletDoInput, FcitxTabletGetCandWords, NULL, NULL, NULL, NULL, 1, "zh_CN" ); return ud; }
void* XimCreate(FcitxInstance* instance, int frontendid) { if (ximfrontend != NULL) return NULL; FcitxXimFrontend *xim = fcitx_utils_new(FcitxXimFrontend); if (xim == NULL) return NULL; ximfrontend = xim; char *imname = NULL; char *p; UT_array *addons = FcitxInstanceGetAddons(instance); FcitxAddon *ximaddon = FcitxAddonsGetAddonByName(addons, "fcitx-xim"); xim->display = FcitxX11GetDisplay(instance); if (xim->display == NULL) { FcitxLog(FATAL, _("X11 not initialized")); free(xim); return NULL; } xim->iScreen = DefaultScreen(xim->display); xim->owner = instance; xim->frontendid = frontendid; xim->xim_window = XCreateWindow(xim->display, DefaultRootWindow(xim->display), 0, 0, 1, 1, 0, 0, InputOnly, CopyFromParent, 0, NULL); if (!xim->xim_window) { FcitxLog(FATAL, _("Can't Create imWindow")); free(xim); return NULL; } if (!imname) { imname = getenv("XMODIFIERS"); if (imname) { if (!strncmp(imname, "@im=", strlen("@im="))) { imname += 4; } else { FcitxLog(WARNING, _("XMODIFIERS Error.")); imname = DEFAULT_IMNAME; } } else { FcitxLog(WARNING, _("Please set XMODIFIERS.")); imname = DEFAULT_IMNAME; } } XimQueueInit(xim); if (GetXimConfigDesc() == NULL) xim->bUseOnTheSpotStyle = false; else { FcitxConfigFileDesc* configDesc = GetXimConfigDesc(); FILE *fp; char *file; fp = FcitxXDGGetFileUserWithPrefix("conf", "fcitx-xim.config", "r", &file); FcitxLog(DEBUG, "Load Config File %s", file); free(file); if (!fp) { if (errno == ENOENT) { char *file; FILE *fp2 = FcitxXDGGetFileUserWithPrefix("conf", "fcitx-xim.config", "w", &file); FcitxLog(DEBUG, "Save Config to %s", file); FcitxConfigSaveConfigFileFp(fp2, &xim->gconfig, configDesc); free(file); if (fp2) fclose(fp2); } } FcitxConfigFile *cfile = FcitxConfigParseConfigFileFp(fp, configDesc); FcitxXimFrontendConfigBind(xim, cfile, configDesc); FcitxConfigBindSync((FcitxGenericConfig*)xim); if (fp) fclose(fp); } XIMStyles input_styles; if (xim->bUseOnTheSpotStyle) { input_styles.count_styles = sizeof(OnTheSpot_Styles) / sizeof(XIMStyle) - 1; input_styles.supported_styles = OnTheSpot_Styles; } else { input_styles.count_styles = sizeof(OverTheSpot_Styles) / sizeof(XIMStyle) - 1; input_styles.supported_styles = OverTheSpot_Styles; } XIMEncodings encodings = { .count_encodings = sizeof(zhEncodings) / sizeof(XIMEncoding) - 1, .supported_encodings = zhEncodings }; p = getenv("LC_CTYPE"); if (!p) { p = getenv("LC_ALL"); if (!p) p = getenv("LANG"); } if (p) { int p_l = strlen(p); if (strlen(LOCALES_STRING) + p_l + 1 < LOCALES_BUFSIZE) { strLocale[strlen(LOCALES_STRING)] = ','; memcpy(strLocale + strlen(LOCALES_STRING) + 1, p, p_l + 1); } } xim->ims = IMOpenIM(xim->display, IMModifiers, "Xi18n", IMServerWindow, xim->xim_window, IMServerName, imname, IMLocale, strLocale, IMServerTransport, "X/", IMInputStyles, &input_styles, IMEncodingList, &encodings, IMProtocolHandler, XimProtocolHandler, IMFilterEventMask, KeyPressMask | KeyReleaseMask, NULL); if (xim->ims == (XIMS) NULL) { FcitxLog(ERROR, _("Start XIM error. Another XIM daemon named %s is running?"), imname); XimDestroy(xim); FcitxInstanceEnd(instance); return NULL; } FcitxModuleAddFunction(ximaddon, XimConsumeQueue); return xim; } Bool XimProtocolHandler(XIMS _ims, IMProtocol * call_data) { switch (call_data->major_code) { case XIM_OPEN: FcitxLog(DEBUG, "XIM_OPEN:\t\ticid=%d\tconnect_id=%d", ((IMForwardEventStruct *) call_data)->icid, ((IMForwardEventStruct *) call_data)->connect_id); break; case XIM_CLOSE: FcitxLog(DEBUG, "XIM_CLOSE:\t\ticid=%d\tconnect_id=%d", ((IMForwardEventStruct *) call_data)->icid, ((IMForwardEventStruct *) call_data)->connect_id); break; case XIM_CREATE_IC: FcitxLog(DEBUG, "XIM_CREATE_IC:\t\ticid=%d\tconnect_id=%d", ((IMForwardEventStruct *) call_data)->icid, ((IMForwardEventStruct *) call_data)->connect_id); break; case XIM_DESTROY_IC: FcitxLog(DEBUG, "XIM_DESTROY_IC:\t\ticid=%d\tconnect_id=%d", ((IMForwardEventStruct *) call_data)->icid, ((IMForwardEventStruct *) call_data)->connect_id); break; case XIM_SET_IC_VALUES: FcitxLog(DEBUG, "XIM_SET_IC_VALUES:\t\ticid=%d\tconnect_id=%d", ((IMForwardEventStruct *) call_data)->icid, ((IMForwardEventStruct *) call_data)->connect_id); break; case XIM_GET_IC_VALUES: FcitxLog(DEBUG, "XIM_GET_IC_VALUES:\ticid=%d\tconnect_id=%d", ((IMForwardEventStruct *) call_data)->icid, ((IMForwardEventStruct *) call_data)->connect_id); break; case XIM_FORWARD_EVENT: FcitxLog(DEBUG, "XIM_FORWARD_EVENT:\ticid=%d\tconnect_id=%d", ((IMForwardEventStruct *) call_data)->icid, ((IMForwardEventStruct *) call_data)->connect_id); break; case XIM_SET_IC_FOCUS: FcitxLog(DEBUG, "XIM_SET_IC_FOCUS:\ticid=%d\tconnect_id=%d", ((IMForwardEventStruct *) call_data)->icid, ((IMForwardEventStruct *) call_data)->connect_id); break; case XIM_UNSET_IC_FOCUS: FcitxLog(DEBUG, "XIM_UNSET_IC_FOCUS:\ticid=%d\tconnect_id=%d", ((IMForwardEventStruct *) call_data)->icid, ((IMForwardEventStruct *) call_data)->connect_id); break; case XIM_RESET_IC: FcitxLog(DEBUG, "XIM_RESET_IC:\t\ticid=%d\tconnect_id=%d", ((IMForwardEventStruct *) call_data)->icid, ((IMForwardEventStruct *) call_data)->connect_id); break; case XIM_TRIGGER_NOTIFY: FcitxLog(DEBUG, "XIM_TRIGGER_NOTIFY:\t\ticid=%d\tconnect_id=%d", ((IMForwardEventStruct *) call_data)->icid, ((IMForwardEventStruct *) call_data)->connect_id); break; default: FcitxLog(DEBUG, "XIM_DEFAULT:\t\ticid=%d\tconnect_id=%d\t%d", ((IMForwardEventStruct *) call_data)->icid, ((IMForwardEventStruct *) call_data)->connect_id, call_data->major_code); break; } switch (call_data->major_code) { case XIM_OPEN: return XIMOpenHandler(ximfrontend, (IMOpenStruct *) call_data); case XIM_CLOSE: return XIMCloseHandler(ximfrontend, (IMOpenStruct *) call_data); case XIM_CREATE_IC: return XIMCreateICHandler(ximfrontend, (IMChangeICStruct *) call_data); case XIM_DESTROY_IC: return XIMDestroyICHandler(ximfrontend, (IMChangeICStruct *) call_data); case XIM_SET_IC_VALUES: return XIMSetICValuesHandler(ximfrontend, (IMChangeICStruct *) call_data); case XIM_GET_IC_VALUES: return XIMGetICValuesHandler(ximfrontend, (IMChangeICStruct *) call_data); case XIM_FORWARD_EVENT: XIMProcessKey(ximfrontend, (IMForwardEventStruct *) call_data); return True; case XIM_SET_IC_FOCUS: return XIMSetFocusHandler(ximfrontend, (IMChangeFocusStruct *) call_data); case XIM_UNSET_IC_FOCUS: return XIMUnsetFocusHandler(ximfrontend, (IMChangeICStruct *) call_data);; case XIM_RESET_IC: return True; case XIM_PREEDIT_START_REPLY: return 0; case XIM_PREEDIT_CARET_REPLY: return 0; case XIM_SYNC_REPLY: return 0; default: return True; } } boolean XimDestroy(void* arg) { FcitxXimFrontend* xim = (FcitxXimFrontend*) arg; /** * Destroy the window BEFORE(!!!!!) CloseIM!!! * Work arround for a bug in libX11. See wengxt's commit log: * f773dd4f7152a4b4b7f406fe01bff466e0de3dc2 * [xim, x11] correctly shutdown xim, destroy x11 with error handling **/ if (xim->xim_window) { XDestroyWindow(xim->display, xim->xim_window); } if (xim->ims) { IMCloseIM(xim->ims); xim->ims = NULL; } XimQueueDestroy(xim); free(xim); return true; }
void* ClassicUICreate(FcitxInstance* instance) { FcitxAddon* classicuiaddon = FcitxAddonsGetAddonByName(FcitxInstanceGetAddons(instance), FCITX_CLASSIC_UI_NAME); FcitxModuleFunctionArg arg; FcitxClassicUI* classicui = fcitx_utils_malloc0(sizeof(FcitxClassicUI)); classicui->owner = instance; if (!LoadClassicUIConfig(classicui)) { free(classicui); return NULL; } if (GetSkinDesc() == NULL) { free(classicui); return NULL; } classicui->dpy = InvokeFunction(instance, FCITX_X11, GETDISPLAY, arg); if (classicui->dpy == NULL) { free(classicui); return NULL; } if (LoadSkinConfig(&classicui->skin, &classicui->skinType)) { free(classicui); return NULL; } classicui->isfallback = FcitxUIIsFallback(instance, classicuiaddon); classicui->iScreen = DefaultScreen(classicui->dpy); classicui->protocolAtom = XInternAtom(classicui->dpy, "WM_PROTOCOLS", False); classicui->killAtom = XInternAtom(classicui->dpy, "WM_DELETE_WINDOW", False); InitSkinMenu(classicui); FcitxUIRegisterMenu(instance, &classicui->skinMenu); /* Main Menu Initial */ FcitxMenuInit(&classicui->mainMenu); FcitxMenuAddMenuItem(&classicui->mainMenu, _("About Fcitx"), MENUTYPE_SIMPLE, NULL); FcitxMenuAddMenuItem(&classicui->mainMenu, _("Online Help"), MENUTYPE_SIMPLE, NULL); FcitxMenuAddMenuItem(&classicui->mainMenu, NULL, MENUTYPE_DIVLINE, NULL); FcitxUIMenu **menupp; UT_array* uimenus = FcitxInstanceGetUIMenus(instance); for (menupp = (FcitxUIMenu **) utarray_front(uimenus); menupp != NULL; menupp = (FcitxUIMenu **) utarray_next(uimenus, menupp) ) { FcitxUIMenu * menup = *menupp; if (!menup->isSubMenu) FcitxMenuAddMenuItem(&classicui->mainMenu, menup->name, MENUTYPE_SUBMENU, menup); } FcitxMenuAddMenuItem(&classicui->mainMenu, NULL, MENUTYPE_DIVLINE, NULL); FcitxMenuAddMenuItem(&classicui->mainMenu, _("Configure"), MENUTYPE_SIMPLE, NULL); FcitxMenuAddMenuItem(&classicui->mainMenu, _("Exit"), MENUTYPE_SIMPLE, NULL); classicui->mainMenu.MenuAction = MainMenuAction; classicui->mainMenu.priv = classicui; classicui->mainMenu.mark = -1; classicui->inputWindow = CreateInputWindow(classicui); classicui->mainWindow = CreateMainWindow(classicui); classicui->trayWindow = CreateTrayWindow(classicui); classicui->aboutWindow = CreateAboutWindow(classicui); classicui->messageWindow = CreateMessageWindow(classicui); classicui->mainMenuWindow = CreateMainMenuWindow(classicui); FcitxIMEventHook resethk; resethk.arg = classicui; resethk.func = ClassicUIInputReset; FcitxInstanceRegisterResetInputHook(instance, resethk); DisplaySkin(classicui, classicui->skinType); /* ensure order ! */ AddFunction(classicuiaddon, ClassicUILoadImage); AddFunction(classicuiaddon, ClassicUIGetKeyBoardFontColor); AddFunction(classicuiaddon, ClassicUIGetFont); return classicui; }
void* DBusCreate(FcitxInstance* instance) { FcitxDBus *dbusmodule = (FcitxDBus*) fcitx_utils_malloc0(sizeof(FcitxDBus)); FcitxAddon* dbusaddon = FcitxAddonsGetAddonByName(FcitxInstanceGetAddons(instance), FCITX_DBUS_NAME); dbusmodule->owner = instance; DBusError err; if (FcitxInstanceIsTryReplace(instance)) { fcitx_utils_launch_tool("fcitx-remote", "-e"); sleep(1); } dbus_threads_init_default(); // first init dbus dbus_error_init(&err); int retry = 0; DBusConnection* conn = NULL; char* servicename = NULL; asprintf(&servicename, "%s-%d", FCITX_DBUS_SERVICE, fcitx_utils_get_display_number()); /* do session dbus initialize */ do { if (!getenv("DISPLAY") && !getenv("DBUS_SESSION_BUS_ADDRESS")) { FcitxLog(WARNING, "Without DISPLAY or DBUS_SESSION_BUS_ADDRESS session bus will not work"); break; } /* try to get session dbus */ while (1) { conn = dbus_bus_get(DBUS_BUS_SESSION, &err); if (dbus_error_is_set(&err)) { FcitxLog(WARNING, "Connection Error (%s)", err.message); dbus_error_free(&err); dbus_error_init(&err); } if (NULL == conn && retry < MAX_RETRY_TIMES) { retry ++; sleep(RETRY_INTERVAL * retry); } else { break; } } if (NULL == conn) { break; } if (!dbus_connection_add_filter(conn, DBusModuleFilter, dbusmodule, NULL)) break; if (!dbus_connection_set_watch_functions(conn, DBusAddWatch, DBusRemoveWatch, NULL, &dbusmodule->watches, NULL)) { FcitxLog(WARNING, "Add Watch Function Error"); dbus_error_free(&err); dbus_error_init(&err); dbus_connection_unref(conn); conn = NULL; break; } /* from here we know dbus connection is successful, now we need to register the service */ dbus_connection_set_exit_on_disconnect(conn, FALSE); dbusmodule->conn = conn; boolean request_retry = false; int replaceCountdown = FcitxInstanceIsTryReplace(instance) ? 3 : 0; FcitxInstanceResetTryReplace(instance); do { request_retry = false; // request a name on the bus int ret = dbus_bus_request_name(conn, servicename, DBUS_NAME_FLAG_DO_NOT_QUEUE, &err); if (dbus_error_is_set(&err)) { FcitxLog(WARNING, "Name Error (%s)", err.message); goto dbus_init_failed; } if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) { FcitxLog(WARNING, "DBus Service Already Exists"); if (replaceCountdown > 0) { replaceCountdown --; fcitx_utils_launch_tool("fcitx-remote", "-e"); /* sleep for a while and retry */ sleep(1); request_retry = true; continue; } /* if we know fcitx exists, we should exit. */ dbus_error_free(&err); free(servicename); free(dbusmodule); FcitxInstanceEnd(instance); return NULL; } } while (request_retry); dbus_connection_flush(dbusmodule->conn); } while(0); DBusConnection* privconn = NULL; do { int noPrivateDBus = fcitx_utils_get_boolean_env("FCITX_NO_PRIVATE_DBUS", false); if (noPrivateDBus) break; char* file; FILE* dbusfp = FcitxXDGGetFileWithPrefix("dbus", "daemon.conf", "r", &file); if (dbusfp) { fclose(dbusfp); } else { free(file); file = NULL; } dbusmodule->daemon = DBusLaunch(file); fcitx_utils_free(file); if (dbusmodule->daemon.pid == 0) break; privconn = dbus_connection_open(dbusmodule->daemon.address, &err); if (dbus_error_is_set(&err)) { FcitxLog(ERROR, "Private dbus daemon connection error (%s)", err.message); break; } dbus_bus_register(privconn, &err); if (dbus_error_is_set(&err)) { FcitxLog(ERROR, "Private dbus bus register error (%s)", err.message); break; } int ret = dbus_bus_request_name(privconn, servicename, DBUS_NAME_FLAG_DO_NOT_QUEUE, &err); if (dbus_error_is_set(&err)) { FcitxLog(WARNING, "Private Name Error (%s)", err.message); break; } if (DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER != ret) { FcitxLog(ERROR, "Private DBus Service Already Exists, fcitx being hacked?"); break; } if (!dbus_connection_add_filter(privconn, DBusModuleFilter, dbusmodule, NULL)) break; if (!dbus_connection_set_watch_functions(privconn, DBusAddWatch, DBusRemoveWatch, NULL, &dbusmodule->watches, NULL)) { FcitxLog(WARNING, "Add Watch Function Error"); break; } char* addressFile = NULL; char* localMachineId = dbus_get_local_machine_id(); asprintf(&addressFile, "%s-%d", localMachineId, fcitx_utils_get_display_number()); dbus_free(localMachineId); FILE* fp = FcitxXDGGetFileUserWithPrefix("dbus", addressFile, "w", NULL); free(addressFile); if (!fp) break; fprintf(fp, "%s", dbusmodule->daemon.address); fwrite("\0", sizeof(char), 1, fp); pid_t curPid = getpid(); fwrite(&dbusmodule->daemon.pid, sizeof(pid_t), 1, fp); fwrite(&curPid, sizeof(pid_t), 1, fp); fclose(fp); dbusmodule->privconn = privconn; char* command = fcitx_utils_get_fcitx_path_with_filename("bindir", "/fcitx-dbus-watcher"); char* pidstring = NULL; asprintf(&pidstring, "%d", dbusmodule->daemon.pid); char* args[] = { command, dbusmodule->daemon.address, pidstring, NULL }; fcitx_utils_start_process(args); free(command); free(pidstring); } while(0); if (!dbusmodule->privconn) { if (privconn) { dbus_connection_unref(privconn); DBusKill(&dbusmodule->daemon); } } FcitxModuleAddFunction(dbusaddon, DBusGetConnection); FcitxModuleAddFunction(dbusaddon, DBusGetPrivateConnection); dbus_error_free(&err); dbusmodule->serviceName = servicename; return dbusmodule; dbus_init_failed: dbus_error_free(&err); fcitx_utils_free(servicename); if (conn) dbus_connection_unref(conn); DBusKill(&dbusmodule->daemon); fcitx_utils_free(dbusmodule); return NULL; }
void* XimCreate(FcitxInstance* instance, int frontendid) { if (ximfrontend != NULL) return NULL; FcitxXimFrontend* xim = fcitx_utils_malloc0(sizeof(FcitxXimFrontend)); if (xim == NULL) return NULL; ximfrontend = xim; XIMStyles *input_styles; XIMEncodings *encodings; char *imname = NULL; char *p; xim->display = InvokeVaArgs(instance, FCITX_X11, GETDISPLAY); if (xim->display == NULL) { FcitxLog(FATAL, _("X11 not initialized")); free(xim); return NULL; } FcitxAddon* ximaddon = FcitxAddonsGetAddonByName(FcitxInstanceGetAddons(instance), "fcitx-xim"); xim->x11addon = FcitxAddonsGetAddonByName(FcitxInstanceGetAddons(instance), "fcitx-x11"); xim->iScreen = DefaultScreen(xim->display); xim->owner = instance; xim->frontendid = frontendid; xim->ximWindow = XCreateSimpleWindow(xim->display, DefaultRootWindow(xim->display), 0, 0, 1, 1, 1, 0, 0); if (xim->ximWindow == (Window) NULL) { FcitxLog(FATAL, _("Can't Create imWindow")); free(xim); return NULL; } if (!imname) { imname = getenv("XMODIFIERS"); if (imname) { if (strstr(imname, "@im=")) imname += 4; else { FcitxLog(WARNING, _("XMODIFIERS Error.")); imname = DEFAULT_IMNAME; } } else { FcitxLog(WARNING, _("Please set XMODIFIERS.")); imname = DEFAULT_IMNAME; } } XimQueueInit(xim); if (GetXimConfigDesc() == NULL) xim->bUseOnTheSpotStyle = false; else { FcitxConfigFileDesc* configDesc = GetXimConfigDesc(); FILE *fp; char *file; fp = FcitxXDGGetFileUserWithPrefix("conf", "fcitx-xim.config", "r", &file); FcitxLog(DEBUG, "Load Config File %s", file); free(file); if (!fp) { if (errno == ENOENT) { char *file; FILE *fp2 = FcitxXDGGetFileUserWithPrefix("conf", "fcitx-xim.config", "w", &file); FcitxLog(DEBUG, "Save Config to %s", file); FcitxConfigSaveConfigFileFp(fp2, &xim->gconfig, configDesc); free(file); if (fp2) fclose(fp2); } } FcitxConfigFile *cfile = FcitxConfigParseConfigFileFp(fp, configDesc); FcitxXimFrontendConfigBind(xim, cfile, configDesc); FcitxConfigBindSync((FcitxGenericConfig*)xim); if (fp) fclose(fp); } input_styles = (XIMStyles *) malloc(sizeof(XIMStyles)); if (xim->bUseOnTheSpotStyle) { input_styles->count_styles = sizeof(OnTheSpot_Styles) / sizeof(XIMStyle) - 1; input_styles->supported_styles = OnTheSpot_Styles; } else { input_styles->count_styles = sizeof(OverTheSpot_Styles) / sizeof(XIMStyle) - 1; input_styles->supported_styles = OverTheSpot_Styles; } encodings = (XIMEncodings *) malloc(sizeof(XIMEncodings)); encodings->count_encodings = sizeof(zhEncodings) / sizeof(XIMEncoding) - 1; encodings->supported_encodings = zhEncodings; p = getenv("LC_CTYPE"); if (!p) { p = getenv("LC_ALL"); if (!p) p = getenv("LANG"); } if (p) { if (!strcasestr(strLocale, p)) { strcat(strLocale, ","); strcat(strLocale, p); } } xim->ims = IMOpenIM(xim->display, IMModifiers, "Xi18n", IMServerWindow, xim->ximWindow, IMServerName, imname, IMLocale, strLocale, IMServerTransport, "X/", IMInputStyles, input_styles, IMEncodingList, encodings, IMProtocolHandler, XimProtocolHandler, IMFilterEventMask, KeyPressMask | KeyReleaseMask, NULL); free(input_styles); free(encodings); if (xim->ims == (XIMS) NULL) { FcitxLog(ERROR, _("Start XIM error. Another XIM daemon named %s is running?"), imname); free(xim); FcitxInstanceEnd(instance); return NULL; } FcitxModuleAddFunction(ximaddon, XimConsumeQueue); return xim; }
/** * @brief initialize the extra input method * * @param arg * @return successful or not **/ __EXPORT_API void* FcitxLibpinyinCreate (FcitxInstance* instance) { FcitxLibpinyinAddonInstance* libpinyinaddon = (FcitxLibpinyinAddonInstance*) fcitx_utils_malloc0(sizeof(FcitxLibpinyinAddonInstance)); bindtextdomain("fcitx-libpinyin", LOCALEDIR); libpinyinaddon->owner = instance; FcitxAddon* addon = FcitxAddonsGetAddonByName(FcitxInstanceGetAddons(instance), "fcitx-libpinyin"); if (!LoadLibpinyinConfig(&libpinyinaddon->config)) { free(libpinyinaddon); return NULL; } libpinyinaddon->pinyin = FcitxLibpinyinNew(libpinyinaddon, LPT_Pinyin); libpinyinaddon->shuangpin = FcitxLibpinyinNew(libpinyinaddon, LPT_Shuangpin); libpinyinaddon->zhuyin = FcitxLibpinyinNew(libpinyinaddon, LPT_Zhuyin); ConfigLibpinyin(libpinyinaddon); FcitxInstanceRegisterIM(instance, libpinyinaddon->pinyin, "pinyin-libpinyin", _("Pinyin (LibPinyin)"), "pinyin", FcitxLibpinyinInit, FcitxLibpinyinReset, FcitxLibpinyinDoInput, FcitxLibpinyinGetCandWords, NULL, FcitxLibpinyinSave, ReloadConfigFcitxLibpinyin, NULL, 5, libpinyinaddon->config.bTraditionalDataForPinyin ? "zh_TW" : "zh_CN" ); FcitxInstanceRegisterIM(instance, libpinyinaddon->shuangpin, "shuangpin-libpinyin", _("Shuangpin (LibPinyin)"), "shuangpin", FcitxLibpinyinInit, FcitxLibpinyinReset, FcitxLibpinyinDoInput, FcitxLibpinyinGetCandWords, NULL, FcitxLibpinyinSave, ReloadConfigFcitxLibpinyin, NULL, 5, libpinyinaddon->config.bTraditionalDataForPinyin ? "zh_TW" : "zh_CN" ); FcitxInstanceRegisterIM(instance, libpinyinaddon->zhuyin, "zhuyin-libpinyin", _("Bopomofo (LibPinyin)"), "bopomofo", FcitxLibpinyinInit, FcitxLibpinyinReset, FcitxLibpinyinDoInput, FcitxLibpinyinGetCandWords, NULL, FcitxLibpinyinSave, ReloadConfigFcitxLibpinyin, NULL, 5, libpinyinaddon->config.bSimplifiedDataForZhuyin ? "zh_CN" : "zh_TW" ); FcitxModuleAddFunction(addon, LibpinyinSavePinyinWord); return libpinyinaddon; }
void* ClassicUICreate(FcitxInstance* instance) { FcitxAddon* classicuiaddon = FcitxAddonsGetAddonByName(FcitxInstanceGetAddons(instance), FCITX_CLASSIC_UI_NAME); FcitxClassicUI* classicui = fcitx_utils_malloc0(sizeof(FcitxClassicUI)); classicui->owner = instance; if (!LoadClassicUIConfig(classicui)) { free(classicui); return NULL; } if (GetSkinDesc() == NULL) { free(classicui); return NULL; } classicui->dpy = FcitxX11GetDisplay(instance); if (classicui->dpy == NULL) { free(classicui); return NULL; } FcitxX11GetDPI(instance, &classicui->dpi, NULL); if (classicui->dpi <= 0) classicui->dpi = 96; if (LoadSkinConfig(&classicui->skin, &classicui->skinType)) { free(classicui); return NULL; } classicui->isfallback = FcitxUIIsFallback(instance, classicuiaddon); classicui->iScreen = DefaultScreen(classicui->dpy); classicui->protocolAtom = XInternAtom(classicui->dpy, "WM_PROTOCOLS", False); classicui->killAtom = XInternAtom(classicui->dpy, "WM_DELETE_WINDOW", False); InitSkinMenu(classicui); FcitxUIRegisterMenu(instance, &classicui->skinMenu); /* Main Menu Initial */ FcitxMenuInit(&classicui->mainMenu); classicui->mainMenu.UpdateMenu = UpdateMainMenu; classicui->mainMenu.MenuAction = MainMenuAction; classicui->mainMenu.priv = classicui; classicui->mainMenu.mark = -1; classicui->inputWindow = CreateInputWindow(classicui); classicui->mainWindow = CreateMainWindow(classicui); classicui->trayWindow = CreateTrayWindow(classicui); classicui->messageWindow = CreateMessageWindow(classicui); classicui->mainMenuWindow = CreateMainMenuWindow(classicui); FcitxIMEventHook resethk; resethk.arg = classicui; resethk.func = ClassicUIInputReset; FcitxInstanceRegisterResetInputHook(instance, resethk); DisplaySkin(classicui, classicui->skinType); /* ensure order ! */ FcitxModuleAddFunction(classicuiaddon, ClassicUILoadImage); FcitxModuleAddFunction(classicuiaddon, ClassicUIGetKeyBoardFontColor); FcitxModuleAddFunction(classicuiaddon, ClassicUIGetFont); return classicui; }