Compare commits

..

1 Commits

Author SHA1 Message Date
b54b64b223 fix(ui): raise pad redraw threshold above buffer cap to fix history scroll
All checks were successful
CI Code / Check spelling (pull_request) Successful in 17s
CI Code / Check coding style (pull_request) Successful in 32s
CI Code / Linux (debian) (pull_request) Successful in 4m42s
CI Code / Linux (ubuntu) (pull_request) Successful in 4m50s
CI Code / Code Coverage (pull_request) Successful in 7m28s
CI Code / Linux (arch) (pull_request) Successful in 11m8s
PAD_THRESHOLD (3000) sat below the buffer line cap (PAD_SIZE - PAD_SIZE/10 = 9000), so _win_ensure_pad_capacity() fired a full win_redraw() from the hot print path on every message once a chat exceeded 3000 rendered lines. During history paging this turned one redraw per fetch into dozens, corrupting per-entry y_start_pos (offset jumps, dropped/skipped messages) and causing ~10s lag per page. The flat-file backend was byte-identical across the regression; the fault was purely in the UI pad path from the upstream merge.

Raise PAD_THRESHOLD to 12000 (above the cap) so the reclaim redraw only fires to drop dead pad space in long append-only sessions, never during scrolling. Also size the pad once to buffer->lines+100 in win_redraw() instead of shrinking to PAD_MIN_HEIGHT and regrowing per entry, removing the residual per-redraw wresize churn.
2026-06-08 12:32:33 +03:00
15 changed files with 25 additions and 77 deletions

View File

