move input watching responsibility into UserInterface implementations

This commit is contained in:
Maxime Coste 2013-01-11 19:17:21 +01:00
parent d2f0e2de66
commit 310ec1f791
8 changed files with 50 additions and 34 deletions

View File

@ -27,7 +27,7 @@ String ClientManager::generate_name() const
} }
void ClientManager::create_client(std::unique_ptr<UserInterface>&& ui, void ClientManager::create_client(std::unique_ptr<UserInterface>&& ui,
int event_fd, const String& init_commands) const String& init_commands)
{ {
Buffer& buffer = **BufferManager::instance().begin(); Buffer& buffer = **BufferManager::instance().begin();
m_clients.emplace_back(new Client{std::move(ui), get_unused_window_for_buffer(buffer), 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<UserInterface>&& ui,
catch (Kakoune::client_removed&) catch (Kakoune::client_removed&)
{ {
m_clients.pop_back(); m_clients.pop_back();
close(event_fd);
return; return;
} }
new FDWatcher(event_fd, [input_handler, context, this](FDWatcher& watcher) { context->ui().set_input_callback([input_handler, context, this]() {
try try
{ {
input_handler->handle_available_inputs(*context); input_handler->handle_available_inputs(*context);
@ -64,8 +63,6 @@ void ClientManager::create_client(std::unique_ptr<UserInterface>&& ui,
catch (Kakoune::client_removed&) catch (Kakoune::client_removed&)
{ {
ClientManager::instance().remove_client_by_context(*context); ClientManager::instance().remove_client_by_context(*context);
close(watcher.fd());
delete &watcher;
} }
ClientManager::instance().redraw_clients(); ClientManager::instance().redraw_clients();
}); });

View File

@ -13,7 +13,7 @@ class ClientManager : public Singleton<ClientManager>
{ {
public: public:
void create_client(std::unique_ptr<UserInterface>&& ui, void create_client(std::unique_ptr<UserInterface>&& ui,
int event_fd, const String& init_cmd); const String& init_cmd);
bool empty() const { return m_clients.empty(); } bool empty() const { return m_clients.empty(); }
size_t count() const { return m_clients.size(); } size_t count() const { return m_clients.size(); }

View File

@ -517,6 +517,8 @@ public:
DisplayCoord dimensions() override { return { 0, 0 }; } DisplayCoord dimensions() override { return { 0, 0 }; }
void set_input_callback(InputCallback callback) {}
private: private:
const KeyList& m_keys; const KeyList& m_keys;
size_t m_pos; size_t m_pos;

View File

@ -685,7 +685,7 @@ void create_local_client(const String& init_command)
UserInterface* ui = new LocalNCursesUI{}; UserInterface* ui = new LocalNCursesUI{};
ClientManager::instance().create_client( ClientManager::instance().create_client(
std::unique_ptr<UserInterface>{ui}, 0, init_command); std::unique_ptr<UserInterface>{ui}, init_command);
} }
RemoteClient* connect_to(const String& pid, const String& 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{}; NCursesUI* ui = new NCursesUI{};
RemoteClient* remote_client = new RemoteClient{sock, ui, init_command}; 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; return remote_client;
} }

View File

@ -88,6 +88,7 @@ void on_sigint(int)
} }
NCursesUI::NCursesUI() NCursesUI::NCursesUI()
: m_stdin_watcher{0, [this](FDWatcher&){ if (m_input_callback) m_input_callback(); }}
{ {
//setlocale(LC_CTYPE, ""); //setlocale(LC_CTYPE, "");
initscr(); initscr();
@ -468,4 +469,9 @@ DisplayCoord NCursesUI::dimensions()
return m_dimensions; return m_dimensions;
} }
void NCursesUI::set_input_callback(InputCallback callback)
{
m_input_callback = std::move(callback);
}
} }

View File

@ -6,6 +6,7 @@
#include "user_interface.hh" #include "user_interface.hh"
#include "display_buffer.hh" #include "display_buffer.hh"
#include "event_manager.hh"
namespace Kakoune namespace Kakoune
{ {
@ -35,6 +36,8 @@ public:
const DisplayCoord& anchor, MenuStyle style) override; const DisplayCoord& anchor, MenuStyle style) override;
void info_hide() override; void info_hide() override;
void set_input_callback(InputCallback callback) override;
DisplayCoord dimensions() override; DisplayCoord dimensions() override;
private: private:
friend void on_term_resize(int); friend void on_term_resize(int);
@ -55,6 +58,9 @@ private:
int m_menu_bg; int m_menu_bg;
WINDOW* m_info_win = nullptr; WINDOW* m_info_win = nullptr;
FDWatcher m_stdin_watcher;
InputCallback m_input_callback;
}; };
} }

View File

