Fix WriteText() not scrolling to bottom with GTK >= 3.14, part 2
Detecting that the scrollbar position was at the bottom did not work while a scrollbar animation was in progress. Work around this by updating the position whenever the scrollbar parameters are changed during the incremental layout. Setting the position directly will prevent any scrollbar animation from starting. See #18864
This commit is contained in:
@@ -1105,8 +1105,34 @@ bool wxTextCtrl::IsEmpty() const
|
||||
return wxTextEntry::IsEmpty();
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
static void adjustmentChanged(GtkAdjustment* adj, GtkTextMark** mark)
|
||||
{
|
||||
if (*mark)
|
||||
{
|
||||
const double value = gtk_adjustment_get_value(adj);
|
||||
const double upper = gtk_adjustment_get_upper(adj);
|
||||
const double page_size = gtk_adjustment_get_page_size(adj);
|
||||
if (value < upper - page_size)
|
||||
{
|
||||
GtkTextIter iter;
|
||||
GtkTextBuffer* buffer = gtk_text_mark_get_buffer(*mark);
|
||||
gtk_text_buffer_get_iter_at_mark(buffer, &iter, *mark);
|
||||
if (gtk_text_iter_is_end(&iter))
|
||||
{
|
||||
// Keep position at bottom as scrollbar is updated during layout
|
||||
gtk_adjustment_set_value(adj, upper - page_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void wxTextCtrl::GTKAfterLayout()
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func(
|
||||
gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(m_widget)),
|
||||
(void*)adjustmentChanged, &m_showPositionDefer);
|
||||
m_afterLayoutId = 0;
|
||||
if (m_showPositionDefer && !IsFrozen())
|
||||
{
|
||||
@@ -1118,8 +1144,12 @@ void wxTextCtrl::GTKAfterLayout()
|
||||
extern "C" {
|
||||
static gboolean afterLayout(void* data)
|
||||
{
|
||||
gdk_threads_enter();
|
||||
|
||||
wxTextCtrl* win = static_cast<wxTextCtrl*>(data);
|
||||
win->GTKAfterLayout();
|
||||
|
||||
gdk_threads_leave();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1193,10 +1223,11 @@ void wxTextCtrl::WriteText( const wxString &text )
|
||||
|
||||
gtk_text_buffer_insert( m_buffer, &iter, buffer, buffer.length() );
|
||||
|
||||
GtkAdjustment* adj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(m_widget));
|
||||
|
||||
// Scroll to cursor, if it is at the end and scrollbar thumb is at the bottom
|
||||
if (insertIsEnd)
|
||||
{
|
||||
GtkAdjustment* adj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(m_widget));
|
||||
const double value = gtk_adjustment_get_value(adj);
|
||||
const double upper = gtk_adjustment_get_upper(adj);
|
||||
const double page_size = gtk_adjustment_get_page_size(adj);
|
||||
@@ -1212,6 +1243,7 @@ void wxTextCtrl::WriteText( const wxString &text )
|
||||
}
|
||||
if (m_afterLayoutId == 0)
|
||||
{
|
||||
g_signal_connect(adj, "changed", G_CALLBACK(adjustmentChanged), &m_showPositionDefer);
|
||||
m_afterLayoutId =
|
||||
g_idle_add_full(GTK_TEXT_VIEW_PRIORITY_VALIDATE + 1, afterLayout, this, NULL);
|
||||
}
|
||||
@@ -1397,7 +1429,11 @@ void wxTextCtrl::SetInsertionPoint( long pos )
|
||||
// defer until Thaw, text view is not using m_buffer now
|
||||
m_showPositionDefer = mark;
|
||||
else
|
||||
{
|
||||
gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(m_text), mark);
|
||||
if (m_afterLayoutId)
|
||||
m_showPositionDefer = mark;
|
||||
}
|
||||
}
|
||||
else // single line
|
||||
{
|
||||
@@ -1514,7 +1550,11 @@ void wxTextCtrl::ShowPosition( long pos )
|
||||
// defer until Thaw, text view is not using m_buffer now
|
||||
m_showPositionDefer = mark;
|
||||
else
|
||||
{
|
||||
gtk_text_view_scroll_mark_onscreen(GTK_TEXT_VIEW(m_text), mark);
|
||||
if (m_afterLayoutId)
|
||||
m_showPositionDefer = mark;
|
||||
}
|
||||
}
|
||||
else // single line
|
||||
{ // This function not only shows character at required position
|
||||
|
Reference in New Issue
Block a user