Rework client redrawing, delay menu/info methods until next refresh
That avoid sending lots of spurious info_hide/menu_hide, just set a flag and wait until the client is asked to redraw.
This commit is contained in:
parent
a15cdeae6e
commit
6c8f8fe691
101
src/client.cc
101
src/client.cc
|
@ -36,7 +36,7 @@ Client::Client(std::unique_ptr<UserInterface>&& ui,
|
|||
|
||||
m_ui->set_ui_options(m_window->options()["ui_options"].get<UserInterface::Options>());
|
||||
m_ui->set_input_callback([this](EventMode mode) { handle_available_input(mode); });
|
||||
m_ui_dirty = true;
|
||||
force_redraw();
|
||||
}
|
||||
|
||||
Client::~Client()
|
||||
|
@ -101,7 +101,8 @@ void Client::handle_available_input(EventMode mode)
|
|||
|
||||
void Client::print_status(DisplayLine status_line)
|
||||
{
|
||||
m_pending_status_line = std::move(status_line);
|
||||
m_status_line = std::move(status_line);
|
||||
m_ui_pending |= StatusLine;
|
||||
}
|
||||
|
||||
DisplayLine Client::generate_mode_line() const
|
||||
|
@ -159,7 +160,7 @@ void Client::change_buffer(Buffer& buffer)
|
|||
context().selections_write_only() = std::move(ws.selections);
|
||||
context().set_window(*m_window);
|
||||
m_window->set_dimensions(m_ui->dimensions());
|
||||
m_ui_dirty = true;
|
||||
force_redraw();
|
||||
|
||||
m_window->hooks().run_hook("WinDisplay", buffer.name(), context());
|
||||
}
|
||||
|
@ -171,56 +172,70 @@ static bool is_inline(InfoStyle style)
|
|||
style == InfoStyle::InlineBelow;
|
||||
}
|
||||
|
||||
void Client::redraw_ifn(bool force)
|
||||
void Client::redraw_ifn()
|
||||
{
|
||||
Window& window = context().window();
|
||||
if (window.needs_redraw(context()))
|
||||
m_ui_pending |= Draw;
|
||||
|
||||
const bool needs_redraw = window.needs_redraw(context());
|
||||
if (needs_redraw or force)
|
||||
DisplayLine mode_line = generate_mode_line();
|
||||
if (mode_line.atoms() != m_mode_line.atoms())
|
||||
{
|
||||
m_ui_pending |= StatusLine;
|
||||
m_mode_line = std::move(mode_line);
|
||||
}
|
||||
|
||||
if (m_ui_pending == 0)
|
||||
return;
|
||||
|
||||
if (m_ui_pending & Draw)
|
||||
{
|
||||
auto window_pos = window.position();
|
||||
m_ui->draw(window.update_display_buffer(context()), get_face("Default"));
|
||||
|
||||
// window moved, reanchor eventual menu and info
|
||||
if (force or window_pos != window.position())
|
||||
if (window_pos != window.position())
|
||||
{
|
||||
if (not m_menu.items.empty() and m_menu.style == MenuStyle::Inline)
|
||||
{
|
||||
m_ui->menu_show(m_menu.items, window.display_position(m_menu.anchor),
|
||||
get_face("MenuForeground"), get_face("MenuBackground"), m_menu.style);
|
||||
m_ui->menu_select(m_menu.selected);
|
||||
}
|
||||
m_ui_pending |= (MenuShow | MenuSelect);
|
||||
if (not m_info.content.empty() and is_inline(m_info.style))
|
||||
m_ui->info_show(m_info.title, m_info.content,
|
||||
window.display_position(m_info.anchor),
|
||||
get_face("Information"), m_info.style);
|
||||
m_ui_pending |= InfoShow;
|
||||
}
|
||||
m_ui_dirty = true;
|
||||
}
|
||||
|
||||
DisplayLine mode_line = generate_mode_line();
|
||||
if (force or needs_redraw or
|
||||
m_status_line.atoms() != m_pending_status_line.atoms() or
|
||||
mode_line.atoms() != m_mode_line.atoms())
|
||||
if (m_ui_pending & MenuShow)
|
||||
{
|
||||
m_mode_line = std::move(mode_line);
|
||||
m_status_line = m_pending_status_line;
|
||||
const CharCoord ui_anchor = m_menu.style == MenuStyle::Inline ?
|
||||
window.display_position(m_menu.anchor) : CharCoord{};
|
||||
m_ui->menu_show(m_menu.items, ui_anchor,
|
||||
get_face("MenuForeground"), get_face("MenuBackground"),
|
||||
m_menu.style);
|
||||
}
|
||||
if (m_ui_pending & MenuSelect)
|
||||
m_ui->menu_select(m_menu.selected);
|
||||
if (m_ui_pending & MenuHide)
|
||||
m_ui->menu_hide();
|
||||
|
||||
if (m_ui_pending & InfoShow)
|
||||
{
|
||||
const CharCoord ui_anchor = is_inline(m_info.style) ?
|
||||
window.display_position(m_info.anchor) : CharCoord{};
|
||||
m_ui->info_show(m_info.title, m_info.content, ui_anchor,
|
||||
get_face("Information"), m_info.style);
|
||||
}
|
||||
if (m_ui_pending & InfoHide)
|
||||
m_ui->info_hide();
|
||||
|
||||
if (m_ui_pending & StatusLine)
|
||||
m_ui->draw_status(m_status_line, m_mode_line, get_face("StatusLine"));
|
||||
m_ui_dirty = true;
|
||||
}
|
||||
|
||||
if (m_ui_dirty or force)
|
||||
{
|
||||
m_ui_dirty = false;
|
||||
m_ui->refresh(force);
|
||||
}
|
||||
m_ui->refresh(m_ui_pending | Refresh);
|
||||
m_ui_pending = 0;
|
||||
}
|
||||
|
||||
void Client::force_redraw()
|
||||
{
|
||||
if (m_window)
|
||||
m_window->force_redraw();
|
||||
m_ui_pending |= Refresh;
|
||||
}
|
||||
|
||||
void Client::reload_buffer()
|
||||
|
@ -310,45 +325,43 @@ void Client::on_option_changed(const Option& option)
|
|||
if (option.name() == "ui_options")
|
||||
{
|
||||
m_ui->set_ui_options(option.get<UserInterface::Options>());
|
||||
m_ui_dirty = true;
|
||||
m_ui_pending |= Draw;
|
||||
}
|
||||
}
|
||||
|
||||
void Client::menu_show(Vector<DisplayLine> choices, ByteCoord anchor, MenuStyle style)
|
||||
{
|
||||
m_menu = Menu{ std::move(choices), anchor, style, -1 };
|
||||
CharCoord ui_anchor = style == MenuStyle::Inline ? context().window().display_position(anchor) : CharCoord{};
|
||||
m_ui->menu_show(m_menu.items, ui_anchor, get_face("MenuForeground"), get_face("MenuBackground"), style);
|
||||
m_ui_dirty = true;
|
||||
m_ui_pending |= MenuShow;
|
||||
m_ui_pending &= ~MenuHide;
|
||||
}
|
||||
|
||||
void Client::menu_select(int selected)
|
||||
{
|
||||
m_menu.selected = selected;
|
||||
m_ui->menu_select(selected);
|
||||
m_ui_dirty = true;
|
||||
m_ui_pending |= MenuSelect;
|
||||
m_ui_pending &= ~MenuHide;
|
||||
}
|
||||
|
||||
void Client::menu_hide()
|
||||
{
|
||||
m_menu = Menu{};
|
||||
m_ui->menu_hide();
|
||||
m_ui_dirty = true;
|
||||
m_ui_pending |= MenuHide;
|
||||
m_ui_pending &= ~(MenuShow | MenuSelect);
|
||||
}
|
||||
|
||||
void Client::info_show(String title, String content, ByteCoord anchor, InfoStyle style)
|
||||
{
|
||||
m_info = Info{ std::move(title), std::move(content), anchor, style };
|
||||
CharCoord ui_anchor = is_inline(style) ? context().window().display_position(anchor) : CharCoord{};
|
||||
m_ui->info_show(m_info.title, m_info.content, ui_anchor, get_face("Information"), style);
|
||||
m_ui_dirty = true;
|
||||
m_ui_pending |= InfoShow;
|
||||
m_ui_pending &= ~InfoHide;
|
||||
}
|
||||
|
||||
void Client::info_hide()
|
||||
{
|
||||
m_info = Info{};
|
||||
m_ui->info_hide();
|
||||
m_ui_dirty = true;
|
||||
m_ui_pending |= InfoHide;
|
||||
m_ui_pending &= ~InfoShow;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ public:
|
|||
CharCoord dimensions() const { return m_ui->dimensions(); }
|
||||
|
||||
void force_redraw();
|
||||
void redraw_ifn(bool force = false);
|
||||
void redraw_ifn();
|
||||
|
||||
void check_if_buffer_needs_reloading();
|
||||
|
||||
|
@ -74,7 +74,6 @@ private:
|
|||
|
||||
DisplayLine generate_mode_line() const;
|
||||
|
||||
bool m_ui_dirty = false;
|
||||
std::unique_ptr<UserInterface> m_ui;
|
||||
std::unique_ptr<Window> m_window;
|
||||
|
||||
|
@ -83,9 +82,21 @@ private:
|
|||
InputHandler m_input_handler;
|
||||
|
||||
DisplayLine m_status_line;
|
||||
DisplayLine m_pending_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;
|
||||
|
|
|
@ -1563,7 +1563,10 @@ void ensure_forward(Context& context, NormalParams)
|
|||
void force_redraw(Context& context, NormalParams)
|
||||
{
|
||||
if (context.has_client())
|
||||
context.client().redraw_ifn(true);
|
||||
{
|
||||
context.client().force_redraw();
|
||||
context.client().redraw_ifn();
|
||||
}
|
||||
}
|
||||
|
||||
static NormalCmdDesc cmds[] =
|
||||
|
|
Loading…
Reference in New Issue
Block a user