@@ -1240,7 +1240,7 @@ gtk_xtext_adjustment_changed (GtkAdjustment * adj, GtkXText * xtext)
12401240 }
12411241
12421242 /* Re-read value after ensure_range + anchor restore, which may
1243- * have shifted it. Needed for old_value update at bottom . */
1243+ * have shifted it. Needed for the change-gate update below . */
12441244 value = gtk_adjustment_get_value (xtext -> adj );
12451245
12461246 /* Re-check scroll-to-top after ensure_range. When mat_first_index
@@ -1264,29 +1264,17 @@ gtk_xtext_adjustment_changed (GtkAdjustment * adj, GtkXText * xtext)
12641264 }
12651265 }
12661266
1267- if (value + 1 == xtext -> buffer -> old_value ||
1268- value - 1 == xtext -> buffer -> old_value ) /* clicked an arrow? */
1267+ /* Queue a redraw. The old code distinguished arrow clicks (±1 line,
1268+ * immediate redraw) from jumps (thumb drag, debounced 20ms). With
1269+ * GTK4 queue_draw is already deferred to the next frame, so the
1270+ * distinction is unnecessary. Cancel any pending debounce timer
1271+ * and redraw immediately. */
1272+ if (xtext -> io_tag )
12691273 {
1270- if (xtext -> io_tag )
1271- {
1272- g_source_remove (xtext -> io_tag );
1273- xtext -> io_tag = 0 ;
1274- }
1275- /* GTK3: Queue a redraw instead of rendering directly */
1276- gtk_widget_queue_draw (GTK_WIDGET (xtext ));
1277- } else
1278- {
1279- /* Invalidate pagetop cache — the scroll position jumped (thumb drag,
1280- * page click, etc.) so the cached entry no longer matches. Without
1281- * this, motion_notify → find_char → nth() uses the stale cache and
1282- * returns the wrong entry, causing flicker. */
1283-
1284- if (!xtext -> io_tag )
1285- xtext -> io_tag = g_timeout_add (REFRESH_TIMEOUT ,
1286- (GSourceFunc )
1287- gtk_xtext_adjustment_timeout ,
1288- xtext );
1274+ g_source_remove (xtext -> io_tag );
1275+ xtext -> io_tag = 0 ;
12891276 }
1277+ gtk_widget_queue_draw (GTK_WIDGET (xtext ));
12901278 }
12911279 xtext -> buffer -> old_value = value ;
12921280}
@@ -7579,7 +7567,6 @@ gtk_xtext_remove_top (xtext_buffer *buffer)
75797567 else
75807568 buffer -> text_last = NULL ;
75817569
7582- buffer -> old_value -= ent_lines ;
75837570 if (buffer -> xtext -> buffer == buffer ) /* is it the current buffer? */
75847571 {
75857572 g_signal_handler_block (buffer -> xtext -> adj , buffer -> xtext -> vc_signal_tag );
@@ -8376,7 +8363,6 @@ gtk_xtext_render_page_timeout (GtkXText * xtext)
83768363 /* less than a complete page? */
83778364 if (xtext -> buffer -> num_lines <= gtk_adjustment_get_page_size (adj ))
83788365 {
8379- xtext -> buffer -> old_value = 0 ;
83808366 gtk_adjustment_set_value (adj , 0 );
83818367 /* GTK3: Queue a redraw instead of rendering directly */
83828368 gtk_widget_queue_draw (GTK_WIDGET (xtext ));
@@ -8386,7 +8372,6 @@ gtk_xtext_render_page_timeout (GtkXText * xtext)
83868372 gtk_xtext_adjustment_set (xtext -> buffer , FALSE);
83878373 gtk_adjustment_set_value (adj , gtk_adjustment_get_upper (adj ) - gtk_adjustment_get_page_size (adj ));
83888374 g_signal_handler_unblock (xtext -> adj , xtext -> vc_signal_tag );
8389- xtext -> buffer -> old_value = gtk_adjustment_get_value (adj );
83908375 xtext -> buffer -> scroll_anchor .anchor_to_bottom = TRUE;
83918376 /* GTK3: Queue a redraw instead of rendering directly */
83928377 gtk_widget_queue_draw (GTK_WIDGET (xtext ));
@@ -8686,12 +8671,6 @@ gtk_xtext_append_entry (xtext_buffer *buf, textentry * ent, time_t stamp)
86868671 buf -> xtext );
86878672 }
86888673 }
8689- if (buf -> scroll_anchor .anchor_to_bottom )
8690- {
8691- buf -> old_value = buf -> num_lines - gtk_adjustment_get_page_size (buf -> xtext -> adj );
8692- if (buf -> old_value < 0 )
8693- buf -> old_value = 0 ;
8694- }
86958674 if (buf -> search_flags & follow )
86968675 {
86978676 GList * gl ;
@@ -8727,7 +8706,6 @@ gtk_xtext_prepend_entry (xtext_buffer *buf, textentry *ent, time_t stamp)
87278706 }
87288707
87298708 /* Adjust scroll position - we added lines at the top, so everything shifts down */
8730- buf -> old_value += new_lines ;
87318709 if (buf -> xtext && buf -> xtext -> buffer == buf )
87328710 {
87338711 buf -> xtext -> select_start_adj += new_lines ;
@@ -8878,7 +8856,6 @@ gtk_xtext_insert_sorted_entry (xtext_buffer *buf, textentry *ent, time_t stamp)
88788856 /* Adjust scroll position if we inserted before current view */
88798857 if (inserted_before_pagetop )
88808858 {
8881- buf -> old_value += new_lines ;
88828859 if (buf -> xtext && buf -> xtext -> buffer == buf && !buf -> batch_mode )
88838860 {
88848861 buf -> xtext -> select_start_adj += new_lines ;
@@ -8892,13 +8869,8 @@ gtk_xtext_insert_sorted_entry (xtext_buffer *buf, textentry *ent, time_t stamp)
88928869 /* Don't update marker_pos for historical entries */
88938870
88948871 /* Keep scroll anchored to bottom if appropriate */
8895- if (buf -> scroll_anchor .anchor_to_bottom )
8896- {
8897- buf -> old_value = buf -> num_lines - gtk_adjustment_get_page_size (buf -> xtext -> adj );
8898- if (buf -> old_value < 0 )
8899- buf -> old_value = 0 ;
8900- }
8901- else if (!inserted_before_pagetop && buf -> xtext && buf -> xtext -> buffer == buf
8872+ if (!buf -> scroll_anchor .anchor_to_bottom
8873+ && !inserted_before_pagetop && buf -> xtext && buf -> xtext -> buffer == buf
89028874 && !buf -> batch_mode )
89038875 {
89048876 /* Entry inserted after viewport (e.g., chathistory catch-up while
@@ -9846,11 +9818,8 @@ gtk_xtext_buffer_show (GtkXText *xtext, xtext_buffer *buf, int render)
98469818
98479819/*printf("text_buffer_show: xtext=%p buffer=%p\n", xtext, buf);*/
98489820
9849- /* Save the current buffer's scroll position before switching */
9850- if (xtext -> buffer != NULL )
9851- {
9852- xtext -> buffer -> old_value = gtk_adjustment_get_value (xtext -> adj );
9853- }
9821+ /* Scroll position is preserved in buf->scroll_anchor, updated by
9822+ * adjustment_changed on every value change. No explicit save needed. */
98549823
98559824 if (xtext -> add_io_tag )
98569825 {
@@ -9903,9 +9872,12 @@ gtk_xtext_buffer_show (GtkXText *xtext, xtext_buffer *buf, int render)
99039872 buf -> scroll_anchor .anchor_to_bottom = TRUE;
99049873 gtk_adjustment_set_value (xtext -> adj , gtk_adjustment_get_upper (xtext -> adj ) - gtk_adjustment_get_page_size (xtext -> adj ));
99059874 }
9906- else if ( buf -> old_value >= 0 )
9875+ else
99079876 {
9908- gtk_adjustment_set_value (xtext -> adj , buf -> old_value );
9877+ /* Restore scroll position from the persistent anchor.
9878+ * The anchor was captured in adjustment_changed when the
9879+ * user last interacted with this buffer. */
9880+ gtk_xtext_restore_scroll_anchor (buf , & buf -> scroll_anchor );
99099881 }
99109882 }
99119883
@@ -10098,11 +10070,11 @@ gtk_xtext_buffer_set_virtual (xtext_buffer *buf, void *db, const char *channel,
1009810070 {
1009910071 gdouble upper = gtk_adjustment_get_upper (buf -> xtext -> adj );
1010010072 gdouble page = gtk_adjustment_get_page_size (buf -> xtext -> adj );
10073+ gdouble bottom = upper - page ;
10074+ if (bottom < 0 )
10075+ bottom = 0 ;
1010110076 buf -> scroll_anchor .anchor_to_bottom = TRUE;
10102- buf -> old_value = (gfloat )(upper - page );
10103- if (buf -> old_value < 0 )
10104- buf -> old_value = 0 ;
10105- gtk_adjustment_set_value (buf -> xtext -> adj , buf -> old_value );
10077+ gtk_adjustment_set_value (buf -> xtext -> adj , bottom );
1010610078 }
1010710079 else if (was_down )
1010810080 {
@@ -10640,7 +10612,6 @@ gtk_xtext_virt_should_materialize (xtext_buffer *buf, time_t stamp,
1064010612 g_signal_handler_block (adj , buf -> xtext -> vc_signal_tag );
1064110613 gtk_adjustment_configure (adj , new_val , 0 , new_upper , 1 , page , page );
1064210614 g_signal_handler_unblock (adj , buf -> xtext -> vc_signal_tag );
10643- buf -> old_value = (gfloat ) new_val ;
1064410615 }
1064510616
1064610617 return FALSE;
0 commit comments