Rewrite of key event processing, thanks to /dev/humancontroller and Ben Millwood. https://bugzilla.icculus.org/show_bug.cgi?id=3374

This commit is contained in:
Thilo Schulz 2009-10-03 23:35:07 +00:00
parent 3a952ff196
commit dd572db7d6

View file

@ -1118,94 +1118,72 @@ void CL_InitKeyCommands( void ) {
/* /*
=================== ===================
CL_AddKeyUpCommands CL_ParseBinding
Execute the commands in the bind string
=================== ===================
*/ */
void CL_AddKeyUpCommands( int key, char *kb, unsigned time) { void CL_ParseBinding( int key, qboolean down, unsigned time )
int i; {
char button[1024], *buttonPtr; char buf[ MAX_STRING_CHARS ], *p = buf, *end;
char cmd[1024];
qboolean keyevent;
if ( !kb ) { if( !keys[key].binding || !keys[key].binding[0] )
return; return;
Q_strncpyz( buf, keys[key].binding, sizeof( buf ) );
while( 1 )
{
while( isspace( *p ) )
p++;
end = strchr( p, ';' );
if( end )
*end = '\0';
if( *p == '+' )
{
// button commands add keynum and time as parameters
// so that multiple sources can be discriminated and
// subframe corrected
char cmd[1024];
Com_sprintf( cmd, sizeof( cmd ), "%c%s %d %d\n",
( down ) ? '+' : '-', p + 1, key, time );
Cbuf_AddText( cmd );
} }
keyevent = qfalse; else if( down )
buttonPtr = button; {
for ( i = 0; ; i++ ) { // normal commands only execute on key press
if ( kb[i] == ';' || !kb[i] ) { Cbuf_AddText( p );
*buttonPtr = '\0'; Cbuf_AddText( "\n" );
if ( button[0] == '+') {
// button commands add keynum and time as parms so that multiple
// sources can be discriminated and subframe corrected
Com_sprintf (cmd, sizeof(cmd), "-%s %i %i\n", button+1, key, time);
Cbuf_AddText (cmd);
keyevent = qtrue;
} else {
if (keyevent) {
// down-only command
Cbuf_AddText (button);
Cbuf_AddText ("\n");
} }
} if( !end )
buttonPtr = button;
while ( (kb[i] <= ' ' || kb[i] == ';') && kb[i] != 0 ) {
i++;
}
}
*buttonPtr++ = kb[i];
if ( !kb[i] ) {
break; break;
} p = end + 1;
} }
} }
/* /*
=================== ===================
CL_KeyEvent CL_KeyDownEvent
Called by the system for both key up and key down events Called by CL_KeyEvent to handle a keypress
=================== ===================
*/ */
void CL_KeyEvent (int key, qboolean down, unsigned time) { void CL_KeyDownEvent( int key, unsigned time )
char *kb; {
char cmd[1024]; keys[key].down = qtrue;
// update auto-repeat status and BUTTON_ANY status
keys[key].down = down;
if (down) {
keys[key].repeats++; keys[key].repeats++;
if ( keys[key].repeats == 1) { if( keys[key].repeats == 1 )
anykeydown++; anykeydown++;
}
} else {
keys[key].repeats = 0;
anykeydown--;
if (anykeydown < 0) {
anykeydown = 0;
}
}
if (key == K_ENTER) if( keys[K_ALT].down && key == K_ENTER )
{
if (down)
{
if (keys[K_ALT].down)
{ {
Cvar_SetValue( "r_fullscreen", Cvar_SetValue( "r_fullscreen",
!Cvar_VariableIntegerValue( "r_fullscreen" ) ); !Cvar_VariableIntegerValue( "r_fullscreen" ) );
return; return;
} }
}
}
// console key is hardcoded, so the user can never unbind it // console key is hardcoded, so the user can never unbind it
if (key == K_CONSOLE || if( key == K_CONSOLE || ( keys[K_SHIFT].down && key == K_ESCAPE ) )
( key == K_ESCAPE && keys[K_SHIFT].down ) ) { {
if (!down) {
return;
}
Con_ToggleConsole_f (); Con_ToggleConsole_f ();
Key_ClearStates (); Key_ClearStates ();
return; return;
@ -1213,7 +1191,7 @@ void CL_KeyEvent (int key, qboolean down, unsigned time) {
// keys can still be used for bound actions // keys can still be used for bound actions
if ( down && ( key < 128 || key == K_MOUSE1 ) && if ( ( key < 128 || key == K_MOUSE1 ) &&
( clc.demoplaying || cls.state == CA_CINEMATIC ) && Key_GetCatcher( ) == 0 ) { ( clc.demoplaying || cls.state == CA_CINEMATIC ) && Key_GetCatcher( ) == 0 ) {
if (Cvar_VariableValue ("com_cameraMode") == 0) { if (Cvar_VariableValue ("com_cameraMode") == 0) {
@ -1222,9 +1200,8 @@ void CL_KeyEvent (int key, qboolean down, unsigned time) {
} }
} }
// escape is always handled special // escape is always handled special
if ( key == K_ESCAPE && down ) { if ( key == K_ESCAPE ) {
if ( Key_GetCatcher( ) & KEYCATCH_MESSAGE ) { if ( Key_GetCatcher( ) & KEYCATCH_MESSAGE ) {
// clear message mode // clear message mode
Message_Key( key ); Message_Key( key );
@ -1250,43 +1227,20 @@ void CL_KeyEvent (int key, qboolean down, unsigned time) {
return; return;
} }
VM_Call( uivm, UI_KEY_EVENT, key, down ); VM_Call( uivm, UI_KEY_EVENT, key, qtrue );
return; return;
} }
//
// key up events only perform actions if the game key binding is
// a button command (leading + sign). These will be processed even in
// console mode and menu mode, to keep the character from continuing
// an action started before a mode switch.
//
if (!down ) {
if ( cls.state != CA_DISCONNECTED ) {
kb = keys[key].binding;
CL_AddKeyUpCommands( key, kb, time );
}
if ( Key_GetCatcher( ) & KEYCATCH_UI && uivm ) {
VM_Call( uivm, UI_KEY_EVENT, key, down );
} else if ( Key_GetCatcher( ) & KEYCATCH_CGAME && cgvm ) {
VM_Call( cgvm, CG_KEY_EVENT, key, down );
}
return;
}
// distribute the key down event to the apropriate handler // distribute the key down event to the apropriate handler
if ( Key_GetCatcher( ) & KEYCATCH_CONSOLE ) { if ( Key_GetCatcher( ) & KEYCATCH_CONSOLE ) {
Console_Key( key ); Console_Key( key );
} else if ( Key_GetCatcher( ) & KEYCATCH_UI ) { } else if ( Key_GetCatcher( ) & KEYCATCH_UI ) {
if ( uivm ) { if ( uivm ) {
VM_Call( uivm, UI_KEY_EVENT, key, down ); VM_Call( uivm, UI_KEY_EVENT, key, qtrue );
} }
} else if ( Key_GetCatcher( ) & KEYCATCH_CGAME ) { } else if ( Key_GetCatcher( ) & KEYCATCH_CGAME ) {
if ( cgvm ) { if ( cgvm ) {
VM_Call( cgvm, CG_KEY_EVENT, key, down ); VM_Call( cgvm, CG_KEY_EVENT, key, qtrue );
} }
} else if ( Key_GetCatcher( ) & KEYCATCH_MESSAGE ) { } else if ( Key_GetCatcher( ) & KEYCATCH_MESSAGE ) {
Message_Key( key ); Message_Key( key );
@ -1294,47 +1248,60 @@ void CL_KeyEvent (int key, qboolean down, unsigned time) {
Console_Key( key ); Console_Key( key );
} else { } else {
// send the bound action // send the bound action
kb = keys[key].binding; CL_ParseBinding( key, qtrue, time );
if ( !kb ) {
if (key >= 200) {
Com_Printf ("%s is unbound, use controls menu to set.\n"
, Key_KeynumToString( key ) );
} }
} else if (kb[0] == '+') { return;
int i; }
char button[1024], *buttonPtr;
buttonPtr = button; /*
for ( i = 0; ; i++ ) { ===================
if ( kb[i] == ';' || !kb[i] ) { CL_KeyUpEvent
*buttonPtr = '\0';
if ( button[0] == '+') { Called by CL_KeyEvent to handle a keyrelease
// button commands add keynum and time as parms so that multiple ===================
// sources can be discriminated and subframe corrected */
Com_sprintf (cmd, sizeof(cmd), "%s %i %i\n", button, key, time); void CL_KeyUpEvent( int key, unsigned time )
Cbuf_AddText (cmd); {
} else { keys[key].repeats = 0;
// down-only command keys[key].down = qfalse;
Cbuf_AddText (button); anykeydown--;
Cbuf_AddText ("\n"); if (anykeydown < 0) {
} anykeydown = 0;
buttonPtr = button;
while ( (kb[i] <= ' ' || kb[i] == ';') && kb[i] != 0 ) {
i++;
}
}
*buttonPtr++ = kb[i];
if ( !kb[i] ) {
break;
}
}
} else {
// down-only command
Cbuf_AddText (kb);
Cbuf_AddText ("\n");
} }
// don't process key-up events for the console key
if ( key == K_CONSOLE || ( key == K_ESCAPE && keys[K_SHIFT].down ) )
return;
//
// key up events only perform actions if the game key binding is
// a button command (leading + sign). These will be processed even in
// console mode and menu mode, to keep the character from continuing
// an action started before a mode switch.
//
if( cls.state != CA_DISCONNECTED )
CL_ParseBinding( key, qfalse, time );
if ( Key_GetCatcher( ) & KEYCATCH_UI && uivm ) {
VM_Call( uivm, UI_KEY_EVENT, key, qfalse );
} else if ( Key_GetCatcher( ) & KEYCATCH_CGAME && cgvm ) {
VM_Call( cgvm, CG_KEY_EVENT, key, qfalse );
} }
} }
/*
===================
CL_KeyEvent
Called by the system for both key up and key down events
===================
*/
void CL_KeyEvent (int key, qboolean down, unsigned time) {
if( down )
CL_KeyDownEvent( key, time );
else
CL_KeyUpEvent( key, time );
}
/* /*
=================== ===================