thirtyflightsofloving/unix/gl_sdl.c
Knightmare66 4eea7036b8 Added Ethan Lee's Linux porting changes.
Moved loadingMessage, loadingMessages, and loadingPercent variables in client into client_static_t struct.
2021-10-11 15:38:20 -04:00

439 lines
8.6 KiB
C

#include <stdio.h>
#include "../renderer/r_local.h"
#include "../client/keys.h"
#include "../ui/ui_local.h"
#include <SDL.h>
#include "glw_unix.h"
glwstate_t glw_state;
int mx, my;
qboolean mouse_active = false;
int GLimp_Init(void *hinstance, void *wndproc)
{
/* No-op */
return 1;
}
void GLimp_Shutdown(void)
{
SDL_SetRelativeMouseMode(SDL_FALSE);
mouse_active = false;
}
void GLimp_BeginFrame(float camera_seperation)
{
/* No-op */
}
void GLimp_EndFrame(void)
{
SDL_GL_SwapWindow(glw_state.glWindow);
}
int GLimp_SetMode(int *pwidth, int *pheight, int mode, dispType_t fullscreen)
{
int width, height;
if (!VID_GetModeInfo(&width, &height, mode))
{
Com_Printf(" invalid mode\n");
return rserr_invalid_mode;
}
if (fullscreen == dt_fullscreen)
{
/* Override the vidmode with the desktop resolution.
* If we wanted to be fancy we could use a faux-backbuffer to
* simulate lower resolutions, but the engine is smart and lets
* us override, so in 2021 let's just assume your PC can run
* Quake 2.
* -flibit
*/
SDL_DisplayMode mode;
SDL_SetWindowFullscreen(
glw_state.glWindow,
SDL_WINDOW_FULLSCREEN_DESKTOP
);
SDL_GetCurrentDisplayMode(
SDL_GetWindowDisplayIndex(glw_state.glWindow),
&mode
);
*pwidth = mode.w;
*pheight = mode.h;
}
else
{
SDL_SetWindowSize(glw_state.glWindow, width, height);
SDL_SetWindowBordered(
glw_state.glWindow,
fullscreen != dt_borderless
);
*pwidth = width;
*pheight = height;
}
SDL_ShowWindow(glw_state.glWindow);
VID_NewWindow(*pwidth, *pheight);
return rserr_ok;
}
void UpdateGammaRamp(void)
{
/* Unsupported in 2021 */
}
char *Sys_GetClipboardData(void)
{
return SDL_GetClipboardText();
}
void IN_Activate(qboolean active)
{
if (active)
{
if (!mouse_active)
{
mx = my = 0;
SDL_SetRelativeMouseMode(SDL_TRUE);
mouse_active = true;
}
}
else
{
if (mouse_active)
{
SDL_SetRelativeMouseMode(SDL_FALSE);
mouse_active = false;
}
}
}
/* IN_Translate functions taken from yquake2 */
/*
* This creepy function translates SDL keycodes into
* the id Tech 2 engines interal representation.
*/
static int
IN_TranslateSDLtoQ2Key(unsigned int keysym)
{
int key = 0;
/* These must be translated */
switch (keysym)
{
case SDLK_TAB:
key = K_TAB;
break;
case SDLK_RETURN:
key = K_ENTER;
break;
case SDLK_ESCAPE:
key = K_ESCAPE;
break;
case SDLK_BACKSPACE:
key = K_BACKSPACE;
break;
case SDLK_CAPSLOCK:
key = K_CAPSLOCK;
break;
case SDLK_PAUSE:
key = K_PAUSE;
break;
case SDLK_UP:
key = K_UPARROW;
break;
case SDLK_DOWN:
key = K_DOWNARROW;
break;
case SDLK_LEFT:
key = K_LEFTARROW;
break;
case SDLK_RIGHT:
key = K_RIGHTARROW;
break;
case SDLK_RALT:
case SDLK_LALT:
key = K_ALT;
break;
case SDLK_LCTRL:
case SDLK_RCTRL:
key = K_CTRL;
break;
case SDLK_LSHIFT:
case SDLK_RSHIFT:
key = K_SHIFT;
break;
case SDLK_INSERT:
key = K_INS;
break;
case SDLK_DELETE:
key = K_DEL;
break;
case SDLK_PAGEDOWN:
key = K_PGDN;
break;
case SDLK_PAGEUP:
key = K_PGUP;
break;
case SDLK_HOME:
key = K_HOME;
break;
case SDLK_END:
key = K_END;
break;
case SDLK_F1:
key = K_F1;
break;
case SDLK_F2:
key = K_F2;
break;
case SDLK_F3:
key = K_F3;
break;
case SDLK_F4:
key = K_F4;
break;
case SDLK_F5:
key = K_F5;
break;
case SDLK_F6:
key = K_F6;
break;
case SDLK_F7:
key = K_F7;
break;
case SDLK_F8:
key = K_F8;
break;
case SDLK_F9:
key = K_F9;
break;
case SDLK_F10:
key = K_F10;
break;
case SDLK_F11:
key = K_F11;
break;
case SDLK_F12:
key = K_F12;
break;
case SDLK_KP_7:
key = K_KP_HOME;
break;
case SDLK_KP_8:
key = K_KP_UPARROW;
break;
case SDLK_KP_9:
key = K_KP_PGUP;
break;
case SDLK_KP_4:
key = K_KP_LEFTARROW;
break;
case SDLK_KP_5:
key = K_KP_5;
break;
case SDLK_KP_6:
key = K_KP_RIGHTARROW;
break;
case SDLK_KP_1:
key = K_KP_END;
break;
case SDLK_KP_2:
key = K_KP_DOWNARROW;
break;
case SDLK_KP_3:
key = K_KP_PGDN;
break;
case SDLK_KP_ENTER:
key = K_KP_ENTER;
break;
case SDLK_KP_0:
key = K_KP_INS;
break;
case SDLK_KP_PERIOD:
key = K_KP_DEL;
break;
case SDLK_KP_DIVIDE:
key = K_KP_SLASH;
break;
case SDLK_KP_MINUS:
key = K_KP_MINUS;
break;
case SDLK_KP_PLUS:
key = K_KP_PLUS;
break;
case SDLK_KP_MULTIPLY:
key = K_KP_MULT;
break;
default:
break;
}
return key;
}
void HandleEvents(void)
{
int multiclicktime = 750;
SDL_Event evt;
while (SDL_PollEvent(&evt) == 1)
{
if (evt.type == SDL_QUIT)
{
Cbuf_ExecuteText(EXEC_NOW, "quit");
}
else if (evt.type == SDL_KEYDOWN || evt.type == SDL_KEYUP)
{
/* KEYDOWN/KEYUP events taken from yquake2 */
qboolean down = (evt.type == SDL_KEYDOWN);
/* workaround for AZERTY-keyboards, which don't have 1, 2, ..., 9, 0 in first row:
* always map those physical keys (scancodes) to those keycodes anyway
* see also https://bugzilla.libsdl.org/show_bug.cgi?id=3188 */
SDL_Scancode sc = evt.key.keysym.scancode;
if (sc >= SDL_SCANCODE_1 && sc <= SDL_SCANCODE_0)
{
/* Note that the SDL_SCANCODEs are SDL_SCANCODE_1, _2, ..., _9, SDL_SCANCODE_0
* while in ASCII it's '0', '1', ..., '9' => handle 0 and 1-9 separately
* (quake2 uses the ASCII values for those keys) */
int key = '0'; /* implicitly handles SDL_SCANCODE_0 */
if (sc <= SDL_SCANCODE_9)
{
key = '1' + (sc - SDL_SCANCODE_1);
}
Key_Event(key, down, Sys_Milliseconds());
}
else
{
SDL_Keycode kc = evt.key.keysym.sym;
if(sc == SDL_SCANCODE_GRAVE && kc != '\'' && kc != '"')
{
// special case/hack: open the console with the "console key"
// (beneath Esc, left of 1, above Tab)
// but not if the keycode for this is a quote (like on Brazilian
// keyboards) - otherwise you couldn't type them in the console
if((evt.key.keysym.mod & (KMOD_CAPS|KMOD_SHIFT|KMOD_ALT|KMOD_CTRL|KMOD_GUI)) == 0)
{
// also, only do this if no modifiers like shift or AltGr or whatever are pressed
// so kc will most likely be the ascii char generated by this and can be ignored
// in case SDL_TEXTINPUT above (so we don't get ^ or whatever as text in console)
// (can't just check for mod == 0 because numlock is a KMOD too)
Key_Event('`', down, Sys_Milliseconds());
}
}
else if ((kc >= SDLK_SPACE) && (kc < SDLK_DELETE))
{
Key_Event(kc, down, false);
}
else
{
int key = IN_TranslateSDLtoQ2Key(kc);
/* yquake2 has this, km does not
if(key == 0)
{
// fallback to scancodes if we don't know the keycode
key = IN_TranslateScancodeToQ2Key(sc);
}
*/
if(key != 0)
{
Key_Event(key, down, Sys_Milliseconds());
}
else
{
Com_DPrintf("Pressed unknown key with SDL_Keycode %d, SDL_Scancode %d.\n", kc, (int)sc);
}
}
}
}
else if (evt.type == SDL_MOUSEMOTION)
{
if (mouse_active)
{
/* Relative should be on here */
mx += evt.motion.xrel;
my += evt.motion.yrel;
}
}
else if (evt.type == SDL_MOUSEBUTTONDOWN)
{
int mouse_button = evt.button.button - 1;
if (mouse_button == 1)
{
mouse_button = 2;
}
else if (mouse_button == 2)
{
mouse_button = 1;
}
if (Sys_Milliseconds() - ui_mousecursor.buttontime[mouse_button] < multiclicktime)
{
ui_mousecursor.buttonclicks[mouse_button] += 1;
}
else
{
ui_mousecursor.buttonclicks[mouse_button] = 1;
}
if (ui_mousecursor.buttonclicks[mouse_button] > 3)
{
ui_mousecursor.buttonclicks[mouse_button] = 3;
}
ui_mousecursor.buttontime[mouse_button] = Sys_Milliseconds();
ui_mousecursor.buttondown[mouse_button] = true;
ui_mousecursor.buttonused[mouse_button] = false;
ui_mousecursor.mouseaction = true;
Key_Event(K_MOUSE1 + mouse_button, 1, Sys_Milliseconds());
}
else if (evt.type == SDL_MOUSEBUTTONUP)
{
int mouse_button = evt.button.button - 1;
if (mouse_button == 1)
{
mouse_button = 2;
}
else if (mouse_button == 2)
{
mouse_button = 1;
}
ui_mousecursor.buttondown[mouse_button] = false;
ui_mousecursor.buttonused[mouse_button] = false;
ui_mousecursor.mouseaction = true;
Key_Event(K_MOUSE1 + mouse_button, 0, Sys_Milliseconds());
}
else if (evt.type == SDL_MOUSEWHEEL)
{
int dir;
if (evt.wheel.y > 0)
{
dir = K_MWHEELUP;
}
else
{
dir = K_MWHEELDOWN;
}
/* We only get one event per wheel change, so instantly press/release */
Key_Event(dir, 1, Sys_Milliseconds());
Key_Event(dir, 0, Sys_Milliseconds());
}
}
}