#include "gl_local.h"
#include "../client/keys.h"
#include <GLFW/glfw3.h>
void *global_uv_loop(void);
uint64_t uv_now(const void *);
GLFWwindow *glfw_window;
extern unsigned sys_msg_time;
extern void AppActivate(bool fActive, bool minimize);
static void mouse_button_callback(GLFWwindow *window, int button, int action, int mods) {
int index = button - GLFW_MOUSE_BUTTON_1;
if(action == GLFW_PRESS)
Key_Event(K_MOUSE1 + index, true, sys_msg_time);
else if(action == GLFW_RELEASE)
Key_Event(K_MOUSE1 + index, false, sys_msg_time);
}
static void scroll_callback(GLFWwindow *window, double xoffset, double yoffset) {
if(yoffset > 0) {
Key_Event(K_MWHEELUP, true, sys_msg_time);
Key_Event(K_MWHEELUP, false, sys_msg_time);
} else if(yoffset < 0) {
Key_Event(K_MWHEELDOWN, true, sys_msg_time);
Key_Event(K_MWHEELDOWN, false, sys_msg_time);
}
}
static void window_iconify_callback(GLFWwindow *window, int iconified) { AppActivate(true, iconified); }
static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods) {
static const int key_map[GLFW_KEY_LAST + 1] = {
[GLFW_KEY_SPACE] = ' ', [GLFW_KEY_APOSTROPHE] = '\'', [GLFW_KEY_COMMA] = ',', [GLFW_KEY_MINUS] = '-', [GLFW_KEY_PERIOD] = '.', [GLFW_KEY_SLASH] = '/', [GLFW_KEY_0] = '0', [GLFW_KEY_1] = '1', [GLFW_KEY_2] = '2', [GLFW_KEY_3] = '3', [GLFW_KEY_4] = '4', [GLFW_KEY_5] = '5', [GLFW_KEY_6] = '6', [GLFW_KEY_7] = '7', [GLFW_KEY_8] = '8', [GLFW_KEY_9] = '9', [GLFW_KEY_SEMICOLON] = ';', [GLFW_KEY_EQUAL] = '=', [GLFW_KEY_A] = 'a', [GLFW_KEY_B] = 'b', [GLFW_KEY_C] = 'c', [GLFW_KEY_D] = 'd', [GLFW_KEY_E] = 'e', [GLFW_KEY_F] = 'f', [GLFW_KEY_G] = 'g', [GLFW_KEY_H] = 'h', [GLFW_KEY_I] = 'i', [GLFW_KEY_J] = 'j', [GLFW_KEY_K] = 'k', [GLFW_KEY_L] = 'l', [GLFW_KEY_M] = 'm', [GLFW_KEY_N] = 'n', [GLFW_KEY_O] = 'o', [GLFW_KEY_P] = 'p', [GLFW_KEY_Q] = 'q', [GLFW_KEY_R] = 'r', [GLFW_KEY_S] = 's', [GLFW_KEY_T] = 't', [GLFW_KEY_U] = 'u', [GLFW_KEY_V] = 'v', [GLFW_KEY_W] = 'w', [GLFW_KEY_X] = 'x', [GLFW_KEY_Y] = 'y', [GLFW_KEY_Z] = 'z', [GLFW_KEY_LEFT_BRACKET] = '[', [GLFW_KEY_BACKSLASH] = '\\', [GLFW_KEY_RIGHT_BRACKET] = ']', [GLFW_KEY_GRAVE_ACCENT] = '`', [GLFW_KEY_WORLD_1] = -1, [GLFW_KEY_WORLD_2] = -1, [GLFW_KEY_ESCAPE] = K_ESCAPE, [GLFW_KEY_ENTER] = K_ENTER, [GLFW_KEY_TAB] = K_TAB, [GLFW_KEY_BACKSPACE] = K_BACKSPACE, [GLFW_KEY_INSERT] = K_INS, [GLFW_KEY_DELETE] = K_DEL, [GLFW_KEY_RIGHT] = K_RIGHTARROW, [GLFW_KEY_LEFT] = K_LEFTARROW, [GLFW_KEY_DOWN] = K_DOWNARROW, [GLFW_KEY_UP] = K_UPARROW, [GLFW_KEY_PAGE_UP] = K_PGUP, [GLFW_KEY_PAGE_DOWN] = K_PGDN, [GLFW_KEY_HOME] = K_HOME, [GLFW_KEY_END] = K_END, [GLFW_KEY_CAPS_LOCK] = -1, [GLFW_KEY_SCROLL_LOCK] = -1, [GLFW_KEY_NUM_LOCK] = -1, [GLFW_KEY_PRINT_SCREEN] = -1, [GLFW_KEY_PAUSE] = K_PAUSE, [GLFW_KEY_F1] = K_F1, [GLFW_KEY_F2] = K_F2, [GLFW_KEY_F3] = K_F3, [GLFW_KEY_F4] = K_F4, [GLFW_KEY_F5] = K_F5, [GLFW_KEY_F6] = K_F6, [GLFW_KEY_F7] = K_F7, [GLFW_KEY_F8] = K_F8, [GLFW_KEY_F9] = K_F9, [GLFW_KEY_F10] = K_F10, [GLFW_KEY_F11] = K_F11, [GLFW_KEY_F12] = K_F12, [GLFW_KEY_F13] = -1, [GLFW_KEY_F14] = -1, [GLFW_KEY_F15] = -1, [GLFW_KEY_F16] = -1, [GLFW_KEY_F17] = -1, [GLFW_KEY_F18] = -1, [GLFW_KEY_F19] = -1, [GLFW_KEY_F20] = -1, [GLFW_KEY_F21] = -1, [GLFW_KEY_F22] = -1, [GLFW_KEY_F23] = -1, [GLFW_KEY_F24] = -1, [GLFW_KEY_F25] = -1, [GLFW_KEY_KP_0] = K_KP_INS, [GLFW_KEY_KP_1] = K_KP_END, [GLFW_KEY_KP_2] = K_KP_DOWNARROW, [GLFW_KEY_KP_3] = K_KP_PGDN, [GLFW_KEY_KP_4] = K_KP_LEFTARROW, [GLFW_KEY_KP_5] = K_KP_5, [GLFW_KEY_KP_6] = K_KP_RIGHTARROW, [GLFW_KEY_KP_7] = K_KP_HOME, [GLFW_KEY_KP_8] = K_KP_UPARROW, [GLFW_KEY_KP_9] = K_KP_PGUP, [GLFW_KEY_KP_DECIMAL] = K_KP_DEL, [GLFW_KEY_KP_DIVIDE] = K_KP_SLASH, [GLFW_KEY_KP_MULTIPLY] = -1, [GLFW_KEY_KP_SUBTRACT] = K_KP_MINUS, [GLFW_KEY_KP_ADD] = K_KP_PLUS, [GLFW_KEY_KP_ENTER] = K_KP_ENTER, [GLFW_KEY_KP_EQUAL] = -1, [GLFW_KEY_LEFT_SHIFT] = K_SHIFT, [GLFW_KEY_LEFT_CONTROL] = -1, [GLFW_KEY_LEFT_ALT] = -1, [GLFW_KEY_LEFT_SUPER] = -1, [GLFW_KEY_RIGHT_SHIFT] = K_SHIFT, [GLFW_KEY_RIGHT_CONTROL] = -1, [GLFW_KEY_RIGHT_ALT] = -1, [GLFW_KEY_RIGHT_SUPER] = -1, [GLFW_KEY_MENU] = -1, };
if(action == GLFW_REPEAT || key == GLFW_KEY_UNKNOWN)
return;
key = key_map[key];
if(key > 0)
Key_Event(key, action == GLFW_PRESS, uv_now(&global_uv_loop));
}
rserr_t GLimp_SetMode(uint32_t *pwidth, uint32_t *pheight, int mode, bool fullscreen) {
int width, height;
if(glfw_window) {
glfwTerminate();
if(!GLimp_Init(NULL, NULL))
return rserr_unknown;
}
if(!ri.Vid_GetModeInfo(&width, &height, mode)) {
ri.Con_Printf(PRINT_ALL, " invalid mode\n");
return rserr_invalid_mode;
}
GLFWmonitor *monitor = NULL;
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE);
glfw_window = glfwCreateWindow(width, height, "Quake 2", monitor, NULL);
if(!glfw_window) {
if(fullscreen)
return rserr_invalid_fullscreen;
return rserr_unknown;
}
glfwSetScrollCallback(glfw_window, scroll_callback);
glfwSetMouseButtonCallback(glfw_window, mouse_button_callback);
glfwSetKeyCallback(glfw_window, key_callback);
glfwSetWindowIconifyCallback(glfw_window, window_iconify_callback);
glfwMakeContextCurrent(glfw_window);
ri.Vid_NewWindow(width, height);
*pwidth = width;
*pheight = height;
AppActivate(true, false);
return rserr_ok;
}
int GLimp_Init(void *a, void *b) {
if(!glfwInit())
return false;
return true;
}
void GLimp_Shutdown(void) {}
void GLimp_BeginFrame(float ignore) {}
void GLimp_EndFrame(void) { glfwSwapBuffers(glfw_window); }
void GLimp_AppActivate(bool active) {
if(active) {
glfwRestoreWindow(glfw_window);
} else {
if(vid_fullscreen->value)
glfwIconifyWindow(glfw_window);
}
}