📄 keywidget.c
字号:
/*cellwriter -- a character recognition input methodCopyright (C) 2007 Michael Levin <risujin@risujin.org>This program is free software; you can redistribute it and/ormodify it under the terms of the GNU General Public Licenseas published by the Free Software Foundation; either version 2of 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.*/#include "config.h"#include "common.h"#include "recognize.h"#include "keys.h"#include <string.h>#include <X11/X.h>#include <X11/Xlib.h>#include <X11/keysym.h>#include <X11/extensions/XTest.h>#include <gdk/gdkx.h>/* Keys*/GdkColor custom_key_color = RGB_TO_GDKCOLOR(103, 107, 120);static GdkColor color_text, color_bg, color_keys_dark, color_keys, color_keys_on;static void key_coord(KeyWidget *key_widget, int x, int y, int *x_out, int *y_out){ *x_out = (x * key_widget->width + key_widget->x_range / 2) / key_widget->x_range + key_widget->x; *y_out = (y * key_widget->height + key_widget->y_range / 2) / key_widget->y_range + key_widget->y;}static void key_coords(KeyWidget *key_widget, Key *key, int *x, int *y, int *width, int *height){ int x2, y2; key_coord(key_widget, key->x, key->y, x, y); key_coord(key_widget, key->x + key->width, key->y + key->height, &x2, &y2); *width = x2 - *x; *height = y2 - *y;}static void render_icon(cairo_t *cairo, double x, double y, double size, int icon, int rotate, GdkColor *color){ cairo_save(cairo); cairo_new_path(cairo); cairo_translate(cairo, x + size / 2., y + size / 2.); cairo_scale(cairo, size, size); cairo_rotate(cairo, rotate * M_PI / -180); cairo_set_source_gdk_color(cairo, color, 1.); cairo_set_line_width(cairo, 1 / size); switch (icon) { default: cairo_identity_matrix(cairo); return; case KEY_ARROW: cairo_move_to(cairo, 0.50, 0.00); cairo_line_to(cairo, 0.00, -0.50); cairo_line_to(cairo, 0.00, -0.15); cairo_line_to(cairo, -0.50, -0.15); cairo_line_to(cairo, -0.50, 0.15); cairo_line_to(cairo, 0.00, 0.15); cairo_line_to(cairo, 0.00, 0.50); cairo_line_to(cairo, 0.50, 0.00); cairo_fill(cairo); break; case KEY_TOGGLE_ON: cairo_rectangle(cairo, -0.25, -0.15, 0.5, 0.5); cairo_fill(cairo); break; case KEY_TOGGLE_OFF: cairo_rectangle(cairo, -0.25, -0.15, 0.5, 0.5); cairo_stroke(cairo); break; } cairo_restore(cairo);}static int is_shifted(const Key *key)/* Determine if the key is in a shifted state */{ int shifted = key_shifted; if (!(key->flags & KEY_SHIFTABLE)) return FALSE; if (g_ascii_isalpha(key->string[0]) && key_caps_locked) shifted = !shifted; if (key->flags & KEY_NUM_LOCKABLE && !key_num_locked) shifted = !shifted; return shifted;}static void render_key(KeyWidget *key_widget, int n, int dirty){ Key *key; PangoLayout *layout; PangoRectangle ink_ext, log_ext; cairo_pattern_t *pattern; double icon_size; int x, y, w, h; key = key_widget->keys + n; if (key->width < 1 || key->height < 1) return; key_coords(key_widget, key, &x, &y, &w, &h); /* Cairo clip region */ cairo_reset_clip(key_widget->cairo); cairo_rectangle(key_widget->cairo, x, y, w, h); cairo_clip(key_widget->cairo); /* Render background */ if (!key->active && (((key->flags & KEY_CAPS_LOCK) && key_caps_locked) || ((key->flags & KEY_NUM_LOCK) && key_num_locked))) { GdkColor new_bg; new_bg.red = (color_keys_on.red + color_keys.red) / 2; new_bg.green = (color_keys_on.green + color_keys.green) / 2; new_bg.blue = (color_keys_on.blue + color_keys.blue) / 2; gdk_gc_set_rgb_fg_color(key_widget->pixmap_gc, &new_bg); } else gdk_gc_set_rgb_fg_color(key_widget->pixmap_gc, key->active ? &color_keys_on : &color_keys); gdk_draw_rectangle(key_widget->pixmap, key_widget->pixmap_gc, TRUE, x, y, w, h); /* Draw text */ log_ext.width = 0; icon_size = 0; if ((key->flags & KEY_ICON_MASK) && (!(key->flags & KEY_ICON_SHIFT) || is_shifted(key))) icon_size = h * 3 / 7; if (key->string[0]) { const char *string = key->string; if (is_shifted(key)) string = key->string_shift; layout = pango_layout_new(key_widget->pango); cairo_move_to(key_widget->cairo, x, y + h / 2); pango_layout_set_text(layout, string, -1); pango_layout_set_font_description(layout, key_widget->pango_font_desc); pango_layout_get_pixel_extents(layout, &ink_ext, &log_ext); cairo_rel_move_to(key_widget->cairo, w / 2 - log_ext.width / 2 + icon_size / 2 + 1, log_ext.height / -2 + (key->active ? 2 : 1)); /* Draw text shadow */ cairo_set_source_gdk_color(key_widget->cairo, &color_keys_dark, 1.); pango_cairo_show_layout(key_widget->cairo, layout); /* Draw the normal text */ cairo_rel_move_to(key_widget->cairo, -1, -1); cairo_set_source_gdk_color(key_widget->cairo, &color_text, 1.); pango_cairo_show_layout(key_widget->cairo, layout); g_object_unref(layout); } /* Render icon */ if (icon_size) { int icon_x, icon_y; icon_x = x + w / 2. - log_ext.width / 2. - icon_size / 2.; icon_y = y + h / 2. - icon_size / 2. + (key->active ? 1 : 0); render_icon(key_widget->cairo, icon_x + 1, icon_y + 1, icon_size, key->flags & KEY_ICON_MASK, key->rotate, &color_keys_dark); render_icon(key_widget->cairo, icon_x, icon_y, icon_size, key->flags & KEY_ICON_MASK, key->rotate, &color_text); } /* Render border */ if (!key->active) { cairo_new_path(key_widget->cairo); cairo_set_line_width(key_widget->cairo, 1.); /* Top border */ cairo_set_source_rgba(key_widget->cairo, 1., 1., 1., 0.5); cairo_move_to(key_widget->cairo, x + 0.5, y + 0.5); cairo_line_to(key_widget->cairo, x + w - 0.5, y + 0.5); cairo_stroke(key_widget->cairo); /* Left border */ pattern = cairo_pattern_create_linear(x, y, x, y + h); cairo_pattern_add_color_stop_rgba(pattern, 0., 1., 1., 1., 0.5); cairo_pattern_add_color_stop_rgba(pattern, 1., 1., 1., 1., 0.); cairo_set_source(key_widget->cairo, pattern); cairo_move_to(key_widget->cairo, x + 0.5, y + 0.5); cairo_line_to(key_widget->cairo, x + 0.5, y + h - 0.5); cairo_stroke(key_widget->cairo); cairo_pattern_destroy(pattern); /* Right border */ pattern = cairo_pattern_create_linear(x, y, x, y + h); cairo_pattern_add_color_stop_rgba(pattern, 0., 0., 0., 0., 0.); cairo_pattern_add_color_stop_rgba(pattern, 1., 0., 0., 0., 0.5); cairo_set_source(key_widget->cairo, pattern); cairo_move_to(key_widget->cairo, x + w - 0.5, y + 0.5); cairo_line_to(key_widget->cairo, x + w - 0.5, y + h - 0.5); cairo_stroke(key_widget->cairo); cairo_pattern_destroy(pattern); /* Bottom border */ cairo_set_source_rgba(key_widget->cairo, 0., 0., 0., 0.5); cairo_move_to(key_widget->cairo, x + 0.5, y + h - 0.5); cairo_line_to(key_widget->cairo, x + w - 0.5, y + h - 0.5); cairo_stroke(key_widget->cairo); } /* Mark key area as dirty */ if (dirty) gtk_widget_queue_draw_area(key_widget->drawing_area, x, y, w, h);}void key_widget_render(KeyWidget *key_widget){ int i; if (!key_widget->pixmap_gc || !key_widget->pixmap) return; /* Render background */ if (!key_widget->slaved) { gdk_gc_set_rgb_fg_color(key_widget->pixmap_gc, &color_bg); gdk_draw_rectangle(key_widget->pixmap, key_widget->pixmap_gc, TRUE, 0, 0, key_widget->drawing_area->allocation.width, key_widget->drawing_area->allocation.height); } /* Render keys */ for (i = 0; i < key_widget->len; i++) render_key(key_widget, i, FALSE); /* Dirty the drawing area if we aren't slaved */ if (!key_widget->slaved) gtk_widget_queue_draw(key_widget->drawing_area);}static Key *add_key(KeyWidget *key_widget, int keysym, const char *string, int x, int y, int width, int height)/* Adds a key to a key widget and resizes it if necessary */{ Key *key; if (key_widget->len >= key_widget->max_len) { g_warning("Not enough room on keyboard for key '%s'", string); return NULL; } key = key_widget->keys + key_widget->len++; key->keysym = keysym; key->string = !string ? XKeysymToString(keysym) : string; key->x = x; key->y = y; key->width = width; key->height = height; if (key->x + key->width > key_widget->x_range) key_widget->x_range = key->x + key->width; if (key->y + key->height > key_widget->y_range) key_widget->y_range = key->y + key->height; if (key->height < key_widget->min_height || !key_widget->min_height) key_widget->min_height = key->height; return key;}static void set_flags(Key *key, int flags, int rotate){ if (!key) return; key->flags = flags; key->rotate = rotate;}static void set_shifted(Key *key, unsigned int keysym, const char *string){ if (!key) return; key->keysym_shift = keysym; key->string_shift = !string ? XKeysymToString(keysym) : string; key->flags |= KEY_SHIFTABLE;}int key_widget_update_colors(void){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -