/* =================== Key_Event Called by the system between frames for both key up and key down events Should NOT be called during an interrupt! =================== */ void Key_Event(unsigned key, qboolean down, unsigned time) { char *kb; char cmd[MAX_STRING_CHARS]; if (key >= 256) { Com_Error(ERR_FATAL, "%s: bad key", __func__); } Com_DDDPrintf("%u: %c%s\n", time, down ? '+' : '-', Key_KeynumToString(key)); // hack for menu key binding if (key_wait_cb && down && !key_wait_cb(key_wait_arg, key)) { return; } // update key down and auto-repeat status if (down) { if (keydown[key] < 255) keydown[key]++; } else { keydown[key] = 0; } // console key is hardcoded, so the user can never unbind it if (!Key_IsDown(K_SHIFT) && (key == '`' || key == '~')) { if (keydown[key] == 1) { Con_ToggleConsole_f(); } return; } // Alt+Enter is hardcoded for all systems if (Key_IsDown(K_ALT) && key == K_ENTER) { if (keydown[key] == 1) { VID_ToggleFullscreen(); } return; } // menu key is hardcoded, so the user can never unbind it if (key == K_ESCAPE) { if (!down) { return; } if (cls.key_dest == KEY_GAME && cl.frame.ps.stats[STAT_LAYOUTS] && cls.demo.playback == qfalse) { if (keydown[key] == 2) { // force main menu if escape is held UI_OpenMenu(UIMENU_GAME); } else if (keydown[key] == 1) { // put away help computer / inventory CL_ClientCommand("putaway"); } return; } // ignore autorepeats if (keydown[key] > 1) { return; } if (cls.key_dest & KEY_CONSOLE) { if (cls.state < ca_active && !(cls.key_dest & KEY_MENU)) { UI_OpenMenu(UIMENU_MAIN); } else { Con_Close(qtrue); } } else if (cls.key_dest & KEY_MENU) { UI_Keydown(key); } else if (cls.key_dest & KEY_MESSAGE) { Key_Message(key); } else if (cls.state == ca_active) { UI_OpenMenu(UIMENU_GAME); } else { UI_OpenMenu(UIMENU_MAIN); } return; } // track if any key is down for BUTTON_ANY if (down) { if (keydown[key] == 1) anykeydown++; } else { anykeydown--; if (anykeydown < 0) anykeydown = 0; } // hack for demo freelook in windowed mode if (cls.key_dest == KEY_GAME && cls.demo.playback && key == K_SHIFT && keydown[key] <= 1) { IN_Activate(); } // // if not a consolekey, send to the interpreter no matter what mode is // if ((cls.key_dest == KEY_GAME) || ((cls.key_dest & KEY_CONSOLE) && !Q_IsBitSet(consolekeys, key)) || ((cls.key_dest & KEY_MENU) && (key >= K_F1 && key <= K_F12)) || (!down && Q_IsBitSet(buttondown, key))) { // // Key up events only generate commands if the game key binding is a button // command (leading + sign). These will occur even in console mode, to keep the // character from continuing an action started before a console switch. Button // commands include the kenum as a parameter, so multiple downs can be matched // with ups. // if (!down) { kb = keybindings[key]; if (kb && kb[0] == '+') { Q_snprintf(cmd, sizeof(cmd), "-%s %i %i\n", kb + 1, key, time); Cbuf_AddText(&cmd_buffer, cmd); } Q_ClearBit(buttondown, key); return; } // ignore autorepeats if (keydown[key] > 1) { return; } // generate button up command when released Q_SetBit(buttondown, key); kb = keybindings[key]; if (kb) { if (kb[0] == '+') { // button commands add keynum and time as a parm Q_snprintf(cmd, sizeof(cmd), "%s %i %i\n", kb, key, time); Cbuf_AddText(&cmd_buffer, cmd); } else { Cbuf_AddText(&cmd_buffer, kb); Cbuf_AddText(&cmd_buffer, "\n"); } } return; } if (cls.key_dest == KEY_GAME) return; if (!down) return; // other subsystems only care about key down events if (cls.key_dest & KEY_CONSOLE) { Key_Console(key); } else if (cls.key_dest & KEY_MENU) { UI_Keydown(key); } else if (cls.key_dest & KEY_MESSAGE) { Key_Message(key); } if (Key_IsDown(K_CTRL) || Key_IsDown(K_ALT)) { return; } switch (key) { case K_KP_SLASH: key = '/'; break; case K_KP_MULTIPLY: key = '*'; break; case K_KP_MINUS: key = '-'; break; case K_KP_PLUS: key = '+'; break; case K_KP_HOME: key = '7'; break; case K_KP_UPARROW: key = '8'; break; case K_KP_PGUP: key = '9'; break; case K_KP_LEFTARROW: key = '4'; break; case K_KP_5: key = '5'; break; case K_KP_RIGHTARROW: key = '6'; break; case K_KP_END: key = '1'; break; case K_KP_DOWNARROW: key = '2'; break; case K_KP_PGDN: key = '3'; break; case K_KP_INS: key = '0'; break; case K_KP_DEL: key = '.'; break; } // if key is printable, generate char events if (key < 32 || key >= 127) { return; } if (Key_IsDown(K_SHIFT)) { key = keyshift[key]; } if (cls.key_dest & KEY_CONSOLE) { Char_Console(key); } else if (cls.key_dest & KEY_MENU) { UI_CharEvent(key); } else if (cls.key_dest & KEY_MESSAGE) { Char_Message(key); } }
// main window procedure STATIC LONG WINAPI Win_MainWndProc ( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ) { switch( uMsg ) { case WM_MOUSEWHEEL: if( win.mouse.initialized == WIN_MOUSE_LEGACY ) { mouse_wheel_event( ( short )HIWORD( wParam ) ); } break; case WM_MOUSEHWHEEL: if( win.mouse.initialized == WIN_MOUSE_LEGACY ) { mouse_hwheel_event( ( short )HIWORD( wParam ) ); } break; case WM_NCMOUSEMOVE: if( win.mouse.initialized ) { // don't hide cursor IN_MouseEvent( -1, -1 ); } break; case WM_MOUSEMOVE: if( win.mouse.initialized ) { int x = ( short )LOWORD( lParam ); int y = ( short )HIWORD( lParam ); IN_MouseEvent( x, y ); } // fall through case WM_LBUTTONDOWN: case WM_LBUTTONUP: case WM_RBUTTONDOWN: case WM_RBUTTONUP: case WM_MBUTTONDOWN: case WM_MBUTTONUP: case WM_XBUTTONDOWN: case WM_XBUTTONUP: if( win.mouse.initialized == WIN_MOUSE_LEGACY ) { legacy_mouse_event( wParam ); } break; case WM_HOTKEY: return FALSE; case WM_INPUT: if( wParam == RIM_INPUT && win.mouse.initialized == WIN_MOUSE_RAW ) { raw_input_event( ( HANDLE )lParam ); } break; case WM_CLOSE: PostQuitMessage( 0 ); return FALSE; case WM_ACTIVATE: Win_Activate( wParam ); break; case WM_WINDOWPOSCHANGING: if( !( win.flags & QVF_FULLSCREEN ) ) { WINDOWPOS *pos = ( WINDOWPOS * )lParam; if( !( pos->flags & SWP_NOSIZE ) ) { resizing_event( hWnd, pos ); } } break; case WM_SIZE: if( wParam == SIZE_RESTORED && !( win.flags & QVF_FULLSCREEN ) ) { int w = ( short )LOWORD( lParam ); int h = ( short )HIWORD( lParam ); win.rc.width = w; win.rc.height = h; win.mode_changed |= MODE_SIZE; } break; case WM_MOVE: if( !( win.flags & QVF_FULLSCREEN ) ) { int x = ( short )LOWORD( lParam ); int y = ( short )HIWORD( lParam ); RECT r; // adjust for non-client area get_nc_area_size( hWnd, &r ); win.rc.x = x + r.left; win.rc.y = y + r.top; win.mode_changed |= MODE_POS; } break; case WM_SYSCOMMAND: switch( wParam & 0xFFF0 ) { case SC_SCREENSAVE: return FALSE; case SC_MAXIMIZE: if( !vid_fullscreen->integer ) { VID_ToggleFullscreen(); } return FALSE; } break; case WM_KEYDOWN: case WM_SYSKEYDOWN: legacy_key_event( wParam, lParam, qtrue ); return FALSE; case WM_KEYUP: case WM_SYSKEYUP: legacy_key_event( wParam, lParam, qfalse ); return FALSE; case WM_SYSCHAR: case WM_CHAR: #if USE_CHAR_EVENTS Key_CharEvent( wParam ); #endif return FALSE; default: break; } // pass all unhandled messages to DefWindowProc return DefWindowProc( hWnd, uMsg, wParam, lParam ); }
/* ================ VID_MenuKey ================ */ static void VID_MenuKey (int key) { switch (key) { case K_ESCAPE: vid_cursor = (num_fmodes) ? 0 : VID_RESOLUTION; M_Menu_Options_f (); return; case K_ENTER: switch (vid_cursor) { case VID_RESET: vid_menu_fs = (modestate != MS_WINDOWED); vid_menunum = vid_modenum; vid_cursor = (num_fmodes) ? 0 : VID_RESOLUTION; break; case VID_APPLY: if (need_apply) { Cvar_SetValue("vid_mode", vid_menunum); Cvar_SetValue("vid_config_fscr", vid_menu_fs); VID_Restart_f(); } vid_cursor = (num_fmodes) ? 0 : VID_RESOLUTION; break; } return; case K_LEFTARROW: switch (vid_cursor) { case VID_FULLSCREEN: vid_menu_fs = !vid_menu_fs; if (fs_toggle_works) VID_ToggleFullscreen(); break; case VID_RESOLUTION: S_LocalSound ("raven/menu1.wav"); vid_menunum--; if (vid_menunum < 0) vid_menunum = 0; break; } return; case K_RIGHTARROW: switch (vid_cursor) { case VID_FULLSCREEN: vid_menu_fs = !vid_menu_fs; if (fs_toggle_works) VID_ToggleFullscreen(); break; case VID_RESOLUTION: S_LocalSound ("raven/menu1.wav"); vid_menunum++; if (vid_menunum >= *nummodes) vid_menunum = *nummodes - 1; break; } return; case K_UPARROW: S_LocalSound ("raven/menu1.wav"); vid_cursor--; if (vid_cursor < 0) { vid_cursor = (need_apply) ? VID_ITEMS-1 : VID_BLANKLINE-1; } else if (vid_cursor == VID_BLANKLINE) { vid_cursor--; } break; case K_DOWNARROW: S_LocalSound ("raven/menu1.wav"); vid_cursor++; if (vid_cursor >= VID_ITEMS) { vid_cursor = (num_fmodes) ? 0 : VID_RESOLUTION; break; } if (vid_cursor >= VID_BLANKLINE) { if (need_apply) { if (vid_cursor == VID_BLANKLINE) vid_cursor++; } else { vid_cursor = (num_fmodes) ? 0 : VID_RESOLUTION; } } break; default: return; } }
void IN_SendKeyEvents (void) { SDL_Event event; int sym, state; int modstate; while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_ACTIVEEVENT: if (event.active.state & (SDL_APPINPUTFOCUS|SDL_APPACTIVE)) { if (event.active.gain) { // Sys_Printf("FOCUS GAIN\n"); S_UnblockSound(); } else { // Sys_Printf("FOCUS LOSS\n"); S_BlockSound(); } } break; case SDL_KEYDOWN: if ((event.key.keysym.sym == SDLK_RETURN) && (event.key.keysym.mod & KMOD_ALT)) { VID_ToggleFullscreen(); break; } else if ((event.key.keysym.sym == SDLK_ESCAPE) && (event.key.keysym.mod & KMOD_SHIFT)) { Con_ToggleConsole_f(); break; } else if ((event.key.keysym.sym == SDLK_g) && (event.key.keysym.mod & KMOD_CTRL)) { SDL_WM_GrabInput( (SDL_WM_GrabInput (SDL_GRAB_QUERY) == SDL_GRAB_ON) ? SDL_GRAB_OFF : SDL_GRAB_ON ); break; } case SDL_KEYUP: sym = event.key.keysym.sym; state = event.key.state; modstate = SDL_GetModState(); switch (key_dest) { case key_game: if ((event.key.keysym.unicode != 0) || (modstate & KMOD_SHIFT)) { /* only use unicode for ~ and ` in game mode */ if ((event.key.keysym.unicode & 0xFF80) == 0) { if (((event.key.keysym.unicode & 0x7F) == '`') || ((event.key.keysym.unicode & 0x7F) == '~') ) sym = event.key.keysym.unicode & 0x7F; } } break; case key_message: case key_console: if ((event.key.keysym.unicode != 0) || (modstate & KMOD_SHIFT)) { #if defined(__QNX__) if ((sym == SDLK_BACKSPACE) || (sym == SDLK_RETURN)) break; // S.A: fixes QNX weirdness #endif /* __QNX__ */ if ((event.key.keysym.unicode & 0xFF80) == 0) sym = event.key.keysym.unicode & 0x7F; /* else: it's an international character */ } // printf("You pressed %s (%d) (%c)\n", SDL_GetKeyName(sym), sym, sym); break; default: break; } switch (sym) { case SDLK_DELETE: sym = K_DEL; break; case SDLK_BACKSPACE: sym = K_BACKSPACE; break; case SDLK_F1: sym = K_F1; break; case SDLK_F2: sym = K_F2; break; case SDLK_F3: sym = K_F3; break; case SDLK_F4: sym = K_F4; break; case SDLK_F5: sym = K_F5; break; case SDLK_F6: sym = K_F6; break; case SDLK_F7: sym = K_F7; break; case SDLK_F8: sym = K_F8; break; case SDLK_F9: sym = K_F9; break; case SDLK_F10: sym = K_F10; break; case SDLK_F11: sym = K_F11; break; case SDLK_F12: sym = K_F12; break; case SDLK_BREAK: case SDLK_PAUSE: sym = K_PAUSE; break; case SDLK_UP: sym = K_UPARROW; break; case SDLK_DOWN: sym = K_DOWNARROW; break; case SDLK_RIGHT: sym = K_RIGHTARROW; break; case SDLK_LEFT: sym = K_LEFTARROW; break; case SDLK_INSERT: sym = K_INS; break; case SDLK_HOME: sym = K_HOME; break; case SDLK_END: sym = K_END; break; case SDLK_PAGEUP: sym = K_PGUP; break; case SDLK_PAGEDOWN: sym = K_PGDN; break; case SDLK_RSHIFT: case SDLK_LSHIFT: sym = K_SHIFT; break; case SDLK_RCTRL: case SDLK_LCTRL: sym = K_CTRL; break; case SDLK_RALT: case SDLK_LALT: sym = K_ALT; break; case SDLK_KP0: if (modstate & KMOD_NUM) sym = K_INS; else sym = SDLK_0; break; case SDLK_KP1: if (modstate & KMOD_NUM) sym = K_END; else sym = SDLK_1; break; case SDLK_KP2: if (modstate & KMOD_NUM) sym = K_DOWNARROW; else sym = SDLK_2; break; case SDLK_KP3: if (modstate & KMOD_NUM) sym = K_PGDN; else sym = SDLK_3; break; case SDLK_KP4: if (modstate & KMOD_NUM) sym = K_LEFTARROW; else sym = SDLK_4; break; case SDLK_KP5: sym = SDLK_5; break; case SDLK_KP6: if (modstate & KMOD_NUM) sym = K_RIGHTARROW; else sym = SDLK_6; break; case SDLK_KP7: if (modstate & KMOD_NUM) sym = K_HOME; else sym = SDLK_7; break; case SDLK_KP8: if (modstate & KMOD_NUM) sym = K_UPARROW; else sym = SDLK_8; break; case SDLK_KP9: if (modstate & KMOD_NUM) sym = K_PGUP; else sym = SDLK_9; break; case SDLK_KP_PERIOD: if (modstate & KMOD_NUM) sym = K_DEL; else sym = SDLK_PERIOD; break; case SDLK_KP_DIVIDE: sym = SDLK_SLASH; break; case SDLK_KP_MULTIPLY: sym = SDLK_ASTERISK; break; case SDLK_KP_MINUS: sym = SDLK_MINUS; break; case SDLK_KP_PLUS: sym = SDLK_PLUS; break; case SDLK_KP_ENTER: sym = SDLK_RETURN; break; case SDLK_KP_EQUALS: sym = SDLK_EQUALS; break; case 178: /* the '²' key */ sym = '~'; break; } // If we're not directly handled and still // above 255, just force it to 0 if (sym > 255) sym = 0; Key_Event (sym, state); break; case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: if (!mouseactive || in_mode_set) break; if (event.button.button < 1 || event.button.button > sizeof(buttonremap) / sizeof(buttonremap[0])) { Con_Printf ("Ignored event for mouse button %d\n", event.button.button); break; } Key_Event(buttonremap[event.button.button - 1], event.button.state == SDL_PRESSED); break; case SDL_MOUSEMOTION: // SDL_GetMouseState (NULL, NULL); break; #if USE_JOYSTICK case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONUP: if (!in_joystick.value) break; if (event.jbutton.button > K_AUX32 - K_JOY1) { Con_Printf ("Ignored event for joystick button %d\n", event.jbutton.button); break; } Key_Event(K_JOY1 + event.jbutton.button, event.jbutton.state == SDL_PRESSED); break; case SDL_JOYAXISMOTION: case SDL_JOYHATMOTION: case SDL_JOYBALLMOTION: /* to be coded.. */ break; #endif /* USE_JOYSTICK */ case SDL_QUIT: CL_Disconnect (); Sys_Quit (); break; default: break; } } }