Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 59 additions & 5 deletions src/desktop/backends/glfw2.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#ifdef _WIN32
#include <windows.h>
#include <mmsystem.h>
#endif

#ifdef ENABLE_SW_RENDERER
Expand Down Expand Up @@ -39,9 +40,29 @@ bool platformGetScaledWindowSize(int32_t* outW, int32_t* outH) {
return platformGetWindowSize(outW, outH);
}

static void platformGetTrueDesktopSize(int* outW, int* outH) {
GLFWvidmode list[256];
int numModes = glfwGetVideoModes(list, 256);

if (numModes > 0) {
*outW = list[numModes - 1].Width;
*outH = list[numModes - 1].Height;
} else {
GLFWvidmode mode;
glfwGetDesktopMode(&mode);
*outW = mode.Width;
*outH = mode.Height;
}
}

void platformSetWindowSize(int32_t width, int32_t height) {
if (width <= 0 || height <= 0) return;
if (!platformCacheWindowSize(width, height)) return;
glfwSetWindowSize(width, height);

int desktopW, desktopH;
platformGetTrueDesktopSize(&desktopW, &desktopH);
glfwSetWindowPos(((desktopW - width) / 2), ((desktopH - height) / 2));
}

void platformGetMousePos(double *xPos, double *yPos) {
Expand Down Expand Up @@ -139,8 +160,8 @@ static void GLFWCALL mouseButtonCallback(int button, int action) {
else if (action == GLFW_RELEASE) RunnerMouse_onButtonUp(g_runner->mouse, gmlButton);
}

static int g_last_wheel_pos = 0;
static void GLFWCALL scrollCallback(int pos) {
static int g_last_wheel_pos = 0;
double yoffset = (double)(pos - g_last_wheel_pos);
g_last_wheel_pos = pos;
if (g_runner) RunnerMouse_onWheel(g_runner->mouse, yoffset);
Expand All @@ -151,7 +172,9 @@ bool platformInit(int32_t reqW, int32_t reqH, const char *title, bool headless)
fprintf(stderr, "Headless mode is not supported with GLFW 2\n");
return false;
}

#ifdef _WIN32
timeBeginPeriod(1);
#endif
#ifdef GLFW_OPENGL_VERSION_MAJOR
if (gfx == SOFTWARE) {
glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 1);
Expand All @@ -177,6 +200,9 @@ bool platformInit(int32_t reqW, int32_t reqH, const char *title, bool headless)
// Init GLFW
if (!glfwInit()) {
fprintf(stderr, "Failed to initialize GLFW\n");
#ifdef _WIN32
timeEndPeriod(1);
#endif
return false;
}

Expand All @@ -196,12 +222,27 @@ bool platformInit(int32_t reqW, int32_t reqH, const char *title, bool headless)
}
#endif

int window = glfwOpenWindow(reqW, reqH, 8, 8, 8, 8, 24, 8, GLFW_WINDOW);
int desktopW, desktopH;
platformGetTrueDesktopSize(&desktopW, &desktopH);

int finalW = reqW;
int finalH = reqH;
if (reqW >= desktopW || reqH >= desktopH) {
platformGetBestFitRes(reqW, reqH, desktopW, desktopH, &finalW, &finalH);
fprintf(stderr, "Warning: Requested resolution %dx%d is bigger than %dx%d, adjusting to %dx%d\n",
reqW, reqH, desktopW, desktopH, finalW, finalH);
}

int window = glfwOpenWindow(finalW, finalH, 8, 8, 8, 8, 24, 8, GLFW_WINDOW);
if (!window) {
fprintf(stderr, "Failed to create GLFW window\n");
glfwTerminate();
#ifdef _WIN32
timeEndPeriod(1);
#endif
return false;
}
glfwSetWindowPos(((desktopW - finalW) / 2), ((desktopH - finalH) / 2));

glfwSetWindowTitle(title);

Expand All @@ -220,14 +261,27 @@ bool platformInit(int32_t reqW, int32_t reqH, const char *title, bool headless)
void platformExit(void) {
glfwCloseWindow();
glfwTerminate();
#ifdef _WIN32
timeEndPeriod(1);
#endif
}

