Skip to content
Draft
Show file tree
Hide file tree
Changes from 2 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
67 changes: 62 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;
PLATFORM_CACHE_WINDOW_SIZE(width, height);
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) {
PLATFORM_GET_BEST_FIT_RES(reqW, reqH, desktopW, desktopH, finalW, finalH);
fprintf(stderr, "Warning: Requested resolution %dx%d is bigger than the screen, adjusting to %dx%d\n",
reqW, reqH, 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,10 @@ bool platformHandleEvents(void) {
}

void platformSleepUntil(uint64_t time) {
double remaining = ((int64_t)time - nowNanos()) / 1000000000.0;
int64_t delta = (int64_t)time - nowNanos();
if (delta <= 0) return; // If the target timestamp is already in the past, skip sleeping
Comment thread
AloXado320 marked this conversation as resolved.
Outdated

double remaining = delta / 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;
PLATFORM_CACHE_WINDOW_SIZE(width, height);

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) {
PLATFORM_GET_BEST_FIT_RES(reqW, reqH, workW, workH, finalW, finalH);
fprintf(stderr, "Warning: Requested resolution %dx%d is bigger than the screen, adjusting to %dx%d\n",
reqW, reqH, 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
70 changes: 60 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;
PLATFORM_CACHE_WINDOW_SIZE(width, height);
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,71 @@ static bool platformGetWindowFocus(void) {
return SDL_GetAppState() & SDL_APPINPUTFOCUS;
}

// SDL1.2 redirects stdio messages to stdout.txt and stderr.txt on Windows in SDL_main
Comment thread
AloXado320 marked this conversation as resolved.
Outdated
// So set the env variable to 0 before it reaches out main so there's no need to set it manually
#ifdef _WIN32
#if defined(__GNUC__) || defined(__clang__)
__attribute__((constructor)) static void platformDisableRedirect(void) {
SDL_putenv("SDL_STDIO_REDIRECT=0");
}
#elif defined(_MSC_VER)
static int platformDisableRedirect(void) {
SDL_putenv("SDL_STDIO_REDIRECT=0");
return 0;
}
#pragma section(".CRT$XCU", read)
__declspec(allocate(".CRT$XCU")) static int (*pDisableRedirect)(void) = platformDisableRedirect;
#endif
#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)) {
PLATFORM_GET_BEST_FIT_RES(reqW, reqH, info->current_w, info->current_h, finalW, finalH);
fprintf(stderr, "Warning: Requested resolution %dx%d is bigger than the screen, adjusting to %dx%d\n",
reqW, reqH, finalW, finalH);
}
#else
// Old SDL1.2: Set a period appropriate resolution as fallback
int oldW = 1024;
Comment thread
AloXado320 marked this conversation as resolved.
Outdated
int oldH = 768;
if (reqW >= oldW || reqH >= oldH) {
PLATFORM_GET_BEST_FIT_RES(reqW, reqH, oldW, oldH, finalW, finalH);
fprintf(stderr, "Warning: Requested resolution %dx%d is bigger than the screen, adjusting to %dx%d\n",
reqW, reqH, 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 +259,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;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this break; it does nothing

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 +293,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