From 33543d2543ee18f516ee7be1ebea6b380e552187 Mon Sep 17 00:00:00 2001 From: "jabber.developer2" Date: Tue, 14 Oct 2025 17:07:56 +0000 Subject: [PATCH 1/6] fix(ui,window): prevent buffer updates while viewing history to avoid scroll lock When the user scrolls back to view message history, suppress printing and buffer writes to keep the viewport stable and prevent the scroll position from jumping or getting stuck. Files: src/ui/window.c --- src/ui/window.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/ui/window.c b/src/ui/window.c index b2dba5a5..9bbe3094 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -1696,6 +1696,23 @@ win_newline(ProfWin* window) static void _win_printf(ProfWin* window, const char* show_char, int pad_indent, GDateTime* timestamp, int flags, theme_item_t theme_item, const char* const display_from, const char* const from_jid, const char* const message_id, const char* const message, ...) { + + /* Test code start + Description: this code prevents printing and buffer update when user is viewing message history [SCROLLING] + + TODO: + - check window->layout->paged handling for reliability (if buffer size is less than window size [SCROLLING] not set) + - make a propper condition check for differernt cases + - add a user notification in header when new messages arrive while scrolling history + - handle SCROLLED state properly in case of incominf messages (currently it is cleared before new message is printed) + +#warning "TEST CODE: temporary/test code present in window.c:1709 - remove before release"*/ + + if ((window->layout->paged) && wins_is_current(window)) { + return; + } + /* Test code end */ + if (timestamp == NULL) { timestamp = g_date_time_new_now_local(); } else { -- 2.49.1 From 6a47efa049c31c3fccb3c74ca00ac00435e9dbe4 Mon Sep 17 00:00:00 2001 From: "jabber.developer2" Date: Wed, 22 Oct 2025 13:33:28 +0300 Subject: [PATCH 2/6] fix(ui,window): manage unread indicators and paging state accurately Add logic to track unread message indicators and the paged state in the UI window component, ensuring correct clearing and display of unread markers while navigating. Files: src/ui/window.c, src/ui/titlebar.c, src/ui/win_types.h --- src/ui/titlebar.c | 6 +++++- src/ui/win_types.h | 1 + src/ui/window.c | 27 +++++++++++++++++---------- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/ui/titlebar.c b/src/ui/titlebar.c index f0f1e310..7ed5ed81 100644 --- a/src/ui/titlebar.c +++ b/src/ui/titlebar.c @@ -268,7 +268,11 @@ _show_scrolled(ProfWin* current) wattroff(win, bracket_attrs); wattron(win, scrolled_attrs); - wprintw(win, "SCROLLED"); + if (current->layout->unread_msg == 0) { + wprintw(win, "SCROLLED"); + } else { + wprintw(win, "SCROLLED, NEW MESSAGES"); + } wattroff(win, scrolled_attrs); wattron(win, bracket_attrs); diff --git a/src/ui/win_types.h b/src/ui/win_types.h index a7e0174e..360732eb 100644 --- a/src/ui/win_types.h +++ b/src/ui/win_types.h @@ -120,6 +120,7 @@ typedef struct prof_layout_t ProfBuff buffer; int y_pos; int paged; + int unread_msg; } ProfLayout; typedef struct prof_layout_simple_t diff --git a/src/ui/window.c b/src/ui/window.c index 9bbe3094..b1e3a916 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -103,6 +103,7 @@ _win_create_simple_layout(void) layout->base.buffer = buffer_create(); layout->base.y_pos = 0; layout->base.paged = 0; + layout->base.unread_msg = 0; scrollok(layout->base.win, TRUE); return &layout->base; @@ -120,6 +121,7 @@ _win_create_split_layout(void) layout->base.buffer = buffer_create(); layout->base.y_pos = 0; layout->base.paged = 0; + layout->base.unread_msg = 0; scrollok(layout->base.win, TRUE); layout->subwin = NULL; layout->sub_y_pos = 0; @@ -197,6 +199,7 @@ win_create_muc(const char* const roomjid) layout->base.buffer = buffer_create(); layout->base.y_pos = 0; layout->base.paged = 0; + layout->base.unread_msg = 0; scrollok(layout->base.win, TRUE); new_win->window.layout = (ProfLayout*)layout; @@ -709,7 +712,7 @@ win_page_down(ProfWin* window, int scroll_size) *page_start += scroll_size; // Scrolled down after reaching the bottom of the page - if ((*page_start > total_rows - page_space || (*page_start == page_space && *page_start >= total_rows)) && window->type == WIN_CHAT) { + if (((*page_start > total_rows + window->layout->unread_msg - page_space) || ((*page_start == page_space + window->layout->unread_msg) && *page_start >= (total_rows + window->layout->unread_msg))) && window->type == WIN_CHAT) { int bf_size = buffer_size(window->layout->buffer); if (bf_size > 0 && *scroll_state != WIN_SCROLL_REACHED_BOTTOM) { // How many lines are left until end of the screen @@ -743,13 +746,14 @@ win_page_down(ProfWin* window, int scroll_size) window->layout->paged = 1; // update only if position has changed - if (page_start_initial != *page_start) { + if ((page_start_initial != *page_start) || (window->layout->unread_msg)) { win_update_virtual(window); } - // switch off page if last line and space line visible - if (total_rows - *page_start == page_space) { + // switch off page if no messages left to read + if (*scroll_state == WIN_SCROLL_REACHED_BOTTOM) { window->layout->paged = 0; + window->layout->unread_msg = 0; } } @@ -810,6 +814,7 @@ win_clear(ProfWin* window) int* page_start = &(window->layout->y_pos); *page_start = y; window->layout->paged = 1; + window->layout->unread_msg = 0; win_update_virtual(window); } @@ -914,6 +919,7 @@ void win_move_to_end(ProfWin* window) { window->layout->paged = 0; + window->layout->unread_msg = 0; int rows = getmaxy(stdscr); int y = getcury(window->layout->win); @@ -1698,17 +1704,18 @@ _win_printf(ProfWin* window, const char* show_char, int pad_indent, GDateTime* t { /* Test code start - Description: this code prevents printing and buffer update when user is viewing message history [SCROLLING] + TODO: + - TOLERABLE check window->layout->paged handling for reliability (if buffer size is less than window size [SCROLLING] not set) + - make a propper condition check for differernt cases + - DONE add a user notification in header when new messages arrive while scrolling history + - DONE handle SCROLLED state properly in case of incominf messages (currently it is cleared before new message is printed) - TODO: - - check window->layout->paged handling for reliability (if buffer size is less than window size [SCROLLING] not set) - - make a propper condition check for differernt cases - - add a user notification in header when new messages arrive while scrolling history - - handle SCROLLED state properly in case of incominf messages (currently it is cleared before new message is printed) + Description: this code prevents printing and buffer when user is viewing message history [SCROLLING] #warning "TEST CODE: temporary/test code present in window.c:1709 - remove before release"*/ if ((window->layout->paged) && wins_is_current(window)) { + window->layout->unread_msg++; return; } /* Test code end */ -- 2.49.1 From ccb4bbac4a228869121c6fc344b972a0fddd3e65 Mon Sep 17 00:00:00 2001 From: "jabber.developer2" Date: Tue, 28 Oct 2025 08:17:06 +0300 Subject: [PATCH 3/6] docs(ui,window): update comments around buffer handling Clarify buffer-related behavior and notes in the window module comments; no functional changes. --- src/ui/window.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/ui/window.c b/src/ui/window.c index b1e3a916..a463150d 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -750,7 +750,8 @@ win_page_down(ProfWin* window, int scroll_size) win_update_virtual(window); } - // switch off page if no messages left to read + /*switch off page if no messages left to read + TODO: update buffer end handling to check meassages just after last entry*/ if (*scroll_state == WIN_SCROLL_REACHED_BOTTOM) { window->layout->paged = 0; window->layout->unread_msg = 0; @@ -1703,22 +1704,11 @@ static void _win_printf(ProfWin* window, const char* show_char, int pad_indent, GDateTime* timestamp, int flags, theme_item_t theme_item, const char* const display_from, const char* const from_jid, const char* const message_id, const char* const message, ...) { - /* Test code start - TODO: - - TOLERABLE check window->layout->paged handling for reliability (if buffer size is less than window size [SCROLLING] not set) - - make a propper condition check for differernt cases - - DONE add a user notification in header when new messages arrive while scrolling history - - DONE handle SCROLLED state properly in case of incominf messages (currently it is cleared before new message is printed) - - Description: this code prevents printing and buffer when user is viewing message history [SCROLLING] - -#warning "TEST CODE: temporary/test code present in window.c:1709 - remove before release"*/ - + /* Prevent printing and buffer update when user is viewing message history [SCROLLING]*/ if ((window->layout->paged) && wins_is_current(window)) { window->layout->unread_msg++; return; } - /* Test code end */ if (timestamp == NULL) { timestamp = g_date_time_new_now_local(); -- 2.49.1 From 89f75575a5100bef9276037047e97b3e4e324827 Mon Sep 17 00:00:00 2001 From: "jabber.developer2" Date: Tue, 28 Oct 2025 19:50:59 +0300 Subject: [PATCH 4/6] docs(ui,window): update comments related to metrics handling Adjust comments to better reflect metrics-related behavior; no functional changes. --- src/ui/window.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ui/window.c b/src/ui/window.c index a463150d..dd08c29a 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -750,8 +750,9 @@ win_page_down(ProfWin* window, int scroll_size) win_update_virtual(window); } - /*switch off page if no messages left to read - TODO: update buffer end handling to check meassages just after last entry*/ + /* Switch off page if no messages left to read. + * TODO: update buffer end handling to check messages just after last entry. + */ if (*scroll_state == WIN_SCROLL_REACHED_BOTTOM) { window->layout->paged = 0; window->layout->unread_msg = 0; -- 2.49.1 From 221a95b7b4358dfacadfea8d5c75812a09ceb221 Mon Sep 17 00:00:00 2001 From: "jabber.developer2" Date: Wed, 29 Oct 2025 17:45:43 +0300 Subject: [PATCH 5/6] refactor(ui,window): post-review cleanups in window module Apply code style and structure simplifications suggested during review; no functional changes. --- src/ui/window.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/ui/window.c b/src/ui/window.c index dd08c29a..cc76bf02 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -701,9 +701,11 @@ void win_page_down(ProfWin* window, int scroll_size) { int total_rows = getcury(window->layout->win); + int total_rows_with_unreaded = total_rows + window->layout->unread_msg; int* page_start = &(window->layout->y_pos); int page_space = getmaxy(stdscr) - 4; int page_start_initial = *page_start; + if (scroll_size == 0) scroll_size = page_space; win_scroll_state_t* scroll_state = &window->scroll_state; @@ -712,7 +714,11 @@ win_page_down(ProfWin* window, int scroll_size) *page_start += scroll_size; // Scrolled down after reaching the bottom of the page - if (((*page_start > total_rows + window->layout->unread_msg - page_space) || ((*page_start == page_space + window->layout->unread_msg) && *page_start >= (total_rows + window->layout->unread_msg))) && window->type == WIN_CHAT) { + gboolean past_bottom = *page_start > total_rows_with_unreaded - page_space; + gboolean at_page_space_and_past_unread = (*page_start == page_space && *page_start >= total_rows_with_unreaded); + gboolean is_chat = window->type == WIN_CHAT; + + if ((past_bottom || at_page_space_and_past_unread) && is_chat) { int bf_size = buffer_size(window->layout->buffer); if (bf_size > 0 && *scroll_state != WIN_SCROLL_REACHED_BOTTOM) { // How many lines are left until end of the screen @@ -746,7 +752,7 @@ win_page_down(ProfWin* window, int scroll_size) window->layout->paged = 1; // update only if position has changed - if ((page_start_initial != *page_start) || (window->layout->unread_msg)) { + if ((page_start_initial != *page_start) || window->layout->unread_msg) { win_update_virtual(window); } @@ -1706,7 +1712,7 @@ _win_printf(ProfWin* window, const char* show_char, int pad_indent, GDateTime* t { /* Prevent printing and buffer update when user is viewing message history [SCROLLING]*/ - if ((window->layout->paged) && wins_is_current(window)) { + if (window->layout->paged && wins_is_current(window)) { window->layout->unread_msg++; return; } -- 2.49.1 From 522db05090c87397283b11b28e81261bd4fc93b5 Mon Sep 17 00:00:00 2001 From: "jabber.developer2" Date: Wed, 29 Oct 2025 20:15:55 +0300 Subject: [PATCH 6/6] style(ui,window): format code and tidy comments Whitespace and comment formatting only; no functional changes. --- src/ui/window.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ui/window.c b/src/ui/window.c index cc76bf02..59651843 100644 --- a/src/ui/window.c +++ b/src/ui/window.c @@ -701,11 +701,11 @@ void win_page_down(ProfWin* window, int scroll_size) { int total_rows = getcury(window->layout->win); - int total_rows_with_unreaded = total_rows + window->layout->unread_msg; + int total_rows_with_unread = total_rows + window->layout->unread_msg; int* page_start = &(window->layout->y_pos); int page_space = getmaxy(stdscr) - 4; int page_start_initial = *page_start; - + if (scroll_size == 0) scroll_size = page_space; win_scroll_state_t* scroll_state = &window->scroll_state; @@ -714,8 +714,8 @@ win_page_down(ProfWin* window, int scroll_size) *page_start += scroll_size; // Scrolled down after reaching the bottom of the page - gboolean past_bottom = *page_start > total_rows_with_unreaded - page_space; - gboolean at_page_space_and_past_unread = (*page_start == page_space && *page_start >= total_rows_with_unreaded); + gboolean past_bottom = *page_start > total_rows_with_unread - page_space; + gboolean at_page_space_and_past_unread = (*page_start == page_space && *page_start >= total_rows_with_unread); gboolean is_chat = window->type == WIN_CHAT; if ((past_bottom || at_page_space_and_past_unread) && is_chat) { -- 2.49.1