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 + -
显示快捷键?