// GLFW2's mouse cursor locks the mouse position when it's invisible on Windows.
// This just makes it visible/invisible as intended.
static void platformSetCursor(int32_t cursorType) {
// GLFW2 only supports showing/hiding
if (cursorType == GML_CR_NONE) {
#ifdef _WIN32
while (ShowCursor(FALSE) >= 0);
#else
glfwDisable(GLFW_MOUSE_CURSOR);
#endif
} else {
#ifdef _WIN32
while (ShowCursor(TRUE) < 0);
#else
glfwEnable(GLFW_MOUSE_CURSOR);
#endif
}
}

Expand Down Expand Up @@ -269,7 +323,7 @@ void platformSwapBuffers(void) {

void *platformGetProcAddress(const char *name) {
#ifdef _WIN32
// glfw2's glfwGetProcAddress is broken on Windows.
// GLFW2's glfwGetProcAddress is broken on Windows.
// This just implements it in a way that's fixed so it can be passed to GLAD.
void *ret = (void *)wglGetProcAddress(name);
// Fallback for driver-specific error codes and legacy OpenGL core functions.
Expand All @@ -292,7 +346,7 @@ bool platformHandleEvents(void) {
}

void platformSleepUntil(uint64_t time) {
double remaining = ((int64_t)time - nowNanos()) / 1000000000.0;
double remaining = ((int64_t)time - (int64_t)nowNanos()) / 1000000000.0;
if (remaining > 0.002) // glfwSleep takes seconds as a double
glfwSleep(remaining - 0.001);

Expand Down
43 changes: 38 additions & 5 deletions src/desktop/backends/glfw3.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#ifdef _WIN32
#include <windows.h>
#include <mmsystem.h>
#endif

#ifdef ENABLE_SW_RENDERER
Expand Down Expand Up @@ -57,13 +58,20 @@ bool platformGetScaledWindowSize(int32_t* outW, int32_t* outH) {
}

void platformSetWindowSize(int32_t width, int32_t height) {
if (width <= 0 || height <= 0) return;
if (!window) return;
if (width <= 0 || height <= 0 || !window) return;
if (glfwGetWindowAttrib(window, GLFW_MAXIMIZED)) return;
if (!platformCacheWindowSize(width, height)) return;

float xs = 1.0f, ys = 1.0f;
glfwGetWindowContentScale(window, &xs, &ys);
int logicalW, logicalH;
framebufferToLogical(xs, ys, width, height, &logicalW, &logicalH);
glfwSetWindowSize(window, logicalW, logicalH);

const GLFWvidmode* mode = glfwGetVideoMode(glfwGetPrimaryMonitor());
if (mode != NULL) {
glfwSetWindowPos(window, ((mode->width - logicalW) / 2), ((mode->height - logicalH) / 2));
}
}

void platformGetMousePos(double *xPos, double *yPos) {
Expand All @@ -72,7 +80,7 @@ void platformGetMousePos(double *xPos, double *yPos) {
}

static bool platformGetWindowFocus(void) {
return glfwGetWindowAttrib(window, GLFW_FOCUSED) != 0;
return glfwGetWindowAttrib(window, GLFW_FOCUSED);
}

static void glfwErrorCallback(int code, const char* description) {
Expand Down Expand Up @@ -170,10 +178,16 @@ static void scrollCallback(GLFWwindow* window, double xoffset, double yoffset) {
}

bool platformInit(int32_t reqW, int32_t reqH, const char *title, bool headless) {
#ifdef _WIN32
timeBeginPeriod(1);
#endif
// Init GLFW
glfwSetErrorCallback(glfwErrorCallback);
if (!glfwInit()) {
fprintf(stderr, "Failed to initialize GLFW\n");
#ifdef _WIN32
timeEndPeriod(1);
#endif
return false;
}

Expand Down Expand Up @@ -224,10 +238,26 @@ bool platformInit(int32_t reqW, int32_t reqH, const char *title, bool headless)
if (headless)
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);

window = glfwCreateWindow(reqW, reqH, title, nullptr, nullptr);
int finalW = reqW;
int finalH = reqH;
GLFWmonitor* primaryMonitor = glfwGetPrimaryMonitor();
if (primaryMonitor) {
int workX, workY, workW, workH;
glfwGetMonitorWorkarea(primaryMonitor, &workX, &workY, &workW, &workH);
if (reqW >= workW || reqH >= workH) {
platformGetBestFitRes(reqW, reqH, workW, workH, &finalW, &finalH);
fprintf(stderr, "Warning: Requested resolution %dx%d is bigger than %dx%d, adjusting to %dx%d\n",
reqW, reqH, workW, workH, finalW, finalH);
}
}

window = glfwCreateWindow(finalW, finalH, title, nullptr, nullptr);
if (!window) {
fprintf(stderr, "Failed to create GLFW window\n");
glfwTerminate();
#ifdef _WIN32
timeEndPeriod(1);
#endif
return false;
}

Expand All @@ -236,7 +266,7 @@ bool platformInit(int32_t reqW, int32_t reqH, const char *title, bool headless)

// If we don't do this, the window will be larger than it should be if you are using Wayland fractional scaling
// We set the window size AFTER the window creation so we can use glfwGetWindowContentScale
platformSetWindowSize(reqW, reqH);
platformSetWindowSize(finalW, finalH);

// Set up keyboard input
glfwSetKeyCallback(window, keyCallback);
Expand All @@ -251,6 +281,9 @@ bool platformInit(int32_t reqW, int32_t reqH, const char *title, bool headless)
void platformExit(void) {
glfwDestroyWindow(window);
glfwTerminate();
#ifdef _WIN32
timeEndPeriod(1);
#endif
}

static void platformSetCursor(int32_t cursorType) {
Expand Down
75 changes: 65 additions & 10 deletions src/desktop/backends/sdl1.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,10 @@ bool platformGetScaledWindowSize(int32_t* outW, int32_t* outH) {

void platformSetWindowSize(int32_t width, int32_t height) {
if (width <= 0 || height <= 0) return;
if (!platformCacheWindowSize(width, height)) return;
fbWidth = width;
fbHeight = height;
scr = SDL_SetVideoMode(width, height, 0, (gfx == SOFTWARE ? 0 : SDL_OPENGL) | SDL_RESIZABLE);
scr = SDL_SetVideoMode(fbWidth, fbHeight, 0, (gfx == SOFTWARE ? 0 : SDL_OPENGL) | SDL_RESIZABLE);
}

void platformGetMousePos(double *xPos, double *yPos) {
Expand All @@ -59,30 +60,76 @@ static bool platformGetWindowFocus(void) {
return SDL_GetAppState() & SDL_APPINPUTFOCUS;
}

#if !SDL_VERSION_ATLEAST(1, 2, 10)
static inline void platformGetTrueDesktopSize(int* outW, int* outH) {
SDL_Rect** modes = SDL_ListModes(NULL, SDL_FULLSCREEN);
if (modes != (SDL_Rect**)0 && modes != (SDL_Rect**)-1) {
int maxHardwareW = 0;
int maxHardwareH = 0;
int i;

for (i = 0; modes[i]; ++i) {
if (modes[i]->w > maxHardwareW) maxHardwareW = modes[i]->w;
if (modes[i]->h > maxHardwareH) maxHardwareH = modes[i]->h;
}

if (maxHardwareW > 0 && maxHardwareH > 0) {
if (maxHardwareW < *outW) *outW = maxHardwareW;
if (maxHardwareH < *outH) *outH = maxHardwareH;
}
}
}
#endif

bool platformInit(int32_t reqW, int32_t reqH, const char *title, bool headless) {
if (headless && gfx != SOFTWARE) {
fprintf(stderr, "Headless mode on SDL 1.2 requires the software renderer!\n");
return false;
}

#if SDL_VERSION_ATLEAST(1, 2, 10) // Old SDL1.2: Center pos doesn't matter assuming it's running in low res
SDL_putenv("SDL_VIDEO_WINDOW_POS=center");
#endif

// Init SDL
if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER)) {
fprintf(stderr, "Failed to initialize SDL\n");
return false;
}

fbWidth = reqW;
fbHeight = reqH;
if(!headless) {
int finalW = reqW;
int finalH = reqH;
#if SDL_VERSION_ATLEAST(1, 2, 10)
const SDL_VideoInfo* info = SDL_GetVideoInfo();
if (info && (reqW >= info->current_w || reqH >= info->current_h)) {
platformGetBestFitRes(reqW, reqH, info->current_w, info->current_h, &finalW, &finalH);
fprintf(stderr, "Warning: Requested resolution %dx%d is bigger than %dx%d, adjusting to %dx%d\n",
reqW, reqH, info->current_w, info->current_h, finalW, finalH);
}
#else
// Old SDL1.2: Set a default lower res then check if the screen supports it, if not, use the max supported res
int oldW = 800;
int oldH = 600;
platformGetTrueDesktopSize(oldW, oldH);
if (reqW >= oldW || reqH >= oldH) {
platformGetBestFitRes(reqW, reqH, oldW, oldH, &finalW, &finalH);
fprintf(stderr, "Warning: Requested resolution %dx%d is bigger than %dx%d, adjusting to %dx%d\n",
reqW, reqH, oldW, oldH, finalW, finalH);
}
#endif

fbWidth = finalW;
fbHeight = finalH;
if (!headless) {
scr = SDL_SetVideoMode(fbWidth, fbHeight, 0, (gfx == SOFTWARE ? 0 : SDL_OPENGL) | SDL_RESIZABLE);
if (!scr && gfx == SOFTWARE) {
SDL_Rect** modes = SDL_ListModes(NULL, SDL_FULLSCREEN);
if (modes && modes != (SDL_Rect**) -1 && modes[0]) {
fprintf(stderr, "Warning: %dx%d unavailable, falling back to %dx%d: %s\n",
reqW, reqH, modes[0]->w, modes[0]->h, SDL_GetError());
scr = SDL_SetVideoMode(modes[0]->w, modes[0]->h, 0, 0);
fbWidth, fbHeight, modes[0]->w, modes[0]->h, SDL_GetError());
fbWidth = modes[0]->w;
fbHeight = modes[0]->h;
scr = SDL_SetVideoMode(fbWidth, fbHeight, 0, 0);
}
}
if (!scr) {
Expand Down Expand Up @@ -217,21 +264,30 @@ static int32_t SDLMouseButtonToGml(int sdlButton) {
bool platformHandleEvents(void) {
SDL_Event e;
while (SDL_PollEvent(&e)) {
switch (e.type) {
default:
if (InputRecording_isPlaybackActive(globalInputRecording)) continue;
break;
case SDL_VIDEORESIZE:
case SDL_QUIT:
break;
}
switch(e.type) {
case SDL_KEYDOWN:
// SDL1.2 needs to manually intercept Alt+F4 to exit properly
if (e.key.keysym.sym == SDLK_F4 && (e.key.keysym.mod & KMOD_ALT)) {
return true;
}
// During playback, suppress real keyboard input
if (InputRecording_isPlaybackActive(globalInputRecording)) break;
RunnerKeyboard_onKeyDown(g_runner->keyboard, SDLKeyToGml(e.key.keysym.sym));
if (e.key.keysym.unicode != 0)
RunnerKeyboard_onCharacter(g_runner->keyboard, e.key.keysym.unicode);
break;
case SDL_KEYUP:
// During playback, suppress real keyboard input
if (InputRecording_isPlaybackActive(globalInputRecording)) break;
RunnerKeyboard_onKeyUp(g_runner->keyboard, SDLKeyToGml(e.key.keysym.sym));
break;
case SDL_MOUSEBUTTONDOWN:
if (InputRecording_isPlaybackActive(globalInputRecording)) break;
if (e.button.button == SDL_BUTTON_WHEELUP) {
RunnerMouse_onWheel(g_runner->mouse, 1.0);
} else if (e.button.button == SDL_BUTTON_WHEELDOWN) {
Expand All @@ -242,7 +298,6 @@ bool platformHandleEvents(void) {
}
break;
case SDL_MOUSEBUTTONUP:
if (InputRecording_isPlaybackActive(globalInputRecording)) break;
if (e.button.button != SDL_BUTTON_WHEELUP && e.button.button != SDL_BUTTON_WHEELDOWN) {
int32_t gmlBtn = SDLMouseButtonToGml(e.button.button);
if (gmlBtn >= 0) RunnerMouse_onButtonUp(g_runner->mouse, gmlBtn);
Expand Down
Loading
Loading