diff options
| author | Andrew Dunai <andunai@gmail.com> | 2018-01-07 02:31:03 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-01-07 02:31:03 +0200 |
| commit | 1704e374ba55e6fdfe8d68870bd1781ce8afedcd (patch) | |
| tree | c415bbc54580a315eeb6241eedba6bc60ed76735 /urwid | |
| parent | 9c3d68da020b028a55d38b1061db8aacae74ba89 (diff) | |
| parent | 626deb940841f57d331e5a9d2f023f3461c97cb7 (diff) | |
| download | urwid-1704e374ba55e6fdfe8d68870bd1781ce8afedcd.tar.gz | |
Merge pull request #270 from federicotdn/master
Allow Screen class to set signal handlers using a function provided by the event loop
Diffstat (limited to 'urwid')
| -rwxr-xr-x | urwid/main_loop.py | 65 | ||||
| -rw-r--r-- | urwid/raw_display.py | 21 |
2 files changed, 80 insertions, 6 deletions
diff --git a/urwid/main_loop.py b/urwid/main_loop.py index 442c27d..3d18c52 100755 --- a/urwid/main_loop.py +++ b/urwid/main_loop.py @@ -27,6 +27,7 @@ import time import heapq import select import os +import signal from functools import wraps from itertools import count from weakref import WeakKeyDictionary @@ -129,6 +130,11 @@ class MainLoop(object): event_loop = SelectEventLoop() self.event_loop = event_loop + if hasattr(self.screen, 'signal_handler_setter'): + # Tell the screen what function it must use to set + # signal handlers + self.screen.signal_handler_setter = self.event_loop.set_signal_handler + self._watch_pipes = {} def _set_widget(self, widget): @@ -645,6 +651,12 @@ class SelectEventLoop(object): return True return False + def set_signal_handler(self, signum, handler): + """ + Proxy function to signal.signal() + """ + return signal.signal(signum, handler) + def enter_idle(self, callback): """ Add a callback for entering idle. @@ -740,6 +752,7 @@ class GLibEventLoop(object): self._loop = GLib.MainLoop() self._exc_info = None self._enable_glib_idle() + self._signal_handlers = {} def alarm(self, seconds, callback): """ @@ -760,6 +773,40 @@ class GLibEventLoop(object): self._alarms.append(fd) return (fd, callback) + def set_signal_handler(self, signum, handler): + """ + Sets a handler for a specified signal. This method's behaviour + method tries to imitate the signal() function from the signal + module. + """ + glib_signals = [ + signal.SIGHUP, + signal.SIGINT, + signal.SIGTERM, + signal.SIGUSR1, + signal.SIGUSR2, + signal.SIGWINCH + ] + + if signum not in glib_signals: + # The GLib event loop supports only the signals listed above + return + + if signum in self._signal_handlers: + self.GLib.source_remove(self._signal_handlers.pop(signum)) + + if handler == signal.SIG_IGN: + handler = lambda x: None + elif handler == signal.SIG_DFL: + return + + def final_handler(signal_number): + handler(signal_number) + return self.GLib.SOURCE_CONTINUE + + source = self.GLib.unix_signal_add(self.GLib.PRIORITY_DEFAULT, signum, final_handler, signum) + self._signal_handlers[signum] = source + def remove_alarm(self, handle): """ Remove an alarm. @@ -987,6 +1034,12 @@ class TornadoEventLoop(object): self._ioloop.remove_handler(fd) return True + def set_signal_handler(self, signum, handler): + """ + Proxy function to signal.signal() + """ + return signal.signal(signum, handler) + def enter_idle(self, callback): self._max_idle_handle += 1 handle = self._max_idle_handle @@ -1132,6 +1185,12 @@ class TwistedEventLoop(object): return True return False + def set_signal_handler(self, signum, handler): + """ + Proxy function to signal.signal() + """ + return signal.signal(signum, handler) + def enter_idle(self, callback): """ Add a callback for entering idle. @@ -1279,6 +1338,12 @@ class AsyncioEventLoop(object): """ return self._loop.remove_reader(handle) + def set_signal_handler(self, signum, handler): + """ + Proxy function to signal.signal() + """ + return signal.signal(signum, handler) + def enter_idle(self, callback): """ Add a callback for entering idle. diff --git a/urwid/raw_display.py b/urwid/raw_display.py index 365e311..626891d 100644 --- a/urwid/raw_display.py +++ b/urwid/raw_display.py @@ -81,6 +81,7 @@ class Screen(BaseScreen, RealTerminal): self.back_color_erase = not self.term.startswith("screen") self.register_palette_entry( None, 'default','default') self._next_timeout = None + self.signal_handler_setter = signal.signal # Our connections to the world self._term_output_file = output @@ -121,13 +122,21 @@ class Screen(BaseScreen, RealTerminal): self.complete_wait = complete_wait self.resize_wait = resize_wait - def _sigwinch_handler(self, signum, frame): + def _sigwinch_handler(self, signum, frame=None): + """ + frame -- will always be None when the GLib event loop is being used. + """ + if not self._resized: os.write(self._resize_pipe_wr, B('R')) self._resized = True self.screen_buf = None - def _sigcont_handler(self, signum, frame): + def _sigcont_handler(self, signum, frame=None): + """ + frame -- will always be None when the GLib event loop is being used. + """ + self.stop() self.start() self._sigwinch_handler(None, None) @@ -140,8 +149,8 @@ class Screen(BaseScreen, RealTerminal): Override this function to call from main thread in threaded applications. """ - signal.signal(signal.SIGWINCH, self._sigwinch_handler) - signal.signal(signal.SIGCONT, self._sigcont_handler) + self.signal_handler_setter(signal.SIGWINCH, self._sigwinch_handler) + self.signal_handler_setter(signal.SIGCONT, self._sigcont_handler) def signal_restore(self): """ @@ -151,8 +160,8 @@ class Screen(BaseScreen, RealTerminal): Override this function to call from main thread in threaded applications. """ - signal.signal(signal.SIGCONT, signal.SIG_DFL) - signal.signal(signal.SIGWINCH, signal.SIG_DFL) + self.signal_handler_setter(signal.SIGCONT, signal.SIG_DFL) + self.signal_handler_setter(signal.SIGWINCH, signal.SIG_DFL) def set_mouse_tracking(self, enable=True): """ |
