//根据Menu内容来绘制菜单内容 void DrawXlibMenu(XlibMenu * menu) { FcitxSkin *sc = &menu->owner->skin; FcitxClassicUI *classicui = menu->owner; Display* dpy = classicui->dpy; GC gc = XCreateGC(dpy, menu->menuWindow, 0, NULL); int i = 0; int fontheight; int iPosY = 0; int dpi = sc->skinFont.respectDPI? menu->owner->dpi: 0; FCITX_UNUSED(dpi); fontheight = FontHeight(menu->owner->menuFont, sc->skinFont.menuFontSize, dpi); SkinImage *background = LoadImage(sc, sc->skinMenu.backImg, false); GetMenuSize(menu); EnlargeCairoSurface(&menu->menu_cs, menu->width, menu->height); if (background) { cairo_t* cr = cairo_create(menu->menu_cs); DrawResizableBackground(cr, background->image, menu->height, menu->width, sc->skinMenu.marginLeft, sc->skinMenu.marginTop, sc->skinMenu.marginRight, sc->skinMenu.marginBottom, sc->skinMenu.fillV, sc->skinMenu.fillH ); cairo_destroy(cr); } iPosY = sc->skinMenu.marginTop; for (i = 0; i < utarray_len(&menu->menushell->shell); i++) { if (GetMenuItem(menu->menushell, i)->type == MENUTYPE_SIMPLE || GetMenuItem(menu->menushell, i)->type == MENUTYPE_SUBMENU) { DisplayText(menu, i, iPosY, fontheight); if (menu->menushell->mark == i) MenuMark(menu, iPosY, i); if (GetMenuItem(menu->menushell, i)->type == MENUTYPE_SUBMENU) DrawArrow(menu, iPosY); iPosY = iPosY + 6 + fontheight; } else if (GetMenuItem(menu->menushell, i)->type == MENUTYPE_DIVLINE) { DrawDivLine(menu, iPosY); iPosY += 5; } } XResizeWindow(dpy, menu->menuWindow, menu->width, menu->height); _CAIRO_SETSIZE(menu->menu_x_cs, menu->width, menu->height); cairo_t* c = cairo_create(menu->menu_x_cs); cairo_set_operator(c, CAIRO_OPERATOR_SOURCE); cairo_set_source_surface(c, menu->menu_cs, 0, 0); cairo_rectangle(c, 0, 0, menu->width, menu->height); cairo_clip(c); cairo_paint(c); cairo_destroy(c); cairo_surface_flush(menu->menu_x_cs); XFreeGC(dpy, gc); }
//根据Menu内容来绘制菜单内容 void DrawXlibMenu(XlibMenu * menu) { FcitxLightUI *lightui = menu->owner; Display* dpy = lightui->dpy; GC gc = XCreateGC( dpy, menu->menuWindow, 0, NULL ); int i=0; int fontheight; int iPosY = 0; fontheight= MenuFontSize; GetMenuSize(menu); DrawResizableBackground(menu->owner, menu->pixmap, menu->height, menu->width, menu->owner->backcolor, menu->owner->bordercolor, gc); iPosY=MenuMarginTop; for (i=0;i<utarray_len(&menu->menushell->shell);i++) { if ( GetMenuShell(menu->menushell, i)->type == MENUTYPE_SIMPLE || GetMenuShell(menu->menushell, i)->type == MENUTYPE_SUBMENU) { DisplayText( menu,i,iPosY); if (menu->menushell->mark == i) MenuMark(menu,iPosY,i); if (GetMenuShell(menu->menushell, i)->type == MENUTYPE_SUBMENU) DrawArrow(menu, iPosY); iPosY=iPosY+6+fontheight; } else if ( GetMenuShell(menu->menushell, i)->type == MENUTYPE_DIVLINE) { DrawDivLine(menu,iPosY); iPosY+=5; } } XResizeWindow(dpy, menu->menuWindow, menu->width, menu->height); XCopyArea (dpy, menu->pixmap, menu->menuWindow, gc, 0, 0, menu->width, menu->height, 0, 0); XFreeGC(dpy, gc); }
void DrawInputBar(FcitxSkin* sc, InputWindow* inputWindow, int iCursorPos, FcitxMessages * msgup, FcitxMessages *msgdown , unsigned int * iheight, unsigned int *iwidth) { int i; char *strUp[MAX_MESSAGE_COUNT]; char *strDown[MAX_MESSAGE_COUNT]; int posUpX[MAX_MESSAGE_COUNT], posUpY[MAX_MESSAGE_COUNT]; int posDownX[MAX_MESSAGE_COUNT], posDownY[MAX_MESSAGE_COUNT]; int oldHeight = *iheight, oldWidth = *iwidth; int newHeight = 0, newWidth = 0; int cursor_pos = 0; int inputWidth = 0, outputWidth = 0; int outputHeight = 0; cairo_t *c = NULL; FcitxInputState* input = FcitxInstanceGetInputState(inputWindow->owner->owner); FcitxInstance* instance = inputWindow->owner->owner; FcitxClassicUI* classicui = inputWindow->owner; int iChar = iCursorPos; int strWidth = 0, strHeight = 0; SkinImage *inputimg, *prev, *next; inputimg = LoadImage(sc, sc->skinInputBar.backImg, false); prev = LoadImage(sc, sc->skinInputBar.backArrow, false); next = LoadImage(sc, sc->skinInputBar.forwardArrow, false); if (!FcitxMessagesIsMessageChanged(msgup) && !FcitxMessagesIsMessageChanged(msgdown)) return; inputWidth = 0; int dpi = sc->skinFont.respectDPI? classicui->dpi : 0; FCITX_UNUSED(dpi); #ifdef _ENABLE_PANGO /* special case which only macro unable to handle */ SetFontContext(dummy, inputWindow->owner->font, inputWindow->owner->fontSize > 0 ? inputWindow->owner->fontSize : sc->skinFont.fontSize, dpi); #endif int fontHeight = FontHeightWithContext(inputWindow->c_font[0], dpi); 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] = sc->skinInputBar.marginLeft + inputWidth; StringSizeWithContext(inputWindow->c_font[FcitxMessagesGetMessageType(msgup, i)], dpi, strUp[i], &strWidth, &strHeight); if (sc->skinFont.respectDPI) posUpY[i] = sc->skinInputBar.marginTop + sc->skinInputBar.iInputPos; else posUpY[i] = sc->skinInputBar.marginTop + 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; StringSizeWithContext(inputWindow->c_font[FcitxMessagesGetMessageType(msgup, i)], dpi, strGBKT, &strWidth, &strHeight); cursor_pos = posUpX[i] + strWidth + 2; } iChar -= length; } } } if (iChar >= 0) cursor_pos = inputWidth + sc->skinInputBar.marginLeft; outputWidth = 0; outputHeight = 0; int currentX = 0; int offsetY; if (sc->skinFont.respectDPI) offsetY = sc->skinInputBar.marginTop + sc->skinInputBar.iInputPos + fontHeight + (FcitxMessagesGetMessageCount(msgdown) ? sc->skinInputBar.iOutputPos : 0); else offsetY = sc->skinInputBar.marginTop + sc->skinInputBar.iOutputPos - fontHeight; 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 (inputWindow->owner->bVerticalList) { /* vertical */ if (FcitxMessagesGetMessageType(msgdown, i) == MSG_INDEX) { if (currentX > outputWidth) outputWidth = currentX; if (i != 0) { currentX = 0; } } posDownX[i] = sc->skinInputBar.marginLeft + currentX; StringSizeWithContext(inputWindow->c_font[FcitxMessagesGetMessageType(msgdown, i)], dpi, strDown[i], &strWidth, &strHeight); if (FcitxMessagesGetMessageType(msgdown, i) == MSG_INDEX && i != 0) outputHeight += fontHeight + 2; currentX += strWidth; } else { /* horizontal */ posDownX[i] = sc->skinInputBar.marginLeft + outputWidth; StringSizeWithContext(inputWindow->c_font[FcitxMessagesGetMessageType(msgdown, i)], dpi, strDown[i], &strWidth, &strHeight); outputWidth += strWidth; } posDownY[i] = offsetY + outputHeight; } if (inputWindow->owner->bVerticalList && currentX > outputWidth) outputWidth = currentX; newHeight = offsetY + outputHeight + sc->skinInputBar.marginBottom + (FcitxMessagesGetMessageCount(msgdown) || !sc->skinFont.respectDPI ? fontHeight : 0); newWidth = (inputWidth < outputWidth) ? outputWidth : inputWidth; newWidth += sc->skinInputBar.marginLeft + sc->skinInputBar.marginRight; /* round to ROUND_SIZE in order to decrease resize */ newWidth = (newWidth / ROUND_SIZE) * ROUND_SIZE + ROUND_SIZE; if (inputWindow->owner->bVerticalList) { /* vertical */ newWidth = (newWidth < INPUT_BAR_VMIN_WIDTH) ? INPUT_BAR_VMIN_WIDTH : newWidth; } else { newWidth = (newWidth < INPUT_BAR_HMIN_WIDTH) ? INPUT_BAR_HMIN_WIDTH : newWidth; } *iwidth = newWidth; *iheight = newHeight; EnlargeCairoSurface(&inputWindow->cs_input_back, newWidth, newHeight); if (EnlargeCairoSurface(&inputWindow->cs_input_bar, newWidth, newHeight)) { LoadInputMessage(&classicui->skin, classicui->inputWindow, classicui->font); } if (oldHeight != newHeight || oldWidth != newWidth) { c = cairo_create(inputWindow->cs_input_back); DrawResizableBackground(c, inputimg->image, newHeight, newWidth, sc->skinInputBar.marginLeft, sc->skinInputBar.marginTop, sc->skinInputBar.marginRight, sc->skinInputBar.marginBottom, sc->skinInputBar.fillV, sc->skinInputBar.fillH ); cairo_destroy(c); } c = cairo_create(inputWindow->cs_input_bar); cairo_set_source_surface(c, inputWindow->cs_input_back, 0, 0); cairo_save(c); cairo_rectangle(c, 0, 0, newWidth, newHeight); cairo_set_operator(c, CAIRO_OPERATOR_SOURCE); cairo_clip(c); cairo_paint(c); cairo_restore(c); cairo_set_operator(c, CAIRO_OPERATOR_OVER); if (FcitxInputStateGetShowCursor(input)) { //画向前向后箭头 if (prev && next) { cairo_set_source_surface(inputWindow->c_back, prev->image, newWidth - sc->skinInputBar.iBackArrowX , sc->skinInputBar.iBackArrowY); if (FcitxCandidateWordHasPrev(FcitxInputStateGetCandidateList(input))) cairo_paint(inputWindow->c_back); else cairo_paint_with_alpha(inputWindow->c_back, 0.5); //画向前箭头 cairo_set_source_surface(inputWindow->c_back, next->image, newWidth - sc->skinInputBar.iForwardArrowX , sc->skinInputBar.iForwardArrowY); if (FcitxCandidateWordHasNext(FcitxInputStateGetCandidateList(input))) cairo_paint(inputWindow->c_back); else cairo_paint_with_alpha(inputWindow->c_back, 0.5); } } for (i = 0; i < FcitxMessagesGetMessageCount(msgup) ; i++) { OutputStringWithContext(inputWindow->c_font[FcitxMessagesGetMessageType(msgup, i)], dpi, strUp[i], posUpX[i], posUpY[i]); if (strUp[i] != FcitxMessagesGetMessageString(msgup, i)) free(strUp[i]); } for (i = 0; i < FcitxMessagesGetMessageCount(msgdown) ; i++) { OutputStringWithContext(inputWindow->c_font[FcitxMessagesGetMessageType(msgdown, i)], dpi, strDown[i], posDownX[i], posDownY[i]); if (strDown[i] != FcitxMessagesGetMessageString(msgdown, i)) free(strDown[i]); } int cursorY1, cursorY2; if (sc->skinFont.respectDPI) { cursorY1 = sc->skinInputBar.marginTop + sc->skinInputBar.iInputPos; cursorY2 = sc->skinInputBar.marginTop + sc->skinInputBar.iInputPos + fontHeight; } else { cursorY1 = sc->skinInputBar.marginTop + sc->skinInputBar.iInputPos - fontHeight - 4; cursorY2 = sc->skinInputBar.marginTop + sc->skinInputBar.iInputPos; } //画光标 if (FcitxInputStateGetShowCursor(input)) { cairo_move_to(inputWindow->c_cursor, cursor_pos, cursorY1); cairo_line_to(inputWindow->c_cursor, cursor_pos, cursorY2); cairo_stroke(inputWindow->c_cursor); } ResetFontContext(); cairo_destroy(c); FcitxMessagesSetMessageChanged(msgup, false); FcitxMessagesSetMessageChanged(msgdown, false); }
void DrawInputBar(InputWindow* inputWindow, int iCursorPos, Messages * msgup, Messages *msgdown ,unsigned int * iheight, unsigned int *iwidth) { int i; char *strUp[MAX_MESSAGE_COUNT]; char *strDown[MAX_MESSAGE_COUNT]; int posUpX[MAX_MESSAGE_COUNT], posUpY[MAX_MESSAGE_COUNT]; int posDownX[MAX_MESSAGE_COUNT], posDownY[MAX_MESSAGE_COUNT]; int oldHeight = *iheight, oldWidth = *iwidth; int newHeight = 0, newWidth = 0; int cursor_pos=0; int inputWidth = 0, outputWidth = 0; int outputHeight = 0; FcitxInputState* input = &inputWindow->owner->owner->input; FcitxInstance* instance = inputWindow->owner->owner; int iChar = iCursorPos; int strWidth = 0, strHeight = 0; int fontSize = FONTHEIGHT; if (!IsMessageChanged(msgup) && !IsMessageChanged(msgdown)) return; inputWidth = 0; strHeight = FONTHEIGHT; for (i = 0; i < GetMessageCount(msgup) ; i++) { char *trans = ProcessOutputFilter(instance, GetMessageString(msgup, i)); if (trans) strUp[i] = trans; else strUp[i] = GetMessageString(msgup, i); posUpX[i] = MarginLeft + inputWidth; strWidth = StringWidth(inputWindow->dpy, inputWindow->owner->xftfont, strUp[i]); posUpY[i] = MarginTop + InputPos - strHeight; inputWidth += strWidth; if (input->bShowCursor) { int length = strlen(GetMessageString(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; strWidth = StringWidth(inputWindow->dpy, inputWindow->owner->xftfont, strGBKT); cursor_pos= posUpX[i] + strWidth + 2; } iChar -= length; } } } if (iChar >= 0) cursor_pos = inputWidth + MarginLeft; outputWidth = 0; outputHeight = 0; int currentX = 0; for (i = 0; i < GetMessageCount(msgdown) ; i++) { char *trans = ProcessOutputFilter(instance, GetMessageString(msgdown, i)); if (trans) strDown[i] = trans; else strDown[i] = GetMessageString(msgdown, i); if (inputWindow->owner->bVerticalList) /* vertical */ { if (GetMessageType(msgdown, i) == MSG_INDEX) { if (currentX > outputWidth) outputWidth = currentX; if (i != 0) { outputHeight += fontSize + 2; currentX = 0; } } posDownX[i] = MarginLeft + currentX; strWidth = StringWidth(inputWindow->dpy, inputWindow->owner->xftfont, strDown[i]); currentX += strWidth; posDownY[i] = MarginTop + OutputPos + outputHeight - strHeight; } else /* horizontal */ { posDownX[i] = MarginLeft + outputWidth; strWidth = StringWidth(inputWindow->dpy, inputWindow->owner->xftfont, strDown[i]); posDownY[i] = MarginTop + OutputPos - strHeight; outputWidth += strWidth; } } if (inputWindow->owner->bVerticalList && currentX > outputWidth) outputWidth = currentX; newHeight = MarginTop + OutputPos + outputHeight + MarginBottom; newWidth = (inputWidth<outputWidth)?outputWidth:inputWidth; newWidth+=MarginLeft+MarginRight; /* round to ROUND_SIZE in order to decrease resize */ newWidth = (newWidth / ROUND_SIZE) * ROUND_SIZE + ROUND_SIZE; //输入条长度应该比背景图长度要长,比最大长度要短 newWidth=(newWidth>=INPUT_BAR_MAX_WIDTH)?INPUT_BAR_MAX_WIDTH:newWidth; if (inputWindow->owner->bVerticalList) /* vertical */ { newWidth = (newWidth < INPUT_BAR_VMIN_WIDTH)?INPUT_BAR_VMIN_WIDTH:newWidth; } else { newWidth = (newWidth < INPUT_BAR_HMIN_WIDTH)?INPUT_BAR_HMIN_WIDTH:newWidth; } *iwidth = newWidth; *iheight = newHeight; if (oldHeight != newHeight || oldWidth != newWidth) { DrawResizableBackground(inputWindow->owner, inputWindow->pixmap2, newHeight, newWidth, inputWindow->owner->backcolor, inputWindow->owner->bordercolor, inputWindow->pixmap2_gc ); } XGCValues gcvalues; GC gc = XCreateGC(inputWindow->dpy, inputWindow->pixmap, 0, &gcvalues); XCopyArea( inputWindow->dpy, inputWindow->pixmap2, inputWindow->pixmap, gc, 0, 0, inputWindow->iInputWindowWidth, inputWindow->iInputWindowHeight, 0, 0 ); XFreeGC(inputWindow->dpy, gc); if (input->bShowCursor ) { //画向前向后箭头 } for (i = 0; i < GetMessageCount(msgup) ; i++) { OutputString(inputWindow->dpy, inputWindow->xftDraw, inputWindow->pixmap, inputWindow->owner->xftfont, strUp[i], posUpX[i], posUpY[i], inputWindow->owner->fontColor[GetMessageType(msgup, i)]); if (strUp[i] != GetMessageString(msgup, i)) free(strUp[i]); } for (i = 0; i < GetMessageCount(msgdown) ; i++) { OutputString(inputWindow->dpy, inputWindow->xftDraw, inputWindow->pixmap, inputWindow->owner->xftfont, strDown[i], posDownX[i], posDownY[i], inputWindow->owner->fontColor[GetMessageType(msgdown, i)]); if (strDown[i] != GetMessageString(msgdown, i)) free(strDown[i]); } //画光标 if (input->bShowCursor ) { GC gc = LightUICreateGC(inputWindow->dpy, inputWindow->pixmap, inputWindow->owner->cursorColor); XDrawLine(inputWindow->dpy, inputWindow->pixmap, gc, cursor_pos, MarginTop + InputPos, cursor_pos, MarginTop + InputPos - fontSize - 4); XFreeGC(inputWindow->dpy, gc); } SetMessageChanged(msgup, false); SetMessageChanged(msgdown, false); }