From 02870d72210967411fbd2f5a966672e0c76715b1 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 6 Sep 2017 20:26:04 +0530 Subject: [PATCH] Move the signal received handler into the C module --- kitty/boss.py | 7 +------ kitty/child-monitor.c | 34 ++++++++++++++++++++++++---------- kitty/glfw.c | 6 ++++++ kitty/main.py | 3 +-- 4 files changed, 32 insertions(+), 18 deletions(-) diff --git a/kitty/boss.py b/kitty/boss.py index 9cc974b1c..17435299f 100644 --- a/kitty/boss.py +++ b/kitty/boss.py @@ -96,7 +96,7 @@ class Boss: self.shutting_down = False self.ui_timers = Timers() self.child_monitor = ChildMonitor( - opts.repaint_delay / 1000.0, + opts.repaint_delay / 1000.0, glfw_window.window_id(), self.on_child_death, self.update_screen, self.ui_timers, DumpCommands(args) if args.dump_commands or args.dump_bytes else None) set_boss(self) @@ -122,11 +122,6 @@ class Boss: self.show_mouse_cursor() self.start_cursor_blink() - def close_signal_received(self): - if not self.shutting_down: - self.glfw_window.set_should_close(True) - glfw_post_empty_event() - @property def current_tab_bar_height(self): return self.tab_manager.tab_bar_height diff --git a/kitty/child-monitor.c b/kitty/child-monitor.c index cbe44e037..b792ce906 100644 --- a/kitty/child-monitor.c +++ b/kitty/child-monitor.c @@ -48,6 +48,7 @@ static pthread_mutex_t children_lock = {{0}}; static bool created = false, signal_received = false; static uint8_t drain_buf[1024]; static int signal_fds[2], wakeup_fds[2]; +static void *glfw_window_id = NULL; // Main thread functions {{{ @@ -88,12 +89,13 @@ 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; + PyObject *dump_callback, *death_notify, *update_screen, *timers, *wid; int ret; double repaint_delay; if (created) { PyErr_SetString(PyExc_RuntimeError, "Can have only a single ChildMonitor instance"); return NULL; } - if (!PyArg_ParseTuple(args, "dOOOO", &repaint_delay, &death_notify, &update_screen, &timers, &dump_callback)) return NULL; + if (!PyArg_ParseTuple(args, "dOOOOO", &repaint_delay, &wid, &death_notify, &update_screen, &timers, &dump_callback)) return NULL; + glfw_window_id = PyLong_AsVoidPtr(wid); created = true; if ((ret = pthread_mutex_init(&children_lock, NULL)) != 0) { PyErr_Format(PyExc_RuntimeError, "Failed to create children_lock mutex: %s", strerror(ret)); @@ -254,6 +256,7 @@ do_parse(ChildMonitor *self, Screen *screen, unsigned long child_id) { static PyObject * parse_input(ChildMonitor *self) { #define parse_input_doc "parse_input() -> Parse all available input that was read in the I/O thread." + size_t count = 0; children_mutex(lock); while (num_dead_children) { PyObject *t = PyObject_CallFunction(self->death_notify, "k", dead_children[--num_dead_children]); @@ -265,12 +268,15 @@ parse_input(ChildMonitor *self) { FREE_CHILD(remove_queue[remove_queue_count]); } - size_t count = self->count; - bool sr = signal_received; - signal_received = false; - for (size_t i = 0; i < count; i++) { - scratch[i] = children[i]; - INCREF_CHILD(scratch[i]); + if (UNLIKELY(signal_received)) { + glfwSetWindowShouldClose(glfw_window_id, true); + glfwPostEmptyEvent(); + } else { + count = self->count; + for (size_t i = 0; i < count; i++) { + scratch[i] = children[i]; + INCREF_CHILD(scratch[i]); + } } children_mutex(unlock); @@ -291,8 +297,7 @@ parse_input(ChildMonitor *self) { if (wait_for < self->repaint_delay) { timers_add(self->timers, wait_for, false, Py_None, NULL); } - if (sr) { Py_RETURN_TRUE; } - Py_RETURN_FALSE; + Py_RETURN_NONE; } static PyObject * @@ -315,6 +320,14 @@ mark_for_close(ChildMonitor *self, PyObject *args) { #undef INCREF_CHILD #undef DECREF_CHILD +static PyObject* +main_loop(ChildMonitor UNUSED *self) { +#define main_loop_doc "The main thread loop" + while (!glfwWindowShouldClose(glfw_window_id)) { + } + Py_RETURN_NONE; +} + // }}} @@ -498,6 +511,7 @@ static PyMethodDef methods[] = { METHOD(join, METH_NOARGS) 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/glfw.c b/kitty/glfw.c index 292947dff..e298d04f5 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -242,6 +242,11 @@ make_context_current(Window *self) { Py_RETURN_NONE; } +static PyObject* +window_id(Window *self) { + return PyLong_FromVoidPtr(self->window); +} + static PyObject* should_close(Window *self) { PyObject *ans = glfwWindowShouldClose(self->window) ? Py_True : Py_False; @@ -417,6 +422,7 @@ static PyMethodDef methods[] = { MND(set_click_cursor, METH_VARARGS), MND(set_clipboard_string, METH_VARARGS), MND(make_context_current, METH_NOARGS), + MND(window_id, METH_NOARGS), {"set_title", (PyCFunction)_set_title, METH_VARARGS, ""}, {"set_icon", (PyCFunction)set_window_icon, METH_VARARGS, ""}, {NULL} /* Sentinel */ diff --git a/kitty/main.py b/kitty/main.py index 19efbbea3..1c3427010 100644 --- a/kitty/main.py +++ b/kitty/main.py @@ -168,8 +168,7 @@ def clear_buffers(window, opts): def dispatch_pending_calls(boss): boss.ui_timers.call() - if boss.child_monitor.parse_input(): - boss.close_signal_received() + boss.child_monitor.parse_input() def run_app(opts, args):