gui.c#1.79

来自「linux 下的 oxim 输入法,简单易用.」· 79 代码 · 共 1,095 行 · 第 1/2 页

79
1,095
字号
/*    Copyright (C) 2006 by OXIM TEAM    This program is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License    along with this program; if not, write to the Free Software    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA*/#ifdef HAVE_CONFIG_H#  include "config.h"#endif#include <unistd.h>#include <signal.h>#include <stdlib.h>#include <string.h>#include <sys/select.h>#include <X11/Xlib.h>#include <X11/Xatom.h>#include <X11/Xutil.h>#include <X11/Xos.h>#include <X11/xpm.h>#include <X11/extensions/shape.h>#include "gui.h"#include "oxim.h"#include <X11/Xft/Xft.h>#define BUFLEN		1024#define WINPOS_FILE	"windows.position"typedef struct {    unsigned int key_id;    unsigned int color_idx;} color_t;static color_t colors[] ={    {WinBoxColor, WINBOX_COLOR},    {BorderColor, BORDER_COLOR},    {LightColor, LIGHT_COLOR},    {DarkColor, DARK_COLOR},    {CursorColor, CURSOR_COLOR},    {CursorFontColor, CURSORFONT_COLOR},    {FontColor, FONT_COLOR},    {ConvertNameColor, CONVERTNAME_COLOR},    {InputNameColor, INPUTNAME_COLOR},    {UnderlineColor, UNDERLINE_COLOR},    {KeystrokeColor, KEYSTROKE_COLOR},    {KeystrokeBoxColor, KEYSTROKEBOX_COLOR},    {SelectFontColor, SELECTFONT_COLOR},    {SelectBoxColor, SELECTBOX_COLOR},    {MenuBGColor, MENU_BG_COLOR},    {MenuFontColor, MENU_FONT_COLOR},    {XcinBorderColor, XCIN_BORDER_COLOR},    {XcinBGColor, XCIN_BG_COLOR},    {XcinFontColor, XCIN_FONT_COLOR},    {XcinStatusFGColor, XCIN_STATUS_FG_COLOR},    {XcinStatusBGColor, XCIN_STATUS_BG_COLOR},    {XcinCursorFGColor, XCIN_CURSOR_FG_COLOR},    {XcinCursorBGColor, XCIN_CURSOR_BG_COLOR},    {XcinUnderlineColor, XCIN_UNDERLINE_COLOR},    {0, 0}};Cursor gui_cursor_hand;Cursor gui_cursor_move;Cursor gui_cursor_arrow;void gui_root_init(void);void gui_status_init(void);void gui_preedit_init(void);void gui_select_init(void);void gui_tray_init(void);void gui_menu_init(void);void gui_symbol_init(void);void gui_keyboard_init(void);void gui_xcin_init(void);int check_tray_manager(void);void xim_terminate(void);gui_t *gui;/*----------------------------------------------------------------------------	Basic WinList handling functions.----------------------------------------------------------------------------*/static winlist_t *winlist = NULL, *free_win = NULL;static voidfree_win_content(winlist_t *win){    int i;    if ((win->winmode & WMODE_EXIT))	return;    XUnmapWindow(gui->display, win->window);    win->winmode &= ~WMODE_MAP;    XftDrawDestroy(win->draw);    XDestroyWindow(gui->display, win->window);    win->winmode |= WMODE_EXIT;}winlist_t *gui_search_win(Window window){    winlist_t *w = winlist;    while (w) {	if (w->window == window)	    return w;	w = w->next;    }    return NULL;}winlist_t *gui_new_win(void){    winlist_t *win;    if (free_win)    {	win = free_win;	free_win = free_win->next;	bzero(win, sizeof(winlist_t));    }    else    {	win = oxim_malloc(sizeof(winlist_t), True);    }    win->window = XCreateSimpleWindow(gui->display, gui->root,		0, 0, 1, 1, 1, 0, 0);    win->win_draw_func = NULL;    win->win_event_func = NULL;    win->next = winlist;    winlist = win;    return win;}voidgui_freewin(Window window){    winlist_t *w = winlist, *wp = NULL;    while (w) {	if (w->window == window) {	    free_win_content(w);	    if (wp == NULL)		winlist = w->next;	    else		wp->next = w->next;	    w->next = free_win;	    free_win = w;	    return;	}	wp = w;	w  = w->next;    }}voidgui_winmap_change(winlist_t *win, int state){    if ((win->winmode & WMODE_EXIT))	return;    if (state && !(win->winmode & WMODE_MAP))    {	XMapRaised(gui->display, win->window);	win->winmode |= WMODE_MAP;    }    else if (!state && (win->winmode & WMODE_MAP))    {	XUnmapWindow(gui->display, win->window);	win->winmode &= ~WMODE_MAP;    }}intgui_check_window(Window window){    Window root;    int x, y;    unsigned width, height, bw, depth;    XGetGeometry(gui->display, window,		&root, &x, &y, &width, &height, &bw, &depth);    XSync(gui->display, False);    if (errstatus == 0)	return True;    else {	errstatus = 0;	return False;    }}intgui_check_input_focus(xccore_t *xccore, Window win){    Window w;    int revert_to_return;    XGetInputFocus(gui->display, &w, &revert_to_return);    return (w == win) ? True : False;}Window gui_get_input_focus(void){    Window w;    int rt;    XGetInputFocus(gui->display, &w, &rt);    return w;}/* 取得 LED 狀態 */int gui_get_led_state(KeySym keysym){    KeyCode keycode = XKeysymToKeycode(gui->display, keysym);    if (keycode == NoSymbol)	return 0;    int keymask;    Window w1, w2;    int n1,n2,n3,n4;    unsigned int imask;    XModifierKeymap *map = XGetModifierMapping(gui->display);    int i;    for (i = 0 ; i < 8 ; i++)    {	if (map->modifiermap[map->max_keypermod * i] == keycode)	{	    keymask = 1 << i;	}    }    XQueryPointer(gui->display, gui->root, &w1, &w2,			&n1, &n2, &n3, &n4, &imask);    XFreeModifiermap(map);    return ((keymask & imask) != 0);}/*----------------------------------------------------------------------------	GUI Initialization & Main loop----------------------------------------------------------------------------*/static int errhandle(Display *disp, XErrorEvent *xevent){    errstatus = xevent->error_code;    return 1;}static void gui_save_window_pos(void){    char *buf = oxim_malloc(BUFLEN, False);    sprintf(buf, "%s/%s", oxim_user_dir(), WINPOS_FILE);    gzFile *fp = oxim_open_file(buf, "w",  OXIMMSG_EMPTY);    if (fp)    {	gzprintf(fp, "# 這是紀錄各個視窗最後座標的檔案,每次移動視窗都會更新\n");	gzprintf(fp, "# 格式: 視窗名稱 = \"X座標,Y座標\"\n\n");	gzprintf(fp, "root_win = \"%d,%d\"\n", gui->root_win->pos_x, gui->root_win->pos_y);	gzprintf(fp, "xcin_win = \"%d,%d\"\n", gui->xcin_win->pos_x, gui->xcin_win->pos_y);	gzprintf(fp, "status_win = \"%d,%d\"\n", gui->status_win->pos_x, gui->status_win->pos_y);	gzprintf(fp, "preedit_win = \"%d,%d\"\n", gui->preedit_win->pos_x, gui->preedit_win->pos_y);	gzprintf(fp, "select_win = \"%d,%d\"\n", gui->select_win->pos_x, gui->select_win->pos_y);	gzprintf(fp, "symbol_win = \"%d,%d\"\n", gui->symbol_win->pos_x, gui->symbol_win->pos_y);	gzprintf(fp, "keyboard_win = \"%d,%d\"\n", gui->keyboard_win->pos_x, gui->keyboard_win->pos_y);	gzprintf(fp, "\n#--- End of file.\n");	gzclose(fp);    }    free(buf);}static int gui_restore_window_pos(void){    int success = False;    char *buf = oxim_malloc(BUFLEN, False);    sprintf(buf, "%s/%s", oxim_user_dir(), WINPOS_FILE);    gzFile *fp = oxim_open_file(buf, "r",  OXIMMSG_EMPTY);    if (fp)    {	while (oxim_get_line(buf, BUFLEN, fp, NULL, "#\n"))	{	    char *s = buf;	    set_item_t *set_item = oxim_get_key_value(s);	    if (set_item)	    {		int x, y;		char *commapos = index(set_item->value, ',');		if (commapos)		{		    *commapos = (char)0;		    x = atoi(set_item->value);		    y = atoi(commapos+1);		    if (x >= gui->display_width || y >= gui->display_height)		    {			continue;		    }		    if (strcasecmp("xcin_win", set_item->key) == 0)		    {			gui->xcin_win->pos_x = x;			gui->xcin_win->pos_y = y;		    }		    else if (strcasecmp("root_win", set_item->key) == 0)		    {			gui->root_win->pos_x = x;			gui->root_win->pos_y = y;		    }		    else if (strcasecmp("status_win", set_item->key) == 0)		    {			gui->status_win->pos_x = x;			gui->status_win->pos_y = y;		    }		    else if (strcasecmp("preedit_win", set_item->key) == 0)		    {			gui->preedit_win->pos_x = x;			gui->preedit_win->pos_y = y;		    }		    else if (strcasecmp("select_win", set_item->key) == 0)		    {			gui->select_win->pos_x = x;			gui->select_win->pos_y = y;		    }		    else if (strcasecmp("symbol_win", set_item->key) == 0)		    {			gui->symbol_win->pos_x = x;			gui->symbol_win->pos_y = y;		    }		    else if (strcasecmp("keyboard_win", set_item->key) == 0)		    {			gui->keyboard_win->pos_x = x;			gui->keyboard_win->pos_y = y;		    }		}		oxim_key_value_destroy(set_item);	    }	}	gzclose(fp);	success = True;    }    free(buf);    return success;}/* 偵測 Tray Manager */static void gui_tray_monitor(int sig){    if (!check_tray_manager())    {	    alarm(1);    }}static void MakeDefaultFont(winlist_t *win){    int font_size = win->font_size;    if (font_size <= 0)	font_size = gui->default_fontsize;    int i;    double chk_size;    /* 找找看有沒有相同的 size */    for (i = 0 ; i < gui->num_fonts; i++)    {	/* 有的話,就結束 */	if (FcPatternGetDouble(gui->xftfonts[i]->pattern, XFT_PIXEL_SIZE, 0, &chk_size) == FcResultMatch && (int)chk_size == font_size)	    return;    }    gui->num_fonts ++;    if (gui->num_fonts == 1)    {	gui->xftfonts = (XftFont **)oxim_malloc(sizeof(XftFont *), False);    }    else    {	gui->xftfonts = (XftFont **)oxim_realloc(gui->xftfonts, gui->num_fonts * sizeof(XftFont *));    }    gui->xftfonts[gui->num_fonts -1] = XftFontOpen(gui->display, gui->screen,	XFT_FAMILY, XftTypeString, oxim_get_config(DefaultFontName),	XFT_PIXEL_SIZE, XftTypeDouble, (double)font_size,	NULL);}static void gui_init_xft(void){    int i;    /* 釋放原有的字型 */    if (gui->xftfonts)    {	for (i=0 ; i < gui->num_fonts ; i++)	{	    XftFontClose(gui->display, gui->xftfonts[i]);	}	free(gui->xftfonts);    }    gui->num_fonts = 0;    gui->xftfonts = NULL;    /* 釋放缺字表 */    if (gui->missing_chars)    {	FcCharSetDestroy(gui->missing_chars);    }    gui->missing_chars = FcCharSetCreate();    /* */    for (i = 0 ; i < MAX_COLORS ; i++)    {	XftColorFree(gui->display, gui->visual, gui->colormap, &gui->colors[i]);	XftColorAllocName(gui->display, gui->visual, gui->colormap,	oxim_get_config(colors[i].key_id), &gui->colors[colors[i].color_idx]);    }    /* 紀錄預設字型大小 */    unsigned int default_fontsize = atoi(oxim_get_config(DefaultFontSize));    if (default_fontsize < 12 || default_fontsize > 48)	default_fontsize = 16;    gui->default_fontsize = default_fontsize;}static void InitWindows(xccore_t *xccore){    gui_status_init();    gui_root_init();    gui_preedit_init();    gui_select_init();    gui_tray_init();    gui_menu_init();    gui_symbol_init();    gui_keyboard_init();    gui_xcin_init();    int isok = gui_restore_window_pos();    winlist_t *win = winlist;    while (win)    {	win->data = (void *)xccore;	if (win->draw)	{	    XftDrawDestroy(win->draw);	}	win->draw = XftDrawCreate(gui->display, win->window, gui->visual, gui->colormap);	XSelectInput(gui->display, win->window, (ExposureMask|ButtonPressMask|ButtonReleaseMask|PointerMotionMask|EnterWindowMask|LeaveWindowMask|StructureNotifyMask)); 	MakeDefaultFont(win); /* 建立預設字型 */	XMoveResizeWindow(gui->display, win->window,			win->pos_x, win->pos_y, win->width, win->height);	win = win->next;    }}voidgui_init(xccore_t *xccore){    gui = oxim_malloc(sizeof(gui_t), True);    if (! (gui->display = XOpenDisplay(xccore->display_name)))    {	oxim_perr(OXIMMSG_ERROR, N_("cannot open display: %s\n"),			    xccore->display_name);    }    Atom oxim_atom = XInternAtom(gui->display, OXIM_ATOM, True);    if (oxim_atom != None && XGetSelectionOwner(gui->display, oxim_atom) != None)    {	oxim_perr(OXIMMSG_ERROR, N_("OXIM already running!\n"));    }    (void) XSetErrorHandler(errhandle);    gui->screen = DefaultScreen(gui->display);    gui->visual = DefaultVisual(gui->display, gui->screen);    gui->colormap = DefaultColormap(gui->display, gui->screen);    gui->display_width = DisplayWidth(gui->display, gui->screen);    gui->display_height = DisplayHeight(gui->display, gui->screen);    gui->root = RootWindow(gui->display, gui->screen);    gui_cursor_hand = XCreateFontCursor(gui->display, XC_hand2);    gui_cursor_move = XCreateFontCursor(gui->display, XC_fleur);    gui_cursor_arrow = XCreateFontCursor(gui->display, XC_left_ptr);    gui_init_xft();    InitWindows(xccore);    gui->xcin_style = False;    if (strcasecmp("yes", oxim_get_config(XcinStyleEnabled)) == 0)    {	gui->xcin_style = True;    }    gui->onspot_enabled = False;    if (strcasecmp("yes", oxim_get_config(OnSpotEnabled)) == 0)    {	gui->onspot_enabled = True;    }    xccore->display = gui->display;    xccore->window  = gui->status_win->window;    /* 利用計時中斷,偵測 WM 的 Tray Manager 是否 Ready */    signal(SIGALRM, gui_tray_monitor);    gui_tray_monitor(SIGALRM);}voidgui_loop(xccore_t *xccore){    while (1)    {	XEvent event;	winlist_t *win;	if ((xccore->oxim_mode & OXIM_RUN_EXITALL)) {	    xim_terminate();	    exit(0);	}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?