fixing screen redraw/region invalidation (less flicker, faster)

This commit is contained in:
cy384 2020-08-17 22:21:38 -04:00
parent a9fbb1092a
commit 30a64faf16
5 changed files with 48 additions and 37 deletions

View File

@ -19,7 +19,6 @@ system requirements
to do to do
----- -----
* terminal resizing * terminal resizing
* proper region invalidation/redraw
* good console emulation (to be implemented with libvterm) * good console emulation (to be implemented with libvterm)
* saving/loading connection settings * saving/loading connection settings
* nicer connection dialog * nicer connection dialog

View File

@ -10,6 +10,26 @@
void draw_char(int x, int y, Rect* r, char c) void draw_char(int x, int y, Rect* r, char c)
{ {
MoveTo(r->left + x * con.cell_width + 2, r->top + ((y+1) * con.cell_height) - 2);
DrawChar(c);
}
}
void draw_screen(Rect* r)
{
// get the intersection of our console region and the update region
Rect bounds = (con.win->portRect);
SectRect(r, &bounds, r);
short minRow = (0 > (r->top - bounds.top) / con.cell_height) ? 0 : (r->top - bounds.top) / con.cell_height;
short maxRow = (24 < (r->bottom - bounds.top + con.cell_height - 1) / con.cell_height) ? 24 : (r->bottom - bounds.top + con.cell_height - 1) / con.cell_height;
short minCol = (0 > (r->left - bounds.left) / con.cell_width) ? 0 : (r->left - bounds.left) / con.cell_width;
short maxCol = (80 < (r->right - bounds.left + con.cell_width - 1) / con.cell_width) ? 80 : (r->right - bounds.left + con.cell_width - 1) / con.cell_width;
EraseRect(r);
// don't clobber font settings // don't clobber font settings
short save_font = qd.thePort->txFont; short save_font = qd.thePort->txFont;
short save_font_size = qd.thePort->txSize; short save_font_size = qd.thePort->txSize;
@ -19,25 +39,17 @@ void draw_char(int x, int y, Rect* r, char c)
TextSize(9); TextSize(9);
TextFace(normal); TextFace(normal);
int cell_height = 12; for(int i = minRow; i < maxRow; i++)
int cell_width = CharWidth('M'); {
for (int j = minCol; j < maxCol; j++)
MoveTo(r->left + x * cell_width + 2, r->top + ((y+1) * cell_height) - 2); draw_char(j, i, r, con.data[j][i]);
DrawChar(c); }
TextFont(save_font); TextFont(save_font);
TextSize(save_font_size); TextSize(save_font_size);
TextFace(save_font_face); TextFace(save_font_face);
} }
void draw_screen(Rect* r)
{
EraseRect(r);
for (int x = 0; x < 80; x++)
for (int y = 0; y < 24; y++)
draw_char(x, y, r, con.data[x][y]);
}
void ruler(Rect* r) void ruler(Rect* r)
{ {
char itoc[] = {'0','1','2','3','4','5','6','7','8','9'}; char itoc[] = {'0','1','2','3','4','5','6','7','8','9'};
@ -58,6 +70,8 @@ void bump_up_line()
} }
for (int x = 0; x < 80; x++) con.data[x][23] = ' '; for (int x = 0; x < 80; x++) con.data[x][23] = ' ';
InvalRect(&(con.win->portRect));
} }
int is_printable(char c) int is_printable(char c)
@ -72,6 +86,8 @@ void print_char(char c)
{ {
// erase current location // erase current location
con.data[con.cursor_x][con.cursor_y] = ' '; con.data[con.cursor_x][con.cursor_y] = ' ';
Rect inval = cell_rect(con.cursor_x, con.cursor_y, (con.win->portRect));
InvalRect(&inval);
// wrap back to the previous line if possible and necessary // wrap back to the previous line if possible and necessary
if (con.cursor_x == 0 && con.cursor_y != 0) if (con.cursor_x == 0 && con.cursor_y != 0)
@ -100,6 +116,8 @@ void print_char(char c)
if (is_printable(c)) if (is_printable(c))
{ {
con.data[con.cursor_x][con.cursor_y] = c; con.data[con.cursor_x][con.cursor_y] = c;
Rect inval = cell_rect(con.cursor_x, con.cursor_y, (con.win->portRect));
InvalRect(&inval);
con.cursor_x++; con.cursor_x++;
} }
@ -138,13 +156,6 @@ void print_int(int d)
print_string(buffer+i+1); print_string(buffer+i+1);
} }
void print_string_i(const char* c)
{
print_string(c);
// TODO invalidate only the correct region
InvalRect(&(con.win->portRect));
}
void print_string(const char* c) void print_string(const char* c)
{ {
while (*c != '\0') while (*c != '\0')
@ -185,8 +196,6 @@ void printf_i(const char* str, ...)
str++; str++;
} }
InvalRect(&(con.win->portRect));
va_end(args); va_end(args);
} }
@ -211,8 +220,8 @@ void console_setup(void)
TextSize(9); TextSize(9);
TextFace(normal); TextFace(normal);
int cell_height = 12; con.cell_height = 12;
int cell_width = CharWidth('M'); con.cell_width = CharWidth('M');
TextFont(save_font); TextFont(save_font);
TextSize(save_font_size); TextSize(save_font_size);
@ -222,8 +231,8 @@ void console_setup(void)
InsetRect(&initial_window_bounds, 20, 20); InsetRect(&initial_window_bounds, 20, 20);
initial_window_bounds.top += 40; initial_window_bounds.top += 40;
initial_window_bounds.bottom = initial_window_bounds.top + cell_height * 24 + 2; initial_window_bounds.bottom = initial_window_bounds.top + con.cell_height * 24 + 2;
initial_window_bounds.right = initial_window_bounds.left + cell_width * 80 + 4; initial_window_bounds.right = initial_window_bounds.left + con.cell_width * 80 + 4;
// limits on window size changes: // limits on window size changes:
// top = min vertical // top = min vertical
@ -248,6 +257,12 @@ void console_setup(void)
con.cursor_x = 0; con.cursor_x = 0;
con.cursor_y = 0; con.cursor_y = 0;
} }
Rect cell_rect(int x, int y, Rect bounds)
{
Rect r = { (short) (bounds.top + y * con.cell_height), (short) (bounds.left + x * con.cell_width + 2),
(short) (bounds.top + (y+1) * con.cell_height), (short) (bounds.left + (x+1) * con.cell_width + 2) };
return r;
}

