Greatly reduce redundant window refreshing

This should substantially reduce CPU usage and possibly fix some
issues with interface jittering/flashing
This commit is contained in:
jfreegman 2021-11-19 15:03:08 -05:00
parent 13337041ce
commit 8fa3f6fd8c
No known key found for this signature in database
GPG Key ID: 3627F3144076AE63
7 changed files with 92 additions and 14 deletions

View File

@ -1072,13 +1072,12 @@ static void draw_infobox(ToxWindow *self)
time_t curtime = get_unix_time();
/* update elapsed time string once per second */
if (curtime > infobox->lastupdate) {
/* update interface once per second */
if (timed_out(infobox->lastupdate, 1)) {
get_elapsed_time_str(infobox->timestr, sizeof(infobox->timestr), curtime - infobox->starttime);
infobox->lastupdate = curtime;
}
infobox->lastupdate = curtime;
const char *in_is_muted = infobox->in_is_muted ? "yes" : "no";
const char *out_is_muted = infobox->out_is_muted ? "yes" : "no";

View File

@ -346,5 +346,9 @@ bool input_handle(ToxWindow *self, wint_t key, int x, int mx_x)
}
}
if (match) {
flag_interface_change(1);
}
return match;
}

View File

@ -444,6 +444,8 @@ int line_info_add(ToxWindow *self, bool show_timestamp, const char *name1, const
hst->queue[hst->queue_size++] = new_line;
flag_interface_change(1);
return new_line->id;
}
@ -454,6 +456,7 @@ static void line_info_check_queue(ToxWindow *self)
struct line_info *line = line_info_ret_queue(hst);
if (line == NULL) {
flag_interface_change(0);
return;
}
@ -469,6 +472,8 @@ static void line_info_check_queue(ToxWindow *self)
if (!self->scroll_pause) {
line_info_reset_start(self, hst);
}
flag_interface_change(1);
}
#define NOREAD_FLAG_TIMEOUT 5 /* seconds before a sent message with no read receipt is flagged as unread */
@ -763,6 +768,8 @@ void line_info_set(ToxWindow *self, uint32_t id, char *msg)
line = line->prev;
}
flag_interface_change(1);
}
static void line_info_scroll_up(ToxWindow *self, struct history *hst)
@ -771,6 +778,8 @@ static void line_info_scroll_up(ToxWindow *self, struct history *hst)
hst->line_start = hst->line_start->prev;
self->scroll_pause = true;
}
flag_interface_change(1);
}
static void line_info_scroll_down(ToxWindow *self, struct history *hst)
@ -786,6 +795,8 @@ static void line_info_scroll_down(ToxWindow *self, struct history *hst)
} else {
line_info_reset_start(self, hst);
}
flag_interface_change(1);
}
static void line_info_page_up(ToxWindow *self, struct history *hst)
@ -805,6 +816,8 @@ static void line_info_page_up(ToxWindow *self, struct history *hst)
}
self->scroll_pause = true;
flag_interface_change(1);
}
static void line_info_page_down(ToxWindow *self, struct history *hst)
@ -834,6 +847,8 @@ static void line_info_page_down(ToxWindow *self, struct history *hst)
hst->line_start = next;
next = hst->line_start->next;
}
flag_interface_change(1);
}
bool line_info_onKey(ToxWindow *self, wint_t key)
@ -855,6 +870,10 @@ bool line_info_onKey(ToxWindow *self, wint_t key)
match = false;
}
if (match) {
flag_interface_change(1);
}
return match;
}
@ -862,4 +881,6 @@ void line_info_clear(struct history *hst)
{
hst->line_start = hst->line_end;
hst->start_id = hst->line_start->id;
flag_interface_change(1);
}

View File

