📄 keywidget.c
字号:
GdkColor old_keys, old_text; old_keys = color_keys; old_text = color_text; color_keys = custom_key_color; color_text.red = 255 * COLOR_SCALE; color_text.green = 255 * COLOR_SCALE; color_text.blue = 255 * COLOR_SCALE; color_bg = window->style->bg[0]; if (style_colors) { color_keys = window->style->dark[3]; color_text = window->style->fg[3]; } shade_gdk_color(&color_keys, &color_keys_dark, 0.67); shade_gdk_color(&color_keys, &color_keys_on, 0.75); return !gdk_colors_equal(&old_keys, &color_keys) || !gdk_colors_equal(&old_text, &color_text);}void key_widget_configure(KeyWidget *key_widget, int x, int y, int width, int height){ key_widget->x = x; key_widget->y = y; key_widget->width = width; key_widget->height = height; key_widget_update_colors(); pango_font_description_set_absolute_size(key_widget->pango_font_desc, PANGO_SCALE * key_widget->height * key_widget->min_height / key_widget->y_range / 2);}/* Widget*/int keyboard_size = 640;static void style_set(GtkWidget *w, GtkStyle *previous_style, KeyWidget *key_widget){ if (key_widget_update_colors() && key_widget) key_widget_render(key_widget);}void key_widget_resize(KeyWidget *key_widget){ int width, height; if (keyboard_size < KEYBOARD_SIZE_MIN) keyboard_size = KEYBOARD_SIZE_MIN; if (window_embedded) { width = key_widget->drawing_area->allocation.width; height = key_widget->drawing_area->allocation.height; } else if (window_docked) { GdkScreen *screen; screen = gdk_screen_get_default(); width = gdk_screen_get_width(screen); height = width / 4; } else { width = keyboard_size; height = keyboard_size / 4; } if (key_widget->width == width && key_widget->height == height) return; key_widget->width = width; key_widget->height = height; gtk_widget_set_size_request(key_widget->drawing_area, width, height);}static gboolean configure_event(GtkWidget *widget, GdkEventConfigure *event, KeyWidget *key_widget)/* Create a new backing pixmap of the appropriate size */{ PangoCairoFontMap *font_map; /* Backing pixmap */ if (key_widget->pixmap) { int old_width, old_height; /* Do not update if the size has not changed */ gdk_drawable_get_size(key_widget->pixmap, &old_width, &old_height); if (old_width == widget->allocation.width && old_height == widget->allocation.height) return TRUE; g_object_unref(key_widget->pixmap); } if (widget->allocation.width <= 1) return TRUE; trace("%dx%d", widget->allocation.width, widget->allocation.height); key_widget->pixmap = gdk_pixmap_new(widget->window, widget->allocation.width, widget->allocation.height, -1); /* GDK graphics context */ if (key_widget->pixmap_gc) g_object_unref(key_widget->pixmap_gc); key_widget->pixmap_gc = gdk_gc_new(GDK_DRAWABLE(key_widget->pixmap)); /* Cairo context */ if (key_widget->cairo) cairo_destroy(key_widget->cairo); key_widget->cairo = gdk_cairo_create(GDK_DRAWABLE(key_widget->pixmap)); /* Pango context */ if (key_widget->pango) g_object_unref(key_widget->pango); font_map = PANGO_CAIRO_FONT_MAP(pango_cairo_font_map_new()); key_widget->pango = pango_cairo_font_map_create_context(font_map); g_object_unref(font_map); /* Resize the widget */ if (window_docked || window_embedded) key_widget_resize(key_widget); /* Font size is determined by smallest key */ pango_font_description_set_absolute_size(key_widget->pango_font_desc, PANGO_SCALE * key_widget->height * key_widget->min_height / key_widget->y_range / 2); key_widget_update_colors(); key_widget_render(key_widget); return TRUE;}static gboolean expose_event(GtkWidget *widget, GdkEventExpose *event, KeyWidget *key_widget)/* Redraw the drawing area from the backing pixmap */{ if (!key_widget->pixmap) return FALSE; gdk_draw_drawable(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE(widget)], key_widget->pixmap, event->area.x, event->area.y, event->area.x, event->area.y, event->area.width, event->area.height); return FALSE;}static int which_key(KeyWidget *key_widget, int ex, int ey){ int i; for (i = 0; i < key_widget->len; i++) { Key *key = key_widget->keys + i; int x, y, w, h; key_coords(key_widget, key, &x, &y, &w, &h); if (ex >= x && ey >= y && ex < x + w && ey < y + h) return i; } return -1;}static void update_shifted(KeyWidget *key_widget){ int i; for (i = 0; i < key_widget->len; i++) if (key_widget->keys[i].flags & KEY_SHIFTABLE) render_key(key_widget, i, TRUE);}static void press_sticky_keys(KeyWidget *key_widget, int on)/* Find all active sticky keys and press or release their KeySyms */{ int i, old_shifted; old_shifted = key_shifted; for (i = 0; i < key_widget->len; i++) { Key *sticky_key = key_widget->keys + i; int keysym; if (!(sticky_key->flags & KEY_STICKY) || !sticky_key->active || ((sticky_key->flags & KEY_SHIFT) && on)) continue; keysym = sticky_key->keysym; if (is_shifted(sticky_key)) keysym = sticky_key->keysym_shift; if (!keysym) continue; if (on) { key_event_new(&sticky_key->key_event, keysym); key_event_press(&sticky_key->key_event); } else { key_event_release(&sticky_key->key_event); key_event_free(&sticky_key->key_event); sticky_key->active = FALSE; render_key(key_widget, i, TRUE); } } if (old_shifted != key_shifted) update_shifted(key_widget);}gboolean key_widget_button_press(GtkWidget *widget, GdkEventButton *event, KeyWidget *key_widget)/* Mouse button is pressed over drawing area */{ Key *key; int index, keysym, old_shifted; /* Don't process double clicks */ if (event->type != GDK_BUTTON_PRESS) return FALSE; /* Find the key */ index = which_key(key_widget, event->x, event->y); if (index < 0) return FALSE; key = key_widget->keys + index; /* Toggle activated state */ key->active = !key->active; if (key->active) key_widget->active = index; old_shifted = key_shifted; if (!(key->flags & KEY_STICKY) || (key->flags & KEY_SHIFT)) { /* Pressing a non-sticky key causes all sticky keys except shifts to send their keysyms */ if (!(key->flags & KEY_SHIFT)) press_sticky_keys(key_widget, TRUE); /* Prepare for sending key events */ key_event_update_mappings(); /* Press down the active key's keysym */ keysym = key->keysym; if (is_shifted(key)) keysym = key->keysym_shift; if (key->active) { key_event_new(&key->key_event, keysym); key_event_press(&key->key_event); } else { key_event_release(&key->key_event); key_event_free(&key->key_event); } } /* Keep track of shifted state */ if (old_shifted != key_shifted || (key->flags & KEY_CAPS_LOCK) || (key->flags & KEY_NUM_LOCK)) update_shifted(key_widget); render_key(key_widget, index, TRUE); return TRUE;}gboolean key_widget_button_release(GtkWidget *widget, GdkEventButton *event, KeyWidget *key_widget)/* Mouse button is released over drawing area */{ Key *key; int old_shifted; /* The last pressed key is the one we are releasing now */ if (key_widget->active < 0 || key_widget->active > key_widget->len) return FALSE; key = key_widget->keys + key_widget->active; if (key->flags & KEY_STICKY || !key->active) return TRUE; key->active = FALSE; /* Send the keysym released event */ old_shifted = key_shifted; key_event_release(&key->key_event); key_event_free(&key->key_event); /* Releasing a non-sticky key causes all sticky keys to be released */ press_sticky_keys(key_widget, FALSE); /* Keep track of shifted state */ if (old_shifted != key_shifted) update_shifted(key_widget); render_key(key_widget, key_widget->active, TRUE); key_widget->active = -1; return TRUE;}void key_widget_cleanup(KeyWidget *key_widget)/* Turn off any active keys */{ int i, old_shifted; if (!key_widget) return; old_shifted = key_shifted; for (i = 0; i < key_widget->len; i++) { Key *key; key = key_widget->keys + i; if (!key->active) continue; key->active = FALSE; key_event_release(&key->key_event); key_event_free(&key->key_event); render_key(key_widget, i, TRUE); g_debug("Released held key '%s'", key->string); } if (key_shifted != old_shifted) update_shifted(key_widget);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -