📄 sdl_x11events.c
字号:
if ( SDL_VideoSurface->flags & SDL_FULLSCREEN ) {
if ( go_fullscreen ) {
X11_EnterFullScreen(this);
} else {
X11_LeaveFullScreen(this);
}
}
/* Handle focus in/out when grabbed */
if ( go_fullscreen ) {
X11_GrabInputNoLock(this, this->input_grab);
} else {
X11_GrabInputNoLock(this, SDL_GRAB_OFF);
}
X11_CheckMouseModeNoLock(this);
}
}
}
void X11_InitKeymap(void)
{
int i;
/* Odd keys used in international keyboards */
for ( i=0; i<SDL_TABLESIZE(ODD_keymap); ++i )
ODD_keymap[i] = SDLK_UNKNOWN;
#ifdef XK_dead_circumflex
/* These X keysyms have 0xFE as the high byte */
ODD_keymap[XK_dead_circumflex&0xFF] = SDLK_CARET;
#endif
/* Map the miscellaneous keys */
for ( i=0; i<SDL_TABLESIZE(MISC_keymap); ++i )
MISC_keymap[i] = SDLK_UNKNOWN;
/* These X keysyms have 0xFF as the high byte */
MISC_keymap[XK_BackSpace&0xFF] = SDLK_BACKSPACE;
MISC_keymap[XK_Tab&0xFF] = SDLK_TAB;
MISC_keymap[XK_Clear&0xFF] = SDLK_CLEAR;
MISC_keymap[XK_Return&0xFF] = SDLK_RETURN;
MISC_keymap[XK_Pause&0xFF] = SDLK_PAUSE;
MISC_keymap[XK_Escape&0xFF] = SDLK_ESCAPE;
MISC_keymap[XK_Delete&0xFF] = SDLK_DELETE;
MISC_keymap[XK_KP_0&0xFF] = SDLK_KP0; /* Keypad 0-9 */
MISC_keymap[XK_KP_1&0xFF] = SDLK_KP1;
MISC_keymap[XK_KP_2&0xFF] = SDLK_KP2;
MISC_keymap[XK_KP_3&0xFF] = SDLK_KP3;
MISC_keymap[XK_KP_4&0xFF] = SDLK_KP4;
MISC_keymap[XK_KP_5&0xFF] = SDLK_KP5;
MISC_keymap[XK_KP_6&0xFF] = SDLK_KP6;
MISC_keymap[XK_KP_7&0xFF] = SDLK_KP7;
MISC_keymap[XK_KP_8&0xFF] = SDLK_KP8;
MISC_keymap[XK_KP_9&0xFF] = SDLK_KP9;
MISC_keymap[XK_KP_Insert&0xFF] = SDLK_KP0;
MISC_keymap[XK_KP_End&0xFF] = SDLK_KP1;
MISC_keymap[XK_KP_Down&0xFF] = SDLK_KP2;
MISC_keymap[XK_KP_Page_Down&0xFF] = SDLK_KP3;
MISC_keymap[XK_KP_Left&0xFF] = SDLK_KP4;
MISC_keymap[XK_KP_Begin&0xFF] = SDLK_KP5;
MISC_keymap[XK_KP_Right&0xFF] = SDLK_KP6;
MISC_keymap[XK_KP_Home&0xFF] = SDLK_KP7;
MISC_keymap[XK_KP_Up&0xFF] = SDLK_KP8;
MISC_keymap[XK_KP_Page_Up&0xFF] = SDLK_KP9;
MISC_keymap[XK_KP_Delete&0xFF] = SDLK_KP_PERIOD;
MISC_keymap[XK_KP_Decimal&0xFF] = SDLK_KP_PERIOD;
MISC_keymap[XK_KP_Divide&0xFF] = SDLK_KP_DIVIDE;
MISC_keymap[XK_KP_Multiply&0xFF] = SDLK_KP_MULTIPLY;
MISC_keymap[XK_KP_Subtract&0xFF] = SDLK_KP_MINUS;
MISC_keymap[XK_KP_Add&0xFF] = SDLK_KP_PLUS;
MISC_keymap[XK_KP_Enter&0xFF] = SDLK_KP_ENTER;
MISC_keymap[XK_KP_Equal&0xFF] = SDLK_KP_EQUALS;
MISC_keymap[XK_Up&0xFF] = SDLK_UP;
MISC_keymap[XK_Down&0xFF] = SDLK_DOWN;
MISC_keymap[XK_Right&0xFF] = SDLK_RIGHT;
MISC_keymap[XK_Left&0xFF] = SDLK_LEFT;
MISC_keymap[XK_Insert&0xFF] = SDLK_INSERT;
MISC_keymap[XK_Home&0xFF] = SDLK_HOME;
MISC_keymap[XK_End&0xFF] = SDLK_END;
MISC_keymap[XK_Page_Up&0xFF] = SDLK_PAGEUP;
MISC_keymap[XK_Page_Down&0xFF] = SDLK_PAGEDOWN;
MISC_keymap[XK_F1&0xFF] = SDLK_F1;
MISC_keymap[XK_F2&0xFF] = SDLK_F2;
MISC_keymap[XK_F3&0xFF] = SDLK_F3;
MISC_keymap[XK_F4&0xFF] = SDLK_F4;
MISC_keymap[XK_F5&0xFF] = SDLK_F5;
MISC_keymap[XK_F6&0xFF] = SDLK_F6;
MISC_keymap[XK_F7&0xFF] = SDLK_F7;
MISC_keymap[XK_F8&0xFF] = SDLK_F8;
MISC_keymap[XK_F9&0xFF] = SDLK_F9;
MISC_keymap[XK_F10&0xFF] = SDLK_F10;
MISC_keymap[XK_F11&0xFF] = SDLK_F11;
MISC_keymap[XK_F12&0xFF] = SDLK_F12;
MISC_keymap[XK_F13&0xFF] = SDLK_F13;
MISC_keymap[XK_F14&0xFF] = SDLK_F14;
MISC_keymap[XK_F15&0xFF] = SDLK_F15;
MISC_keymap[XK_Num_Lock&0xFF] = SDLK_NUMLOCK;
MISC_keymap[XK_Caps_Lock&0xFF] = SDLK_CAPSLOCK;
MISC_keymap[XK_Scroll_Lock&0xFF] = SDLK_SCROLLOCK;
MISC_keymap[XK_Shift_R&0xFF] = SDLK_RSHIFT;
MISC_keymap[XK_Shift_L&0xFF] = SDLK_LSHIFT;
MISC_keymap[XK_Control_R&0xFF] = SDLK_RCTRL;
MISC_keymap[XK_Control_L&0xFF] = SDLK_LCTRL;
MISC_keymap[XK_Alt_R&0xFF] = SDLK_RALT;
MISC_keymap[XK_Alt_L&0xFF] = SDLK_LALT;
MISC_keymap[XK_Meta_R&0xFF] = SDLK_RMETA;
MISC_keymap[XK_Meta_L&0xFF] = SDLK_LMETA;
MISC_keymap[XK_Super_L&0xFF] = SDLK_LSUPER; /* Left "Windows" */
MISC_keymap[XK_Super_R&0xFF] = SDLK_RSUPER; /* Right "Windows */
MISC_keymap[XK_Mode_switch&0xFF] = SDLK_MODE; /* "Alt Gr" key */
MISC_keymap[XK_Multi_key&0xFF] = SDLK_COMPOSE; /* Multi-key compose */
MISC_keymap[XK_Help&0xFF] = SDLK_HELP;
MISC_keymap[XK_Print&0xFF] = SDLK_PRINT;
MISC_keymap[XK_Sys_Req&0xFF] = SDLK_SYSREQ;
MISC_keymap[XK_Break&0xFF] = SDLK_BREAK;
MISC_keymap[XK_Menu&0xFF] = SDLK_MENU;
MISC_keymap[XK_Hyper_R&0xFF] = SDLK_MENU; /* Windows "Menu" key */
}
SDL_keysym *X11_TranslateKey(Display *display, XKeyEvent *xkey, KeyCode kc,
SDL_keysym *keysym)
{
KeySym xsym;
/* Get the raw keyboard scancode */
keysym->scancode = kc;
xsym = XKeycodeToKeysym(display, kc, 0);
#ifdef DEBUG_KEYS
fprintf(stderr, "Translating key 0x%.4x (%d)\n", xsym, kc);
#endif
/* Get the translated SDL virtual keysym */
keysym->sym = SDLK_UNKNOWN;
if ( xsym ) {
switch (xsym>>8) {
case 0x1005FF:
#ifdef SunXK_F36
if ( xsym == SunXK_F36 )
keysym->sym = SDLK_F11;
#endif
#ifdef SunXK_F37
if ( xsym == SunXK_F37 )
keysym->sym = SDLK_F12;
#endif
break;
case 0x00: /* Latin 1 */
case 0x01: /* Latin 2 */
case 0x02: /* Latin 3 */
case 0x03: /* Latin 4 */
case 0x04: /* Katakana */
case 0x05: /* Arabic */
case 0x06: /* Cyrillic */
case 0x07: /* Greek */
case 0x08: /* Technical */
case 0x0A: /* Publishing */
case 0x0C: /* Hebrew */
case 0x0D: /* Thai */
keysym->sym = (SDLKey)(xsym&0xFF);
/* Map capital letter syms to lowercase */
if ((keysym->sym >= 'A')&&(keysym->sym <= 'Z'))
keysym->sym += ('a'-'A');
break;
case 0xFE:
keysym->sym = ODD_keymap[xsym&0xFF];
break;
case 0xFF:
keysym->sym = MISC_keymap[xsym&0xFF];
break;
default:
fprintf(stderr,
"X11: Unknown xsym, sym = 0x%04x\n",
(unsigned int)xsym);
break;
}
} else {
/* X11 doesn't know how to translate the key! */
switch (kc) {
/* Caution:
These keycodes are from the Microsoft Keyboard
*/
case 115:
keysym->sym = SDLK_LSUPER;
break;
case 116:
keysym->sym = SDLK_RSUPER;
break;
case 117:
keysym->sym = SDLK_MENU;
break;
default:
/*
* no point in an error message; happens for
* several keys when we get a keymap notify
*/
break;
}
}
keysym->mod = KMOD_NONE;
/* If UNICODE is on, get the UNICODE value for the key */
keysym->unicode = 0;
if ( SDL_TranslateUNICODE && xkey ) {
static XComposeStatus state;
/* Until we handle the IM protocol, use XLookupString() */
unsigned char keybuf[32];
#define BROKEN_XFREE86_INTERNATIONAL_KBD
/* This appears to be a magical flag that is used with AltGr on
international keyboards to signal alternate key translations.
The flag doesn't show up when in fullscreen mode (?)
FIXME: Check to see if this code is safe for other servers.
*/
#ifdef BROKEN_XFREE86_INTERNATIONAL_KBD
/* Work around what appears to be a bug in XFree86 */
if ( SDL_GetModState() & KMOD_MODE ) {
xkey->state |= (1<<13);
}
#endif
/* Look up the translated value for the key event */
if ( XLookupString(xkey, (char *)keybuf, sizeof(keybuf),
NULL, &state) ) {
/*
* FIXME,: XLookupString() may yield more than one
* character, so we need a mechanism to allow for
* this (perhaps generate null keypress events with
* a unicode value)
*/
keysym->unicode = keybuf[0];
}
}
return(keysym);
}
/* X11 modifier masks for various keys */
static unsigned meta_l_mask, meta_r_mask, alt_l_mask, alt_r_mask;
static unsigned num_mask, mode_switch_mask;
static void get_modifier_masks(Display *display)
{
static unsigned got_masks;
int i, j;
XModifierKeymap *xmods;
unsigned n;
if(got_masks)
return;
xmods = XGetModifierMapping(display);
n = xmods->max_keypermod;
for(i = 3; i < 8; i++) {
for(j = 0; j < n; j++) {
KeyCode kc = xmods->modifiermap[i * n + j];
KeySym ks = XKeycodeToKeysym(display, kc, 0);
unsigned mask = 1 << i;
switch(ks) {
case XK_Num_Lock:
num_mask = mask; break;
case XK_Alt_L:
alt_l_mask = mask; break;
case XK_Alt_R:
alt_r_mask = mask; break;
case XK_Meta_L:
meta_l_mask = mask; break;
case XK_Meta_R:
meta_r_mask = mask; break;
case XK_Mode_switch:
mode_switch_mask = mask; break;
}
}
}
XFreeModifiermap(xmods);
got_masks = 1;
}
/*
* This function is semi-official; it is not officially exported and should
* not be considered part of the SDL API, but may be used by client code
* that *really* needs it (including legacy code).
* It is slow, though, and should be avoided if possible.
*
* Note that it isn't completely accurate either; in particular, multi-key
* sequences (dead accents, compose key sequences) will not work since the
* state has been irrevocably lost.
*/
Uint16 X11_KeyToUnicode(SDLKey keysym, SDLMod modifiers)
{
struct SDL_VideoDevice *this = current_video;
char keybuf[32];
int i;
KeySym xsym = 0;
XKeyEvent xkey;
Uint16 unicode;
if ( !this || !SDL_Display ) {
return 0;
}
memset(&xkey, 0, sizeof(xkey));
xkey.display = SDL_Display;
xsym = keysym; /* last resort if not found */
for (i = 0; i < 256; ++i) {
if ( MISC_keymap[i] == keysym ) {
xsym = 0xFF00 | i;
break;
} else if ( ODD_keymap[i] == keysym ) {
xsym = 0xFE00 | i;
break;
}
}
xkey.keycode = XKeysymToKeycode(xkey.display, xsym);
get_modifier_masks(SDL_Display);
if(modifiers & KMOD_SHIFT)
xkey.state |= ShiftMask;
if(modifiers & KMOD_CAPS)
xkey.state |= LockMask;
if(modifiers & KMOD_CTRL)
xkey.state |= ControlMask;
if(modifiers & KMOD_MODE)
xkey.state |= mode_switch_mask;
if(modifiers & KMOD_LALT)
xkey.state |= alt_l_mask;
if(modifiers & KMOD_RALT)
xkey.state |= alt_r_mask;
if(modifiers & KMOD_LMETA)
xkey.state |= meta_l_mask;
if(modifiers & KMOD_RMETA)
xkey.state |= meta_r_mask;
if(modifiers & KMOD_NUM)
xkey.state |= num_mask;
unicode = 0;
if ( XLookupString(&xkey, keybuf, sizeof(keybuf), NULL, NULL) )
unicode = (unsigned char)keybuf[0];
return(unicode);
}
/*
* Called when focus is regained, to read the keyboard state and generate
* synthetic keypress/release events.
* key_vec is a bit vector of keycodes (256 bits)
*/
void X11_SetKeyboardState(Display *display, const char *key_vec)
{
char keys_return[32];
int i, gen_event;
KeyCode xcode[SDLK_LAST];
Uint8 new_kstate[SDLK_LAST];
Uint8 *kstate = SDL_GetKeyState(NULL);
SDLMod modstate;
Window junk_window;
int x, y;
unsigned int mask;
/* The first time the window is mapped, we initialize key state */
if ( ! key_vec ) {
key_vec = keys_return;
XQueryKeymap(display, keys_return);
gen_event = 0;
} else {
#if 1 /* We no longer generate key down events, just update state */
gen_event = 0;
#else
gen_event = 1;
#endif
}
/* Get the keyboard modifier state */
modstate = 0;
get_modifier_masks(display);
if ( XQueryPointer(display, DefaultRootWindow(display),
&junk_window, &junk_window, &x, &y, &x, &y, &mask) ) {
if ( mask & LockMask ) {
modstate |= KMOD_CAPS;
}
if ( mask & mode_switch_mask ) {
modstate |= KMOD_MODE;
}
if ( mask & num_mask ) {
modstate |= KMOD_NUM;
}
}
/* Zero the new keyboard state and generate it */
memset(new_kstate, SDL_RELEASED, sizeof(new_kstate));
/*
* An obvious optimisation is to check entire longwords at a time in
* both loops, but we can't be sure the arrays are aligned so it's not
* worth the extra complexity
*/
for(i = 0; i < 32; i++) {
int j;
if(!key_vec[i])
continue;
for(j = 0; j < 8; j++) {
if(key_vec[i] & (1 << j)) {
SDL_keysym sk;
KeyCode kc = i << 3 | j;
X11_TranslateKey(display, NULL, kc, &sk);
new_kstate[sk.sym] = SDL_PRESSED;
xcode[sk.sym] = kc;
}
}
}
for(i = SDLK_FIRST+1; i < SDLK_LAST; i++) {
int state = new_kstate[i];
if ( state == SDL_PRESSED ) {
switch (i) {
case SDLK_LSHIFT:
modstate |= KMOD_LSHIFT;
break;
case SDLK_RSHIFT:
modstate |= KMOD_RSHIFT;
break;
case SDLK_LCTRL:
modstate |= KMOD_LCTRL;
break;
case SDLK_RCTRL:
modstate |= KMOD_RCTRL;
break;
case SDLK_LALT:
modstate |= KMOD_LALT;
break;
case SDLK_RALT:
modstate |= KMOD_RALT;
break;
case SDLK_LMETA:
modstate |= KMOD_LMETA;
break;
case SDLK_RMETA:
modstate |= KMOD_RMETA;
break;
default:
break;
}
}
if ( kstate[i] == state )
continue;
/*
* Send a fake keyboard event correcting the difference between
* SDL's keyboard state and the actual. Note that there is no
* way to find out the scancode for key releases, but since all
* keys are released when focus is lost only keypresses should
* be sent here
*/
if ( gen_event ) {
SDL_keysym sk;
memset(&sk, 0, sizeof(sk));
sk.sym = i;
sk.scancode = xcode[i]; /* only valid for key press */
SDL_PrivateKeyboard(state, &sk);
} else {
kstate[i] = state;
}
}
/* Hack - set toggle key state */
if ( modstate & KMOD_CAPS ) {
kstate[SDLK_CAPSLOCK] = SDL_PRESSED;
} else {
kstate[SDLK_CAPSLOCK] = SDL_RELEASED;
}
if ( modstate & KMOD_NUM ) {
kstate[SDLK_NUMLOCK] = SDL_PRESSED;
} else {
kstate[SDLK_NUMLOCK] = SDL_RELEASED;
}
/* Set the final modifier state */
SDL_SetModState(modstate);
}
void X11_InitOSKeymap(_THIS)
{
X11_InitKeymap();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -