kitty/kitty/glfw.c

771 lines
22 KiB
C

/*
* Copyright (C) 2016 Kovid Goyal <kovid at kovidgoyal.net>
*
* Distributed under terms of the GPL3 license.
*/
#include "state.h"
#include <structmember.h>
#include <GLFW/glfw3.h>
#if defined(__APPLE__)
#define GLFW_EXPOSE_NATIVE_COCOA
#include <GLFW/glfw3native.h>
#endif
#if GLFW_VERSION_MAJOR < 3 || (GLFW_VERSION_MAJOR == 3 && GLFW_VERSION_MINOR < 2)
#error "glfw >= 3.2 required"
#endif
#if GLFW_VERSION_MAJOR > 3 || (GLFW_VERSION_MAJOR == 3 && GLFW_VERSION_MINOR > 2)
#define has_request_attention
#define has_init_hint_string
#endif
#if GLFW_KEY_LAST >= MAX_KEY_COUNT
#error "glfw has too many keys, you should increase MAX_KEY_COUNT"
#endif
#define CALLBACK(name, fmt, ...) \
if ((name) != NULL) { \
PyObject *_pyret = PyObject_CallFunction((name), fmt, __VA_ARGS__); \
if (_pyret == NULL) PyErr_Print(); \
else Py_DECREF(_pyret); \
}
#define WINDOW_CALLBACK(name, fmt, ...) \
CALLBACK(the_window->name, "O" fmt, the_window, __VA_ARGS__);
typedef struct {
PyObject_HEAD
GLFWwindow *window;
PyObject *framebuffer_size_callback, *window_focus_callback;
GLFWcursor *standard_cursor, *click_cursor, *arrow_cursor;
} WindowWrapper;
static void update_viewport(GLFWwindow *window) {
int w, h;
glfwGetFramebufferSize(window, &global_state.viewport_width, &global_state.viewport_height);
glfwGetWindowSize(window, &w, &h);
global_state.viewport_x_ratio = (double)global_state.viewport_width / (double)w;
global_state.viewport_y_ratio = (double)global_state.viewport_height / (double)h;
}
// callbacks {{{
static WindowWrapper* the_window = NULL;
update_viewport_size_func update_viewport_size = NULL;
static void
framebuffer_size_callback(GLFWwindow *w, int width, int height) {
if (width > 100 && height > 100) {
update_viewport_size(width, height);
update_viewport(w);
WINDOW_CALLBACK(framebuffer_size_callback, "ii", width, height);
glfwPostEmptyEvent();
} else fprintf(stderr, "Ignoring resize request for tiny size: %dx%d\n", width, height);
}
static void
char_mods_callback(GLFWwindow UNUSED *w, unsigned int codepoint, int mods) {
global_state.cursor_blink_zero_time = monotonic();
on_text_input(codepoint, mods);
}
static void
key_callback(GLFWwindow UNUSED *w, int key, int scancode, int action, int mods) {
global_state.cursor_blink_zero_time = monotonic();
if (key >= 0 && key <= GLFW_KEY_LAST) {
global_state.is_key_pressed[key] = action == GLFW_RELEASE ? false : true;
on_key_input(key, scancode, action, mods);
}
}
static void
mouse_button_callback(GLFWwindow *w, int button, int action, int mods) {
if (glfwGetInputMode(w, GLFW_CURSOR) != GLFW_CURSOR_NORMAL) { glfwSetInputMode(w, GLFW_CURSOR, GLFW_CURSOR_NORMAL); }
double now = monotonic();
global_state.last_mouse_activity_at = now;
if (button >= 0 && (unsigned int)button < sizeof(global_state.mouse_button_pressed)/sizeof(global_state.mouse_button_pressed[0])) {
global_state.mouse_button_pressed[button] = action == GLFW_PRESS ? true : false;
mouse_event(button, mods);
}
}
static void
cursor_pos_callback(GLFWwindow *w, double x, double y) {
if (glfwGetInputMode(w, GLFW_CURSOR) != GLFW_CURSOR_NORMAL) { glfwSetInputMode(w, GLFW_CURSOR, GLFW_CURSOR_NORMAL); }
double now = monotonic();
global_state.last_mouse_activity_at = now;
global_state.cursor_blink_zero_time = now;
global_state.mouse_x = x * global_state.viewport_x_ratio;
global_state.mouse_y = y * global_state.viewport_y_ratio;
mouse_event(-1, 0);
}
static void
scroll_callback(GLFWwindow *w, double xoffset, double yoffset) {
if (glfwGetInputMode(w, GLFW_CURSOR) != GLFW_CURSOR_NORMAL) { glfwSetInputMode(w, GLFW_CURSOR, GLFW_CURSOR_NORMAL); }
double now = monotonic();
global_state.last_mouse_activity_at = now;
scroll_event(xoffset, yoffset);
}
static void
window_focus_callback(GLFWwindow UNUSED *w, int focused) {
global_state.application_focused = focused ? true : false;
double now = monotonic();
global_state.last_mouse_activity_at = now;
global_state.cursor_blink_zero_time = now;
WINDOW_CALLBACK(window_focus_callback, "O", focused ? Py_True : Py_False);
}
// }}}
void
set_mouse_cursor(MouseShape type) {
switch(type) {
case HAND:
glfwSetCursor(the_window->window, the_window->click_cursor);
break;
case ARROW:
glfwSetCursor(the_window->window, the_window->arrow_cursor);
break;
default:
glfwSetCursor(the_window->window, the_window->standard_cursor);
break;
}
}
static PyObject*
new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
WindowWrapper *self;
char *title;
int width, height;
if (!PyArg_ParseTuple(args, "iis", &width, &height, &title)) return NULL;
if (the_window != NULL) { PyErr_SetString(PyExc_ValueError, "Only one glfw window is supported"); return NULL; }
self = (WindowWrapper *)type->tp_alloc(type, 0);
if (self != NULL) {
the_window = self;
self->window = glfwCreateWindow(width, height, title, NULL, NULL);
if (self->window == NULL) { Py_CLEAR(self); the_window = NULL; PyErr_SetString(PyExc_ValueError, "Failed to create GLFWwindow"); return NULL; }
update_viewport(self->window);
self->standard_cursor = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR);
self->click_cursor = glfwCreateStandardCursor(GLFW_HAND_CURSOR);
self->arrow_cursor = glfwCreateStandardCursor(GLFW_ARROW_CURSOR);
if (self->standard_cursor == NULL || self->click_cursor == NULL || self->arrow_cursor == NULL) {
Py_CLEAR(self); PyErr_SetString(PyExc_ValueError, "Failed to create standard mouse cursors"); return NULL; }
set_mouse_cursor(0);
glfwSetFramebufferSizeCallback(self->window, framebuffer_size_callback);
glfwSetCharModsCallback(self->window, char_mods_callback);
glfwSetMouseButtonCallback(self->window, mouse_button_callback);
glfwSetScrollCallback(self->window, scroll_callback);
glfwSetCursorPosCallback(self->window, cursor_pos_callback);
glfwSetKeyCallback(self->window, key_callback);
glfwSetWindowFocusCallback(self->window, window_focus_callback);
}
return (PyObject*)self;
}
// Global functions {{{
static void
error_callback(int error, const char* description) {
fprintf(stderr, "[glfw error %d]: %s\n", error, description);
}
PyObject*
glfw_init(PyObject UNUSED *self) {
glfwSetErrorCallback(error_callback);
PyObject *ans = glfwInit() ? Py_True: Py_False;
Py_INCREF(ans);
return ans;
}
PyObject*
glfw_terminate(PyObject UNUSED *self) {
glfwTerminate();
Py_RETURN_NONE;
}
PyObject*
glfw_window_hint(PyObject UNUSED *self, PyObject *args) {
int hint, value;
if (!PyArg_ParseTuple(args, "ii", &hint, &value)) return NULL;
glfwWindowHint(hint, value);
Py_RETURN_NONE;
}
PyObject*
glfw_swap_interval(PyObject UNUSED *self, PyObject *args) {
int value;
if (!PyArg_ParseTuple(args, "i", &value)) return NULL;
glfwSwapInterval(value);
Py_RETURN_NONE;
}
PyObject*
glfw_wait_events(PyObject UNUSED *self, PyObject *args) {
double time = -1;
if (PyTuple_GET_SIZE(args) > 0) {
time = PyFloat_AsDouble(PyTuple_GET_ITEM(args, 0));
if (PyErr_Occurred()) PyErr_Clear();
}
if (time < 0) glfwWaitEvents();
else glfwWaitEventsTimeout(time);
Py_RETURN_NONE;
}
PyObject*
glfw_post_empty_event(PyObject UNUSED *self) {
glfwPostEmptyEvent();
Py_RETURN_NONE;
}
static PyObject*
get_physical_dpi(GLFWmonitor *m) {
int width = 0, height = 0;
glfwGetMonitorPhysicalSize(m, &width, &height);
if (width == 0 || height == 0) { PyErr_SetString(PyExc_ValueError, "Failed to get primary monitor size"); return NULL; }
const GLFWvidmode *vm = glfwGetVideoMode(m);
if (vm == NULL) { PyErr_SetString(PyExc_ValueError, "Failed to get video mode for monitor"); return NULL; }
float dpix = vm->width / (width / 25.4);
float dpiy = vm->height / (height / 25.4);
return Py_BuildValue("ff", dpix, dpiy);
}
PyObject*
glfw_get_physical_dpi(PyObject UNUSED *self) {
GLFWmonitor *m = glfwGetPrimaryMonitor();
if (m == NULL) { PyErr_SetString(PyExc_ValueError, "Failed to get primary monitor"); return NULL; }
return get_physical_dpi(m);
}
PyObject*
glfw_get_key_name(PyObject UNUSED *self, PyObject *args) {
int key, scancode;
if (!PyArg_ParseTuple(args, "ii", &key, &scancode)) return NULL;
return Py_BuildValue("s", glfwGetKeyName(key, scancode));
}
PyObject*
glfw_init_hint_string(PyObject UNUSED *self, PyObject *args) {
int hint_id;
char *hint;
if (!PyArg_ParseTuple(args, "is", &hint_id, &hint)) return NULL;
#ifdef has_init_hint_string
glfwInitHintString(hint_id, hint);
#endif
Py_RETURN_NONE;
}
// }}}
static void
dealloc(WindowWrapper* self) {
the_window = NULL;
Py_CLEAR(self->framebuffer_size_callback); Py_CLEAR(self->window_focus_callback);
if (self->window != NULL) glfwDestroyWindow(self->window);
Py_TYPE(self)->tp_free((PyObject*)self);
}
static PyObject*
swap_buffers(WindowWrapper *self) {
glfwSwapBuffers(self->window);
Py_RETURN_NONE;
}
static PyObject*
make_context_current(WindowWrapper *self) {
glfwMakeContextCurrent(self->window);
Py_RETURN_NONE;
}
static PyObject*
window_id(WindowWrapper *self) {
return PyLong_FromVoidPtr(self->window);
}
static PyObject*
show(WindowWrapper *self) {
glfwShowWindow(self->window);
Py_RETURN_NONE;
}
static PyObject*
hide(WindowWrapper *self) {
glfwHideWindow(self->window);
Py_RETURN_NONE;
}
static PyObject*
should_close(WindowWrapper *self) {
PyObject *ans = glfwWindowShouldClose(self->window) ? Py_True : Py_False;
Py_INCREF(ans);
return ans;
}
static PyObject*
get_clipboard_string(WindowWrapper *self) {
return Py_BuildValue("s", glfwGetClipboardString(self->window));
}
static PyObject*
get_cursor_pos(WindowWrapper *self) {
double x=0, y=0;
glfwGetCursorPos(self->window, &x, &y);
return Py_BuildValue("dd", x, y);
}
static PyObject*
set_should_close(WindowWrapper *self, PyObject *args) {
int c;
if (!PyArg_ParseTuple(args, "p", &c)) return NULL;
glfwSetWindowShouldClose(self->window, c);
Py_RETURN_NONE;
}
static PyObject*
set_pos(WindowWrapper *self, PyObject *args) {
int x, y;
if (!PyArg_ParseTuple(args, "ii", &x, &y)) return NULL;
glfwSetWindowPos(self->window, x, y);
Py_RETURN_NONE;
}
static PyObject*
is_key_pressed(WindowWrapper *self, PyObject *args) {
int c;
if (!PyArg_ParseTuple(args, "i", &c)) return NULL;
PyObject *ans = glfwGetKey(self->window, c) == GLFW_PRESS ? Py_True : Py_False;
Py_INCREF(ans);
return ans;
}
static PyObject*
set_clipboard_string(WindowWrapper *self, PyObject *args) {
char *title;
if(!PyArg_ParseTuple(args, "s", &title)) return NULL;
glfwSetClipboardString(self->window, title);
Py_RETURN_NONE;
}
static PyObject*
set_window_icon(WindowWrapper *self, PyObject *args) {
GLFWimage logo;
Py_ssize_t sz;
if(!PyArg_ParseTuple(args, "s#ii", &(logo.pixels), &sz, &(logo.width), &(logo.height))) return NULL;
glfwSetWindowIcon(self->window, 1, &logo);
Py_RETURN_NONE;
}
static PyObject*
get_framebuffer_size(WindowWrapper *self) {
int w, h;
glfwGetFramebufferSize(self->window, &w, &h);
return Py_BuildValue("ii", w, h);
}
static PyObject*
get_window_size(WindowWrapper *self) {
int w, h;
glfwGetWindowSize(self->window, &w, &h);
return Py_BuildValue("ii", w, h);
}
static GLFWmonitor*
current_monitor(GLFWwindow *window) {
// Find the monitor that has the maximum overlap with this window
int nmonitors, i;
int wx, wy, ww, wh;
int mx, my, mw, mh;
int overlap = 0, bestoverlap = 0;
GLFWmonitor *bestmonitor = NULL;
GLFWmonitor **monitors = NULL;
const GLFWvidmode *mode;
glfwGetWindowPos(window, &wx, &wy);
glfwGetWindowSize(window, &ww, &wh);
monitors = glfwGetMonitors(&nmonitors);
if (monitors == NULL || nmonitors < 1) { PyErr_SetString(PyExc_ValueError, "No monitors connected"); return NULL; }
for (i = 0; i < nmonitors; i++) {
mode = glfwGetVideoMode(monitors[i]);
glfwGetMonitorPos(monitors[i], &mx, &my);
mw = mode->width;
mh = mode->height;
overlap =
MAX(0, MIN(wx + ww, mx + mw) - MAX(wx, mx)) *
MAX(0, MIN(wy + wh, my + mh) - MAX(wy, my));
if (bestoverlap < overlap || bestmonitor == NULL) {
bestoverlap = overlap;
bestmonitor = monitors[i];
}
}
return bestmonitor;
}
static PyObject*
current_monitor_dpi(WindowWrapper *self) {
GLFWmonitor *m = current_monitor(self->window);
if (m == NULL) return NULL;
return get_physical_dpi(m);
}
void
request_window_attention() {
#ifdef has_request_attention
glfwRequestWindowAttention(the_window->window);
#endif
glfwPostEmptyEvent();
}
#ifdef __APPLE__
static PyObject*
cocoa_window_id(WindowWrapper *self) {
void *wid = glfwGetCocoaWindow(self->window);
if (wid == NULL) { PyErr_SetString(PyExc_ValueError, "Failed to get native window handle"); return NULL; }
return PyLong_FromVoidPtr(wid);
}
#endif
static PyObject*
primary_monitor_size(PyObject UNUSED *self) {
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
const GLFWvidmode* mode = glfwGetVideoMode(monitor);
return Py_BuildValue("ii", mode->width, mode->height);
}
// Boilerplate {{{
#define MND(name, args) {#name, (PyCFunction)name, args, ""}
static PyMethodDef methods[] = {
MND(swap_buffers, METH_NOARGS),
MND(get_clipboard_string, METH_NOARGS),
MND(get_cursor_pos, METH_NOARGS),
MND(should_close, METH_NOARGS),
MND(get_framebuffer_size, METH_NOARGS),
MND(get_window_size, METH_NOARGS),
MND(current_monitor_dpi, METH_NOARGS),
#ifdef __APPLE__
MND(cocoa_window_id, METH_NOARGS),
#endif
MND(set_should_close, METH_VARARGS),
MND(is_key_pressed, METH_VARARGS),
MND(set_pos, METH_VARARGS),
MND(set_clipboard_string, METH_VARARGS),
MND(make_context_current, METH_NOARGS),
MND(window_id, METH_NOARGS),
MND(show, METH_NOARGS),
MND(hide, METH_NOARGS),
{"set_icon", (PyCFunction)set_window_icon, METH_VARARGS, ""},
{NULL} /* Sentinel */
};
static PyMemberDef members[] = {
#define CBE(name) {#name, T_OBJECT_EX, offsetof(WindowWrapper, name), 0, #name}
CBE(framebuffer_size_callback),
CBE(window_focus_callback),
{NULL}
#undef CBE
};
PyTypeObject WindowWrapper_Type = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "fast_data_types.GLFWWindow",
.tp_basicsize = sizeof(WindowWrapper),
.tp_dealloc = (destructor)dealloc,
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_doc = "A GLFW window",
.tp_methods = methods,
.tp_members = members,
.tp_new = new,
};
static PyMethodDef module_methods[] = {
{"glfw_init", (PyCFunction)glfw_init, METH_NOARGS, ""}, \
{"glfw_terminate", (PyCFunction)glfw_terminate, METH_NOARGS, ""}, \
{"glfw_window_hint", (PyCFunction)glfw_window_hint, METH_VARARGS, ""}, \
{"glfw_swap_interval", (PyCFunction)glfw_swap_interval, METH_VARARGS, ""}, \
{"glfw_wait_events", (PyCFunction)glfw_wait_events, METH_VARARGS, ""}, \
{"glfw_post_empty_event", (PyCFunction)glfw_post_empty_event, METH_NOARGS, ""}, \
{"glfw_get_physical_dpi", (PyCFunction)glfw_get_physical_dpi, METH_NOARGS, ""}, \
{"glfw_get_key_name", (PyCFunction)glfw_get_key_name, METH_VARARGS, ""}, \
{"glfw_init_hint_string", (PyCFunction)glfw_init_hint_string, METH_VARARGS, ""}, \
{"glfw_primary_monitor_size", (PyCFunction)primary_monitor_size, METH_NOARGS, ""}, \
{NULL, NULL, 0, NULL} /* Sentinel */
};
// constants {{{
bool
init_glfw(PyObject *m) {
if (PyModule_AddFunctions(m, module_methods) != 0) return false;
if (PyType_Ready(&WindowWrapper_Type) < 0) return false;
if (PyModule_AddObject(m, "GLFWWindow", (PyObject *)&WindowWrapper_Type) != 0) return 0;
Py_INCREF(&WindowWrapper_Type);
#define ADDC(n) if(PyModule_AddIntConstant(m, #n, n) != 0) return false;
#ifdef GLFW_X11_WM_CLASS_NAME
ADDC(GLFW_X11_WM_CLASS_NAME)
ADDC(GLFW_X11_WM_CLASS_CLASS)
#endif
ADDC(GLFW_RELEASE);
ADDC(GLFW_PRESS);
ADDC(GLFW_REPEAT);
// --- Keys --------------------------------------------------------------------
// --- The unknown key ---------------------------------------------------------
ADDC(GLFW_KEY_UNKNOWN);
// --- Printable keys ----------------------------------------------------------
ADDC(GLFW_KEY_SPACE);
ADDC(GLFW_KEY_APOSTROPHE);
ADDC(GLFW_KEY_COMMA);
ADDC(GLFW_KEY_MINUS);
ADDC(GLFW_KEY_PERIOD);
ADDC(GLFW_KEY_SLASH);
ADDC(GLFW_KEY_0);
ADDC(GLFW_KEY_1);
ADDC(GLFW_KEY_2);
ADDC(GLFW_KEY_3);
ADDC(GLFW_KEY_4);
ADDC(GLFW_KEY_5);
ADDC(GLFW_KEY_6);
ADDC(GLFW_KEY_7);
ADDC(GLFW_KEY_8);
ADDC(GLFW_KEY_9);
ADDC(GLFW_KEY_SEMICOLON);
ADDC(GLFW_KEY_EQUAL);
ADDC(GLFW_KEY_A);
ADDC(GLFW_KEY_B);
ADDC(GLFW_KEY_C);
ADDC(GLFW_KEY_D);
ADDC(GLFW_KEY_E);
ADDC(GLFW_KEY_F);
ADDC(GLFW_KEY_G);
ADDC(GLFW_KEY_H);
ADDC(GLFW_KEY_I);
ADDC(GLFW_KEY_J);
ADDC(GLFW_KEY_K);
ADDC(GLFW_KEY_L);
ADDC(GLFW_KEY_M);
ADDC(GLFW_KEY_N);
ADDC(GLFW_KEY_O);
ADDC(GLFW_KEY_P);
ADDC(GLFW_KEY_Q);
ADDC(GLFW_KEY_R);
ADDC(GLFW_KEY_S);
ADDC(GLFW_KEY_T);
ADDC(GLFW_KEY_U);
ADDC(GLFW_KEY_V);
ADDC(GLFW_KEY_W);
ADDC(GLFW_KEY_X);
ADDC(GLFW_KEY_Y);
ADDC(GLFW_KEY_Z);
ADDC(GLFW_KEY_LEFT_BRACKET);
ADDC(GLFW_KEY_BACKSLASH);
ADDC(GLFW_KEY_RIGHT_BRACKET);
ADDC(GLFW_KEY_GRAVE_ACCENT);
ADDC(GLFW_KEY_WORLD_1);
ADDC(GLFW_KEY_WORLD_2);
// --- Function keys -----------------------------------------------------------
ADDC(GLFW_KEY_ESCAPE);
ADDC(GLFW_KEY_ENTER);
ADDC(GLFW_KEY_TAB);
ADDC(GLFW_KEY_BACKSPACE);
ADDC(GLFW_KEY_INSERT);
ADDC(GLFW_KEY_DELETE);
ADDC(GLFW_KEY_RIGHT);
ADDC(GLFW_KEY_LEFT);
ADDC(GLFW_KEY_DOWN);
ADDC(GLFW_KEY_UP);
ADDC(GLFW_KEY_PAGE_UP);
ADDC(GLFW_KEY_PAGE_DOWN);
ADDC(GLFW_KEY_HOME);
ADDC(GLFW_KEY_END);
ADDC(GLFW_KEY_CAPS_LOCK);
ADDC(GLFW_KEY_SCROLL_LOCK);
ADDC(GLFW_KEY_NUM_LOCK);
ADDC(GLFW_KEY_PRINT_SCREEN);
ADDC(GLFW_KEY_PAUSE);
ADDC(GLFW_KEY_F1);
ADDC(GLFW_KEY_F2);
ADDC(GLFW_KEY_F3);
ADDC(GLFW_KEY_F4);
ADDC(GLFW_KEY_F5);
ADDC(GLFW_KEY_F6);
ADDC(GLFW_KEY_F7);
ADDC(GLFW_KEY_F8);
ADDC(GLFW_KEY_F9);
ADDC(GLFW_KEY_F10);
ADDC(GLFW_KEY_F11);
ADDC(GLFW_KEY_F12);
ADDC(GLFW_KEY_F13);
ADDC(GLFW_KEY_F14);
ADDC(GLFW_KEY_F15);
ADDC(GLFW_KEY_F16);
ADDC(GLFW_KEY_F17);
ADDC(GLFW_KEY_F18);
ADDC(GLFW_KEY_F19);
ADDC(GLFW_KEY_F20);
ADDC(GLFW_KEY_F21);
ADDC(GLFW_KEY_F22);
ADDC(GLFW_KEY_F23);
ADDC(GLFW_KEY_F24);
ADDC(GLFW_KEY_F25);
ADDC(GLFW_KEY_KP_0);
ADDC(GLFW_KEY_KP_1);
ADDC(GLFW_KEY_KP_2);
ADDC(GLFW_KEY_KP_3);
ADDC(GLFW_KEY_KP_4);
ADDC(GLFW_KEY_KP_5);
ADDC(GLFW_KEY_KP_6);
ADDC(GLFW_KEY_KP_7);
ADDC(GLFW_KEY_KP_8);
ADDC(GLFW_KEY_KP_9);
ADDC(GLFW_KEY_KP_DECIMAL);
ADDC(GLFW_KEY_KP_DIVIDE);
ADDC(GLFW_KEY_KP_MULTIPLY);
ADDC(GLFW_KEY_KP_SUBTRACT);
ADDC(GLFW_KEY_KP_ADD);
ADDC(GLFW_KEY_KP_ENTER);
ADDC(GLFW_KEY_KP_EQUAL);
ADDC(GLFW_KEY_LEFT_SHIFT);
ADDC(GLFW_KEY_LEFT_CONTROL);
ADDC(GLFW_KEY_LEFT_ALT);
ADDC(GLFW_KEY_LEFT_SUPER);
ADDC(GLFW_KEY_RIGHT_SHIFT);
ADDC(GLFW_KEY_RIGHT_CONTROL);
ADDC(GLFW_KEY_RIGHT_ALT);
ADDC(GLFW_KEY_RIGHT_SUPER);
ADDC(GLFW_KEY_MENU);
ADDC(GLFW_KEY_LAST);
// --- Modifiers ---------------------------------------------------------------
ADDC(GLFW_MOD_SHIFT);
ADDC(GLFW_MOD_CONTROL);
ADDC(GLFW_MOD_ALT);
ADDC(GLFW_MOD_SUPER);
// --- Mouse -------------------------------------------------------------------
ADDC(GLFW_MOUSE_BUTTON_1);
ADDC(GLFW_MOUSE_BUTTON_2);
ADDC(GLFW_MOUSE_BUTTON_3);
ADDC(GLFW_MOUSE_BUTTON_4);
ADDC(GLFW_MOUSE_BUTTON_5);
ADDC(GLFW_MOUSE_BUTTON_6);
ADDC(GLFW_MOUSE_BUTTON_7);
ADDC(GLFW_MOUSE_BUTTON_8);
ADDC(GLFW_MOUSE_BUTTON_LAST);
ADDC(GLFW_MOUSE_BUTTON_LEFT);
ADDC(GLFW_MOUSE_BUTTON_RIGHT);
ADDC(GLFW_MOUSE_BUTTON_MIDDLE);
// --- Joystick ----------------------------------------------------------------
ADDC(GLFW_JOYSTICK_1);
ADDC(GLFW_JOYSTICK_2);
ADDC(GLFW_JOYSTICK_3);
ADDC(GLFW_JOYSTICK_4);
ADDC(GLFW_JOYSTICK_5);
ADDC(GLFW_JOYSTICK_6);
ADDC(GLFW_JOYSTICK_7);
ADDC(GLFW_JOYSTICK_8);
ADDC(GLFW_JOYSTICK_9);
ADDC(GLFW_JOYSTICK_10);
ADDC(GLFW_JOYSTICK_11);
ADDC(GLFW_JOYSTICK_12);
ADDC(GLFW_JOYSTICK_13);
ADDC(GLFW_JOYSTICK_14);
ADDC(GLFW_JOYSTICK_15);
ADDC(GLFW_JOYSTICK_16);
ADDC(GLFW_JOYSTICK_LAST);
// --- Error codes -------------------------------------------------------------
ADDC(GLFW_NOT_INITIALIZED);
ADDC(GLFW_NO_CURRENT_CONTEXT);
ADDC(GLFW_INVALID_ENUM);
ADDC(GLFW_INVALID_VALUE);
ADDC(GLFW_OUT_OF_MEMORY);
ADDC(GLFW_API_UNAVAILABLE);
ADDC(GLFW_VERSION_UNAVAILABLE);
ADDC(GLFW_PLATFORM_ERROR);
ADDC(GLFW_FORMAT_UNAVAILABLE);
// ---
ADDC(GLFW_FOCUSED);
ADDC(GLFW_ICONIFIED);
ADDC(GLFW_RESIZABLE);
ADDC(GLFW_VISIBLE);
ADDC(GLFW_DECORATED);
ADDC(GLFW_AUTO_ICONIFY);
ADDC(GLFW_FLOATING);
// ---
ADDC(GLFW_RED_BITS);
ADDC(GLFW_GREEN_BITS);
ADDC(GLFW_BLUE_BITS);
ADDC(GLFW_ALPHA_BITS);
ADDC(GLFW_DEPTH_BITS);
ADDC(GLFW_STENCIL_BITS);
ADDC(GLFW_ACCUM_RED_BITS);
ADDC(GLFW_ACCUM_GREEN_BITS);
ADDC(GLFW_ACCUM_BLUE_BITS);
ADDC(GLFW_ACCUM_ALPHA_BITS);
ADDC(GLFW_AUX_BUFFERS);
ADDC(GLFW_STEREO);
ADDC(GLFW_SAMPLES);
ADDC(GLFW_SRGB_CAPABLE);
ADDC(GLFW_REFRESH_RATE);
ADDC(GLFW_DOUBLEBUFFER);
// ---
ADDC(GLFW_CLIENT_API);
ADDC(GLFW_CONTEXT_VERSION_MAJOR);
ADDC(GLFW_CONTEXT_VERSION_MINOR);
ADDC(GLFW_CONTEXT_REVISION);
ADDC(GLFW_CONTEXT_ROBUSTNESS);
ADDC(GLFW_OPENGL_FORWARD_COMPAT);
ADDC(GLFW_OPENGL_DEBUG_CONTEXT);
ADDC(GLFW_OPENGL_PROFILE);
// ---
ADDC(GLFW_OPENGL_API);
ADDC(GLFW_OPENGL_ES_API);
// ---
ADDC(GLFW_NO_ROBUSTNESS);
ADDC(GLFW_NO_RESET_NOTIFICATION);
ADDC(GLFW_LOSE_CONTEXT_ON_RESET);
// ---
ADDC(GLFW_OPENGL_ANY_PROFILE);
ADDC(GLFW_OPENGL_CORE_PROFILE);
ADDC(GLFW_OPENGL_COMPAT_PROFILE);
// ---
ADDC(GLFW_CURSOR);
ADDC(GLFW_STICKY_KEYS);
ADDC(GLFW_STICKY_MOUSE_BUTTONS);
// ---
ADDC(GLFW_CURSOR_NORMAL);
ADDC(GLFW_CURSOR_HIDDEN);
ADDC(GLFW_CURSOR_DISABLED);
// ---
ADDC(GLFW_CONNECTED);
ADDC(GLFW_DISCONNECTED);
return true;
#undef ADDC
}
// }}}
// }}}