gui.c#1.79
来自「linux 下的 oxim 输入法,简单易用.」· 79 代码 · 共 1,095 行 · 第 1/2 页
79
1,095 行
XFlush(gui->display); if (XPending(gui->display)) { XNextEvent(gui->display, &event); if (XFilterEvent(&event, None) != True) { win = gui_search_win(event.xany.window); if (win && win->win_event_func) { win->win_event_func(win, &(event)); } } } else { struct timeval tv; fd_set readfds; int fd = ConnectionNumber(gui->display); FD_ZERO(&readfds); FD_SET(fd, &readfds); tv.tv_sec = 5; tv.tv_usec = 0; if (select(fd + 1, &readfds, NULL, NULL, &tv) == 0) { continue; } } }}/*---------------------------------------------------------------------------- GUI update window list functions.----------------------------------------------------------------------------*/void gui_update_winlist(void){ if (gui->xcin_style) { gui->xcin_win->win_draw_func(gui->xcin_win); } else { gui->root_win->win_draw_func(gui->root_win); gui->preedit_win->win_draw_func(gui->preedit_win); gui->status_win->win_draw_func(gui->status_win); } if (gui->keyboard_win->win_draw_func) { gui->keyboard_win->win_draw_func(gui->keyboard_win); }}/*---------------------------------------------------------------------------- Mouse Event----------------------------------------------------------------------------*/void gui_get_workarea(int *ret_x, int *ret_y, unsigned int *ret_width, unsigned int *ret_height){// 有些發行版回報不正確,在找到更好的方式之前,先暫時不用 :-(#if 0 Atom hints = XInternAtom (gui->display, "_NET_WORKAREA", True); unsigned long nitems, bytesLeft; Atom actualType; int actualFormat; long* workarea = 0; if (XGetWindowProperty (gui->display, gui->root, hints, 0, 4, False, XA_CARDINAL, &actualType, &actualFormat, &nitems, &bytesLeft, (unsigned char**) &workarea) == Success) { if (actualType == XA_CARDINAL && actualFormat == 32 && nitems == 4) { *ret_x = workarea[0]; *ret_y = workarea[1]; *ret_width = workarea[2]; *ret_height = workarea[3]; } if (workarea) { XFree(workarea); } } else#endif { *ret_x = 0; *ret_y = 0; *ret_width = gui->display_width; *ret_height = gui->display_height; }}static void gui_get_mouse_xy(int *x, int *y){ Window ret_root, ret_child; int win_x, win_y, mx, my; unsigned int mask; XQueryPointer(gui->display, gui->root, &ret_root, &ret_child, &win_x, &win_y, &mx, &my, &mask); *x = mx; *y = my;}static void gui_draw_xor_box(GC gc, int x, int y, int width, int height){ XSetForeground(gui->display, gc, WhitePixel(gui->display, gui->screen) ^ BlackPixel(gui->display, gui->screen)); XDrawRectangle(gui->display, gui->root, gc, x, y, width, height);}voidgui_move_window(winlist_t *win){ xccore_t *xccore = (xccore_t *)win->data; int event_x, event_y; int offset_x, offset_y; int move_x, move_y; GC moveGC; int draw_flag = False; int workarea_x, workarea_y; int workarea_x2, workarea_y2; unsigned int workarea_width, workarea_height; gui_get_workarea(&workarea_x, &workarea_y, &workarea_width, &workarea_height); workarea_x2 = workarea_x + workarea_width; workarea_y2 = workarea_y + workarea_height; gui_get_mouse_xy(&event_x, &event_y); offset_x = event_x - win->pos_x; offset_y = event_y - win->pos_y; moveGC = XCreateGC(gui->display, gui->root, 0, NULL); XSetSubwindowMode(gui->display, moveGC, IncludeInferiors); XSetForeground(gui->display, moveGC, BlackPixel(gui->display, gui->screen)); XSetFunction(gui->display, moveGC, GXxor); XChangeActivePointerGrab(gui->display, PointerMotionMask | ButtonMotionMask | ButtonReleaseMask | OwnerGrabButtonMask, None, CurrentTime); XGrabServer(gui->display); XEvent myevent; while(1) { XNextEvent(gui->display, &myevent); switch(myevent.type) { case ButtonRelease: if(myevent.xbutton.button == Button1) { if (draw_flag) { gui_draw_xor_box(moveGC, move_x - offset_x, move_y - offset_y, win->width, win->height); } XFreeGC(gui->display, moveGC); gui_get_mouse_xy(&move_x, &move_y); win->pos_x = move_x - offset_x; win->pos_y = move_y - offset_y; /* */ if (win->pos_x < workarea_x) win->pos_x = workarea_x; if (win->pos_y < workarea_y) win->pos_y = workarea_y; if (win->pos_x + win->width > workarea_x2) win->pos_x = workarea_x2 - win->width - 2; if (win->pos_y + win->height > workarea_y2) win->pos_y = workarea_y2 - win->height - 2; XMoveWindow(gui->display, win->window, win->pos_x, win->pos_y); XUngrabServer(gui->display); gui_save_window_pos(); /* 儲存視窗位置 */ return; } break; case MotionNotify: if (draw_flag) { gui_draw_xor_box(moveGC, move_x - offset_x, move_y - offset_y, win->width, win->height); } gui_get_mouse_xy(&move_x, &move_y); gui_draw_xor_box(moveGC, move_x - offset_x, move_y - offset_y, win->width, win->height); draw_flag = True; break; default: break; } }}/**************************************************************************************************************************************//* 計算字串繪圖寬度 */static unsigned int Utf8_Char_Escapement(XftDraw *draw, XftFont *font, char *Utf8Char, int Utf8len){ XGlyphInfo GlyphInfo; XftTextExtentsUtf8(XftDrawDisplay(draw), font, (FcChar8 *)Utf8Char, Utf8len, &GlyphInfo); return GlyphInfo.xOff;}/* 繪出Utf8字元 */static unsigned int Draw_Utf8_Char(winlist_t *win, XftFont *font, int foreground_idx, int background_idx, int x, int y, char *Utf8Char, int Utf8len){ unsigned int width = Utf8_Char_Escapement(win->draw, font, Utf8Char, Utf8len); if (background_idx >= 0 && background_idx <= MAX_COLORS) { XftDrawRect(win->draw, &gui->colors[background_idx], x, y - win->font_size+1, width, win->font_size); } XftDrawStringUtf8(win->draw, &gui->colors[foreground_idx], font, x, y, (FcChar8 *)Utf8Char, Utf8len); return width;}/* 繪出虛線方框 */static unsigned int Draw_Missing_Char(winlist_t *win, int foreground_idx, int background_idx, int x, int y){ int width = win->font_size; int x1, y1, x2, y2; x1 = x; y1 = y - win->font_size + 1; x2 = x1 + width - 1; y2 = y; if (background_idx >= 0 && background_idx <= MAX_COLORS) { XftDrawRect(win->draw, &gui->colors[background_idx], x1, y1, width, width); } x1++ ; y1++ ; x2 --; y2--; /* top */ gui_Draw_Line(win, x1, y1, x2, y1, foreground_idx, False); /* right */ gui_Draw_Line(win, x2, y1, x2, y2+1, foreground_idx, False); /* bottom */ gui_Draw_Line(win, x1, y2, x2, y2, foreground_idx, False); /* left */ gui_Draw_Line(win, x1, y1, x1, y2, foreground_idx, False); return win->font_size;}static XftFont *gui_find_font(winlist_t *win, FcChar32 ucs4){ unsigned int i; int weight, slant, scalable; double font_size; FcFontSet *fontset; XftFont *font = NULL; /* 缺字列表有這個字,那就不用再找啦 */ if (FcCharSetHasChar(gui->missing_chars, ucs4)) { return NULL; } /* 找出 Cache 相符的字型 */ for (i=0 ; i < gui->num_fonts ; i++) { XftPatternGetDouble(gui->xftfonts[i]->pattern, XFT_PIXEL_SIZE, 0, &font_size); if ((int)font_size == win->font_size && FcCharSetHasChar(gui->xftfonts[i]->charset, ucs4)) { return gui->xftfonts[i]; } } /* 列出所有可能的字型 */ FcObjectSet *os = FcObjectSetBuild(FC_FAMILY, FC_FILE, FC_INDEX, FC_CHARSET, NULL); /* 只要標準、非斜體、可縮放字型即可 */ FcPattern *listpat = FcPatternBuild(NULL, FC_SLANT, FcTypeInteger, FC_SLANT_ROMAN, FC_SCALABLE, FcTypeBool, FcTrue, NULL); fontset = FcFontList(NULL, listpat, os); FcPatternDestroy(listpat); FcObjectSetDestroy(os); for (i=0; i< fontset->nfont; i++) { FcPattern *pat = fontset->fonts[i]; FcCharSet *fcs = NULL; if (FcPatternGetCharSet(pat, FC_CHARSET, 0, &fcs) != FcResultMatch) continue; if (!FcCharSetHasChar(fcs, ucs4)) continue; FcResult res; FcPattern *mpat = FcFontMatch(0, pat, &res); if (!mpat) continue; XftPatternAddDouble(mpat, XFT_PIXEL_SIZE, (double)win->font_size); XftFont *chkfont = XftFontOpenPattern(gui->display, mpat); if (chkfont) { gui->num_fonts ++; gui->xftfonts = (XftFont **)oxim_realloc(gui->xftfonts, gui->num_fonts * sizeof(XftFont *)); if (!gui->xftfonts) { FcPatternDestroy(mpat); continue; } gui->xftfonts[gui->num_fonts - 1] = chkfont; font = chkfont; break; } else { FcPatternDestroy(mpat); } } FcFontSetDestroy(fontset); if (!font) FcCharSetAddChar(gui->missing_chars, ucs4); return font;}unsigned int gui_Draw_String(winlist_t *win, int foreground_idx, int background_idx, int x, int y, char *string, int len){ char *p = string; unsigned int ucs4; unsigned int string_width = 0; int nbytes; while (len && (nbytes = oxim_utf8_to_ucs4(p, &ucs4, len)) > 0) { unsigned int width; XftFont *font = gui_find_font(win, ucs4); if (font) width = Draw_Utf8_Char(win, font, foreground_idx, background_idx, x, y, p, nbytes); else width = Draw_Missing_Char(win, foreground_idx, background_idx, x, y); x += width; string_width += width; p += nbytes; len -= nbytes; } return string_width;}unsigned int gui_TextEscapement(winlist_t *win, char *string, int len){ char *p = string; unsigned int ucs4; unsigned int string_width = 0; int nbytes; while (len && (nbytes = oxim_utf8_to_ucs4(p, &ucs4, len)) > 0) { XftFont *font = gui_find_font(win, ucs4); unsigned int width = font ? Utf8_Char_Escapement(win->draw, font, p, nbytes) : win->font_size; string_width += width; p += nbytes; len -= nbytes; } return string_width;}void gui_Draw_3D_Box(winlist_t *win, int x, int y, int width, int height, int fill_idx, int boxstyle){ Window w = win->window; GC lightGC = XCreateGC(gui->display, w, 0, NULL); GC darkGC = XCreateGC(gui->display, w, 0, NULL); if (boxstyle) { XSetForeground(gui->display, lightGC, gui_Color(LIGHT_COLOR)); XSetForeground(gui->display, darkGC, gui_Color(DARK_COLOR)); } else { XSetForeground(gui->display, lightGC, gui_Color(DARK_COLOR)); XSetForeground(gui->display, darkGC, gui_Color(LIGHT_COLOR)); } XSetLineAttributes(gui->display, lightGC, 1, LineSolid, CapRound, JoinRound); XSetLineAttributes(gui->display, darkGC, 1, LineSolid, CapRound, JoinRound); int x2 = x + width - 1; int y2 = y + height - 1; XDrawLine(gui->display, w, lightGC, x, y, x2, y); XDrawLine(gui->display, w, lightGC, x, y, x, y2); XDrawLine(gui->display, w, darkGC, x, y2, x2, y2); XDrawLine(gui->display, w, darkGC, x2, y, x2, y2); if (fill_idx >= 0 && fill_idx <= MAX_COLORS) { XftDrawRect(win->draw, &gui->colors[fill_idx], x+1, y + 1, width-2, height-2); } XFreeGC(gui->display, lightGC); XFreeGC(gui->display, darkGC);}void gui_Draw_Line(winlist_t *win, int x, int y, int x1, int y1, int color_idx, int line_style){ XGCValues gv; Window w = win->window; gv.line_width = 1; gv.dashes = 1; gv.line_style = (line_style) ? LineSolid : LineOnOffDash; GC lineGC = XCreateGC(gui->display, w, GCLineWidth|GCLineStyle|GCDashList, &gv); XSetForeground(gui->display, lineGC, gui_Color(color_idx)); XDrawLine(gui->display, w, lineGC, x, y, x1, y1); XFreeGC(gui->display, lineGC);}unsigned long gui_Color(int color_index){ return gui->colors[color_index].pixel;}void gui_Draw_Image(winlist_t *win, int x, int y, char **xpm_data){ XImage *image, *mask; XpmAttributes attr; Window w = win->window; GC pgc = XCreateGC(gui->display, w, 0, NULL); unsigned int px, py; unsigned long mask_val, img_val; bzero(&attr, sizeof(attr)); XpmCreateImageFromData(gui->display, xpm_data, &image, &mask, &attr); if (mask) { for (py=0 ; py < attr.height ; py++) { for (px=0 ; px < attr.width ; px++) { mask_val = XGetPixel(mask, px, py); /* 要顯示的點 */ if (mask_val) { img_val = XGetPixel(image, px, py); XSetForeground(gui->display, pgc, img_val); XDrawPoint(gui->display, w, pgc, px+x, py+y); } } } } else { XPutImage(gui->display, w, DefaultGC(gui->display, gui->screen), image, 0, 0, x, y, attr.width, attr.height); } XDestroyImage(image); if (mask) { XDestroyImage(mask); } XpmFreeAttributes(&attr); XFreeGC(gui->display, pgc);}/* 送出模擬按鍵到指定的視窗 */void gui_send_key(Window win, int state, KeySym keysym){ XEvent Keyevent; Keyevent.type = KeyPress; Keyevent.xany.type = KeyPress; Keyevent.xany.display = gui->display; Keyevent.xkey.serial = 0L; Keyevent.xkey.send_event = True; Keyevent.xkey.window = win; Keyevent.xkey.subwindow = None; Keyevent.xkey.root = gui->root; Keyevent.xkey.time = CurrentTime; Keyevent.xkey.x = 0; Keyevent.xkey.y = 0; Keyevent.xkey.x_root = 0; Keyevent.xkey.y_root = 0; Keyevent.xkey.same_screen = True; Keyevent.xkey.keycode = XKeysymToKeycode(gui->display, keysym); Keyevent.xkey.state = state; XSendEvent(gui->display, win, False, KeyPressMask, (XEvent *)&Keyevent);}void oxim_reload(void){ winlist_t *win = gui->status_win; xccore_t *xccore = (xccore_t *)win->data; IC *ic = xccore->ic; /* 關掉所有視窗 */ gui_hide_symbol(); gui_hide_keyboard(); gui_hide_menu(); /* 關掉輸入狀態,回復英數模式 */ if (ic) { IM_Context_t *imc = ic->imc; inp_state_t inp_state = imc->inp_state; change_IM(ic, -1); if (inp_state & IM_2BYTES) { imc->inp_state &= ~(IM_2BYTES|IM_2BFOCUS|IM_CINPUT); } gui_update_winlist(); } /* 紀錄各個視窗位置 */ gui_save_window_pos(); /* 重新載入系統設定 */ oxim_Reload(); /* 重新初始化字型系統 */ gui_init_xft(); /* 重新初始化視窗 */ InitWindows(xccore); /* 重設所有的 imc */ imc_reset(); /* 重設所有的 Trigger Keys */ xim_set_trigger_keys();}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?