?? window.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 "keys.h"#include <memory.h>#include <X11/Xatom.h>#include <X11/Xlib.h>#include <gdk/gdkx.h>/* options.c */void options_dialog_open(void);/* recognize.c */void update_enabled_samples(void);/* cellwidget.c */extern int training, cell_width, cell_height, cell_cols_pref;GtkWidget *cell_widget_new(void);void cell_widget_clear(void);void cell_widget_render(void);int cell_widget_insert(void);void cell_widget_train(void);void cell_widget_pack(void);int cell_widget_update_colors(void);void cell_widget_show_buffer(GtkWidget *button);int cell_widget_scrollbar_width(void);int cell_widget_get_height(void);/* statusicon.c */int status_icon_create(void);int status_icon_embedded(void);/* main.c */extern int keyboard_only;/* keywidget.c */void key_widget_resize(KeyWidget *key_widget);/* Main window*/GtkWidget *window;GtkTooltips *tooltips;int window_force_x = -1, window_force_y = -1, training_block = 0, window_docked = WINDOW_UNDOCKED, window_force_docked = -1, window_button_labels = TRUE, window_force_show = FALSE, window_force_hide = FALSE, style_colors = TRUE, window_embedded = FALSE, window_struts = FALSE;/* Tab XPM image */static char *tab_xpm[] ={ "7 4 2 1", " c None", ". c #000000", ".......", " ..... ", " ... ", " . "};static KeyWidget *key_widget;static GtkWidget *train_label_box, *train_label_frame, *train_label = NULL, *bottom_box, *blocks_combo, *cell_widget, *setup_button, *keys_button, *insert_button, *clear_button, *train_button, *buffer_button;static GdkRectangle window_frame = {-1, -1, 0, 0}, window_frame_saved;static int screen_width = -1, screen_height = -1, window_shown = TRUE, history_valid = FALSE, keys_on = FALSE;static void toggle_button_labels(int on){ static int labels_off; if (labels_off && on) { gtk_button_set_label(GTK_BUTTON(train_button), "Train"); gtk_button_set_label(GTK_BUTTON(setup_button), "Setup"); gtk_button_set_label(GTK_BUTTON(clear_button), "Clear"); gtk_button_set_label(GTK_BUTTON(insert_button), "Insert"); gtk_button_set_label(GTK_BUTTON(keys_button), "Keys"); } else if (!labels_off && !on) { gtk_button_set_label(GTK_BUTTON(train_button), ""); gtk_button_set_label(GTK_BUTTON(setup_button), ""); gtk_button_set_label(GTK_BUTTON(keys_button), ""); gtk_button_set_label(GTK_BUTTON(clear_button), ""); gtk_button_set_label(GTK_BUTTON(insert_button), ""); gtk_button_set_label(GTK_BUTTON(keys_button), ""); } labels_off = !on;}void window_pack(void){ cell_widget_pack(); toggle_button_labels(window_button_labels); if (training) gtk_widget_show(train_label_frame); key_widget_resize(key_widget);}void window_update_colors(void){ int keys_changed; keys_changed = key_widget_update_colors(); if (cell_widget_update_colors() || keys_changed) cell_widget_render(); if (keys_changed) key_widget_render(key_widget);}static void update_struts(void)/* Reserves screen space for the docked window. FIXME In Metacity it causes the window to be shoved outside of its own struts, which is especially devastating for top docking because this causes an infinite loop of events causing the struts to repeatedly scan down from the top of the screen. GOK and other applications somehow get around this but I can't figure out how. */{ static guint32 struts[12]; guint32 new2 = 0, new3 = 0, new9 = 0, new11 = 0; GdkAtom atom_strut, atom_strut_partial, cardinal; if (!window || !window->window || !window_struts) return; if (window_docked == WINDOW_DOCKED_TOP) { new2 = window_frame.y + window_frame.height; new9 = window_frame.width; } else if (window_docked == WINDOW_DOCKED_BOTTOM) { new3 = window_frame.height; new11 = window_frame.width; } if (new2 == struts[2] && new3 == struts[3] && new9 == struts[9] && new11 == struts[11]) return; trace("top=%d (%d) bottom=%d (%d)", new2, new9, new3, new11); struts[2] = new2; struts[3] = new3; struts[9] = new9; struts[11] = new11; atom_strut = gdk_atom_intern("_NET_WM_STRUT", FALSE), atom_strut_partial = gdk_atom_intern("_NET_WM_STRUT_PARTIAL", FALSE); cardinal = gdk_atom_intern("CARDINAL", FALSE); gdk_property_change(GDK_WINDOW(window->window), atom_strut, cardinal, 32, GDK_PROP_MODE_REPLACE, (guchar*)&struts, 4); gdk_property_change(GDK_WINDOW(window->window), atom_strut_partial, cardinal, 32, GDK_PROP_MODE_REPLACE, (guchar*)&struts, 12);}static void set_geometry_hints(void){ GdkGeometry geometry; geometry.min_width = -1; geometry.min_height = -1; geometry.max_width = -1; geometry.max_height = -1; /* Use window geometry to force the window to be as large as the screen */ if (window_docked) geometry.max_width = geometry.min_width = screen_width; gtk_window_set_geometry_hints(GTK_WINDOW(window), window, &geometry, GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE); trace("%dx%d", geometry.min_width, geometry.min_height); /* In some bright and sunny alternate universe when specifications are actually implemented as inteded, this function alone would cause the window frame to expand upwards without having to perform the ugly hack in window_configure(). XFWM4 does not respect this hint and setting this hint will further mess up the window_configure() movement code. */ /*geometry.win_gravity = window_docked == WINDOW_DOCKED_TOP ? GDK_GRAVITY_NORTH_WEST : GDK_GRAVITY_SOUTH_WEST; gtk_window_set_geometry_hints(GTK_WINDOW(window), window, &geometry, GDK_HINT_WIN_GRAVITY);*/}static void docked_move_resize(void){ GdkScreen *screen; int y = 0; if (!window_docked) return; screen = gtk_window_get_screen(GTK_WINDOW(window)); if (window_docked == WINDOW_DOCKED_BOTTOM) y = gdk_screen_get_height(screen) - window_frame.height; set_geometry_hints(); gtk_window_move(GTK_WINDOW(window), 0, y); cell_widget_pack(); key_widget_resize(key_widget); trace("y=%d", y);}static gboolean window_configure(GtkWidget *widget, GdkEventConfigure *event)/* Intelligently grow the window up and/or left if we are in the bottom or right corners of the screen respectively */{ GdkRectangle new_frame = {0, 0, 0, 0}; GdkScreen *screen; GdkDisplay *display; int screen_w, screen_h, height_change, label_w; if (!window || !window->window) return FALSE; display = gtk_widget_get_display(window); /* Get screen and window information */ screen = gtk_window_get_screen(GTK_WINDOW(window)); screen_w = gdk_screen_get_width(screen); screen_h = gdk_screen_get_height(screen); gdk_window_get_frame_extents(window->window, &new_frame); /* We need to resize wrapped labels manually */ label_w = window->allocation.width - 16; if (train_label && train_label->requisition.width != label_w) gtk_widget_set_size_request(train_label, label_w, -1); /* Docked windows have special placing requirements */ height_change = new_frame.height - window_frame.height; if (window_docked) { window_frame = new_frame; if (screen_w != screen_width || screen_h != screen_height || (height_change && window_docked == WINDOW_DOCKED_BOTTOM)) { screen_width = screen_w; screen_height = screen_h; trace("move-sizing bottom-docked window"); docked_move_resize(); } update_struts(); return FALSE; } screen_width = screen_w; screen_height = screen_h; /* Do nothing on the first configure */ if (window_frame.height <= 1) { window_frame = new_frame; return FALSE; } /* Keep the window aligned to the bottom border */ if (height_change && window_frame.y + window_frame.height / 2 > gdk_screen_get_height(screen) / 2) window_frame.y -= height_change; else height_change = 0; /* Do not allow the window to go off-screen */ if (window_frame.x + new_frame.width > screen_w) window_frame.x = screen_w - new_frame.width; if (window_frame.y + new_frame.height > screen_h) window_frame.y = screen_h - new_frame.height; if (window_frame.x < 0) window_frame.x = 0; if (window_frame.y < 0) window_frame.y = 0; /* Some window managers (Metacity) do not allow windows to resize larger than the screen and will move the window back within the screen bounds when this happens. We don't like this because it screws with our own correcting offset. Fortunately, both the move and the resize are bundled in one configure event so we can work around this by using our old x/y coordinates when the dimensions change. */ if (height_change && (new_frame.x != window_frame.x || new_frame.y != window_frame.y)) { gtk_window_move(GTK_WINDOW(window), window_frame.x, window_frame.y); window_frame.width = new_frame.width; window_frame.height = new_frame.height; trace("moving to (%d, %d)", window_frame.x, window_frame.y); } else window_frame = new_frame; return FALSE;}void window_set_docked(int mode){ if (mode < WINDOW_UNDOCKED) mode = WINDOW_UNDOCKED; if (mode >= WINDOW_DOCKED_BOTTOM) mode = WINDOW_DOCKED_BOTTOM; if (mode && !window_docked) window_frame_saved = window_frame; window_docked = mode; gtk_window_set_decorated(GTK_WINDOW(window), !mode); set_geometry_hints(); cell_widget_pack(); key_widget_resize(key_widget); /* Restore the old window position */ if (!mode) { update_struts(); window_frame = window_frame_saved; gtk_window_move(GTK_WINDOW(window), window_frame.x, window_frame.y); trace("moving to (%d, %d)", window_frame.x, window_frame.y); } /* Move the window into docked position */ else docked_move_resize();}void train_button_toggled(void){ if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(train_button))) { cell_widget_train(); gtk_widget_hide(clear_button); gtk_widget_hide(keys_button); gtk_widget_hide(insert_button); gtk_widget_hide(buffer_button);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -