summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile68
-rw-r--r--src/unix/sdl2/sound.c159
-rw-r--r--src/unix/sdl2/video.c700
-rw-r--r--src/unix/system.c4
4 files changed, 903 insertions, 28 deletions
diff --git a/Makefile b/Makefile
index 8d89cff..abe6bf8 100644
--- a/Makefile
+++ b/Makefile
@@ -476,37 +476,45 @@ ifdef CONFIG_WINDOWS
LIBS_s += -lws2_32 -lwinmm -ladvapi32
LIBS_c += -lws2_32 -lwinmm
else
- SDL_CFLAGS ?= $(shell sdl-config --cflags)
- SDL_LIBS ?= $(shell sdl-config --libs)
- CFLAGS_c += -DUSE_SDL=1 $(SDL_CFLAGS)
- LIBS_c += $(SDL_LIBS)
- OBJS_c += src/unix/sdl/video.o
- OBJS_c += src/unix/sdl/clipboard.o
-
- ifdef CONFIG_SOFTWARE_RENDERER
- OBJS_c += src/unix/sdl/swimp.o
+ ifdef CONFIG_SDL2
+ SDL_CFLAGS ?= $(shell sdl2-config --cflags)
+ SDL_LIBS ?= $(shell sdl2-config --libs)
+ CFLAGS_c += -DUSE_SDL=2 $(SDL_CFLAGS)
+ LIBS_c += $(SDL_LIBS)
+ OBJS_c += src/unix/sdl2/video.o
else
- OBJS_c += src/unix/sdl/glimp.o
- endif
+ SDL_CFLAGS ?= $(shell sdl-config --cflags)
+ SDL_LIBS ?= $(shell sdl-config --libs)
+ CFLAGS_c += -DUSE_SDL=1 $(SDL_CFLAGS)
+ LIBS_c += $(SDL_LIBS)
+ OBJS_c += src/unix/sdl/video.o
+ OBJS_c += src/unix/sdl/clipboard.o
+
+ ifdef CONFIG_SOFTWARE_RENDERER
+ OBJS_c += src/unix/sdl/swimp.o
+ else
+ OBJS_c += src/unix/sdl/glimp.o
+ endif
- ifdef CONFIG_X11
- X11_CFLAGS ?=
- X11_LIBS ?= -lX11
- CFLAGS_c += -DUSE_X11=1 $(X11_CFLAGS)
- LIBS_c += $(X11_LIBS)
- ifndef CONFIG_SOFTWARE_RENDERER
- OBJS_c += src/unix/sdl/glx.o
+ ifdef CONFIG_X11
+ X11_CFLAGS ?=
+ X11_LIBS ?= -lX11
+ CFLAGS_c += -DUSE_X11=1 $(X11_CFLAGS)
+ LIBS_c += $(X11_LIBS)
+ ifndef CONFIG_SOFTWARE_RENDERER
+ OBJS_c += src/unix/sdl/glx.o
+ endif
endif
- endif
- ifdef CONFIG_DIRECT_INPUT
- CFLAGS_c += -DUSE_DINPUT=1
- OBJS_c += src/unix/evdev.o
- ifndef CONFIG_NO_UDEV
- UDEV_CFLAGS ?=
- UDEV_LIBS ?= -ludev
- CFLAGS_c += -DUSE_UDEV=1 $(UDEV_CFLAGS)
- LIBS_c += $(UDEV_LIBS)
+ ifdef CONFIG_DIRECT_INPUT
+ CFLAGS_c += -DUSE_DINPUT=1
+ OBJS_c += src/unix/evdev.o
+ ifndef CONFIG_NO_UDEV
+ UDEV_CFLAGS ?=
+ UDEV_LIBS ?= -ludev
+ CFLAGS_c += -DUSE_UDEV=1 $(UDEV_CFLAGS)
+ LIBS_c += $(UDEV_LIBS)
+ endif
endif
endif
@@ -519,7 +527,11 @@ else
endif
ifndef CONFIG_NO_SOFTWARE_SOUND
- OBJS_c += src/unix/sdl/sound.o
+ ifdef CONFIG_SDL2
+ OBJS_c += src/unix/sdl2/sound.o
+ else
+ OBJS_c += src/unix/sdl/sound.o
+ endif
ifdef CONFIG_DIRECT_SOUND
CFLAGS_c += -DUSE_DSOUND=1
OBJS_c += src/unix/oss.o
diff --git a/src/unix/sdl2/sound.c b/src/unix/sdl2/sound.c
new file mode 100644
index 0000000..a38cb29
--- /dev/null
+++ b/src/unix/sdl2/sound.c
@@ -0,0 +1,159 @@
+/*
+Copyright (C) 2007-2008 Andrey Nazarov
+
+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 2 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.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+//
+// snd_sdl.c
+//
+
+#include "shared/shared.h"
+#include "common/zone.h"
+#include "client/sound/dma.h"
+#include <SDL.h>
+
+static void Filler(void *userdata, Uint8 *stream, int len)
+{
+ int size = dma.samples << 1;
+ int pos = dma.samplepos << 1;
+ int wrapped = pos + len - size;
+
+ if (wrapped < 0) {
+ memcpy(stream, dma.buffer + pos, len);
+ dma.samplepos += len >> 1;
+ } else {
+ int remaining = size - pos;
+ memcpy(stream, dma.buffer + pos, remaining);
+ memcpy(stream + remaining, dma.buffer, wrapped);
+ dma.samplepos = wrapped >> 1;
+ }
+}
+
+static void Shutdown(void)
+{
+ Com_Printf("Shutting down SDL audio.\n");
+
+ SDL_CloseAudio();
+ if (SDL_WasInit(SDL_INIT_EVERYTHING) == SDL_INIT_AUDIO) {
+ SDL_Quit();
+ } else {
+ SDL_QuitSubSystem(SDL_INIT_AUDIO);
+ }
+
+ if (dma.buffer) {
+ Z_Free(dma.buffer);
+ dma.buffer = NULL;
+ }
+}
+
+static sndinitstat_t Init(void)
+{
+ SDL_AudioSpec desired, obtained;
+ int ret;
+
+ if (SDL_WasInit(SDL_INIT_EVERYTHING) == 0) {
+ ret = SDL_Init(SDL_INIT_AUDIO);
+ } else {
+ ret = SDL_InitSubSystem(SDL_INIT_AUDIO);
+ }
+ if (ret == -1) {
+ Com_EPrintf("Couldn't initialize SDL audio: %s\n", SDL_GetError());
+ return SIS_FAILURE;
+ }
+
+ memset(&desired, 0, sizeof(desired));
+ switch (s_khz->integer) {
+ case 48:
+ desired.freq = 48000;
+ break;
+ case 44:
+ desired.freq = 44100;
+ break;
+ case 22:
+ desired.freq = 22050;
+ break;
+ default:
+ desired.freq = 11025;
+ break;
+ }
+
+ desired.format = AUDIO_S16LSB;
+ desired.samples = 512;
+ desired.channels = 2;
+ desired.callback = Filler;
+ ret = SDL_OpenAudio(&desired, &obtained);
+ if (ret == -1) {
+ Com_EPrintf("Couldn't open SDL audio: %s\n", SDL_GetError());
+ return SIS_FAILURE;
+ }
+
+ if (obtained.format != AUDIO_S16LSB) {
+ Com_EPrintf("SDL audio format %d unsupported.\n", obtained.format);
+ goto fail;
+ }
+
+ if (obtained.channels != 1 && obtained.channels != 2) {
+ Com_EPrintf("SDL audio channels %d unsupported.\n", obtained.channels);
+ goto fail;
+ }
+
+ dma.speed = obtained.freq;
+ dma.channels = obtained.channels;
+ dma.samples = 0x8000 * obtained.channels;
+ dma.submission_chunk = 1;
+ dma.samplebits = 16;
+ dma.buffer = Z_Mallocz(dma.samples * 2);
+ dma.samplepos = 0;
+
+ Com_Printf("Using SDL audio driver: %s\n", SDL_GetCurrentAudioDriver());
+
+ SDL_PauseAudio(0);
+
+ return SIS_SUCCESS;
+
+fail:
+ Shutdown();
+ return SIS_FAILURE;
+}
+
+static void BeginPainting(void)
+{
+ SDL_LockAudio();
+}
+
+static void Submit(void)
+{
+ SDL_UnlockAudio();
+}
+
+static void Activate(qboolean active)
+{
+ if (active) {
+ SDL_PauseAudio(0);
+ } else {
+ SDL_PauseAudio(1);
+ }
+}
+
+void WAVE_FillAPI(snddmaAPI_t *api)
+{
+ api->Init = Init;
+ api->Shutdown = Shutdown;
+ api->BeginPainting = BeginPainting;
+ api->Submit = Submit;
+ api->Activate = Activate;
+}
+
diff --git a/src/unix/sdl2/video.c b/src/unix/sdl2/video.c
new file mode 100644
index 0000000..1e649f9
--- /dev/null
+++ b/src/unix/sdl2/video.c
@@ -0,0 +1,700 @@
+/*
+Copyright (C) 2013 Andrey Nazarov
+
+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 2 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.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+//
+// video.c
+//
+
+#include "shared/shared.h"
+#include "common/cvar.h"
+#include "common/common.h"
+#include "common/files.h"
+#include "common/zone.h"
+#include "client/client.h"
+#include "client/input.h"
+#include "client/keys.h"
+#include "client/ui.h"
+#include "client/video.h"
+#include "refresh/refresh.h"
+#include "system/system.h"
+#include "../res/q2pro.xbm"
+#include <SDL.h>
+
+static SDL_Window *sdl_window;
+static vidFlags_t sdl_flags;
+
+/*
+===============================================================================
+
+OPENGL STUFF
+
+===============================================================================
+*/
+
+#if USE_REF == REF_GL
+
+static SDL_GLContext *sdl_context;
+
+static void gl_swapinterval_changed(cvar_t *self)
+{
+ if (SDL_GL_SetSwapInterval(self->integer) < 0) {
+ Com_EPrintf("Couldn't set swap interval %d: %s\n", self->integer, SDL_GetError());
+ }
+}
+
+static qboolean VID_SDL_GL_LoadLibrary(void)
+{
+#if USE_FIXED_LIBGL
+ Cvar_Get("gl_driver", LIBGL, CVAR_ROM);
+ return qtrue;
+#else
+ cvar_t *gl_driver = Cvar_Get("gl_driver", LIBGL, CVAR_REFRESH);
+
+ // don't allow absolute or relative paths
+ FS_SanitizeFilenameVariable(gl_driver);
+
+ while (1) {
+ char *s;
+
+ // ugly hack to work around brain-dead servers that actively
+ // check and enforce `gl_driver' cvar to `opengl32', unaware
+ // of other systems than Windows
+ s = gl_driver->string;
+ if (!Q_stricmp(s, "opengl32") || !Q_stricmp(s, "opengl32.dll")) {
+ Com_Printf("...attempting to load %s instead of %s\n",
+ gl_driver->default_string, s);
+ s = gl_driver->default_string;
+ }
+
+ if (SDL_GL_LoadLibrary(s) == 0) {
+ break;
+ }
+
+ Com_EPrintf("Couldn't load OpenGL library: %s\n", SDL_GetError());
+ if (!strcmp(s, gl_driver->default_string)) {
+ return qfalse;
+ }
+
+ // attempt to recover
+ Com_Printf("...falling back to %s\n", gl_driver->default_string);
+ Cvar_Reset(gl_driver);
+ }
+
+ return qtrue;
+#endif
+}
+
+static void VID_SDL_GL_SetAttributes(void)
+{
+ int colorbits = Cvar_ClampInteger(
+ Cvar_Get("gl_colorbits", "0", CVAR_REFRESH), 0, 32);
+ int depthbits = Cvar_ClampInteger(
+ Cvar_Get("gl_depthbits", "0", CVAR_REFRESH), 0, 32);
+ int stencilbits = Cvar_ClampInteger(
+ Cvar_Get("gl_stencilbits", "8", CVAR_REFRESH), 0, 8);
+ int multisamples = Cvar_ClampInteger(
+ Cvar_Get("gl_multisamples", "0", CVAR_REFRESH), 0, 32);
+
+ if (colorbits == 0)
+ colorbits = 24;
+
+ if (depthbits == 0)
+ depthbits = colorbits > 16 ? 24 : 16;
+
+ if (depthbits < 24)
+ stencilbits = 0;
+
+ if (colorbits > 16) {
+ SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
+ SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
+ } else {
+ SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
+ SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
+ SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
+ }
+
+ SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, depthbits);
+ SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, stencilbits);
+ SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+
+ if (multisamples > 1) {
+ SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
+ SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, multisamples);
+ }
+}
+
+#if !USE_FIXED_LIBGL
+void *VID_GetCoreAddr(const char *sym)
+{
+ void *entry = SDL_GL_GetProcAddress(sym);
+
+ if (!entry)
+ Com_EPrintf("Couldn't get OpenGL entry point: %s\n", sym);
+
+ return entry;
+}
+#endif
+
+void *VID_GetProcAddr(const char *sym)
+{
+ void *entry = SDL_GL_GetProcAddress(sym);
+
+ if (!entry)
+ Com_EPrintf("Couldn't get OpenGL entry point: %s\n", sym);
+
+ return entry;
+}
+
+#endif
+
+/*
+===============================================================================
+
+VIDEO
+
+===============================================================================
+*/
+
+static void VID_SDL_ModeChanged(void)
+{
+ int width, height;
+ void *pixels;
+ int rowbytes;
+
+ SDL_GetWindowSize(sdl_window, &width, &height);
+
+ Uint32 flags = SDL_GetWindowFlags(sdl_window);
+ if (flags & SDL_WINDOW_FULLSCREEN)
+ sdl_flags |= QVF_FULLSCREEN;
+ else
+ sdl_flags &= ~QVF_FULLSCREEN;
+
+#if USE_REF == REF_SOFT
+ SDL_Surface *surf = SDL_GetWindowSurface(sdl_window);
+ if (!surf)
+ Com_Error(ERR_FATAL, "Couldn't (re)create window surface: %s", SDL_GetError());
+ pixels = surf->pixels;
+ rowbytes = surf->pitch;
+#else
+ pixels = NULL;
+ rowbytes = 0;
+#endif
+
+ R_ModeChanged(width, height, sdl_flags, rowbytes, pixels);
+ SCR_ModeChanged();
+}
+
+static void VID_SDL_SetMode(void)
+{
+ Uint32 flags;
+ vrect_t rc;
+ int freq;
+
+ if (vid_fullscreen->integer) {
+ if (VID_GetFullscreen(&rc, &freq, NULL)) {
+ SDL_DisplayMode mode = {
+ .format = SDL_PIXELFORMAT_UNKNOWN,
+ .w = rc.width,
+ .h = rc.height,
+ .refresh_rate = freq,
+ .driverdata = NULL
+ };
+ SDL_SetWindowDisplayMode(sdl_window, &mode);
+ flags = SDL_WINDOW_FULLSCREEN;
+ } else {
+ flags = SDL_WINDOW_FULLSCREEN_DESKTOP;
+ }
+ } else {
+ flags = 0;
+ }
+
+ SDL_SetWindowFullscreen(sdl_window, flags);
+}
+
+void VID_SetMode(void)
+{
+ VID_SDL_SetMode();
+ VID_SDL_ModeChanged();
+}
+
+void VID_VideoWait(void)
+{
+}
+
+qboolean VID_VideoSync(void)
+{
+ return qtrue;
+}
+
+void VID_BeginFrame(void)
+{
+}
+
+void VID_EndFrame(void)
+{
+#if USE_REF == REF_GL
+ SDL_GL_SwapWindow(sdl_window);
+#else
+ SDL_UpdateWindowSurface(sdl_window);
+#endif
+}
+
+void VID_FatalShutdown(void)
+{
+ SDL_SetWindowGrab(sdl_window, SDL_FALSE);
+ SDL_SetRelativeMouseMode(SDL_FALSE);
+ SDL_ShowCursor(SDL_ENABLE);
+ SDL_Quit();
+}
+
+char *VID_GetClipboardData(void)
+{
+ // returned data must be Z_Free'd
+ char *text = SDL_GetClipboardText();
+ char *copy = Z_CopyString(text);
+ SDL_free(text);
+ return copy;
+}
+
+void VID_SetClipboardData(const char *data)
+{
+ SDL_SetClipboardText(data);
+}
+
+void VID_UpdateGamma(const byte *table)
+{
+ Uint16 ramp[256];
+ int i;
+
+ if (sdl_flags & QVF_GAMMARAMP) {
+ for (i = 0; i < 256; i++) {
+ ramp[i] = table[i] << 8;
+ }
+ SDL_SetWindowGammaRamp(sdl_window, ramp, ramp, ramp);
+ }
+}
+
+static int VID_SDL_InitSubSystem(void)
+{
+ int ret;
+
+ ret = SDL_WasInit(SDL_INIT_EVERYTHING);
+ if (ret == 0)
+ ret = SDL_Init(SDL_INIT_VIDEO);
+ else if (!(ret & SDL_INIT_VIDEO))
+ ret = SDL_InitSubSystem(SDL_INIT_VIDEO);
+ else
+ ret = 0;
+
+ if (ret == -1)
+ Com_EPrintf("Couldn't initialize SDL video: %s\n", SDL_GetError());
+
+ return ret;
+}
+
+static int VID_SDL_EventFilter(void *userdata, SDL_Event *event)
+{
+ // SDL uses relative time, we need absolute
+ event->common.timestamp = Sys_Milliseconds();
+ return 1;
+}
+
+char *VID_GetDefaultModeList(void)
+{
+ SDL_DisplayMode mode;
+ size_t size, len;
+ char *buf;
+ int i, num_modes;
+
+ if (VID_SDL_InitSubSystem())
+ return NULL;
+
+ num_modes = SDL_GetNumDisplayModes(0);
+ if (num_modes < 1)
+ return Z_CopyString(VID_MODELIST);
+
+ size = 8 + num_modes * 32 + 1;
+ buf = Z_Malloc(size);
+
+ len = Q_strlcpy(buf, "desktop ", size);
+ for (i = 0; i < num_modes; i++) {
+ if (SDL_GetDisplayMode(0, i, &mode) < 0)
+ break;
+ if (mode.refresh_rate == 0)
+ continue;
+ len += Q_scnprintf(buf + len, size - len, "%dx%d@%d ",
+ mode.w, mode.h, mode.refresh_rate);
+ }
+
+ if (len == 0)
+ buf[0] = 0;
+ else if (buf[len - 1] == ' ')
+ buf[len - 1] = 0;
+
+ return buf;
+}
+
+qboolean VID_Init(void)
+{
+ Uint32 flags = SDL_WINDOW_RESIZABLE;
+ vrect_t rc;
+
+ if (VID_SDL_InitSubSystem()) {
+ return qfalse;
+ }
+
+#if USE_REF == REF_GL
+ if (!VID_SDL_GL_LoadLibrary()) {
+ goto fail;
+ }
+
+ VID_SDL_GL_SetAttributes();
+ flags |= SDL_WINDOW_OPENGL;
+#endif
+
+ SDL_SetEventFilter(VID_SDL_EventFilter, NULL);
+
+ if (!VID_GetGeometry(&rc)) {
+ rc.x = SDL_WINDOWPOS_UNDEFINED;
+ rc.y = SDL_WINDOWPOS_UNDEFINED;
+ }
+
+ sdl_window = SDL_CreateWindow(PRODUCT, rc.x, rc.y, rc.width, rc.height, flags);
+ if (!sdl_window) {
+ Com_EPrintf("Couldn't create SDL window: %s\n", SDL_GetError());
+ goto fail;
+ }
+
+ SDL_SetWindowMinimumSize(sdl_window, 320, 240);
+
+ SDL_Surface *icon = SDL_CreateRGBSurfaceFrom(q2icon_bits, q2icon_width, q2icon_height,
+ 1, q2icon_width / 8, 0, 0, 0, 0);
+ if (icon) {
+ SDL_Color colors[2] = {
+ { 255, 255, 255 },
+ { 0, 128, 128 }
+ };
+ SDL_SetPaletteColors(icon->format->palette, colors, 0, 2);
+ SDL_SetColorKey(icon, SDL_TRUE, 0);
+ SDL_SetWindowIcon(sdl_window, icon);
+ SDL_FreeSurface(icon);
+ }
+
+ VID_SDL_SetMode();
+
+#if USE_REF == REF_GL
+ sdl_context = SDL_GL_CreateContext(sdl_window);
+ if (!sdl_context) {
+ Com_EPrintf("Couldn't create OpenGL context: %s\n", SDL_GetError());
+ goto fail;
+ }
+
+ cvar_t *gl_swapinterval = Cvar_Get("gl_swapinterval", "0", 0);
+ gl_swapinterval->changed = gl_swapinterval_changed;
+ gl_swapinterval_changed(gl_swapinterval);
+#endif
+
+ cvar_t *vid_hwgamma = Cvar_Get("vid_hwgamma", "0", CVAR_REFRESH);
+ if (vid_hwgamma->integer) {
+ Uint16 gamma[3][256];
+
+ if (SDL_GetWindowGammaRamp(sdl_window, gamma[0], gamma[1], gamma[2]) == 0 &&
+ SDL_SetWindowGammaRamp(sdl_window, gamma[0], gamma[1], gamma[2]) == 0) {
+ Com_Printf("...enabling hardware gamma\n");
+ sdl_flags |= QVF_GAMMARAMP;
+ } else {
+ Com_Printf("...hardware gamma not supported\n");
+ Cvar_Reset(vid_hwgamma);
+ }
+ }
+
+ VID_SDL_ModeChanged();
+ return qtrue;
+
+fail:
+ VID_Shutdown();
+ return qfalse;
+}
+
+void VID_Shutdown(void)
+{
+#if USE_REF == REF_GL
+ if (sdl_context) {
+ SDL_GL_DeleteContext(sdl_context);
+ sdl_context = NULL;
+ }
+#endif
+ if (sdl_window) {
+ SDL_DestroyWindow(sdl_window);
+ sdl_window = NULL;
+ }
+ sdl_flags = 0;
+ if (SDL_WasInit(SDL_INIT_EVERYTHING) == SDL_INIT_VIDEO) {
+ SDL_Quit();
+ } else {
+ SDL_QuitSubSystem(SDL_INIT_VIDEO);
+ }
+}
+
+/*
+==========================================================================
+
+EVENTS
+
+==========================================================================
+*/
+
+static void window_event(SDL_WindowEvent *event)
+{
+ Uint32 flags = SDL_GetWindowFlags(sdl_window);
+ active_t active;
+ vrect_t rc;
+
+ switch (event->event) {
+ case SDL_WINDOWEVENT_MINIMIZED:
+ case SDL_WINDOWEVENT_RESTORED:
+ case SDL_WINDOWEVENT_ENTER:
+ case SDL_WINDOWEVENT_LEAVE:
+ case SDL_WINDOWEVENT_FOCUS_GAINED:
+ case SDL_WINDOWEVENT_FOCUS_LOST:
+ if (flags & (SDL_WINDOW_INPUT_FOCUS | SDL_WINDOW_MOUSE_FOCUS)) {
+ active = ACT_ACTIVATED;
+ } else if (flags & SDL_WINDOW_MINIMIZED) {
+ active = ACT_MINIMIZED;
+ } else {
+ active = ACT_RESTORED;
+ }
+ CL_Activate(active);
+ break;
+
+ case SDL_WINDOWEVENT_MOVED:
+ if (!(flags & SDL_WINDOW_FULLSCREEN)) {
+ SDL_GetWindowSize(sdl_window, &rc.width, &rc.height);
+ rc.x = event->data1;
+ rc.y = event->data2;
+ VID_SetGeometry(&rc);
+ }
+ break;
+
+ case SDL_WINDOWEVENT_RESIZED:
+ if (!(flags & SDL_WINDOW_FULLSCREEN)) {
+ SDL_GetWindowPosition(sdl_window, &rc.x, &rc.y);
+ rc.width = event->data1;
+ rc.height = event->data2;
+ VID_SetGeometry(&rc);
+ }
+ VID_SDL_ModeChanged();
+ break;
+ }
+}
+
+static const byte scantokey[128] = {
+// 0 1 2 3 4 5 6 7
+// 8 9 A B C D E F
+ 0, 0, 0, 0, 'a', 'b', 'c', 'd', // 0
+ 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
+ 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', // 1
+ 'u', 'v', 'w', 'x', 'y', 'z', '1', '2',
+ '3', '4', '5', '6', '7', '8', '9', '0', // 2
+ K_ENTER, K_ESCAPE, K_BACKSPACE, K_TAB, K_SPACE, '-', '=', '[',
+ ']', '\\', 0, ';', '\'', '`', ',', '.', // 3
+ '/' , K_CAPSLOCK, K_F1, K_F2, K_F3, K_F4, K_F5, K_F6,
+ K_F7, K_F8, K_F9, K_F10, K_F11, K_F12, K_PRINTSCREEN, K_SCROLLOCK, // 4
+ K_PAUSE, K_INS, K_HOME, K_PGUP, K_DEL, K_END, K_PGDN, K_RIGHTARROW,
+ K_LEFTARROW, K_DOWNARROW, K_UPARROW, K_NUMLOCK, K_KP_SLASH, K_KP_MULTIPLY, K_KP_MINUS, K_KP_PLUS, // 5
+ K_KP_ENTER, K_KP_END, K_KP_DOWNARROW, K_KP_PGDN, K_KP_LEFTARROW, K_KP_5, K_KP_RIGHTARROW, K_KP_HOME,
+ K_KP_UPARROW, K_KP_PGUP, K_KP_INS, K_KP_DEL, K_102ND, 0, 0, 0, // 6
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, K_MENU, 0, // 7
+ K_LCTRL, K_LSHIFT, K_LALT, K_LWINKEY, K_RCTRL, K_RSHIFT, K_RALT, K_RWINKEY, // E
+};
+
+static void key_event(SDL_KeyboardEvent *event)
+{
+ byte result;
+
+ if (event->keysym.scancode < 120)
+ result = scantokey[event->keysym.scancode];
+ else if (event->keysym.scancode >= 224 && event->keysym.scancode < 224 + 8)
+ result = scantokey[event->keysym.scancode - 104];
+ else
+ result = 0;
+
+ if (result == 0) {
+ Com_DPrintf("%s: unknown scancode %d\n", __func__, event->keysym.scancode);
+ return;
+ }
+
+ if (result == K_LALT || result == K_RALT)
+ Key_Event(K_ALT, event->state, event->timestamp);
+ else if (result == K_LCTRL || result == K_RCTRL)
+ Key_Event(K_CTRL, event->state, event->timestamp);
+ else if (result == K_LSHIFT || result == K_RSHIFT)
+ Key_Event(K_SHIFT, event->state, event->timestamp);
+
+ Key_Event(result, event->state, event->timestamp);
+}
+
+static void mouse_button_event(SDL_MouseButtonEvent *event)
+{
+ unsigned key;
+
+ switch (event->button) {
+ case SDL_BUTTON_LEFT:
+ key = K_MOUSE1;
+ break;
+ case SDL_BUTTON_RIGHT:
+ key = K_MOUSE2;
+ break;
+ case SDL_BUTTON_MIDDLE:
+ key = K_MOUSE3;
+ break;
+ case SDL_BUTTON_X1:
+ key = K_MOUSE4;
+ break;
+ case SDL_BUTTON_X2:
+ key = K_MOUSE5;
+ break;
+ default:
+ Com_DPrintf("%s: unknown button %d\n", __func__, event->button);
+ return;
+ }
+
+ Key_Event(key, event->state, event->timestamp);
+}
+
+static void mouse_wheel_event(SDL_MouseWheelEvent *event)
+{
+ if (event->x > 0) {
+ Key_Event(K_MWHEELRIGHT, qtrue, event->timestamp);
+ Key_Event(K_MWHEELRIGHT, qfalse, event->timestamp);
+ } else if (event->x < 0) {
+ Key_Event(K_MWHEELLEFT, qtrue, event->timestamp);
+ Key_Event(K_MWHEELLEFT, qfalse, event->timestamp);
+ }
+
+ if (event->y > 0) {
+ Key_Event(K_MWHEELUP, qtrue, event->timestamp);
+ Key_Event(K_MWHEELUP, qfalse, event->timestamp);
+ } else if (event->y < 0) {
+ Key_Event(K_MWHEELDOWN, qtrue, event->timestamp);
+ Key_Event(K_MWHEELDOWN, qfalse, event->timestamp);
+ }
+}
+
+/*
+============
+VID_PumpEvents
+============
+*/
+void VID_PumpEvents(void)
+{
+ SDL_Event event;
+
+ while (SDL_PollEvent(&event)) {
+ switch (event.type) {
+ case SDL_QUIT:
+ Com_Quit(NULL, ERR_DISCONNECT);
+ break;
+ case SDL_WINDOWEVENT:
+ window_event(&event.window);
+ break;
+ case SDL_KEYDOWN:
+ case SDL_KEYUP:
+ key_event(&event.key);
+ break;
+ case SDL_MOUSEMOTION:
+ UI_MouseEvent(event.motion.x, event.motion.y);
+ break;
+ case SDL_MOUSEBUTTONDOWN:
+ case SDL_MOUSEBUTTONUP:
+ mouse_button_event(&event.button);
+ break;
+ case SDL_MOUSEWHEEL:
+ mouse_wheel_event(&event.wheel);
+ break;
+ }
+ }
+}
+
+/*
+===============================================================================
+
+MOUSE
+
+===============================================================================
+*/
+
+static qboolean GetMouseMotion(int *dx, int *dy)
+{
+ if (!SDL_GetRelativeMouseMode()) {
+ return qfalse;
+ }
+ SDL_GetRelativeMouseState(dx, dy);
+ return qtrue;
+}
+
+static void WarpMouse(int x, int y)
+{
+ SDL_WarpMouseInWindow(sdl_window, x, y);
+ SDL_GetRelativeMouseState(NULL, NULL);
+}
+
+static void ShutdownMouse(void)
+{
+ SDL_SetWindowGrab(sdl_window, SDL_FALSE);
+ SDL_SetRelativeMouseMode(SDL_FALSE);
+ SDL_ShowCursor(SDL_ENABLE);
+}
+
+static qboolean InitMouse(void)
+{
+ if (SDL_WasInit(SDL_INIT_VIDEO) != SDL_INIT_VIDEO) {
+ return qfalse;
+ }
+
+ Com_Printf("SDL mouse initialized.\n");
+ return qtrue;
+}
+
+static void GrabMouse(qboolean grab)
+{
+ SDL_bool relative = grab && !(Key_GetDest() & KEY_MENU);
+ int cursor = (sdl_flags & QVF_FULLSCREEN) ? SDL_DISABLE : SDL_ENABLE;
+
+ SDL_SetWindowGrab(sdl_window, (SDL_bool)grab);
+ SDL_SetRelativeMouseMode(relative);
+ SDL_GetRelativeMouseState(NULL, NULL);
+ SDL_ShowCursor(cursor);
+}
+
+/*
+============
+VID_FillInputAPI
+============
+*/
+void VID_FillInputAPI(inputAPI_t *api)
+{
+ api->Init = InitMouse;
+ api->Shutdown = ShutdownMouse;
+ api->Grab = GrabMouse;
+ api->Warp = WarpMouse;
+ api->GetEvents = NULL;
+ api->GetMotion = GetMouseMotion;
+}
diff --git a/src/unix/system.c b/src/unix/system.c
index 24642a2..7772ec5 100644
--- a/src/unix/system.c
+++ b/src/unix/system.c
@@ -38,6 +38,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include <dlfcn.h>
#include <errno.h>
+#if USE_SDL
+#include <SDL_main.h>
+#endif
+
cvar_t *sys_basedir;
cvar_t *sys_libdir;
cvar_t *sys_homedir;