void SDLash_InputEvent(SDL_TextInputEvent input) { int i; // Pass characters one by one to Con_CharEvent for(i = 0; input.text[i]; ++i) { Con_CharEvent( (int)input.text[i] ); if( cls.key_dest == key_menu ) UI_CharEvent ( (int)input.text[i] ); } }
/* =================== CL_CharEvent Normal keyboard characters, already shifted / capslocked / etc =================== */ void CL_CharEvent( int key ) { // the console key should never be used as a char if( key == '`' || key == '~' ) return; if( cls.key_dest == key_console && !Con_Visible( )) { if((char)key == '¸' || (char)key == '¨' ) return; // don't pass '¸' when we open the console } // distribute the key down event to the apropriate handler if( cls.key_dest == key_console || cls.key_dest == key_message ) { Con_CharEvent( key ); } else if( cls.key_dest == key_menu ) { UI_CharEvent( key ); } }
/* =================== 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); } }
/* ======================== Android_RunEvents Execute all events from queue ======================== */ void Android_RunEvents() { int i; // enter events read Android_Lock(); pthread_mutex_unlock( &events.framemutex ); for( i = 0; i < events.count; i++ ) { switch( events.queue[i].type ) { case event_touch_down: case event_touch_up: case event_touch_move: IN_TouchEvent( events.queue[i].type, events.queue[i].arg, events.queue[i].touch.x, events.queue[i].touch.y, events.queue[i].touch.dx, events.queue[i].touch.dy ); break; case event_key_down: Key_Event( events.queue[i].arg, true ); break; case event_key_up: Key_Event( events.queue[i].arg, false ); break; case event_set_pause: // destroy EGL surface when hiding application if( !events.queue[i].arg ) { host.state = HOST_FRAME; S_Activate( true ); (*jni.env)->CallStaticVoidMethod( jni.env, jni.actcls, jni.toggleEGL, 1 ); Android_UpdateSurface(); Android_SwapInterval( Cvar_VariableInteger( "gl_swapinterval" ) ); } if( events.queue[i].arg ) { host.state = HOST_NOFOCUS; S_Activate( false ); (*jni.env)->CallStaticVoidMethod( jni.env, jni.actcls, jni.toggleEGL, 0 ); negl.valid = false; } break; case event_resize: // reinitialize EGL and change engine screen size if( host.state == HOST_NORMAL && ( scr_width->integer != jni.width || scr_height->integer != jni.height ) ) { (*jni.env)->CallStaticVoidMethod( jni.env, jni.actcls, jni.toggleEGL, 0 ); (*jni.env)->CallStaticVoidMethod( jni.env, jni.actcls, jni.toggleEGL, 1 ); Android_UpdateSurface(); Android_SwapInterval( Cvar_VariableInteger( "gl_swapinterval" ) ); VID_SetMode(); } break; case event_joyadd: Joy_AddEvent( events.queue[i].arg ); break; case event_joyremove: Joy_RemoveEvent( events.queue[i].arg ); break; case event_joyball: Joy_BallMotionEvent( events.queue[i].arg, events.queue[i].ball.ball, events.queue[i].ball.xrel, events.queue[i].ball.yrel ); break; case event_joyhat: Joy_HatMotionEvent( events.queue[i].arg, events.queue[i].hat.hat, events.queue[i].hat.key ); break; case event_joyaxis: Joy_AxisMotionEvent( events.queue[i].arg, events.queue[i].axis.axis, events.queue[i].axis.val ); break; case event_joybutton: Joy_ButtonEvent( events.queue[i].arg, events.queue[i].button.button, (byte)events.queue[i].button.down ); break; } } events.count = 0; // no more events // text input handled separately to allow unicode symbols for( i = 0; events.inputtext[i]; i++ ) { int ch; // if engine does not use utf-8, we need to convert it to preferred encoding if( !Q_stricmp( cl_charset->string, "utf-8" ) ) ch = (unsigned char)events.inputtext[i]; else ch = Con_UtfProcessCharForce( (unsigned char)events.inputtext[i] ); if( !ch ) continue; // otherwise just push it by char, text render will decode unicode strings Con_CharEvent( ch ); if( cls.key_dest == key_menu ) UI_CharEvent ( ch ); } events.inputtext[0] = 0; // no more text //end events read Android_Unlock(); pthread_mutex_lock( &events.framemutex ); }