terminal: preserve content during resize
This patch eliminates the flickering of the terminal during resize.
This commit is contained in:
parent
674b0ba947
commit
8e0cc44e24
|
@ -190,8 +190,39 @@ void Terminal::Main::_handle_config()
|
||||||
bool const reconstruct = !_text_screen_surface.constructed() ||
|
bool const reconstruct = !_text_screen_surface.constructed() ||
|
||||||
_text_screen_surface->size() != new_geometry.size();
|
_text_screen_surface->size() != new_geometry.size();
|
||||||
if (reconstruct) {
|
if (reconstruct) {
|
||||||
|
|
||||||
|
typedef Text_screen_surface<PT>::Snapshot Snapshot;
|
||||||
|
Constructible<Snapshot> snapshot { };
|
||||||
|
|
||||||
|
size_t const snapshot_bytes = _text_screen_surface.constructed()
|
||||||
|
? Snapshot::bytes_needed(*_text_screen_surface)
|
||||||
|
: 0,
|
||||||
|
preserved_bytes = 32*1024,
|
||||||
|
needed_bytes = snapshot_bytes + preserved_bytes,
|
||||||
|
avail_bytes = _env.pd().avail_ram().value;
|
||||||
|
|
||||||
|
bool const preserve_content = (needed_bytes < avail_bytes);
|
||||||
|
|
||||||
|
if (!preserve_content)
|
||||||
|
warning("not enough spare RAM to preserve content (",
|
||||||
|
"need ", Genode::Number_of_bytes(needed_bytes), ", "
|
||||||
|
"have ", Genode::Number_of_bytes(avail_bytes), ")");
|
||||||
|
|
||||||
|
if (preserve_content && _text_screen_surface.constructed())
|
||||||
|
snapshot.construct(_heap, *_text_screen_surface);
|
||||||
|
|
||||||
|
Position const orig_cursor_pos = _text_screen_surface.constructed()
|
||||||
|
? _text_screen_surface->cursor_pos()
|
||||||
|
: Position();
|
||||||
|
|
||||||
_text_screen_surface.construct(_heap, _font->font(),
|
_text_screen_surface.construct(_heap, _font->font(),
|
||||||
_color_palette, _framebuffer);
|
_color_palette, _framebuffer);
|
||||||
|
|
||||||
|
if (snapshot.constructed())
|
||||||
|
_text_screen_surface->import(*snapshot);
|
||||||
|
|
||||||
|
_text_screen_surface->cursor_pos(orig_cursor_pos);
|
||||||
|
|
||||||
_terminal_size = _text_screen_surface->size();
|
_terminal_size = _text_screen_surface->size();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -92,6 +92,34 @@ class Terminal::Text_screen_surface
|
||||||
bool valid() const { return columns*lines > 0; }
|
bool valid() const { return columns*lines > 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Snapshot of text-screen content
|
||||||
|
*/
|
||||||
|
class Snapshot
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
friend class Text_screen_surface;
|
||||||
|
|
||||||
|
Cell_array<Char_cell> _cell_array;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
static size_t bytes_needed(Text_screen_surface const &surface)
|
||||||
|
{
|
||||||
|
return Cell_array<Char_cell>::bytes_needed(surface.size().w(),
|
||||||
|
surface.size().h());
|
||||||
|
}
|
||||||
|
|
||||||
|
Snapshot(Allocator &alloc, Text_screen_surface const &from)
|
||||||
|
:
|
||||||
|
_cell_array(from._cell_array.num_cols(),
|
||||||
|
from._cell_array.num_lines(), alloc)
|
||||||
|
{
|
||||||
|
_cell_array.import_from(from._cell_array);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Font const &_font;
|
Font const &_font;
|
||||||
|
@ -133,6 +161,10 @@ class Terminal::Text_screen_surface
|
||||||
_cell_array.mark_all_lines_as_dirty(); /* trigger refresh */
|
_cell_array.mark_all_lines_as_dirty(); /* trigger refresh */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Position cursor_pos() const { return _character_screen.cursor_pos(); }
|
||||||
|
|
||||||
|
void cursor_pos(Position pos) { _character_screen.cursor_pos(pos); }
|
||||||
|
|
||||||
void redraw()
|
void redraw()
|
||||||
{
|
{
|
||||||
PT *fb_base = _framebuffer.pixel<PT>();
|
PT *fb_base = _framebuffer.pixel<PT>();
|
||||||
|
@ -238,6 +270,11 @@ class Terminal::Text_screen_surface
|
||||||
_decoder.insert(c.c);
|
_decoder.insert(c.c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void import(Snapshot const &snapshot)
|
||||||
|
{
|
||||||
|
_cell_array.import_from(snapshot._cell_array);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return size in colums/rows
|
* Return size in colums/rows
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -94,6 +94,13 @@ class Cell_array
|
||||||
_array[i] = new (alloc) CELL[num_cols];
|
_array[i] = new (alloc) CELL[num_cols];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Genode::size_t bytes_needed(unsigned num_cols, unsigned num_lines)
|
||||||
|
{
|
||||||
|
return sizeof(Char_cell_line[num_lines])
|
||||||
|
+ sizeof(bool[num_lines])
|
||||||
|
+ sizeof(CELL[num_cols])*num_lines;
|
||||||
|
}
|
||||||
|
|
||||||
~Cell_array()
|
~Cell_array()
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < _num_lines; i++)
|
for (unsigned i = 0; i < _num_lines; i++)
|
||||||
|
@ -115,11 +122,23 @@ class Cell_array
|
||||||
_line_dirty[line] = true;
|
_line_dirty[line] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CELL get_cell(int column, int line)
|
CELL get_cell(int column, int line) const
|
||||||
{
|
{
|
||||||
return _array[line][column];
|
return _array[line][column];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void import_from(Cell_array const &other)
|
||||||
|
{
|
||||||
|
unsigned const num_cols = Genode::min(_num_cols, other._num_cols),
|
||||||
|
num_lines = Genode::min(_num_lines, other._num_lines);
|
||||||
|
|
||||||
|
for (unsigned line = 0; line < num_lines; line++)
|
||||||
|
for (unsigned column = 0; column < num_cols; column++)
|
||||||
|
_array[line][column] = other.get_cell(column, line);
|
||||||
|
|
||||||
|
mark_all_lines_as_dirty();
|
||||||
|
}
|
||||||
|
|
||||||
bool line_dirty(int line) { return _line_dirty[line]; }
|
bool line_dirty(int line) { return _line_dirty[line]; }
|
||||||
|
|
||||||
void mark_line_as_clean(int line)
|
void mark_line_as_clean(int line)
|
||||||
|
@ -167,8 +186,8 @@ class Cell_array
|
||||||
_line_dirty[pos.y] = true;
|
_line_dirty[pos.y] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned num_cols() { return _num_cols; }
|
unsigned num_cols() const { return _num_cols; }
|
||||||
unsigned num_lines() { return _num_lines; }
|
unsigned num_lines() const { return _num_lines; }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _TERMINAL__CELL_ARRAY_H_ */
|
#endif /* _TERMINAL__CELL_ARRAY_H_ */
|
||||||
|
|
|
@ -160,6 +160,12 @@ class Char_cell_array_character_screen : public Terminal::Character_screen
|
||||||
|
|
||||||
Terminal::Position cursor_pos() const { return _cursor_pos; }
|
Terminal::Position cursor_pos() const { return _cursor_pos; }
|
||||||
|
|
||||||
|
void cursor_pos(Terminal::Position pos)
|
||||||
|
{
|
||||||
|
_cursor_pos.x = Genode::min(_boundary.width - 1, pos.x);
|
||||||
|
_cursor_pos.y = Genode::min(_boundary.height - 1, pos.y);
|
||||||
|
}
|
||||||
|
|
||||||
void output(Terminal::Character c)
|
void output(Terminal::Character c)
|
||||||
{
|
{
|
||||||
if (c.ascii() > 0x10) {
|
if (c.ascii() > 0x10) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user