void XlibMenuInit(XlibMenu* menu) { FcitxXlibWindow* window = (FcitxXlibWindow*) menu; FcitxClassicUI* classicui = window->owner; FcitxSkin *sc = &classicui->skin; FcitxXlibWindowInit(&menu->parent, MENU_WINDOW_WIDTH, MENU_WINDOW_HEIGHT, 0, 0, "Fcitx Menu Window", FCITX_WINDOW_MENU, &menu->parent.owner->skin.skinMenu.background, KeyPressMask | ExposureMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | LeaveWindowMask, XlibMenuMoveWindow, XlibMenuCalculateContentSize, XlibMenuPaint ); int dpi = sc->skinFont.respectDPI? classicui->dpi: 0; FcitxCairoTextContext* ctc = FcitxCairoTextContextCreate(NULL); FcitxCairoTextContextSet(ctc, classicui->menuFont, sc->skinFont.menuFontSize, dpi); menu->fontheight = FcitxCairoTextContextFontHeight(ctc); FcitxCairoTextContextFree(ctc); }
void InputWindowCalculateContentSize(FcitxXlibWindow* window, unsigned int* width, unsigned int* height) { InputWindow* inputWindow = (InputWindow*) window; FcitxInstance* instance = window->owner->owner; FcitxInputState* input = FcitxInstanceGetInputState(instance); FcitxCandidateWordList* candList = FcitxInputStateGetCandidateList(input); FcitxCandidateLayoutHint layout = FcitxCandidateWordGetLayoutHint(candList); FcitxClassicUI* classicui = window->owner; inputWindow->cursorPos = FcitxUINewMessageToOldStyleMessage(instance, inputWindow->msgUp, inputWindow->msgDown); boolean vertical = window->owner->bVerticalList; if (layout == CLH_Vertical) vertical = true; else if (layout == CLH_Horizontal) vertical = false; inputWindow->vertical = vertical; /* begin evalulation */ FcitxMessages* msgup = inputWindow->msgUp; FcitxMessages* msgdown = inputWindow->msgDown; FcitxSkin* sc = &classicui->skin; int i; FcitxRect* candRect = inputWindow->candRect; char **strUp = inputWindow->strUp; char **strDown = inputWindow->strDown; int *posUpX = inputWindow->posUpX, *posUpY = inputWindow->posUpY; int *posDownX = inputWindow->posDownX, *posDownY = inputWindow->posDownY; int newHeight = 0, newWidth = 0; int pixelCursorPos = 0; int inputWidth = 0, outputWidth = 0; int outputHeight = 0; int iChar = inputWindow->cursorPos; int strWidth = 0, strHeight = 0; inputWidth = 0; int dpi = sc->skinFont.respectDPI? classicui->dpi : 0; FCITX_UNUSED(dpi); FcitxCairoTextContext* ctc = FcitxCairoTextContextCreate(NULL); FcitxCairoTextContextSet(ctc, window->owner->font, window->owner->fontSize > 0 ? window->owner->fontSize : sc->skinFont.fontSize, dpi); int fontHeight = FcitxCairoTextContextFontHeight(ctc); inputWindow->fontHeight = fontHeight; for (i = 0; i < FcitxMessagesGetMessageCount(msgup) ; i++) { char *trans = FcitxInstanceProcessOutputFilter(instance, FcitxMessagesGetMessageString(msgup, i)); if (trans) strUp[i] = trans; else strUp[i] = FcitxMessagesGetMessageString(msgup, i); posUpX[i] = inputWidth; FcitxCairoTextContextStringSize(ctc, strUp[i], &strWidth, &strHeight); if (sc->skinFont.respectDPI) posUpY[i] = sc->skinInputBar.iInputPos + fontHeight - strHeight; else posUpY[i] = sc->skinInputBar.iInputPos - strHeight; inputWidth += strWidth; if (FcitxInputStateGetShowCursor(input)) { int length = strlen(FcitxMessagesGetMessageString(msgup, i)); if (iChar >= 0) { if (iChar < length) { char strTemp[MESSAGE_MAX_LENGTH]; char *strGBKT = NULL; strncpy(strTemp, strUp[i], iChar); strTemp[iChar] = '\0'; strGBKT = strTemp; FcitxCairoTextContextStringSize(ctc, strGBKT, &strWidth, &strHeight); // if the cursor is between two part, add extra pixel for pretty output pixelCursorPos = posUpX[i] + strWidth; } iChar -= length; } } } if (iChar >= 0) pixelCursorPos = inputWidth; inputWindow->pixelCursorPos = pixelCursorPos; outputWidth = 0; outputHeight = 0; int currentX = 0; int offsetY; if (sc->skinFont.respectDPI) offsetY = (FcitxMessagesGetMessageCount(msgup) ? (sc->skinInputBar.iInputPos + fontHeight) : 0) + (FcitxMessagesGetMessageCount(msgdown) ? sc->skinInputBar.iOutputPos : 0); else offsetY = sc->skinInputBar.iOutputPos - fontHeight; int candidateIndex = -1; int lastRightBottomX = 0, lastRightBottomY = 0; for (i = 0; i < FcitxMessagesGetMessageCount(msgdown) ; i++) { char *trans = FcitxInstanceProcessOutputFilter(instance, FcitxMessagesGetMessageString(msgdown, i)); if (trans) strDown[i] = trans; else strDown[i] = FcitxMessagesGetMessageString(msgdown, i); if (vertical) { /* vertical */ if (FcitxMessagesGetMessageType(msgdown, i) == MSG_INDEX) { if (currentX > outputWidth) outputWidth = currentX; if (i != 0) { currentX = 0; } } posDownX[i] = currentX; FcitxCairoTextContextStringSize(ctc, strDown[i], &strWidth, &strHeight); if (FcitxMessagesGetMessageType(msgdown, i) == MSG_INDEX && i != 0) outputHeight += fontHeight + 2; currentX += strWidth; } else { /* horizontal */ posDownX[i] = outputWidth; FcitxCairoTextContextStringSize(ctc, strDown[i], &strWidth, &strHeight); outputWidth += strWidth; } posDownY[i] = offsetY + outputHeight; if (FcitxMessagesGetMessageType(msgdown, i) == MSG_INDEX) { candidateIndex ++; if (candidateIndex > 0 && candidateIndex - 1 < 10) { candRect[candidateIndex - 1].x2 = lastRightBottomX; candRect[candidateIndex - 1].y2 = lastRightBottomY; } if (candidateIndex < 10) { candRect[candidateIndex].x1 = posDownX[i]; candRect[candidateIndex].y1 = posDownY[i]; } } lastRightBottomX = posDownX[i] + strWidth; lastRightBottomY = posDownY[i] + strHeight; } if (candidateIndex >= 0 && candidateIndex < 10) { candRect[candidateIndex].x2 = lastRightBottomX; candRect[candidateIndex].y2 = lastRightBottomY; } if (vertical && currentX > outputWidth) outputWidth = currentX; newHeight = offsetY + outputHeight + (FcitxMessagesGetMessageCount(msgdown) || !sc->skinFont.respectDPI ? fontHeight : 0); newWidth = (inputWidth < outputWidth) ? outputWidth : inputWidth; /* round to ROUND_SIZE in order to decrease resize */ newWidth = (newWidth / ROUND_SIZE) * ROUND_SIZE + ROUND_SIZE; if (vertical) { /* vertical */ newWidth = (newWidth < INPUT_BAR_VMIN_WIDTH) ? INPUT_BAR_VMIN_WIDTH : newWidth; } else { newWidth = (newWidth < INPUT_BAR_HMIN_WIDTH) ? INPUT_BAR_HMIN_WIDTH : newWidth; } FcitxCairoTextContextFree(ctc); *width = newWidth; *height = newHeight; }