diff --git a/src/client_manager.cc b/src/client_manager.cc index 77eb38fb..f9a955e0 100644 --- a/src/client_manager.cc +++ b/src/client_manager.cc @@ -27,7 +27,7 @@ String ClientManager::generate_name() const } void ClientManager::create_client(std::unique_ptr&& ui, - int event_fd, const String& init_commands) + const String& init_commands) { Buffer& buffer = **BufferManager::instance().begin(); m_clients.emplace_back(new Client{std::move(ui), get_unused_window_for_buffer(buffer), @@ -47,11 +47,10 @@ void ClientManager::create_client(std::unique_ptr&& ui, catch (Kakoune::client_removed&) { m_clients.pop_back(); - close(event_fd); return; } - new FDWatcher(event_fd, [input_handler, context, this](FDWatcher& watcher) { + context->ui().set_input_callback([input_handler, context, this]() { try { input_handler->handle_available_inputs(*context); @@ -64,8 +63,6 @@ void ClientManager::create_client(std::unique_ptr&& ui, catch (Kakoune::client_removed&) { ClientManager::instance().remove_client_by_context(*context); - close(watcher.fd()); - delete &watcher; } ClientManager::instance().redraw_clients(); }); diff --git a/src/client_manager.hh b/src/client_manager.hh index 234df8b9..6569d26b 100644 --- a/src/client_manager.hh +++ b/src/client_manager.hh @@ -13,7 +13,7 @@ class ClientManager : public Singleton { public: void create_client(std::unique_ptr&& ui, - int event_fd, const String& init_cmd); + const String& init_cmd); bool empty() const { return m_clients.empty(); } size_t count() const { return m_clients.size(); } diff --git a/src/commands.cc b/src/commands.cc index 7e86d876..f2798e88 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -517,6 +517,8 @@ public: DisplayCoord dimensions() override { return { 0, 0 }; } + void set_input_callback(InputCallback callback) {} + private: const KeyList& m_keys; size_t m_pos; diff --git a/src/main.cc b/src/main.cc index 85a47e9d..585dbb8b 100644 --- a/src/main.cc +++ b/src/main.cc @@ -685,7 +685,7 @@ void create_local_client(const String& init_command) UserInterface* ui = new LocalNCursesUI{}; ClientManager::instance().create_client( - std::unique_ptr{ui}, 0, init_command); + std::unique_ptr{ui}, init_command); } RemoteClient* connect_to(const String& pid, const String& init_command) @@ -703,17 +703,6 @@ RemoteClient* connect_to(const String& pid, const String& init_command) NCursesUI* ui = new NCursesUI{}; RemoteClient* remote_client = new RemoteClient{sock, ui, init_command}; - new FDWatcher{0, [=](FDWatcher& ev) { - try - { - remote_client->write_next_key(); - } - catch (Kakoune::runtime_error& error) - { - ui->print_status(error.description(), -1); - } - }}; - return remote_client; } diff --git a/src/ncurses.cc b/src/ncurses.cc index 12da65fa..98ae34de 100644 --- a/src/ncurses.cc +++ b/src/ncurses.cc @@ -88,6 +88,7 @@ void on_sigint(int) } NCursesUI::NCursesUI() + : m_stdin_watcher{0, [this](FDWatcher&){ if (m_input_callback) m_input_callback(); }} { //setlocale(LC_CTYPE, ""); initscr(); @@ -468,4 +469,9 @@ DisplayCoord NCursesUI::dimensions() return m_dimensions; } +void NCursesUI::set_input_callback(InputCallback callback) +{ + m_input_callback = std::move(callback); +} + } diff --git a/src/ncurses.hh b/src/ncurses.hh index b845fdf2..4f393104 100644 --- a/src/ncurses.hh +++ b/src/ncurses.hh @@ -6,6 +6,7 @@ #include "user_interface.hh" #include "display_buffer.hh" +#include "event_manager.hh" namespace Kakoune { @@ -35,6 +36,8 @@ public: const DisplayCoord& anchor, MenuStyle style) override; void info_hide() override; + void set_input_callback(InputCallback callback) override; + DisplayCoord dimensions() override; private: friend void on_term_resize(int); @@ -55,6 +58,9 @@ private: int m_menu_bg; WINDOW* m_info_win = nullptr; + + FDWatcher m_stdin_watcher; + InputCallback m_input_callback; }; } diff --git a/src/remote.cc b/src/remote.cc index 497ac2a7..f82837df 100644 --- a/src/remote.cc +++ b/src/remote.cc @@ -187,26 +187,30 @@ public: Key get_key() override; DisplayCoord dimensions() override; + void set_input_callback(InputCallback callback) override; + private: - int m_socket; + FDWatcher m_socket_watcher; DisplayCoord m_dimensions; + InputCallback m_input_callback; }; RemoteUI::RemoteUI(int socket) - : m_socket(socket) + : m_socket_watcher(socket, [this](FDWatcher&) { if (m_input_callback) m_input_callback(); }) { - write_debug("remote client connected: " + int_to_str(m_socket)); + write_debug("remote client connected: " + int_to_str(m_socket_watcher.fd())); } RemoteUI::~RemoteUI() { - write_debug("remote client disconnected: " + int_to_str(m_socket)); + write_debug("remote client disconnected: " + int_to_str(m_socket_watcher.fd())); + close(m_socket_watcher.fd()); } void RemoteUI::print_status(const String& status, CharCount cursor_pos) { - Message msg(m_socket); + Message msg(m_socket_watcher.fd()); msg.write(RemoteUIMsg::PrintStatus); msg.write(status); msg.write(cursor_pos); @@ -215,7 +219,7 @@ void RemoteUI::print_status(const String& status, CharCount cursor_pos) void RemoteUI::menu_show(const memoryview& choices, const DisplayCoord& anchor, MenuStyle style) { - Message msg(m_socket); + Message msg(m_socket_watcher.fd()); msg.write(RemoteUIMsg::MenuShow); msg.write(choices); msg.write(anchor); @@ -224,21 +228,21 @@ void RemoteUI::menu_show(const memoryview& choices, void RemoteUI::menu_select(int selected) { - Message msg(m_socket); + Message msg(m_socket_watcher.fd()); msg.write(RemoteUIMsg::MenuSelect); msg.write(selected); } void RemoteUI::menu_hide() { - Message msg(m_socket); + Message msg(m_socket_watcher.fd()); msg.write(RemoteUIMsg::MenuHide); } void RemoteUI::info_show(const String& content, const DisplayCoord& anchor, MenuStyle style) { - Message msg(m_socket); + Message msg(m_socket_watcher.fd()); msg.write(RemoteUIMsg::InfoShow); msg.write(content); msg.write(anchor); @@ -247,14 +251,14 @@ void RemoteUI::info_show(const String& content, void RemoteUI::info_hide() { - Message msg(m_socket); + Message msg(m_socket_watcher.fd()); msg.write(RemoteUIMsg::InfoHide); } void RemoteUI::draw(const DisplayBuffer& display_buffer, const String& mode_line) { - Message msg(m_socket); + Message msg(m_socket_watcher.fd()); msg.write(RemoteUIMsg::Draw); msg.write(display_buffer); msg.write(mode_line); @@ -267,18 +271,19 @@ bool RemoteUI::is_key_available() timeval tv; fd_set rfds; + int sock = m_socket_watcher.fd(); FD_ZERO(&rfds); - FD_SET(m_socket, &rfds); + FD_SET(sock, &rfds); tv.tv_sec = 0; tv.tv_usec = 0; - int res = select(m_socket+1, &rfds, NULL, NULL, &tv); + int res = select(sock+1, &rfds, NULL, NULL, &tv); return res == 1; } Key RemoteUI::get_key() { - Key key = read(m_socket); + Key key = read(m_socket_watcher.fd()); if (key.modifiers == resize_modifier) { m_dimensions = { (int)(key.key >> 16), (int)(key.key & 0xFFFF) }; @@ -292,6 +297,11 @@ DisplayCoord RemoteUI::dimensions() return m_dimensions; } +void RemoteUI::set_input_callback(InputCallback callback) +{ + m_input_callback = std::move(callback); +} + RemoteClient::RemoteClient(int socket, UserInterface* ui, const String& init_command) : m_ui(ui), m_dimensions(ui->dimensions()), @@ -301,6 +311,8 @@ RemoteClient::RemoteClient(int socket, UserInterface* ui, msg.write(init_command); Key key{ resize_modifier, Codepoint(((int)m_dimensions.line << 16) | (int)m_dimensions.column) }; msg.write(key); + + m_ui->set_input_callback([this]{ write_next_key(); }); } void RemoteClient::process_next_message() @@ -370,12 +382,12 @@ void RemoteClient::write_next_key() void handle_remote(FDWatcher& watcher) { int socket = watcher.fd(); + delete &watcher; String init_command = read(socket); RemoteUI* ui = new RemoteUI{socket}; - delete &watcher; ClientManager::instance().create_client( - std::unique_ptr{ui}, socket, init_command); + std::unique_ptr{ui}, init_command); } } diff --git a/src/user_interface.hh b/src/user_interface.hh index 185619e0..4d20a3ac 100644 --- a/src/user_interface.hh +++ b/src/user_interface.hh @@ -19,6 +19,8 @@ enum class MenuStyle Inline }; +using InputCallback = std::function; + class UserInterface : public SafeCountable { public: @@ -39,6 +41,8 @@ public: virtual DisplayCoord dimensions() = 0; virtual bool is_key_available() = 0; virtual Key get_key() = 0; + + virtual void set_input_callback(InputCallback callback) = 0; }; }