home/src/client.hh
Maxime Coste 299e22ca7c Do not block when waiting for next event if we have pending input
Handle next event should never block if we have already accumulated
input that we want to process. As we can accumulate new input in
lots of places (everytime we run a shell process for example, we
might end up reading input keys. That can be triggered during the
mode line generation which takes place during display of the window)

Fixes #1804
2018-01-21 12:00:40 +11:00

160 lines
3.6 KiB
C++

#ifndef client_hh_INCLUDED
#define client_hh_INCLUDED
#include "constexpr_utils.hh"
#include "display_buffer.hh"
#include "env_vars.hh"
#include "input_handler.hh"
#include "safe_ptr.hh"
#include "utils.hh"
#include "option_manager.hh"
#include "enum.hh"
namespace Kakoune
{
class Window;
class UserInterface;
class String;
struct Key;
enum class EventMode;
enum class InfoStyle;
enum class MenuStyle;
class Client : public SafeCountable, public OptionManagerWatcher
{
public:
using OnExitCallback = std::function<void (int status)>;
Client(std::unique_ptr<UserInterface>&& ui,
std::unique_ptr<Window>&& window,
SelectionList selections,
int pid, EnvVarMap env_vars,
String name,
OnExitCallback on_exit);
~Client();
Client(Client&&) = delete;
bool process_pending_inputs();
bool has_pending_inputs() const { return not m_pending_keys.empty(); }
void menu_show(Vector<DisplayLine> choices, BufferCoord anchor, MenuStyle style);
void menu_select(int selected);
void menu_hide();
void info_show(String title, String content, BufferCoord anchor, InfoStyle style);
void info_hide(bool even_modal = false);
void print_status(DisplayLine status_line, bool immediate = false);
DisplayCoord dimensions() const;
void force_redraw();
void redraw_ifn();
void check_if_buffer_needs_reloading();
Context& context() { return m_input_handler.context(); }
const Context& context() const { return m_input_handler.context(); }
InputHandler& input_handler() { return m_input_handler; }
const InputHandler& input_handler() const { return m_input_handler; }
void change_buffer(Buffer& buffer);
StringView get_env_var(StringView name) const;
Buffer* last_buffer() const { return m_last_buffer.get(); }
void set_last_buffer(Buffer* last_buffer) { m_last_buffer = last_buffer; }
void exit(int status) { m_on_exit(status); }
int pid() const { return m_pid; }
private:
void on_option_changed(const Option& option) override;
void on_buffer_reload_key(Key key);
void close_buffer_reload_dialog();
void reload_buffer();
Optional<Key> get_next_key(EventMode mode);
DisplayLine generate_mode_line() const;
std::unique_ptr<UserInterface> m_ui;
std::unique_ptr<Window> m_window;
const int m_pid;
OnExitCallback m_on_exit;
EnvVarMap m_env_vars;
InputHandler m_input_handler;
DisplayLine m_status_line;
DisplayLine m_mode_line;
enum PendingUI : int
{
MenuShow = 1 << 0,
MenuSelect = 1 << 1,
MenuHide = 1 << 2,
InfoShow = 1 << 3,
InfoHide = 1 << 4,
StatusLine = 1 << 5,
Draw = 1 << 6,
Refresh = 1 << 7,
};
int m_ui_pending = 0;
struct Menu
{
Vector<DisplayLine> items;
BufferCoord anchor;
Optional<DisplayCoord> ui_anchor;
MenuStyle style;
int selected;
} m_menu{};
struct Info
{
String title;
String content;
BufferCoord anchor;
Optional<DisplayCoord> ui_anchor;
InfoStyle style;
} m_info{};
Vector<Key, MemoryDomain::Client> m_pending_keys;
bool m_buffer_reload_dialog_opened = false;
SafePtr<Buffer> m_last_buffer;
};
enum class Autoreload
{
Yes,
No,
Ask
};
constexpr auto enum_desc(Meta::Type<Autoreload>)
{
return make_array<EnumDesc<Autoreload>, 5>({
{ Autoreload::Yes, "yes" },
{ Autoreload::No, "no" },
{ Autoreload::Ask, "ask" },
{ Autoreload::Yes, "true" },
{ Autoreload::No, "false" }
});
}
}
#endif // client_hh_INCLUDED