You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
405 lines
8.7 KiB
405 lines
8.7 KiB
/* |
|
vid_sdl.c - SDL input component |
|
Copyright (C) 2018 a1batross |
|
|
|
This program is free software: you can redistribute it and/or modify |
|
it under the terms of the GNU General Public License as published by |
|
the Free Software Foundation, either version 3 of the License, or |
|
(at your option) any later version. |
|
|
|
This program is distributed in the hope that it will be useful, |
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
GNU General Public License for more details. |
|
*/ |
|
#if !XASH_DEDICATED |
|
#include <SDL.h> |
|
|
|
#include "common.h" |
|
#include "keydefs.h" |
|
#include "input.h" |
|
#include "client.h" |
|
#include "vgui_draw.h" |
|
#include "events.h" |
|
#include "sound.h" |
|
#include "vid_common.h" |
|
|
|
SDL_Joystick *g_joy = NULL; |
|
#if !SDL_VERSION_ATLEAST( 2, 0, 0 ) |
|
#define SDL_WarpMouseInWindow( win, x, y ) SDL_WarpMouse( ( x ), ( y ) ) |
|
#else |
|
static struct |
|
{ |
|
qboolean initialized; |
|
SDL_Cursor *cursors[dc_last]; |
|
} cursors; |
|
#endif |
|
|
|
/* |
|
============= |
|
Platform_GetMousePos |
|
|
|
============= |
|
*/ |
|
void GAME_EXPORT Platform_GetMousePos( int *x, int *y ) |
|
{ |
|
SDL_GetMouseState( x, y ); |
|
} |
|
|
|
/* |
|
============= |
|
Platform_SetMousePos |
|
|
|
============ |
|
*/ |
|
void GAME_EXPORT Platform_SetMousePos( int x, int y ) |
|
{ |
|
SDL_WarpMouseInWindow( host.hWnd, x, y ); |
|
} |
|
|
|
/* |
|
======================== |
|
Platform_MouseMove |
|
|
|
======================== |
|
*/ |
|
void Platform_MouseMove( float *x, float *y ) |
|
{ |
|
int m_x, m_y; |
|
SDL_GetRelativeMouseState( &m_x, &m_y ); |
|
*x = (float)m_x; |
|
*y = (float)m_y; |
|
} |
|
|
|
/* |
|
============= |
|
Platform_GetClipobardText |
|
|
|
============= |
|
*/ |
|
int Platform_GetClipboardText( char *buffer, size_t size ) |
|
{ |
|
#if SDL_VERSION_ATLEAST( 2, 0, 0 ) |
|
int textLength; |
|
char *sdlbuffer = SDL_GetClipboardText(); |
|
|
|
if( !sdlbuffer ) |
|
return 0; |
|
|
|
if (buffer && size > 0) |
|
{ |
|
textLength = Q_strncpy( buffer, sdlbuffer, size ); |
|
} |
|
else { |
|
textLength = Q_strlen( sdlbuffer ); |
|
} |
|
SDL_free( sdlbuffer ); |
|
return textLength; |
|
#else // SDL_VERSION_ATLEAST( 2, 0, 0 ) |
|
buffer[0] = 0; |
|
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 ) |
|
return 0; |
|
} |
|
|
|
/* |
|
============= |
|
Platform_SetClipobardText |
|
|
|
============= |
|
*/ |
|
void Platform_SetClipboardText( const char *buffer ) |
|
{ |
|
#if SDL_VERSION_ATLEAST( 2, 0, 0 ) |
|
SDL_SetClipboardText( buffer ); |
|
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 ) |
|
} |
|
|
|
/* |
|
============= |
|
Platform_Vibrate |
|
|
|
============= |
|
*/ |
|
void Platform_Vibrate( float time, char flags ) |
|
{ |
|
// stub |
|
} |
|
|
|
/* |
|
============= |
|
SDLash_EnableTextInput |
|
|
|
============= |
|
*/ |
|
void Platform_EnableTextInput( qboolean enable ) |
|
{ |
|
#if SDL_VERSION_ATLEAST( 2, 0, 0 ) |
|
enable ? SDL_StartTextInput() : SDL_StopTextInput(); |
|
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 ) |
|
} |
|
|
|
/* |
|
============= |
|
SDLash_JoyInit_Old |
|
|
|
============= |
|
*/ |
|
static int SDLash_JoyInit_Old( int numjoy ) |
|
{ |
|
int num; |
|
int i; |
|
|
|
Con_Reportf( "Joystick: SDL\n" ); |
|
|
|
if( SDL_WasInit( SDL_INIT_JOYSTICK ) != SDL_INIT_JOYSTICK && |
|
SDL_InitSubSystem( SDL_INIT_JOYSTICK ) ) |
|
{ |
|
Con_Reportf( "Failed to initialize SDL Joysitck: %s\n", SDL_GetError() ); |
|
return 0; |
|
} |
|
|
|
if( g_joy ) |
|
{ |
|
SDL_JoystickClose( g_joy ); |
|
} |
|
|
|
num = SDL_NumJoysticks(); |
|
|
|
if( num > 0 ) |
|
Con_Reportf( "%i joysticks found:\n", num ); |
|
else |
|
{ |
|
Con_Reportf( "No joystick found.\n" ); |
|
return 0; |
|
} |
|
|
|
#if SDL_VERSION_ATLEAST( 2, 0, 0 ) |
|
for( i = 0; i < num; i++ ) |
|
Con_Reportf( "%i\t: %s\n", i, SDL_JoystickNameForIndex( i ) ); |
|
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 ) |
|
|
|
Con_Reportf( "Pass +set joy_index N to command line, where N is number, to select active joystick\n" ); |
|
|
|
g_joy = SDL_JoystickOpen( numjoy ); |
|
|
|
if( !g_joy ) |
|
{ |
|
Con_Reportf( "Failed to select joystick: %s\n", SDL_GetError( ) ); |
|
return 0; |
|
} |
|
|
|
#if SDL_VERSION_ATLEAST( 2, 0, 0 ) |
|
Con_Reportf( "Selected joystick: %s\n" |
|
"\tAxes: %i\n" |
|
"\tHats: %i\n" |
|
"\tButtons: %i\n" |
|
"\tBalls: %i\n", |
|
SDL_JoystickName( g_joy ), SDL_JoystickNumAxes( g_joy ), SDL_JoystickNumHats( g_joy ), |
|
SDL_JoystickNumButtons( g_joy ), SDL_JoystickNumBalls( g_joy ) ); |
|
|
|
SDL_GameControllerEventState( SDL_DISABLE ); |
|
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 ) |
|
SDL_JoystickEventState( SDL_ENABLE ); |
|
|
|
return num; |
|
} |
|
|
|
#if SDL_VERSION_ATLEAST( 2, 0, 0 ) |
|
/* |
|
============= |
|
SDLash_JoyInit_New |
|
|
|
============= |
|
*/ |
|
static int SDLash_JoyInit_New( int numjoy ) |
|
{ |
|
int count, numJoysticks, i; |
|
|
|
Con_Reportf( "Joystick: SDL GameController API\n" ); |
|
if( SDL_WasInit( SDL_INIT_GAMECONTROLLER ) != SDL_INIT_GAMECONTROLLER && |
|
SDL_InitSubSystem( SDL_INIT_GAMECONTROLLER ) ) |
|
{ |
|
Con_Reportf( "Failed to initialize SDL GameController API: %s\n", SDL_GetError() ); |
|
return 0; |
|
} |
|
|
|
SDL_GameControllerAddMappingsFromFile( "controllermappings.txt" ); |
|
|
|
count = 0; |
|
numJoysticks = SDL_NumJoysticks(); |
|
for ( i = 0; i < numJoysticks; i++ ) |
|
if( SDL_IsGameController( i ) ) |
|
++count; |
|
|
|
return count; |
|
} |
|
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 ) |
|
|
|
/* |
|
============= |
|
Platform_JoyInit |
|
|
|
============= |
|
*/ |
|
int Platform_JoyInit( int numjoy ) |
|
{ |
|
#if SDL_VERSION_ATLEAST( 2, 0, 0 ) |
|
// SDL_Joystick is now an old API |
|
// SDL_GameController is preferred |
|
if( !Sys_CheckParm( "-sdl_joy_old_api" ) ) |
|
return SDLash_JoyInit_New(numjoy); |
|
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 ) |
|
return SDLash_JoyInit_Old(numjoy); |
|
} |
|
|
|
/* |
|
======================== |
|
SDLash_InitCursors |
|
|
|
======================== |
|
*/ |
|
void SDLash_InitCursors( void ) |
|
{ |
|
#if SDL_VERSION_ATLEAST( 2, 0, 0 ) |
|
if( cursors.initialized ) |
|
SDLash_FreeCursors(); |
|
|
|
// load up all default cursors |
|
cursors.cursors[dc_none] = NULL; |
|
cursors.cursors[dc_arrow] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); |
|
cursors.cursors[dc_ibeam] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_IBEAM); |
|
cursors.cursors[dc_hourglass] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_WAIT); |
|
cursors.cursors[dc_crosshair] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_CROSSHAIR); |
|
cursors.cursors[dc_up] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW); |
|
cursors.cursors[dc_sizenwse] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENWSE); |
|
cursors.cursors[dc_sizenesw] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENESW); |
|
cursors.cursors[dc_sizewe] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEWE); |
|
cursors.cursors[dc_sizens] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZENS); |
|
cursors.cursors[dc_sizeall] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_SIZEALL); |
|
cursors.cursors[dc_no] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_NO); |
|
cursors.cursors[dc_hand] = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_HAND); |
|
cursors.initialized = true; |
|
#endif |
|
} |
|
|
|
/* |
|
======================== |
|
SDLash_FreeCursors |
|
|
|
======================== |
|
*/ |
|
void SDLash_FreeCursors( void ) |
|
{ |
|
#if SDL_VERSION_ATLEAST( 2, 0, 0 ) |
|
int i = 0; |
|
|
|
for( ; i < ARRAYSIZE( cursors.cursors ); i++ ) |
|
{ |
|
if( cursors.cursors[i] ) |
|
SDL_FreeCursor( cursors.cursors[i] ); |
|
cursors.cursors[i] = NULL; |
|
} |
|
|
|
cursors.initialized = false; |
|
#endif // SDL_VERSION_ATLEAST( 2, 0, 0 ) |
|
} |
|
|
|
/* |
|
======================== |
|
Platform_SetCursorType |
|
|
|
======================== |
|
*/ |
|
void Platform_SetCursorType( VGUI_DefaultCursor type ) |
|
{ |
|
qboolean visible; |
|
|
|
#if SDL_VERSION_ATLEAST( 2, 0, 0 ) |
|
if( !cursors.initialized ) |
|
return; |
|
#endif |
|
|
|
switch( type ) |
|
{ |
|
case dc_user: |
|
case dc_none: |
|
visible = false; |
|
break; |
|
default: |
|
visible = true; |
|
break; |
|
} |
|
|
|
// never disable cursor in touch emulation mode |
|
if( !visible && touch_emulate.value ) |
|
return; |
|
|
|
host.mouse_visible = visible; |
|
VGui_UpdateInternalCursorState( type ); |
|
|
|
#if SDL_VERSION_ATLEAST( 2, 0, 0 ) |
|
if( host.mouse_visible ) |
|
{ |
|
SDL_SetCursor( cursors.cursors[type] ); |
|
SDL_ShowCursor( true ); |
|
Key_EnableTextInput( true, false ); |
|
} |
|
else |
|
{ |
|
SDL_ShowCursor( false ); |
|
Key_EnableTextInput( false, false ); |
|
} |
|
#else |
|
if( host.mouse_visible ) |
|
{ |
|
SDL_ShowCursor( true ); |
|
} |
|
else |
|
{ |
|
SDL_ShowCursor( false ); |
|
} |
|
#endif |
|
} |
|
|
|
/* |
|
======================== |
|
Platform_GetKeyModifiers |
|
|
|
======================== |
|
*/ |
|
key_modifier_t Platform_GetKeyModifiers( void ) |
|
{ |
|
#if SDL_VERSION_ATLEAST( 2, 0, 0 ) |
|
SDL_Keymod modFlags; |
|
key_modifier_t resultFlags; |
|
|
|
resultFlags = KeyModifier_None; |
|
modFlags = SDL_GetModState(); |
|
if( FBitSet( modFlags, KMOD_LCTRL )) |
|
SetBits( resultFlags, KeyModifier_LeftCtrl ); |
|
if( FBitSet( modFlags, KMOD_RCTRL )) |
|
SetBits( resultFlags, KeyModifier_RightCtrl ); |
|
if( FBitSet( modFlags, KMOD_RSHIFT )) |
|
SetBits( resultFlags, KeyModifier_RightShift ); |
|
if( FBitSet( modFlags, KMOD_LSHIFT )) |
|
SetBits( resultFlags, KeyModifier_LeftShift ); |
|
if( FBitSet( modFlags, KMOD_LALT )) |
|
SetBits( resultFlags, KeyModifier_LeftAlt ); |
|
if( FBitSet( modFlags, KMOD_RALT )) |
|
SetBits( resultFlags, KeyModifier_RightAlt ); |
|
if( FBitSet( modFlags, KMOD_NUM )) |
|
SetBits( resultFlags, KeyModifier_NumLock ); |
|
if( FBitSet( modFlags, KMOD_CAPS )) |
|
SetBits( resultFlags, KeyModifier_CapsLock ); |
|
if( FBitSet( modFlags, KMOD_RGUI )) |
|
SetBits( resultFlags, KeyModifier_RightSuper ); |
|
if( FBitSet( modFlags, KMOD_LGUI )) |
|
SetBits( resultFlags, KeyModifier_LeftSuper ); |
|
|
|
return resultFlags; |
|
#else |
|
return KeyModifier_None; |
|
#endif |
|
} |
|
|
|
#endif // XASH_DEDICATED
|
|
|