diff --git a/kitty/data-types.c b/kitty/data-types.c index 06383164e..5dfd3e060 100644 --- a/kitty/data-types.c +++ b/kitty/data-types.c @@ -16,6 +16,12 @@ static PyMethodDef module_methods[] = { {"parse_bytes_dump", (PyCFunction)parse_bytes_dump, METH_VARARGS, ""}, {"read_bytes", (PyCFunction)read_bytes, METH_VARARGS, ""}, {"read_bytes_dump", (PyCFunction)read_bytes_dump, METH_VARARGS, ""}, + {"glfw_set_error_callback", (PyCFunction)glfw_set_error_callback, METH_O, ""}, + {"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_NOARGS, ""}, {NULL, NULL, 0, NULL} /* Sentinel */ }; diff --git a/kitty/glfw.c b/kitty/glfw.c index d79fce69c..22d29d4af 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -7,8 +7,79 @@ #include "data-types.h" #include +#define MAX_WINDOWS 255 +/* static PyObject* window_weakrefs[MAX_WINDOWS + 1] = {0}; */ + +#define CALLBACK(name, fmt, ...) \ + if ((name) != NULL) { \ + PyGILState_STATE _pystate = PyGILState_Ensure(); \ + PyObject *_pyret = PyObject_CallFunction((name), fmt, __VA_ARGS__); \ + PyGILState_Release(_pystate); \ + if (_pyret == NULL) { PyErr_Print(); PyErr_Clear(); return; } \ + Py_CLEAR(_pyret); \ + } + + +// Library Setup {{{ +static PyObject *error_callback = NULL; + +static void +cb_error_callback(int error, const char* description) { + CALLBACK(error_callback, "is", error, description) else fprintf(stderr, "[glfw error]: %s\n", description); +} + +PyObject* +glfw_set_error_callback(PyObject UNUSED *self, PyObject *callback) { + Py_CLEAR(error_callback); + error_callback = callback; + Py_INCREF(callback); + Py_RETURN_NONE; +} + +PyObject* +glfw_init(PyObject UNUSED *self) { + 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) { + Py_BEGIN_ALLOW_THREADS; + glfwWaitEvents(); + Py_END_ALLOW_THREADS; + Py_RETURN_NONE; +} + +// }}} + +// constants {{{ bool init_glfw(PyObject *m) { + PyEval_InitThreads(); + glfwSetErrorCallback(cb_error_callback); #define ADDC(n) if(PyModule_AddIntConstant(m, #n, n) != 0) return false; ADDC(GLFW_RELEASE); ADDC(GLFW_PRESS); @@ -264,5 +335,4 @@ init_glfw(PyObject *m) { return true; #undef ADDC } - - +// }}} diff --git a/kitty/glfw.h b/kitty/glfw.h index d682cd005..1043afc92 100644 --- a/kitty/glfw.h +++ b/kitty/glfw.h @@ -9,3 +9,9 @@ bool init_glfw(PyObject *m); +PyObject* glfw_set_error_callback(PyObject UNUSED *self, PyObject *callback); +PyObject* glfw_init(PyObject UNUSED *self); +PyObject* glfw_terminate(PyObject UNUSED *self); +PyObject* glfw_window_hint(PyObject UNUSED *self, PyObject *args); +PyObject* glfw_swap_interval(PyObject UNUSED *self, PyObject *args); +PyObject* glfw_wait_events(PyObject UNUSED *self); diff --git a/kitty/main.py b/kitty/main.py index 8ea30a434..234d5e463 100644 --- a/kitty/main.py +++ b/kitty/main.py @@ -17,7 +17,9 @@ from .fast_data_types import ( glewInit, enable_automatic_opengl_error_checking, glClear, glClearColor, GL_COLOR_BUFFER_BIT, GLFW_CONTEXT_VERSION_MAJOR, GLFW_CONTEXT_VERSION_MINOR, GLFW_OPENGL_PROFILE, - GLFW_OPENGL_FORWARD_COMPAT, GLFW_OPENGL_CORE_PROFILE, GLFW_SAMPLES + GLFW_OPENGL_FORWARD_COMPAT, GLFW_OPENGL_CORE_PROFILE, GLFW_SAMPLES, + glfw_set_error_callback, glfw_init, glfw_terminate, glfw_window_hint, + glfw_swap_interval, glfw_wait_events ) import glfw @@ -40,21 +42,21 @@ def option_parser(): def setup_opengl(): - glfw.glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, GL_VERSION[0]) - glfw.glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, GL_VERSION[1]) - glfw.glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE) - glfw.glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, True) - glfw.glfwWindowHint(GLFW_SAMPLES, 0) + glfw_window_hint(GLFW_CONTEXT_VERSION_MAJOR, GL_VERSION[0]) + glfw_window_hint(GLFW_CONTEXT_VERSION_MINOR, GL_VERSION[1]) + glfw_window_hint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE) + glfw_window_hint(GLFW_OPENGL_FORWARD_COMPAT, True) + glfw_window_hint(GLFW_SAMPLES, 0) def clear_buffers(window, opts): bg = opts.background glClearColor(bg.red / 255, bg.green / 255, bg.blue / 255, 1) - glfw.glfwSwapInterval(0) + glfw_swap_interval(0) glClear(GL_COLOR_BUFFER_BIT) glfw.glfwSwapBuffers(window) glClear(GL_COLOR_BUFFER_BIT) - glfw.glfwSwapInterval(1) + glfw_swap_interval(1) def run_app(opts, args): @@ -74,7 +76,7 @@ def run_app(opts, args): while not glfw.glfwWindowShouldClose(window): tabs.render() glfw.glfwSwapBuffers(window) - glfw.glfwWaitEvents() + glfw_wait_events() finally: tabs.destroy() finally: @@ -96,9 +98,9 @@ def main(): exec(args.cmd) return opts = load_config(args.config) - glfw.glfwSetErrorCallback(on_glfw_error) + glfw_set_error_callback(on_glfw_error) enable_automatic_opengl_error_checking(False) - if not glfw.glfwInit(): + if not glfw_init(): raise SystemExit('GLFW initialization failed') try: if args.profile: @@ -120,5 +122,5 @@ def main(): else: run_app(opts, args) finally: - glfw.glfwTerminate() + glfw_terminate() os.closerange(3, 100) diff --git a/kitty/tabs.py b/kitty/tabs.py index 5bf5e8ee9..e26ade165 100644 --- a/kitty/tabs.py +++ b/kitty/tabs.py @@ -382,4 +382,5 @@ class TabManager(Thread): del self.tabs self.sprites.destroy() del self.sprites + del self.glfw_window # }}}