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