// Creates the event addon void* FcitxTabletCreate(FcitxInstance* instance) { FcitxTablet* tablet = fcitx_utils_new(FcitxTablet); FcitxTabletLoadConfig(&tablet->config); // TODO select driver from config, currently using lxbi { // Initialise the driver switch(tablet->config.Driver) { case DRIVER_LXBI: tablet->driverInstance = &lxbi; break; // add other drivers here } tablet->driverData = tablet->driverInstance->Create(); tablet->driverPacket = (char*) malloc(tablet->driverInstance->packet_size); } { // Initialise the X display if(NULL == (tablet->xDisplay = FcitxX11GetDisplay(instance))) { FcitxLog(ERROR, "Unable to open X display"); return NULL; } // get dimensions int screen = DefaultScreen(tablet->xDisplay); tablet->xWidth = tablet->config.Width; tablet->xHeight = tablet->config.Height; int x = tablet->config.XPos > 0 ? tablet->config.XPos : XDisplayWidth(tablet->xDisplay, screen) - tablet->xWidth + tablet->config.XPos; int y = tablet->config.YPos > 0 ? tablet->config.YPos : XDisplayHeight(tablet->xDisplay, screen) - tablet->xHeight + tablet->config.YPos; // create colours XColor back; XColor fore; { char colourString[32]; { int r = (255*tablet->config.BackgroundColour.r); int g = (255*tablet->config.BackgroundColour.g); int b = (255*tablet->config.BackgroundColour.b); sprintf(colourString,"rgb:%x/%x/%x",r,g,b); } Colormap defaultCMap = DefaultColormap(tablet->xDisplay, screen); XParseColor(tablet->xDisplay, defaultCMap, colourString, &back); XAllocColor(tablet->xDisplay, defaultCMap, &back); { int r = (255*tablet->config.StrokeColour.r); int g = (255*tablet->config.StrokeColour.g); int b = (255*tablet->config.StrokeColour.b); sprintf(colourString,"rgb:%x/%x/%x",r,g,b); } XParseColor(tablet->xDisplay, defaultCMap, colourString, &fore); XAllocColor(tablet->xDisplay, defaultCMap, &fore); } // set window attributes and create window XSetWindowAttributes attrs; attrs.override_redirect = True; attrs.background_pixel = back.pixel; tablet->xWindow = XCreateWindow(tablet->xDisplay, DefaultRootWindow(tablet->xDisplay), x, y, tablet->xWidth, tablet->xHeight, tablet->config.BorderWidth, CopyFromParent, InputOutput, CopyFromParent, CWBackPixel | CWOverrideRedirect, &attrs); // set up the foreground line (stroke) style XGCValues gcv; gcv.function = GXcopy; gcv.subwindow_mode = IncludeInferiors; gcv.line_width = 3; gcv.cap_style = CapRound; gcv.join_style = JoinRound; tablet->xGC = XCreateGC(tablet->xDisplay, tablet->xWindow, GCFunction | GCSubwindowMode | GCLineWidth | GCCapStyle | GCJoinStyle, &gcv); XSetForeground(tablet->xDisplay, tablet->xGC, fore.pixel); // prevent the window from getting focus or input XRectangle rect = {0,0,0,0}; XserverRegion region = XFixesCreateRegion(tablet->xDisplay,&rect, 1); XFixesSetWindowShapeRegion(tablet->xDisplay, tablet->xWindow, ShapeInput, 0, 0, region); XFixesDestroyRegion(tablet->xDisplay, region); } { // Initialise the stroke buffer tablet->strokesBufferSize = 2048; // should be heaps. Will get automatically enlarged if required tablet->strokesBuffer = (pt_t*) malloc(sizeof(pt_t) * tablet->strokesBufferSize); tablet->strokesPtr = tablet->strokesBuffer; } { // instantiate the engine switch(tablet->config.Engine) { case ENGINE_ZINNIA: tablet->engineInstance = &engZinnia; break; case ENGINE_FORK: tablet->engineInstance = &engFork; break; // add other engines here } tablet->engineData = tablet->engineInstance->Create(&tablet->config); } { // set up the timerfd tablet->timeoutFd = timerfd_create(CLOCK_MONOTONIC, 0); tablet->delay.it_interval.tv_sec = 0; tablet->delay.it_interval.tv_nsec = 0; tablet->delay.it_value.tv_sec = tablet->config.CommitCharMs / 1000; tablet->delay.it_value.tv_nsec = (tablet->config.CommitCharMs % 1000) * 1000000; tablet->timeoutCommitPending = 0; } tablet->fcitx = instance; return tablet; }
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); 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; }