summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cgame/cg_main.c4
-rw-r--r--src/client/cl_keys.c7
-rw-r--r--src/client/cl_main.c5
-rw-r--r--src/client/client.h3
-rw-r--r--src/client/keycodes.h3
-rw-r--r--src/qcommon/common.c103
-rw-r--r--src/sdl/sdl_input.c206
-rw-r--r--src/ui/ui_main.c36
-rw-r--r--src/ui/ui_public.h6
9 files changed, 290 insertions, 83 deletions
diff --git a/src/cgame/cg_main.c b/src/cgame/cg_main.c
index da38ebae..4abe55f1 100644
--- a/src/cgame/cg_main.c
+++ b/src/cgame/cg_main.c
@@ -77,9 +77,7 @@ intptr_t vmMain( int command, int arg0, int arg1, int arg2, int arg3,
return 0;
case CG_MOUSE_EVENT:
- cgDC.cursorx = cgs.cursorX;
- cgDC.cursory = cgs.cursorY;
- CG_MouseEvent( arg0, arg1 );
+ // cgame doesn't care where the cursor is
return 0;
case CG_EVENT_HANDLING:
diff --git a/src/client/cl_keys.c b/src/client/cl_keys.c
index 8b9dcf4d..ee075ce5 100644
--- a/src/client/cl_keys.c
+++ b/src/client/cl_keys.c
@@ -1124,7 +1124,7 @@ void CL_KeyEvent (int key, qboolean down, unsigned time) {
}
// console key is hardcoded, so the user can never unbind it
- if (key == '`' || key == '~' ||
+ if (key == K_CONSOLE ||
( key == K_ESCAPE && keys[K_SHIFT].down ) ) {
if (!down) {
return;
@@ -1259,11 +1259,6 @@ 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;
- }
-
// delete is not a printable character and is
// otherwise handled by Field_KeyDownEvent
if ( key == 127 ) {
diff --git a/src/client/cl_main.c b/src/client/cl_main.c
index 0bba97d0..f91c80b2 100644
--- a/src/client/cl_main.c
+++ b/src/client/cl_main.c
@@ -97,6 +97,8 @@ cvar_t *cl_lanForcePackets;
cvar_t *cl_guidServerUniq;
+cvar_t *cl_consoleKeys;
+
clientActive_t cl;
clientConnection_t clc;
clientStatic_t cls;
@@ -3016,6 +3018,9 @@ void CL_Init( void ) {
cl_guidServerUniq = Cvar_Get ("cl_guidServerUniq", "1", CVAR_ARCHIVE);
+ // 0x7e = ~ and 0x60 = `
+ cl_consoleKeys = Cvar_Get( "cl_consoleKeys", "0x7e 0x60", CVAR_ARCHIVE);
+
// userinfo
Cvar_Get ("name", Sys_GetCurrentUser( ), CVAR_USERINFO | CVAR_ARCHIVE );
diff --git a/src/client/client.h b/src/client/client.h
index d7f430cb..f19c6230 100644
--- a/src/client/client.h
+++ b/src/client/client.h
@@ -401,6 +401,8 @@ extern cvar_t *cl_inGameVideo;
extern cvar_t *cl_lanForcePackets;
extern cvar_t *cl_autoRecordDemo;
+extern cvar_t *cl_consoleKeys;
+
#ifdef USE_MUMBLE
extern cvar_t *cl_useMumble;
extern cvar_t *cl_mumbleScale;
@@ -489,6 +491,7 @@ void IN_CenterView (void);
void CL_VerifyCode( void );
float CL_KeyState (kbutton_t *key);
+int Key_StringToKeynum( char *str );
char *Key_KeynumToString (int keynum);
//
diff --git a/src/client/keycodes.h b/src/client/keycodes.h
index ae6f189d..8911b0fc 100644
--- a/src/client/keycodes.h
+++ b/src/client/keycodes.h
@@ -262,6 +262,9 @@ typedef enum {
K_EURO,
K_UNDO,
+ // Pseudo-key that brings the console down
+ K_CONSOLE,
+
MAX_KEYS
} keyNum_t;
diff --git a/src/qcommon/common.c b/src/qcommon/common.c
index f16234c2..7c98d45e 100644
--- a/src/qcommon/common.c
+++ b/src/qcommon/common.c
@@ -2983,37 +2983,52 @@ static char *Field_FindFirstSeparator( char *s )
return NULL;
}
-#ifndef DEDICATED
/*
===============
-Field_CompleteKeyname
+Field_Complete
===============
*/
-static void Field_CompleteKeyname( void )
+static qboolean Field_Complete( void )
{
- matchCount = 0;
- shortestMatch[ 0 ] = 0;
-
- Key_KeynameCompletion( FindMatches );
+ int completionOffset;
if( matchCount == 0 )
- return;
+ return qfalse;
+
+ completionOffset = strlen( completionField->buffer ) - strlen( completionString );
+
+ Q_strncpyz( &completionField->buffer[ completionOffset ], shortestMatch,
+ sizeof( completionField->buffer ) - completionOffset );
- Q_strncpyz( &completionField->buffer[ strlen( completionField->buffer ) -
- strlen( completionString ) ], shortestMatch,
- sizeof( completionField->buffer ) );
completionField->cursor = strlen( completionField->buffer );
if( matchCount == 1 )
{
Q_strcat( completionField->buffer, sizeof( completionField->buffer ), " " );
completionField->cursor++;
- return;
+ return qtrue;
}
Com_Printf( "]%s\n", completionField->buffer );
-
- Key_KeynameCompletion( PrintMatches );
+
+ return qfalse;
+}
+
+#ifndef DEDICATED
+/*
+===============
+Field_CompleteKeyname
+===============
+*/
+static void Field_CompleteKeyname( void )
+{
+ matchCount = 0;
+ shortestMatch[ 0 ] = 0;
+
+ Key_KeynameCompletion( FindMatches );
+
+ if( !Field_Complete( ) )
+ Key_KeynameCompletion( PrintMatches );
}
#endif
@@ -3030,24 +3045,8 @@ static void Field_CompleteFilename( const char *dir,
FS_FilenameCompletion( dir, ext, stripExt, FindMatches );
- if( matchCount == 0 )
- return;
-
- Q_strncpyz( &completionField->buffer[ strlen( completionField->buffer ) -
- strlen( completionString ) ], shortestMatch,
- sizeof( completionField->buffer ) );
- completionField->cursor = strlen( completionField->buffer );
-
- if( matchCount == 1 )
- {
- Q_strcat( completionField->buffer, sizeof( completionField->buffer ), " " );
- completionField->cursor++;
- return;
- }
-
- Com_Printf( "]%s\n", completionField->buffer );
-
- FS_FilenameCompletion( dir, ext, stripExt, PrintMatches );
+ if( !Field_Complete( ) )
+ FS_FilenameCompletion( dir, ext, stripExt, PrintMatches );
}
/*
@@ -3185,13 +3184,19 @@ static void Field_CompleteCommand( char *cmd,
Field_CompleteCommand( p, qtrue, qtrue );
}
}
+ else if( !Q_stricmp( baseCmd, "unbind" ) && completionArgument == 2 )
+ {
+ // Skip "unbind "
+ p = Com_SkipTokens( cmd, 1, " " );
+
+ if( p > cmd )
+ Field_CompleteKeyname( );
+ }
#endif
}
}
else
{
- int completionOffset;
-
if( completionString[0] == '\\' || completionString[0] == '/' )
completionString++;
@@ -3207,31 +3212,15 @@ static void Field_CompleteCommand( char *cmd,
if( doCvars )
Cvar_CommandCompletion( FindMatches );
- if( matchCount == 0 )
- return; // no matches
-
- completionOffset = strlen( completionField->buffer ) - strlen( completionString );
-
- Q_strncpyz( &completionField->buffer[ completionOffset ], shortestMatch,
- sizeof( completionField->buffer ) - completionOffset );
-
- completionField->cursor = strlen( completionField->buffer );
-
- if( matchCount == 1 )
+ if( !Field_Complete( ) )
{
- Q_strcat( completionField->buffer, sizeof( completionField->buffer ), " " );
- completionField->cursor++;
- return;
- }
+ // run through again, printing matches
+ if( doCommands )
+ Cmd_CommandCompletion( PrintMatches );
- Com_Printf( "]%s\n", completionField->buffer );
-
- // run through again, printing matches
- if( doCommands )
- Cmd_CommandCompletion( PrintMatches );
-
- if( doCvars )
- Cvar_CommandCompletion( PrintCvarMatches );
+ if( doCvars )
+ Cvar_CommandCompletion( PrintCvarMatches );
+ }
}
}
diff --git a/src/sdl/sdl_input.c b/src/sdl/sdl_input.c
index c209f0a5..98f8525a 100644
--- a/src/sdl/sdl_input.c
+++ b/src/sdl/sdl_input.c
@@ -77,7 +77,7 @@ static cvar_t *in_joystickNo = NULL;
IN_PrintKey
===============
*/
-static void IN_PrintKey( const SDL_keysym *keysym, int key, qboolean down )
+static void IN_PrintKey( const SDL_keysym *keysym, keyNum_t key, qboolean down )
{
if( down )
Com_Printf( "+ " );
@@ -100,15 +100,108 @@ static void IN_PrintKey( const SDL_keysym *keysym, int key, qboolean down )
if( keysym->mod & KMOD_MODE ) Com_Printf( " KMOD_MODE" );
if( keysym->mod & KMOD_RESERVED ) Com_Printf( " KMOD_RESERVED" );
+ Com_Printf( " Q:%d(%s)", key, Key_KeynumToString( key ) );
+
if( keysym->unicode )
{
- Com_Printf( " %d", keysym->unicode );
+ Com_Printf( " U:%d", keysym->unicode );
if( keysym->unicode > ' ' && keysym->unicode < '~' )
Com_Printf( "(%c)", (char)keysym->unicode );
}
- Com_Printf( " %d(%s)\n", key, Key_KeynumToString( key ) );
+ Com_Printf( "\n" );
+}
+
+#define MAX_CONSOLE_KEYS 16
+
+/*
+===============
+IN_IsConsoleKey
+===============
+*/
+static qboolean IN_IsConsoleKey( keyNum_t key, const char character )
+{
+ typedef struct consoleKey_s
+ {
+ enum
+ {
+ KEY,
+ CHARACTER
+ } type;
+
+ union
+ {
+ keyNum_t key;
+ char character;
+ } u;
+ } consoleKey_t;
+
+ static consoleKey_t consoleKeys[ MAX_CONSOLE_KEYS ];
+ static int numConsoleKeys = 0;
+ int i;
+
+ // Only parse the variable when it changes
+ if( cl_consoleKeys->modified )
+ {
+ char *text_p, *token;
+
+ cl_consoleKeys->modified = qfalse;
+ text_p = cl_consoleKeys->string;
+ numConsoleKeys = 0;
+
+ while( numConsoleKeys < MAX_CONSOLE_KEYS )
+ {
+ consoleKey_t *c = &consoleKeys[ numConsoleKeys ];
+ char *keyName;
+
+ token = COM_Parse( &text_p );
+ if( !token[ 0 ] )
+ break;
+
+ c->u.key = Key_StringToKeynum( token );
+
+ // 0 isn't a key
+ if( c->u.key == 0 )
+ continue;
+
+ keyName = Key_KeynumToString( c->u.key );
+
+ if( strlen( keyName ) == 1 )
+ {
+ c->type = CHARACTER;
+ c->u.character = *keyName;
+ }
+ else
+ c->type = KEY;
+
+ numConsoleKeys++;
+ }
+ }
+
+ // Use the character in preference to the key name
+ if( character != '\0' )
+ key = 0;
+
+ for( i = 0; i < numConsoleKeys; i++ )
+ {
+ consoleKey_t *c = &consoleKeys[ i ];
+
+ switch( c->type )
+ {
+ case KEY:
+ if( key && c->u.key == key )
+ return qtrue;
+ break;
+
+ case CHARACTER:
+ if( c->u.character == character )
+ return qtrue;
+ break;
+ }
+ }
+
+ return qfalse;
}
/*
@@ -117,7 +210,7 @@ IN_TranslateSDLToQ3Key
===============
*/
static const char *IN_TranslateSDLToQ3Key( SDL_keysym *keysym,
- int *key, qboolean down )
+ keyNum_t *key, qboolean down )
{
static char buf[ 2 ] = { '\0', '\0' };
@@ -131,7 +224,7 @@ static const char *IN_TranslateSDLToQ3Key( SDL_keysym *keysym,
}
else
{
- switch (keysym->sym)
+ switch( keysym->sym )
{
case SDLK_PAGEUP: *key = K_PGUP; break;
case SDLK_KP9: *key = K_KP_PGUP; break;
@@ -218,15 +311,12 @@ static const char *IN_TranslateSDLToQ3Key( SDL_keysym *keysym,
}
}
- if( down && !( keysym->unicode & 0xFF80 ) )
+ if( down && keysym->unicode && !( keysym->unicode & 0xFF80 ) )
{
char ch = (char)keysym->unicode & 0x7F;
switch( ch )
{
- // So the key marked ~ always drops the console
- case '~': *key = '~'; break;
-
case 127: // ASCII delete
if( *key != K_DEL )
{
@@ -240,13 +330,16 @@ static const char *IN_TranslateSDLToQ3Key( SDL_keysym *keysym,
}
}
- // Never allow a '~' SE_CHAR event to be generated
- if( *key == '~' )
- *buf = '\0';
-
if( in_keyboardDebug->integer )
IN_PrintKey( keysym, *key, down );
+ if( IN_IsConsoleKey( *key, *buf ) )
+ {
+ // Console keys can't be bound or generate characters
+ *key = K_CONSOLE;
+ *buf = '\0';
+ }
+
return buf;
}
@@ -280,6 +373,59 @@ static io_connect_t IN_GetIOHandle(void) // mac os x mouse accel hack
/*
===============
+IN_GobbleMotionEvents
+===============
+*/
+static void IN_GobbleMotionEvents( void )
+{
+ SDL_Event dummy[ 1 ];
+
+ // Gobble any mouse motion events
+ SDL_PumpEvents( );
+ while( SDL_PeepEvents( dummy, 1, SDL_GETEVENT,
+ SDL_EVENTMASK( SDL_MOUSEMOTION ) ) ) { }
+}
+
+/*
+===============
+IN_GetUIMousePosition
+===============
+*/
+static void IN_GetUIMousePosition( int *x, int *y )
+{
+ if( uivm )
+ {
+ int pos = VM_Call( uivm, UI_MOUSE_POSITION );
+ *x = pos & 0xFFFF;
+ *y = ( pos >> 16 ) & 0xFFFF;
+
+ *x = glConfig.vidWidth * *x / 640;
+ *y = glConfig.vidHeight * *y / 480;
+ }
+ else
+ {
+ *x = glConfig.vidWidth / 2;
+ *y = glConfig.vidHeight / 2;
+ }
+}
+
+/*
+===============
+IN_SetUIMousePosition
+===============
+*/
+static void IN_SetUIMousePosition( int x, int y )
+{
+ if( uivm )
+ {
+ x = x * 640 / glConfig.vidWidth;
+ y = y * 480 / glConfig.vidHeight;
+ VM_Call( uivm, UI_SET_MOUSE_POSITION, x, y );
+ }
+}
+
+/*
+===============
IN_ActivateMouse
===============
*/
@@ -333,6 +479,8 @@ static void IN_ActivateMouse( void )
SDL_ShowCursor( 0 );
#endif
SDL_WM_GrabInput( SDL_GRAB_ON );
+
+ IN_GobbleMotionEvents( );
}
// in_nograb makes no sense in fullscreen mode
@@ -365,7 +513,13 @@ static void IN_DeactivateMouse( void )
// Always show the cursor when the mouse is disabled,
// but not when fullscreen
if( !r_fullscreen->integer )
- SDL_ShowCursor( 1 );
+ {
+ if( ( Key_GetCatcher( ) == KEYCATCH_UI ) &&
+ ( SDL_GetAppState( ) & (SDL_APPMOUSEFOCUS|SDL_APPINPUTFOCUS) ) == (SDL_APPMOUSEFOCUS|SDL_APPINPUTFOCUS) )
+ SDL_ShowCursor( 0 );
+ else
+ SDL_ShowCursor( 1 );
+ }
if( !mouseAvailable )
return;
@@ -391,11 +545,17 @@ static void IN_DeactivateMouse( void )
if( mouseActive )
{
+ IN_GobbleMotionEvents( );
+
SDL_WM_GrabInput( SDL_GRAB_OFF );
// Don't warp the mouse unless the cursor is within the window
if( SDL_GetAppState( ) & SDL_APPMOUSEFOCUS )
- SDL_WarpMouse( glConfig.vidWidth / 2, glConfig.vidHeight / 2 );
+ {
+ int x, y;
+ IN_GetUIMousePosition( &x, &y );
+ SDL_WarpMouse( x, y );
+ }
mouseActive = qfalse;
}
@@ -706,7 +866,7 @@ static void IN_ProcessEvents( void )
{
SDL_Event e;
const char *p = NULL;
- int key = 0;
+ keyNum_t key = 0;
if( !SDL_WasInit( SDL_INIT_VIDEO ) )
return;
@@ -787,12 +947,15 @@ IN_Frame
void IN_Frame( void )
{
qboolean loading;
+ qboolean cursorShowing;
+ int x, y;
IN_JoyMove( );
IN_ProcessEvents( );
// If not DISCONNECTED (main menu) or ACTIVE (in game), we're loading
loading = !!( cls.state != CA_DISCONNECTED && cls.state != CA_ACTIVE );
+ cursorShowing = Key_GetCatcher( ) & KEYCATCH_UI;
if( !r_fullscreen->integer && ( Key_GetCatcher( ) & KEYCATCH_CONSOLE ) )
{
@@ -804,6 +967,11 @@ void IN_Frame( void )
// Loading in windowed mode
IN_DeactivateMouse( );
}
+ else if( !r_fullscreen->integer && cursorShowing )
+ {
+ // Use WM cursor when not fullscreen
+ IN_DeactivateMouse( );
+ }
else if( !( SDL_GetAppState() & SDL_APPINPUTFOCUS ) )
{
// Window not got focus
@@ -811,6 +979,12 @@ void IN_Frame( void )
}
else
IN_ActivateMouse( );
+
+ if( !mouseActive )
+ {
+ SDL_GetMouseState( &x, &y );
+ IN_SetUIMousePosition( x, y );
+ }
}
/*
diff --git a/src/ui/ui_main.c b/src/ui/ui_main.c
index d19d5824..304222af 100644
--- a/src/ui/ui_main.c
+++ b/src/ui/ui_main.c
@@ -139,6 +139,8 @@ void UI_Init( qboolean );
void UI_Shutdown( void );
void UI_KeyEvent( int key, qboolean down );
void UI_MouseEvent( int dx, int dy );
+int UI_MousePosition( void );
+void UI_SetMousePosition( int x, int y );
void UI_Refresh( int realtime );
qboolean UI_IsFullscreen( void );
void UI_SetActiveMenu( uiMenuCommand_t menu );
@@ -167,6 +169,13 @@ intptr_t vmMain( int command, int arg0, int arg1, int arg2, int arg3,
UI_MouseEvent( arg0, arg1 );
return 0;
+ case UI_MOUSE_POSITION:
+ return UI_MousePosition( );
+
+ case UI_SET_MOUSE_POSITION:
+ UI_SetMousePosition( arg0, arg1 );
+ return 0;
+
case UI_REFRESH:
UI_Refresh( arg0 );
return 0;
@@ -4014,7 +4023,32 @@ void UI_MouseEvent( int dx, int dy )
else if( uiInfo.uiDC.cursory > SCREEN_HEIGHT )
uiInfo.uiDC.cursory = SCREEN_HEIGHT;
- if( Menu_Count() > 0 )
+ if( Menu_Count( ) > 0 )
+ Display_MouseMove( NULL, uiInfo.uiDC.cursorx, uiInfo.uiDC.cursory );
+}
+
+/*
+=================
+UI_MousePosition
+=================
+*/
+int UI_MousePosition( void )
+{
+ return (int)rint( uiInfo.uiDC.cursorx ) |
+ (int)rint( uiInfo.uiDC.cursory ) << 16;
+}
+
+/*
+=================
+UI_SetMousePosition
+=================
+*/
+void UI_SetMousePosition( int x, int y )
+{
+ uiInfo.uiDC.cursorx = x;
+ uiInfo.uiDC.cursory = y;
+
+ if( Menu_Count( ) > 0 )
Display_MouseMove( NULL, uiInfo.uiDC.cursorx, uiInfo.uiDC.cursory );
}
diff --git a/src/ui/ui_public.h b/src/ui/ui_public.h
index 3de3bc7f..26c6fbd4 100644
--- a/src/ui/ui_public.h
+++ b/src/ui/ui_public.h
@@ -172,6 +172,12 @@ typedef enum
UI_MOUSE_EVENT,
// void UI_MouseEvent( int dx, int dy );
+ UI_MOUSE_POSITION,
+ // int UI_MousePosition( void );
+
+ UI_SET_MOUSE_POSITION,
+ // void UI_SetMousePosition( int x, int y );
+
UI_REFRESH,
// void UI_Refresh( int time );