View File

@ -28,3 +28,5 @@ void printf_i(const char* c, ...);
void set_window_title(WindowPtr w, const char* c_name); void set_window_title(WindowPtr w, const char* c_name);
void ruler(Rect* r); void ruler(Rect* r);
Rect cell_rect(int x, int y, Rect bounds);

View File

@ -16,7 +16,7 @@
#define SSH_CHECK(X) rc = (X); if (rc != LIBSSH2_ERROR_NONE) { printf_i("" #X " failed: %s\n", libssh2_error_string(rc)); return 0;}; #define SSH_CHECK(X) rc = (X); if (rc != LIBSSH2_ERROR_NONE) { printf_i("" #X " failed: %s\n", libssh2_error_string(rc)); return 0;};
// sinful globals // sinful globals
struct ssheven_console con = { NULL, {0}, 0, 0 }; struct ssheven_console con = { NULL, {0}, 0, 0, 0 , 0 };
struct ssheven_ssh_connection ssh_con = { NULL, NULL, kOTInvalidEndpointRef, NULL, NULL }; struct ssheven_ssh_connection ssh_con = { NULL, NULL, kOTInvalidEndpointRef, NULL, NULL };
enum { WAIT, READ, EXIT } read_thread_command = WAIT; enum { WAIT, READ, EXIT } read_thread_command = WAIT;
@ -69,9 +69,6 @@ void ssh_read(void)
{ {
printf_i("channel read error: %s\n", libssh2_error_string(rc)); printf_i("channel read error: %s\n", libssh2_error_string(rc));
} }
// TODO invalidate only the correct region
InvalRect(&(con.win->portRect));
} }
int end_connection(void) int end_connection(void)
@ -244,10 +241,6 @@ void event_loop(void)
while (!WaitNextEvent(everyEvent, &event, sleep_time, NULL)) while (!WaitNextEvent(everyEvent, &event, sleep_time, NULL))
{ {
// timed out without any GUI events // timed out without any GUI events
// process any network events
//check_network_events();
// let any other threads run before we wait for events again // let any other threads run before we wait for events again
YieldToAnyThread(); YieldToAnyThread();
} }
@ -257,7 +250,6 @@ void event_loop(void)
int r = 0; int r = 0;
switch(event.what) switch(event.what)
{ {
// TODO: don't redraw the whole screen, just do needed region
case updateEvt: case updateEvt:
eventWin = (WindowPtr)event.message; eventWin = (WindowPtr)event.message;
BeginUpdate(eventWin); BeginUpdate(eventWin);

View File

@ -36,6 +36,9 @@ struct ssheven_console
int cursor_x; int cursor_x;
int cursor_y; int cursor_y;
int cell_height;
int cell_width;
}; };
extern struct ssheven_console con; extern struct ssheven_console con;