2012-10-30 17:00:44 +04:00
|
|
|
#include "client_manager.hh"
|
|
|
|
|
2012-10-31 17:23:44 +04:00
|
|
|
#include "event_manager.hh"
|
2012-11-07 17:02:23 +04:00
|
|
|
#include "buffer_manager.hh"
|
2012-10-31 17:23:44 +04:00
|
|
|
|
2012-10-30 17:00:44 +04:00
|
|
|
namespace Kakoune
|
|
|
|
{
|
|
|
|
|
2012-10-31 17:23:44 +04:00
|
|
|
void ClientManager::create_client(std::unique_ptr<UserInterface>&& ui,
|
|
|
|
Buffer& buffer, int event_fd)
|
2012-10-30 17:00:44 +04:00
|
|
|
{
|
2012-11-05 22:15:42 +04:00
|
|
|
m_clients.emplace_back(std::move(ui), get_unused_window_for_buffer(buffer));
|
2012-10-31 17:23:44 +04:00
|
|
|
|
|
|
|
InputHandler* input_handler = m_clients.back().input_handler.get();
|
|
|
|
Context* context = m_clients.back().context.get();
|
2012-11-06 16:37:18 +04:00
|
|
|
EventManager::instance().watch(event_fd, [input_handler, context, this](int fd) {
|
2012-10-31 17:23:44 +04:00
|
|
|
try
|
|
|
|
{
|
|
|
|
input_handler->handle_available_inputs(*context);
|
2012-11-05 22:58:04 +04:00
|
|
|
context->window().forget_timestamp();
|
2012-10-31 17:23:44 +04:00
|
|
|
}
|
|
|
|
catch (Kakoune::runtime_error& error)
|
|
|
|
{
|
|
|
|
context->print_status(error.description());
|
|
|
|
}
|
|
|
|
catch (Kakoune::client_removed&)
|
|
|
|
{
|
2012-11-20 21:54:35 +04:00
|
|
|
ClientManager::instance().remove_client_by_context(*context);
|
2012-11-20 22:48:27 +04:00
|
|
|
// do not forget, after this line, the current closure
|
|
|
|
// is dead, do not access captured data.
|
2012-11-06 16:37:18 +04:00
|
|
|
EventManager::instance().unwatch(fd);
|
|
|
|
close(fd);
|
2012-10-31 17:23:44 +04:00
|
|
|
}
|
2012-11-05 22:58:04 +04:00
|
|
|
ClientManager::instance().redraw_clients();
|
2012-10-31 17:23:44 +04:00
|
|
|
});
|
2012-11-05 22:58:04 +04:00
|
|
|
redraw_clients();
|
2012-10-30 17:00:44 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void ClientManager::remove_client_by_context(Context& context)
|
|
|
|
{
|
|
|
|
for (auto it = m_clients.begin(); it != m_clients.end(); ++it)
|
|
|
|
{
|
|
|
|
if (it->context.get() == &context)
|
|
|
|
{
|
|
|
|
m_clients.erase(it);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
assert(false);
|
|
|
|
}
|
|
|
|
|
2012-11-22 17:08:55 +04:00
|
|
|
Window& ClientManager::get_unused_window_for_buffer(Buffer& buffer)
|
2012-11-05 22:15:42 +04:00
|
|
|
{
|
2012-11-22 17:08:55 +04:00
|
|
|
for (auto& w : m_windows)
|
2012-11-05 22:15:42 +04:00
|
|
|
{
|
2012-11-22 17:08:55 +04:00
|
|
|
if (&w->buffer() != &buffer)
|
|
|
|
continue;
|
|
|
|
|
2012-11-05 22:15:42 +04:00
|
|
|
auto it = std::find_if(m_clients.begin(), m_clients.end(),
|
|
|
|
[&](const Client& client) {
|
|
|
|
return &client.context->window() == w.get();
|
|
|
|
});
|
|
|
|
if (it == m_clients.end())
|
2012-11-05 22:58:04 +04:00
|
|
|
{
|
|
|
|
w->forget_timestamp();
|
2012-11-05 22:15:42 +04:00
|
|
|
return *w;
|
2012-11-05 22:58:04 +04:00
|
|
|
}
|
2012-11-05 22:15:42 +04:00
|
|
|
}
|
2012-11-22 17:08:55 +04:00
|
|
|
m_windows.emplace_back(new Window(buffer));
|
|
|
|
return *m_windows.back();
|
2012-11-05 22:15:42 +04:00
|
|
|
}
|
|
|
|
|
2012-11-07 17:02:23 +04:00
|
|
|
void ClientManager::ensure_no_client_uses_buffer(Buffer& buffer)
|
|
|
|
{
|
|
|
|
for (auto& client : m_clients)
|
|
|
|
{
|
2012-11-12 22:59:25 +04:00
|
|
|
client.context->forget_jumps_to_buffer(buffer);
|
|
|
|
|
2012-11-07 17:02:23 +04:00
|
|
|
if (&client.context->buffer() != &buffer)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// change client context to edit the first buffer which is not the
|
|
|
|
// specified one. As BufferManager stores buffer according to last
|
|
|
|
// access, this selects a sensible buffer to display.
|
|
|
|
for (auto& buf : BufferManager::instance())
|
|
|
|
{
|
|
|
|
if (buf != &buffer)
|
|
|
|
{
|
|
|
|
Window& w = get_unused_window_for_buffer(*buf);
|
|
|
|
client.context->change_editor(w);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-11-22 17:08:55 +04:00
|
|
|
auto end = std::remove_if(m_windows.begin(), m_windows.end(),
|
|
|
|
[&buffer](std::unique_ptr<Window>& w)
|
|
|
|
{ return &w->buffer() == &buffer; });
|
|
|
|
m_windows.erase(end, m_windows.end());
|
2012-11-07 17:02:23 +04:00
|
|
|
}
|
|
|
|
|
2012-11-05 22:58:04 +04:00
|
|
|
void ClientManager::redraw_clients() const
|
|
|
|
{
|
|
|
|
for (auto& client : m_clients)
|
|
|
|
{
|
|
|
|
Context& context = *client.context;
|
|
|
|
if (context.window().timestamp() != context.buffer().timestamp())
|
|
|
|
{
|
|
|
|
DisplayCoord dimensions = context.ui().dimensions();
|
|
|
|
if (dimensions == DisplayCoord{0,0})
|
|
|
|
return;
|
|
|
|
context.window().set_dimensions(dimensions);
|
|
|
|
context.window().update_display_buffer();;
|
|
|
|
context.ui().draw(context.window().display_buffer(),
|
|
|
|
context.window().status_line());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-30 17:00:44 +04:00
|
|
|
}
|