mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-16 07:27:35 +00:00
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() ||
|
||||
_text_screen_surface->size() != new_geometry.size();
|
||||
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(),
|
||||
_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();
|
||||
|
||||
} else {
|
||||
|
@ -92,6 +92,34 @@ class Terminal::Text_screen_surface
|
||||
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:
|
||||
|
||||
Font const &_font;
|
||||
@ -133,6 +161,10 @@ class Terminal::Text_screen_surface
|
||||
_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()
|
||||
{
|
||||
PT *fb_base = _framebuffer.pixel<PT>();
|
||||
@ -238,6 +270,11 @@ class Terminal::Text_screen_surface
|
||||
_decoder.insert(c.c);
|
||||
}
|
||||
|
||||
void import(Snapshot const &snapshot)
|
||||
{
|
||||
_cell_array.import_from(snapshot._cell_array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return size in colums/rows
|
||||
*/
|
||||
|
@ -94,6 +94,13 @@ class Cell_array
|
||||
_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()
|
||||
{
|
||||
for (unsigned i = 0; i < _num_lines; i++)
|
||||
@ -115,11 +122,23 @@ class Cell_array
|
||||
_line_dirty[line] = true;
|
||||
}
|
||||
|
||||
CELL get_cell(int column, int line)
|
||||
CELL get_cell(int column, int line) const
|
||||
{
|
||||
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]; }
|
||||
|
||||
void mark_line_as_clean(int line)
|
||||
@ -167,8 +186,8 @@ class Cell_array
|
||||
_line_dirty[pos.y] = true;
|
||||
}
|
||||
|
||||
unsigned num_cols() { return _num_cols; }
|
||||
unsigned num_lines() { return _num_lines; }
|
||||
unsigned num_cols() const { return _num_cols; }
|
||||
unsigned num_lines() const { return _num_lines; }
|
||||
};
|
||||
|
||||
#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; }
|
||||
|
||||
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)
|
||||
{
|
||||
if (c.ascii() > 0x10) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user