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* 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; }