diff --git a/src/main.cc b/src/main.cc index 1026b4f9..7ee0835a 100644 --- a/src/main.cc +++ b/src/main.cc @@ -477,7 +477,6 @@ void register_options() static Client* local_client = nullptr; static int local_client_exit = 0; -static UserInterface* local_ui = nullptr; static bool convert_to_client_pending = false; enum class UIType @@ -550,26 +549,10 @@ std::unique_ptr create_local_ui(UIType ui_type) { LocalUI() { - kak_assert(not local_ui); - local_ui = this; - - m_old_sigtstp = set_signal_handler(SIGTSTP, [](int) { + set_signal_handler(SIGTSTP, [](int) { if (ClientManager::instance().count() == 1 and *ClientManager::instance().begin() == local_client) - { - // Suspend normally if we are the only client - auto current = set_signal_handler(SIGTSTP, static_cast(local_ui)->m_old_sigtstp); - - sigset_t unblock_sigtstp, old_mask; - sigemptyset(&unblock_sigtstp); - sigaddset(&unblock_sigtstp, SIGTSTP); - sigprocmask(SIG_UNBLOCK, &unblock_sigtstp, &old_mask); - - raise(SIGTSTP); - - set_signal_handler(SIGTSTP, current); - sigprocmask(SIG_SETMASK, &old_mask, nullptr); - } + NCursesUI::instance().suspend(); else convert_to_client_pending = true; }); @@ -577,23 +560,17 @@ std::unique_ptr create_local_ui(UIType ui_type) ~LocalUI() override { - set_signal_handler(SIGTSTP, m_old_sigtstp); local_client = nullptr; - local_ui = nullptr; - if (not convert_to_client_pending and - not ClientManager::instance().empty()) + if (convert_to_client_pending or + ClientManager::instance().empty()) + return; + + if (fork_server_to_background()) { - if (fork_server_to_background()) - { - this->NCursesUI::~NCursesUI(); - exit(local_client_exit); - } + this->NCursesUI::~NCursesUI(); + exit(local_client_exit); } } - - private: - using SigHandler = void (*)(int); - SigHandler m_old_sigtstp; }; if (not isatty(1)) diff --git a/src/ncurses_ui.cc b/src/ncurses_ui.cc index c6e67fb1..0add3a6b 100644 --- a/src/ncurses_ui.cc +++ b/src/ncurses_ui.cc @@ -373,6 +373,7 @@ NCursesUI::NCursesUI() set_signal_handler(SIGWINCH, &signal_handler<&resize_pending>); set_signal_handler(SIGHUP, &signal_handler<&sighup_raised>); + set_signal_handler(SIGTSTP, [](int){ NCursesUI::instance().suspend(); }); check_resize(true); redraw(false); @@ -390,6 +391,29 @@ NCursesUI::~NCursesUI() tcsetattr(STDIN_FILENO, TCSAFLUSH, &m_original_termios); set_signal_handler(SIGWINCH, SIG_DFL); set_signal_handler(SIGCONT, SIG_DFL); + set_signal_handler(SIGTSTP, SIG_DFL); +} + +void NCursesUI::suspend() +{ + bool mouse_enabled = m_mouse_enabled; + enable_mouse(false); + tcsetattr(STDIN_FILENO, TCSAFLUSH, &m_original_termios); + + auto current = set_signal_handler(SIGTSTP, SIG_DFL); + sigset_t unblock_sigtstp, old_mask; + sigemptyset(&unblock_sigtstp); + sigaddset(&unblock_sigtstp, SIGTSTP); + sigprocmask(SIG_UNBLOCK, &unblock_sigtstp, &old_mask); + + raise(SIGTSTP); // suspend here + + set_signal_handler(SIGTSTP, current); + sigprocmask(SIG_SETMASK, &old_mask, nullptr); + + check_resize(true); + set_raw_mode(); + enable_mouse(mouse_enabled); } void NCursesUI::set_raw_mode() const @@ -612,15 +636,7 @@ Optional NCursesUI::get_next_key() return {Key::Backspace}; if (c == control('z')) { - bool mouse_enabled = m_mouse_enabled; - enable_mouse(false); - tcsetattr(STDIN_FILENO, TCSAFLUSH, &m_original_termios); - kill(0, SIGTSTP); // We suspend at this line - - check_resize(true); - set_raw_mode(); - enable_mouse(mouse_enabled); return {}; } if (c < 27) diff --git a/src/ncurses_ui.hh b/src/ncurses_ui.hh index ad4ccacc..141750a3 100644 --- a/src/ncurses_ui.hh +++ b/src/ncurses_ui.hh @@ -17,7 +17,7 @@ namespace Kakoune struct NCursesWin; -class NCursesUI : public UserInterface +class NCursesUI : public UserInterface, public Singleton { public: NCursesUI(); @@ -57,6 +57,8 @@ public: static void abort(); + void suspend(); + struct Rect { DisplayCoord pos; @@ -117,7 +119,7 @@ private: Window m_window; DisplayCoord m_dimensions; - termios m_original_termios; + termios m_original_termios{}; void set_raw_mode() const;