1
0
mirror of https://github.com/Tha14/toxic.git synced 2024-11-22 09:43:03 +01:00

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 17:54:35 -05:00
parent 13337041ce
commit f3f81111c8
No known key found for this signature in database
GPG Key ID: 3627F3144076AE63
10 changed files with 134 additions and 21 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";
@ -1443,7 +1442,11 @@ static void chat_onDraw(ToxWindow *self, Tox *m)
}
pthread_mutex_lock(&Winthread.lock);
refresh_file_transfer_progress(self, self->num);
if (refresh_file_transfer_progress(self, self->num)) {
flag_interface_refresh();
}
pthread_mutex_unlock(&Winthread.lock);
}

View File

@ -117,13 +117,27 @@ static void refresh_progress_helper(ToxWindow *self, struct FileTransfer *ft)
ft->last_line_progress = get_unix_time();
}
/* refreshes active file transfer status bars. */
void refresh_file_transfer_progress(ToxWindow *self, uint32_t friendnumber)
/* refreshes active file transfer status bars.
*
* Return true if there is at least one active file transfer in either direction.
*/
bool refresh_file_transfer_progress(ToxWindow *self, uint32_t friendnumber)
{
bool active = false;
for (size_t i = 0; i < MAX_FILES; ++i) {
refresh_progress_helper(self, &Friends.list[friendnumber].file_receiver[i]);
refresh_progress_helper(self, &Friends.list[friendnumber].file_sender[i]);
struct FileTransfer *ft_r = &Friends.list[friendnumber].file_receiver[i];
struct FileTransfer *ft_s = &Friends.list[friendnumber].file_sender[i];
refresh_progress_helper(self, ft_r);
refresh_progress_helper(self, ft_s);
if (ft_r->state != FILE_TRANSFER_INACTIVE || ft_s->state != FILE_TRANSFER_INACTIVE) {
active = true;
}
}
return active;
}
static void clear_file_transfer(struct FileTransfer *ft)

View File

@ -72,8 +72,11 @@ void init_progress_bar(char *progline);
/* prints a progress bar for file transfers */
void print_progress_bar(ToxWindow *self, double pct_done, double bps, uint32_t line_id);
/* refreshes active file transfer status bars. */
void refresh_file_transfer_progress(ToxWindow *self, uint32_t friendnumber);
/* refreshes active file transfer status bars.
*
* Return true if there is at least one active file transfer in either direction.
*/
bool refresh_file_transfer_progress(ToxWindow *self, uint32_t friendnumber);
/* Returns a pointer to friendnumber's FileTransfer struct associated with filenumber.
* Returns NULL if filenumber is invalid.

View File

@ -346,5 +346,9 @@ bool input_handle(ToxWindow *self, wint_t key, int x, int mx_x)
}
}
if (match) {
flag_interface_refresh();
}
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_refresh();
return new_line->id;
}
@ -469,6 +471,8 @@ static void line_info_check_queue(ToxWindow *self)
if (!self->scroll_pause) {
line_info_reset_start(self, hst);
}
flag_interface_refresh();
}
#define NOREAD_FLAG_TIMEOUT 5 /* seconds before a sent message with no read receipt is flagged as unread */
@ -750,6 +754,8 @@ static bool line_info_screen_fit(ToxWindow *self, struct line_info *line)
/* puts msg in specified line_info msg buffer */
void line_info_set(ToxWindow *self, uint32_t id, char *msg)
{
flag_interface_refresh();
struct line_info *line = self->chatwin->hst->line_end;
while (line) {
@ -855,6 +861,10 @@ bool line_info_onKey(ToxWindow *self, wint_t key)
match = false;
}
if (match) {
flag_interface_refresh();
}
return match;
}

View File

@ -125,6 +125,8 @@ void on_self_connection_status(Tox *m, Tox_Connection connection_status, void *u
UNUSED_VAR(userdata);
StatusBar *statusbar = prompt->stb;
statusbar->connection = connection_status;
flag_interface_refresh();
}
/* Updates own nick in prompt statusbar */

View File

@ -1072,6 +1072,37 @@ static void do_toxic(Tox *m)
pthread_mutex_unlock(&Winthread.lock);
}
/* Set interface refresh flag. This should be called whenever the interface changes.
*
* This function is not thread safe.
*/
void flag_interface_refresh(void)
{
Winthread.flag_refresh = 1;
Winthread.last_refresh_flag = get_unix_time();
}
/* How long we wait to idle interface refreshing after last flag set. Should be no less than 2. */
#define ACTIVE_WIN_REFRESH_TIMEOUT 2
static void poll_interface_refresh_flag(void)
{
pthread_mutex_lock(&Winthread.lock);
bool flag = Winthread.flag_refresh;
time_t t = Winthread.last_refresh_flag;
pthread_mutex_unlock(&Winthread.lock);
if (flag == 1 && timed_out(t, ACTIVE_WIN_REFRESH_TIMEOUT)) {
pthread_mutex_lock(&Winthread.lock);
Winthread.flag_refresh = 0;
pthread_mutex_unlock(&Winthread.lock);
}
}
/* How often we refresh windows that aren't focused */
#define INACTIVE_WIN_REFRESH_RATE 10
void *thread_winref(void *data)
@ -1079,11 +1110,12 @@ void *thread_winref(void *data)
Tox *m = (Tox *) data;
uint8_t draw_count = 0;
init_signal_catchers();
while (true) {
draw_active_window(m);
draw_count++;
draw_active_window(m);
if (Winthread.flag_resize) {
on_window_resize();
@ -1097,6 +1129,8 @@ void *thread_winref(void *data)
pthread_mutex_lock(&Winthread.lock);
exit_toxic_success(m);
}
poll_interface_refresh_flag();
}
}

View File

@ -102,6 +102,8 @@ typedef enum _FATAL_ERRS {
void lock_status(void);
void unlock_status(void);
void flag_interface_refresh(void);
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_refresh();
}
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_refresh();
}
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_refresh();
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_refresh();
}
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_refresh();
}
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_refresh();
}
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_refresh();
}
/* Deletes window w and cleans up */
@ -784,21 +800,40 @@ 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) {
touchwin(a->window);
a->onDraw(a, m);
wrefresh(a->window);
}
#ifdef AUDIO
else if (a->is_call && timed_out(a->chatwin->infobox.lastupdate, 1)) {
touchwin(a->window);
a->onDraw(a, m);
wrefresh(a->window);
}
#endif
#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_refresh();
pthread_mutex_unlock(&Winthread.lock);
if (ch == user_settings->key_next_tab || ch == user_settings->key_prev_tab) {
set_next_window(ch);
}
@ -817,6 +852,10 @@ void draw_active_window(Tox *m)
return;
}
pthread_mutex_lock(&Winthread.lock);
flag_interface_refresh();
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 last_refresh_flag;
};
struct cqueue_thread {