@ -1072,8 +1072,24 @@ static void do_toxic(Tox *m)
pthread_mutex_unlock(&Winthread.lock);
}
/* How often we refresh windows that aren't focused */
#define INACTIVE_WIN_REFRESH_RATE 10
/* Set interface change flag. This should be called whenever the interface changes.
*
* `flag` should be a non-zero value if we need to redraw the window or 0 if we want to idle.
*/
void flag_interface_change(unsigned int flag)
{
if (flag == 0 && timed_out(Winthread.flag_refresh_timeout, 1)) {
Winthread.flag_refresh = flag;
} else if (flag != 0) {
Winthread.flag_refresh = 1;
}
Winthread.flag_refresh_timeout = get_unix_time();
}
void *thread_winref(void *data)
{
Tox *m = (Tox *) data;
@ -1082,8 +1098,8 @@ void *thread_winref(void *data)
init_signal_catchers();
while (true) {
draw_active_window(m);
draw_count++;
draw_active_window(m);
if (Winthread.flag_resize) {
on_window_resize();
@ -1470,6 +1486,8 @@ int main(int argc, char **argv)
/* Make sure all written files are read/writeable only by the current user. */
umask(S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
flag_interface_change(1);
srand(time(NULL)); // We use rand() for trivial/non-security related things
parse_args(argc, argv);

View File

@ -102,6 +102,8 @@ typedef enum _FATAL_ERRS {
void lock_status(void);
void unlock_status(void);
void flag_interface_change(unsigned int flag);
void exit_toxic_success(Tox *m);
void exit_toxic_err(const char *errmsg, int errcode);

View File

@ -77,6 +77,8 @@ void on_friend_connection_status(Tox *m, uint32_t friendnumber, Tox_Connection c
windows[i]->onConnectionChange(windows[i], m, friendnumber, connection_status);
}
}
flag_interface_change(1);
}
void on_friend_typing(Tox *m, uint32_t friendnumber, bool is_typing, void *userdata)
@ -92,6 +94,8 @@ void on_friend_typing(Tox *m, uint32_t friendnumber, bool is_typing, void *userd
windows[i]->onTypingChange(windows[i], m, friendnumber, is_typing);
}
}
flag_interface_change(1);
}
void on_friend_message(Tox *m, uint32_t friendnumber, Tox_Message_Type type, const uint8_t *string, size_t length,
@ -123,6 +127,8 @@ void on_friend_name(Tox *m, uint32_t friendnumber, const uint8_t *string, size_t
}
}
flag_interface_change(1);
store_data(m, DATA_FILE);
}
@ -140,6 +146,8 @@ void on_friend_status_message(Tox *m, uint32_t friendnumber, const uint8_t *stri
windows[i]->onStatusMessageChange(windows[i], friendnumber, msg, length);
}
}
flag_interface_change(1);
}
void on_friend_status(Tox *m, uint32_t friendnumber, Tox_User_Status status, void *userdata)
@ -151,6 +159,8 @@ void on_friend_status(Tox *m, uint32_t friendnumber, Tox_User_Status status, voi
windows[i]->onStatusChange(windows[i], m, friendnumber, status);
}
}
flag_interface_change(1);
}
void on_friend_added(Tox *m, uint32_t friendnumber, bool sort)
@ -200,6 +210,8 @@ void on_conference_peer_list_changed(Tox *m, uint32_t conferencenumber, void *us
windows[i]->onConferenceNameListChange(windows[i], m, conferencenumber);
}
}
flag_interface_change(1);
}
void on_conference_peer_name(Tox *m, uint32_t conferencenumber, uint32_t peernumber, const uint8_t *name,
@ -423,11 +435,13 @@ void set_active_window_index(uint8_t index)
*/
void set_next_window(int ch)
{
uint8_t index = 0;
if (ch == user_settings->key_next_tab) {
for (uint8_t i = active_window_index + 1; i < MAX_WINDOWS_NUM; ++i) {
if (windows[i] != NULL) {
set_active_window_index(i);
return;
index = i;
break;
}
}
} else {
@ -435,13 +449,15 @@ void set_next_window(int ch)
for (uint8_t i = start; i > 0; --i) {
if (windows[i] != NULL) {
set_active_window_index(i);
return;
index = i;
break;
}
}
}
set_active_window_index(0);
set_active_window_index(index);
flag_interface_change(1);
}
/* Deletes window w and cleans up */
@ -784,21 +800,33 @@ void draw_active_window(Tox *m)
pthread_mutex_lock(&Winthread.lock);
a->alert = WINDOW_ALERT_NONE;
a->pending_messages = 0;
bool flag_refresh = Winthread.flag_refresh;
pthread_mutex_unlock(&Winthread.lock);
touchwin(a->window);
a->onDraw(a, m);
wrefresh(a->window);
if (flag_refresh || (a->is_call && timed_out(a->chatwin->infobox.lastupdate, 1))) {
touchwin(a->window);
a->onDraw(a, m);
wrefresh(a->window);
}
#ifdef GAMES
if (a->type == WINDOW_TYPE_GAME) {
if (!flag_refresh) { // we always want to be continously refreshing game windows
touchwin(a->window);
a->onDraw(a, m);
wrefresh(a->window);
}
int ch = getch();
if (ch == ERR) {
return;
}
pthread_mutex_lock(&Winthread.lock);
flag_interface_change(1);
pthread_mutex_unlock(&Winthread.lock);
if (ch == user_settings->key_next_tab || ch == user_settings->key_prev_tab) {
set_next_window(ch);
}
@ -817,6 +845,10 @@ void draw_active_window(Tox *m)
return;
}
pthread_mutex_lock(&Winthread.lock);
flag_interface_change(1);
pthread_mutex_unlock(&Winthread.lock);
if (printable == 0 && (ch == user_settings->key_next_tab || ch == user_settings->key_prev_tab)) {
set_next_window((int) ch);
return;

View File

@ -103,6 +103,8 @@ struct Winthread {
pthread_mutex_t lock;
volatile sig_atomic_t sig_exit_toxic;
volatile sig_atomic_t flag_resize;
volatile sig_atomic_t flag_refresh;
volatile sig_atomic_t flag_refresh_timeout;
};
struct cqueue_thread {