@ -187,26 +187,30 @@ public:
Key get_key() override; Key get_key() override;
DisplayCoord dimensions() override; DisplayCoord dimensions() override;
void set_input_callback(InputCallback callback) override;
private: private:
int m_socket; FDWatcher m_socket_watcher;
DisplayCoord m_dimensions; DisplayCoord m_dimensions;
InputCallback m_input_callback;
}; };
RemoteUI::RemoteUI(int socket) 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() 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) 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(RemoteUIMsg::PrintStatus);
msg.write(status); msg.write(status);
msg.write(cursor_pos); msg.write(cursor_pos);
@ -215,7 +219,7 @@ void RemoteUI::print_status(const String& status, CharCount cursor_pos)
void RemoteUI::menu_show(const memoryview<String>& choices, void RemoteUI::menu_show(const memoryview<String>& choices,
const DisplayCoord& anchor, MenuStyle style) const DisplayCoord& anchor, MenuStyle style)
{ {
Message msg(m_socket); Message msg(m_socket_watcher.fd());
msg.write(RemoteUIMsg::MenuShow); msg.write(RemoteUIMsg::MenuShow);
msg.write(choices); msg.write(choices);
msg.write(anchor); msg.write(anchor);
@ -224,21 +228,21 @@ void RemoteUI::menu_show(const memoryview<String>& choices,
void RemoteUI::menu_select(int selected) void RemoteUI::menu_select(int selected)
{ {
Message msg(m_socket); Message msg(m_socket_watcher.fd());
msg.write(RemoteUIMsg::MenuSelect); msg.write(RemoteUIMsg::MenuSelect);
msg.write(selected); msg.write(selected);
} }
void RemoteUI::menu_hide() void RemoteUI::menu_hide()
{ {
Message msg(m_socket); Message msg(m_socket_watcher.fd());
msg.write(RemoteUIMsg::MenuHide); msg.write(RemoteUIMsg::MenuHide);
} }
void RemoteUI::info_show(const String& content, void RemoteUI::info_show(const String& content,
const DisplayCoord& anchor, MenuStyle style) const DisplayCoord& anchor, MenuStyle style)
{ {
Message msg(m_socket); Message msg(m_socket_watcher.fd());
msg.write(RemoteUIMsg::InfoShow); msg.write(RemoteUIMsg::InfoShow);
msg.write(content); msg.write(content);
msg.write(anchor); msg.write(anchor);
@ -247,14 +251,14 @@ void RemoteUI::info_show(const String& content,
void RemoteUI::info_hide() void RemoteUI::info_hide()
{ {
Message msg(m_socket); Message msg(m_socket_watcher.fd());
msg.write(RemoteUIMsg::InfoHide); msg.write(RemoteUIMsg::InfoHide);
} }
void RemoteUI::draw(const DisplayBuffer& display_buffer, void RemoteUI::draw(const DisplayBuffer& display_buffer,
const String& mode_line) const String& mode_line)
{ {
Message msg(m_socket); Message msg(m_socket_watcher.fd());
msg.write(RemoteUIMsg::Draw); msg.write(RemoteUIMsg::Draw);
msg.write(display_buffer); msg.write(display_buffer);
msg.write(mode_line); msg.write(mode_line);
@ -267,18 +271,19 @@ bool RemoteUI::is_key_available()
timeval tv; timeval tv;
fd_set rfds; fd_set rfds;
int sock = m_socket_watcher.fd();
FD_ZERO(&rfds); FD_ZERO(&rfds);
FD_SET(m_socket, &rfds); FD_SET(sock, &rfds);
tv.tv_sec = 0; tv.tv_sec = 0;
tv.tv_usec = 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; return res == 1;
} }
Key RemoteUI::get_key() Key RemoteUI::get_key()
{ {
Key key = read<Key>(m_socket); Key key = read<Key>(m_socket_watcher.fd());
if (key.modifiers == resize_modifier) if (key.modifiers == resize_modifier)
{ {
m_dimensions = { (int)(key.key >> 16), (int)(key.key & 0xFFFF) }; m_dimensions = { (int)(key.key >> 16), (int)(key.key & 0xFFFF) };
@ -292,6 +297,11 @@ DisplayCoord RemoteUI::dimensions()
return m_dimensions; return m_dimensions;
} }
void RemoteUI::set_input_callback(InputCallback callback)
{
m_input_callback = std::move(callback);
}
RemoteClient::RemoteClient(int socket, UserInterface* ui, RemoteClient::RemoteClient(int socket, UserInterface* ui,
const String& init_command) const String& init_command)
: m_ui(ui), m_dimensions(ui->dimensions()), : m_ui(ui), m_dimensions(ui->dimensions()),
@ -301,6 +311,8 @@ RemoteClient::RemoteClient(int socket, UserInterface* ui,
msg.write(init_command); msg.write(init_command);
Key key{ resize_modifier, Codepoint(((int)m_dimensions.line << 16) | (int)m_dimensions.column) }; Key key{ resize_modifier, Codepoint(((int)m_dimensions.line << 16) | (int)m_dimensions.column) };
msg.write(key); msg.write(key);
m_ui->set_input_callback([this]{ write_next_key(); });
} }
void RemoteClient::process_next_message() void RemoteClient::process_next_message()
@ -370,12 +382,12 @@ void RemoteClient::write_next_key()
void handle_remote(FDWatcher& watcher) void handle_remote(FDWatcher& watcher)
{ {
int socket = watcher.fd(); int socket = watcher.fd();
delete &watcher;
String init_command = read<String>(socket); String init_command = read<String>(socket);
RemoteUI* ui = new RemoteUI{socket}; RemoteUI* ui = new RemoteUI{socket};
delete &watcher;
ClientManager::instance().create_client( ClientManager::instance().create_client(
std::unique_ptr<UserInterface>{ui}, socket, init_command); std::unique_ptr<UserInterface>{ui}, init_command);
} }
} }

View File

@ -19,6 +19,8 @@ enum class MenuStyle
Inline Inline
}; };
using InputCallback = std::function<void()>;
class UserInterface : public SafeCountable class UserInterface : public SafeCountable
{ {
public: public:
@ -39,6 +41,8 @@ public:
virtual DisplayCoord dimensions() = 0; virtual DisplayCoord dimensions() = 0;
virtual bool is_key_available() = 0; virtual bool is_key_available() = 0;
virtual Key get_key() = 0; virtual Key get_key() = 0;
virtual void set_input_callback(InputCallback callback) = 0;
}; };
} }