@@ -748,17 +748,17 @@ call_external(gchar** argv)
*
* This function constructs an argument vector (argv) based on the provided template string, replacing placeholders ("%u" and "%p") with the provided URL and filename, respectively.
*
* @param template_fmt The template string with placeholders.
* @param url The URL to replace "%u" (or NULL to skip).
* @param filename The filename to replace "%p" (or NULL to skip).
* @return The constructed argument vector (argv) as a null-terminated array of strings.
* @param template The template string with placeholders.
* @param url The URL to replace "%u" (or NULL to skip).
* @param filename The filename to replace "%p" (or NULL to skip).
* @return The constructed argument vector (argv) as a null-terminated array of strings.
*
* @note Remember to free the returned argument vector using `auto_gcharv` or `g_strfreev()`.
*/
gchar**
format_call_external_argv(const char* template_fmt, const char* url, const char* filename)
format_call_external_argv(const char* template, const char* url, const char* filename)
{
gchar** argv = g_strsplit(template_fmt, " ", 0);
gchar** argv = g_strsplit(template, " ", 0);
guint num_args = 0;
while (argv[num_args]) {
@@ -767,7 +767,7 @@ format_call_external_argv(const char* template_fmt, const char* url, const char*
argv[num_args] = g_strdup(url);
} else if (0 == g_strcmp0(argv[num_args], "%p") && filename != NULL) {
g_free(argv[num_args]);
argv[num_args] = g_strdup(filename);
argv[num_args] = strdup(filename);
}
num_args++;
}

View File

@@ -181,7 +181,7 @@ void get_file_paths_recursive(const char* directory, GSList** contents);
gchar* get_random_string(int length);
gboolean call_external(gchar** argv);
gchar** format_call_external_argv(const char* template_fmt, const char* url, const char* filename);
gchar** format_call_external_argv(const char* template, const char* url, const char* filename);
gchar* unique_filename_from_url(const char* url, const char* path);
gchar* get_expanded_path(const char* path);

View File

@@ -10,8 +10,6 @@
#ifndef EVENT_COMMON_H
#define EVENT_COMMON_H
#include "glib.h"
void ev_disconnect_cleanup(void);
void ev_inc_connection_counter(void);
void ev_reset_connection_counter(void);

View File

@@ -10,8 +10,6 @@
#ifndef PGP_GPG_H
#define PGP_GPG_H
#include "glib.h"
typedef struct pgp_key_t
{
gchar* id;

View File

@@ -10,10 +10,8 @@
#ifndef BOOKMARK_IGNORE_H
#define BOOKMARK_IGNORE_H
#include "xmpp/xmpp.h"
void bookmark_ignore_on_connect(const char* const barejid);
void bookmark_ignore_on_disconnect();
void bookmark_ignore_on_disconnect(void);
gboolean bookmark_ignored(Bookmark* bookmark);
gchar** bookmark_ignore_list(gsize* len);
void bookmark_ignore_add(const char* const barejid);

View File

@@ -10,8 +10,6 @@
#ifndef UI_TITLEBAR_H
#define UI_TITLEBAR_H
#include "glib.h"
void create_title_bar(void);
void free_title_bar(void);
void title_bar_update_virtual(void);

View File

@@ -2175,7 +2175,7 @@ win_redraw(ProfWin* window)
// size the pad to fit the whole buffer (plus headroom) and erase it
int cols = getmaxx(window->layout->win);
int needed = window->layout->buffer->lines + 100;
wresize(window->layout->win, MAX(needed, PAD_MIN_HEIGHT), cols);
wresize(window->layout->win, needed > PAD_MIN_HEIGHT ? needed : PAD_MIN_HEIGHT, cols);
werase(window->layout->win);
for (unsigned int i = 0; i < size; i++) {

View File

@@ -10,8 +10,6 @@
#ifndef XMPP_BLOCKING_H
#define XMPP_BLOCKING_H
#include <strophe.h>
void blocking_request(void);
int blocked_set_handler(xmpp_stanza_t* stanza);
int reporting_set_handler(xmpp_stanza_t* stanza);

View File

@@ -10,8 +10,6 @@
#ifndef XMPP_IQ_H
#define XMPP_IQ_H
#include <strophe.h>
typedef int (*ProfIqCallback)(xmpp_stanza_t* const stanza, void* const userdata);
typedef void (*ProfIqFreeCallback)(void* userdata);

View File

@@ -1132,17 +1132,12 @@ _handle_groupchat(xmpp_stanza_t* const stanza)
message->timestamp = NULL;
}
// XEP-0203 §4: trust <delay> only from the room or our server, not a client-forged stamp
message->timestamp = stanza_get_oldest_delay_from(stanza, from_jid->barejid);
if (!message->timestamp && from_jid->domainpart) {
message->timestamp = stanza_get_oldest_delay_from(stanza, from_jid->domainpart);
}
if (!message->timestamp) {
const char* my_domain = connection_get_domain();
if (my_domain) {
message->timestamp = stanza_get_oldest_delay_from(stanza, my_domain);
}
}
// we want to display the oldest delay
message->timestamp = stanza_get_oldest_delay(stanza);
// now this has nothing to do with MUC history
// it's just setting the time to the received time so upon displaying we can use this time
// for example in win_println_incoming_muc_msg()
if (!message->timestamp) {
message->timestamp = g_date_time_new_now_local();
}
@@ -1273,15 +1268,7 @@ _handle_muc_private_message(xmpp_stanza_t* const stanza)
_receive_omemo(stanza, message);
#endif
// XEP-0203 §4: trust <delay> only from a server domain, not a client-forged stamp
const char* my_domain = connection_get_domain();
message->timestamp = stanza_get_delay_from(stanza, my_domain);
if (!message->timestamp && message->from_jid->domainpart) {
message->timestamp = stanza_get_delay_from(stanza, message->from_jid->domainpart);
}
if (!message->timestamp) {
message->timestamp = g_date_time_new_now_local();
}
message->timestamp = stanza_get_delay(stanza);
message->body = xmpp_message_get_body(stanza);
if (!message->plain && !message->body) {
@@ -1432,12 +1419,8 @@ _handle_chat(xmpp_stanza_t* const stanza, gboolean is_mam, gboolean is_carbon, c
// timestamp provided outside like in a <forwarded> by MAM
message->timestamp = timestamp;
} else {
// XEP-0203 §4: trust <delay> only from a server domain, not a client-forged stamp
const char* my_domain = connection_get_domain();
message->timestamp = stanza_get_delay_from(stanza, my_domain);
if (!message->timestamp && jid->domainpart) {
message->timestamp = stanza_get_delay_from(stanza, jid->domainpart);
}
// timestamp in the message stanza or use time of receival (now)
message->timestamp = stanza_get_delay(stanza);
if (!message->timestamp) {
message->timestamp = g_date_time_new_now_local();
}

View File

@@ -7,8 +7,6 @@
* SPDX-License-Identifier: GPL-3.0-or-later WITH OpenSSL-exception
*/
#include "glib.h"
/*!
* \page OX OX Implementation
*

View File

@@ -10,9 +10,6 @@
#ifndef XMPP_ROSTER_H
#define XMPP_ROSTER_H
#include "glib.h"
#include <strophe.h>
void roster_request(void);
void roster_set_handler(xmpp_stanza_t* const stanza);
void roster_result_handler(xmpp_stanza_t* const stanza);

View File

@@ -1163,7 +1163,7 @@ _stanza_get_delay_timestamp_xep0091(xmpp_stanza_t* const x_stanza)
}
GDateTime*
stanza_get_delay_from(xmpp_stanza_t* const stanza, const char* const from)
stanza_get_delay_from(xmpp_stanza_t* const stanza, gchar* from)
{
xmpp_stanza_t* delay = NULL;
@@ -1195,12 +1195,6 @@ stanza_get_delay_from(xmpp_stanza_t* const stanza, const char* const from)
GDateTime*
stanza_get_oldest_delay(xmpp_stanza_t* const stanza)
{
return stanza_get_oldest_delay_from(stanza, NULL);
}
GDateTime*
stanza_get_oldest_delay_from(xmpp_stanza_t* const stanza, const char* const from)
{
xmpp_stanza_t* child;
const char* child_name;
@@ -1211,37 +1205,27 @@ stanza_get_oldest_delay_from(xmpp_stanza_t* const stanza, const char* const from
child_name = xmpp_stanza_get_name(child);
if (child_name && g_strcmp0(child_name, STANZA_NAME_DELAY) == 0) {
if (from) {
const char* child_from = xmpp_stanza_get_attribute(child, STANZA_ATTR_FROM);
if (!child_from || g_strcmp0(child_from, from) != 0)
continue;
}
GDateTime* tmp = _stanza_get_delay_timestamp_xep0203(child);
if (oldest == NULL) {
oldest = tmp;
} else if (tmp && g_date_time_compare(oldest, tmp) == 1) {
} else if (g_date_time_compare(oldest, tmp) == 1) {
g_date_time_unref(oldest);
oldest = tmp;
} else if (tmp) {
} else {
g_date_time_unref(tmp);
}
}
if (child_name && g_strcmp0(child_name, STANZA_NAME_X) == 0) {
if (from) {
const char* child_from = xmpp_stanza_get_attribute(child, STANZA_ATTR_FROM);
if (!child_from || g_strcmp0(child_from, from) != 0)
continue;
}
GDateTime* tmp = _stanza_get_delay_timestamp_xep0091(child);
if (oldest == NULL) {
oldest = tmp;
} else if (tmp && g_date_time_compare(oldest, tmp) == 1) {
} else if (g_date_time_compare(oldest, tmp) == 1) {
g_date_time_unref(oldest);
oldest = tmp;
} else if (tmp) {
} else {
g_date_time_unref(tmp);
}
}

View File

@@ -305,9 +305,8 @@ xmpp_stanza_t* stanza_create_mediated_invite(xmpp_ctx_t* ctx, const char* const
gboolean stanza_contains_chat_state(xmpp_stanza_t* stanza);
GDateTime* stanza_get_delay(xmpp_stanza_t* const stanza);
GDateTime* stanza_get_delay_from(xmpp_stanza_t* const stanza, const char* const from);
GDateTime* stanza_get_delay_from(xmpp_stanza_t* const stanza, gchar* from);
GDateTime* stanza_get_oldest_delay(xmpp_stanza_t* const stanza);
GDateTime* stanza_get_oldest_delay_from(xmpp_stanza_t* const stanza, const char* const from);
gboolean stanza_is_muc_presence(xmpp_stanza_t* const stanza);
gboolean stanza_is_muc_self_presence(xmpp_stanza_t* const stanza,

View File

@@ -12,7 +12,6 @@
#include "ui/win_types.h"
#include "xmpp/vcard.h"
#include <strophe.h>
vCard* vcard_new();
void vcard_free(vCard* vcard);