?? keyevent.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 "common.h"#include "keys.h"#include <string.h>#include <stdlib.h>#include <X11/X.h>#include <X11/Xlib.h>#include <X11/keysym.h>#include <X11/extensions/XTest.h>#include <gdk/gdkx.h>/* Define this to always overwrite an unused KeyCode to send any KeySym *//* #define ALWAYS_OVERWRITE *//* Define this to print key events without actually generating them *//* #define DEBUG_KEY_EVENTS *//* X11 KeyCodes*/enum { KEY_TAKEN = 0, /* Has KeySyms, cannot be overwritten */ KEY_BAD, /* Manually marked as unusable */ KEY_USABLE, /* Has no KeySyms, can be overwritten */ KEY_ALLOCATED, /* Normally usable, but currently allocated */ /* Values greater than this represent multiple allocations */};static char usable[256], pressed[256];static int key_min, key_max, key_offset, key_codes;static KeySym *keysyms = NULL;static XModifierKeymap *modmap = NULL;/* Bad keycodes: Despite having no KeySym entries, certain KeyCodes will generate special KeySyms even if their KeySym entries have been overwritten. For instance, KeyCode 204 attempts to eject the CD-ROM even if there is no CD-ROM device present! KeyCode 229 will launch GNOME file search even if there is no search button on the physical keyboard. There is no programatic way around this but to keep a list of commonly used "bad" KeyCodes. */void bad_keycodes_read(void){ int keycode; while (!profile_sync_int(&keycode)) { if (keycode < key_min || keycode > key_max) { g_warning("Cannot block bad keycode %d, out of range", keycode); continue; } usable[keycode] = KEY_BAD; }}void bad_keycodes_write(void){ int i; profile_write("bad_keycodes"); for (i = key_min; i < key_max; i++) if (usable[i] == KEY_BAD) profile_write(va(" %d", i)); profile_write("\n");}#ifdef DEBUG_KEY_EVENTSstatic void press_keycode(KeyCode k)/* Just logs the key-down event */{ g_debug("KeyCode %d down", k);}static void release_keycode(KeyCode k)/* Just logs the key-up event */{ g_debug("KeyCode %d up", k);}#elsestatic void press_keycode(KeyCode k)/* Called from various places to generate a key-down event */{ if (k >= key_min && k <= key_max) XTestFakeKeyEvent(GDK_DISPLAY(), k, True, 1);}static void release_keycode(KeyCode k)/* Called from various places to generate a key-up event */{ if (k >= key_min && k <= key_max) XTestFakeKeyEvent(GDK_DISPLAY(), k, False, 1);}#endifstatic void type_keycode(KeyCode k)/* Key-down + key-up */{ press_keycode(k); release_keycode(k);}static void setup_usable(void)/* Find unused slots in the key mapping */{ int i, found; /* Find all free keys */ memset(usable, 0, sizeof (usable)); for (i = key_min, found = 0; i <= key_max; i++) { int j; for (j = 0; j < key_codes && keysyms[(i - key_min) * key_codes + j] == NoSymbol; j++); if (j < key_codes) { usable[i] = KEY_TAKEN; continue; } usable[i] = KEY_USABLE; found++; } key_offset = 0; /* If we haven't found a usable key, it's probably because we have already ran once and used them all up without setting them back */ if (!found) { usable[key_max - key_min - 1] = KEY_USABLE; g_warning("Found no usable KeyCodes, restart the X server!"); } else g_debug("Found %d usable KeyCodes", found);}static void cleanup_usable(void)/* Clear all the usable KeyCodes or we won't have any when we run again! */{ int i, bad, unused = 0, freed; for (i = 0, freed = 0, bad = 0; i <= key_max; i++) if (usable[i] >= KEY_USABLE) { int j, kc_used = FALSE; for (j = 0; j < key_codes; j++) { int index = (i - key_min) * key_codes + j; if (keysyms[index] != NoSymbol) kc_used = TRUE; keysyms[index] = NoSymbol; } if (kc_used) freed++; else unused++; } else if (usable[i] == KEY_BAD) bad++; if (freed) { XChangeKeyboardMapping(GDK_DISPLAY(), key_min, key_codes, keysyms, key_max - key_min + 1); XFlush(GDK_DISPLAY()); } g_debug("Free'd %d KeyCode(s), %d unused, %d marked bad", freed, unused, bad);}static void release_held_keys(void)/* Release all held keys that were not pressed by us */{ int i; char keys[32]; XQueryKeymap(GDK_DISPLAY(), keys); for (i = 0; i < 32; i++) { int j; for (j = 0; j < 8; j++) { KeyCode keycode; keycode = i * 8 + j; if (keys[i] & (1 << j) && !pressed[keycode]) { g_debug("Released held KeyCode %d", keycode); release_keycode(keycode); } } }}/* Key Events*/int key_overwrites = 0, key_recycles = 0, key_shifted = 0, key_num_locked = FALSE, key_caps_locked = FALSE, key_disable_overwrite = FALSE;static int alt_mask, num_lock_mask, meta_mask;static KeyEvent ke_shift, ke_enter, ke_num_lock, ke_caps_lock;static void reset_keyboard(void)/* In order to reliably predict key event behavior we need to be able to reset the keyboard modifier and pressed state */{ Window root, child; int root_x, root_y, win_x, win_y; unsigned int mask; release_held_keys(); XQueryPointer(GDK_DISPLAY(), GDK_WINDOW_XWINDOW(GDK_ROOT_PARENT()), &root, &child, &root_x, &root_y, &win_x, &win_y, &mask); if (mask & LockMask) type_keycode(ke_caps_lock.keycode); if (mask & num_lock_mask) type_keycode(ke_num_lock.keycode);}static int is_modifier(unsigned int keysym)/* Returns TRUE for KeySyms that are tracked internally */{ switch (keysym) { case XK_Shift_L: case XK_Shift_R: case XK_Num_Lock: case XK_Caps_Lock: return TRUE; default: return FALSE; }}static void key_event_allocate(KeyEvent *key_event, unsigned int keysym)/* Either finds the KeyCode associated with the given keysym or overwrites a usable one to generate it */{ int i, start; /* Invalid KeySym */ if (!keysym) { key_event->keycode = -1; key_event->keysym = 0; return;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -