diff --git a/kitty/boss.py b/kitty/boss.py index 17435299f..37a6948a1 100644 --- a/kitty/boss.py +++ b/kitty/boss.py @@ -97,7 +97,7 @@ class Boss: self.ui_timers = Timers() self.child_monitor = ChildMonitor( opts.repaint_delay / 1000.0, glfw_window.window_id(), - self.on_child_death, self.update_screen, self.ui_timers, + self.on_child_death, self.update_screen, self.ui_timers, self.render, DumpCommands(args) if args.dump_commands or args.dump_bytes else None) set_boss(self) self.current_font_size = opts.font_size diff --git a/kitty/child-monitor.c b/kitty/child-monitor.c index b792ce906..cbebb1147 100644 --- a/kitty/child-monitor.c +++ b/kitty/child-monitor.c @@ -89,12 +89,12 @@ self_pipe(int fds[2]) { static PyObject * new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) { ChildMonitor *self; - PyObject *dump_callback, *death_notify, *update_screen, *timers, *wid; + PyObject *dump_callback, *death_notify, *update_screen, *timers, *wid, *render_func; int ret; double repaint_delay; if (created) { PyErr_SetString(PyExc_RuntimeError, "Can have only a single ChildMonitor instance"); return NULL; } - if (!PyArg_ParseTuple(args, "dOOOOO", &repaint_delay, &wid, &death_notify, &update_screen, &timers, &dump_callback)) return NULL; + if (!PyArg_ParseTuple(args, "dOOOOOO", &repaint_delay, &wid, &death_notify, &update_screen, &timers, &render_func, &dump_callback)) return NULL; glfw_window_id = PyLong_AsVoidPtr(wid); created = true; if ((ret = pthread_mutex_init(&children_lock, NULL)) != 0) { @@ -111,6 +111,7 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) { if (self == NULL) return PyErr_NoMemory(); self->death_notify = death_notify; Py_INCREF(death_notify); self->update_screen = update_screen; Py_INCREF(self->update_screen); + self->render_func = render_func; Py_INCREF(self->render_func); self->timers = (Timers*)timers; Py_INCREF(timers); if (dump_callback != Py_None) { self->dump_callback = dump_callback; Py_INCREF(dump_callback); @@ -131,6 +132,7 @@ dealloc(ChildMonitor* self) { Py_CLEAR(self->death_notify); Py_CLEAR(self->update_screen); Py_CLEAR(self->timers); + Py_CLEAR(self->render_func); Py_TYPE(self)->tp_free((PyObject*)self); while (remove_queue_count) { remove_queue_count--; @@ -253,9 +255,9 @@ do_parse(ChildMonitor *self, Screen *screen, unsigned long child_id) { screen_mutex(unlock, read); } -static PyObject * +static void parse_input(ChildMonitor *self) { -#define parse_input_doc "parse_input() -> Parse all available input that was read in the I/O thread." + // Parse all available input that was read in the I/O thread. size_t count = 0; children_mutex(lock); while (num_dead_children) { @@ -297,7 +299,6 @@ parse_input(ChildMonitor *self) { if (wait_for < self->repaint_delay) { timers_add(self->timers, wait_for, false, Py_None, NULL); } - Py_RETURN_NONE; } static PyObject * @@ -321,9 +322,21 @@ mark_for_close(ChildMonitor *self, PyObject *args) { #undef DECREF_CHILD static PyObject* -main_loop(ChildMonitor UNUSED *self) { +main_loop(ChildMonitor *self) { #define main_loop_doc "The main thread loop" + PyObject *ret; + double timeout; + while (!glfwWindowShouldClose(glfw_window_id)) { + ret = PyObject_CallObject(self->render_func, NULL); + if (ret == NULL) return NULL; + else Py_DECREF(ret); + glfwSwapBuffers(glfw_window_id); + timeout = timers_timeout(self->timers); + if (timeout < 0) glfwWaitEvents(); + else if (timeout > 0) glfwWaitEventsTimeout(timeout); + timers_call(self->timers); + parse_input(self); } Py_RETURN_NONE; } @@ -512,7 +525,6 @@ static PyMethodDef methods[] = { METHOD(wakeup, METH_NOARGS) METHOD(shutdown, METH_NOARGS) METHOD(main_loop, METH_NOARGS) - METHOD(parse_input, METH_NOARGS) METHOD(mark_for_close, METH_VARARGS) {NULL} /* Sentinel */ }; diff --git a/kitty/data-types.h b/kitty/data-types.h index e86ef40bf..626644912 100644 --- a/kitty/data-types.h +++ b/kitty/data-types.h @@ -279,7 +279,7 @@ PyTypeObject Timers_Type; typedef struct { PyObject_HEAD - PyObject *dump_callback, *update_screen, *death_notify; + PyObject *dump_callback, *update_screen, *death_notify, *render_func; Timers *timers; double repaint_delay; unsigned int count; diff --git a/kitty/main.py b/kitty/main.py index 1c3427010..a0c99eccc 100644 --- a/kitty/main.py +++ b/kitty/main.py @@ -23,7 +23,7 @@ from .fast_data_types import ( GLFW_STENCIL_BITS, Window, change_wcwidth, check_for_extensions, enable_automatic_opengl_error_checking, glClear, glClearColor, glewInit, glfw_init, glfw_init_hint_string, glfw_set_error_callback, - glfw_swap_interval, glfw_terminate, glfw_wait_events, glfw_window_hint + glfw_swap_interval, glfw_terminate, glfw_window_hint ) from .layout import all_layouts from .shaders import GL_VERSION @@ -166,11 +166,6 @@ def clear_buffers(window, opts): # glfw_swap_interval(1) -def dispatch_pending_calls(boss): - boss.ui_timers.call() - boss.child_monitor.parse_input() - - def run_app(opts, args): setup_opengl(opts) load_cached_values() @@ -212,11 +207,7 @@ def run_app(opts, args): boss.start() clear_buffers(window, opts) try: - while not window.should_close(): - boss.render() - window.swap_buffers() - glfw_wait_events(boss.ui_timers.timeout()) - dispatch_pending_calls(boss) + boss.child_monitor.main_loop() finally: boss.destroy() del window