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 ) );
keyevent = qfalse;
buttonPtr = button; while( 1 )
for ( i = 0; ; i++ ) { {
if ( kb[i] == ';' || !kb[i] ) { while( isspace( *p ) )
*buttonPtr = '\0'; p++;
if ( button[0] == '+') { end = strchr( p, ';' );
// button commands add keynum and time as parms so that multiple if( end )
// sources can be discriminated and subframe corrected *end = '\0';
Com_sprintf (cmd, sizeof(cmd), "-%s %i %i\n", button+1, key, time); if( *p == '+' )
Cbuf_AddText (cmd); {
keyevent = qtrue; // button commands add keynum and time as parameters
} else { // so that multiple sources can be discriminated and
if (keyevent) { // subframe corrected
// down-only command char cmd[1024];
Cbuf_AddText (button); Com_sprintf( cmd, sizeof( cmd ), "%c%s %d %d\n",
Cbuf_AddText ("\n"); ( down ) ? '+' : '-', p + 1, key, time );
} Cbuf_AddText( cmd );
}
buttonPtr = button;
while ( (kb[i] <= ' ' || kb[i] == ';') && kb[i] != 0 ) {
i++;
}
} }
*buttonPtr++ = kb[i]; else if( down )
if ( !kb[i] ) { {
// normal commands only execute on key press
Cbuf_AddText( p );
Cbuf_AddText( "\n" );
}
if( !end )
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;
keys[key].repeats++;
if( keys[key].repeats == 1 )
anykeydown++;
// update auto-repeat status and BUTTON_ANY status if( keys[K_ALT].down && key == K_ENTER )
keys[key].down = down;
if (down) {
keys[key].repeats++;
if ( keys[key].repeats == 1) {
anykeydown++;
}
} else {
keys[key].repeats = 0;
anykeydown--;
if (anykeydown < 0) {
anykeydown = 0;
}
}
if (key == K_ENTER)
{ {
if (down) Cvar_SetValue( "r_fullscreen",
{ !Cvar_VariableIntegerValue( "r_fullscreen" ) );
if (keys[K_ALT].down) return;
{
Cvar_SetValue( "r_fullscreen",
!Cvar_VariableIntegerValue( "r_fullscreen" ) );
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) { return;
Com_Printf ("%s is unbound, use controls menu to set.\n" }
, Key_KeynumToString( key ) );
} /*
} else if (kb[0] == '+') { ===================
int i; CL_KeyUpEvent
char button[1024], *buttonPtr;
buttonPtr = button; Called by CL_KeyEvent to handle a keyrelease
for ( i = 0; ; i++ ) { ===================
if ( kb[i] == ';' || !kb[i] ) { */
*buttonPtr = '\0'; void CL_KeyUpEvent( int key, unsigned time )
if ( button[0] == '+') { {
// button commands add keynum and time as parms so that multiple keys[key].repeats = 0;
// sources can be discriminated and subframe corrected keys[key].down = qfalse;
Com_sprintf (cmd, sizeof(cmd), "%s %i %i\n", button, key, time); anykeydown--;
Cbuf_AddText (cmd); if (anykeydown < 0) {
} else { anykeydown = 0;
// down-only command }
Cbuf_AddText (button);
Cbuf_AddText ("\n"); // don't process key-up events for the console key
} if ( key == K_CONSOLE || ( key == K_ESCAPE && keys[K_SHIFT].down ) )
buttonPtr = button; return;
while ( (kb[i] <= ' ' || kb[i] == ';') && kb[i] != 0 ) {
i++; //
} // key up events only perform actions if the game key binding is
} // a button command (leading + sign). These will be processed even in
*buttonPtr++ = kb[i]; // console mode and menu mode, to keep the character from continuing
if ( !kb[i] ) { // an action started before a mode switch.
break; //
} if( cls.state != CA_DISCONNECTED )
} CL_ParseBinding( key, qfalse, time );
} else {
// down-only command if ( Key_GetCatcher( ) & KEYCATCH_UI && uivm ) {
Cbuf_AddText (kb); VM_Call( uivm, UI_KEY_EVENT, key, qfalse );
Cbuf_AddText ("\n"); } 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 );
}
/* /*
=================== ===================