-1

I am working on a project which has to be in GTK-2.0 and the problem I am facing is that If the window gets Minimized after being Maximized the scrollbar does not goes back the bottom anymore.

enter image description here

enter image description here

Here is a part of the code which could be seen and tested:

#include <gtk/gtk.h>

typedef struct
{
    GtkWidget *entry;
    GtkWidget *textview;
} Widgets;

void chatMSG ( GtkButton *, Widgets * );

int main ( void )
{
    GtkWidget *window, *scrolled_win, *hbox, *vbox, *button;
    Widgets *widg = g_slice_new ( Widgets );
    /// ***
    gtk_init ( NULL, NULL );
    /// ***
    window = gtk_window_new ( GTK_WINDOW_TOPLEVEL );
    g_signal_connect ( G_OBJECT ( window ), "delete_event", gtk_main_quit, NULL );
    gtk_window_set_title ( GTK_WINDOW ( window ), "WhatsChat" );
    gtk_container_set_border_width ( GTK_CONTAINER ( window ), 10 );
    gtk_widget_set_size_request ( window, 250, 200 );
    /// ***
    widg->textview = gtk_text_view_new();
    gtk_text_view_set_editable ( GTK_TEXT_VIEW ( widg->textview ), FALSE );
    gtk_text_view_set_cursor_visible ( GTK_TEXT_VIEW ( widg->textview ), FALSE );
    /// ***
    widg->entry = gtk_entry_new();
    button = gtk_button_new_with_label ( "Send" );
    /// ***
    g_signal_connect ( G_OBJECT ( button      ), "clicked",  G_CALLBACK ( chatMSG ), ( gpointer ) widg );
    g_signal_connect ( G_OBJECT ( widg->entry ), "activate", G_CALLBACK ( chatMSG ), ( gpointer ) widg );
    /// ***
    scrolled_win = gtk_scrolled_window_new ( NULL, NULL );
    gtk_widget_set_size_request ( scrolled_win, -1, 200 );
    gtk_scrolled_window_set_policy ( GTK_SCROLLED_WINDOW ( scrolled_win ), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
    gtk_container_add ( GTK_CONTAINER ( scrolled_win ), widg->textview );
    /// ***
    hbox = gtk_hbox_new ( FALSE, 5 );
    gtk_box_pack_start_defaults ( GTK_BOX ( hbox ), widg->entry );
    gtk_box_pack_start_defaults ( GTK_BOX ( hbox ), button );
    /// ***
    vbox = gtk_vbox_new ( FALSE, 5 );
    gtk_box_pack_start ( GTK_BOX ( vbox ), scrolled_win, TRUE, TRUE, 0 );
    gtk_box_pack_start ( GTK_BOX ( vbox ), hbox, FALSE, TRUE, 0 );
    /// ***
    gtk_container_add ( GTK_CONTAINER ( window ), vbox );
    gtk_widget_show_all ( window );
    gtk_main();
}

void chatMSG ( GtkButton *button, Widgets *widg )
{
    ( void ) button;
    GtkTextBuffer *buffer;
    GtkTextMark *mark;
    GtkTextIter iter, start, end;
    const gchar *text;
    /// ***
    buffer = gtk_text_view_get_buffer ( GTK_TEXT_VIEW ( widg->textview ) );
    text   = gtk_entry_get_text ( GTK_ENTRY ( widg->entry ) );
    /// ***
    mark = gtk_text_buffer_get_insert ( buffer );
    gtk_text_buffer_get_iter_at_mark ( buffer, &iter, mark );
    gtk_text_buffer_get_bounds ( buffer, &start, &end );

    if (  gtk_text_buffer_get_char_count ( buffer ) && strlen( text ) > 0 )
    {
        gtk_text_buffer_insert ( buffer, &iter, "\n", -1 );
    }

    gtk_text_buffer_insert ( buffer, &iter, text, -1 );
    gtk_entry_set_text ( GTK_ENTRY ( widg->entry ), "" );
    /// ***
    mark = gtk_text_buffer_create_mark ( buffer, NULL, &iter, FALSE );
    gtk_text_view_scroll_mark_onscreen ( GTK_TEXT_VIEW ( widg->textview ), mark );
    gtk_text_buffer_delete_mark ( buffer, mark );
}

My guess is that somehow I mixed up things in the chatMSG() Funcion. How do I keep the scrollbar at a bottom after user minimize the Window?

I also tried the following:

GtkAdjustment *adj = gtk_scrolled_window_get_vadjustment ( GTK_SCROLLED_WINDOW ( scrolled_win ) );
gtk_adjustment_set_value ( adj, adj->upper );

But it is not working too.

Michi
  • 5,175
  • 7
  • 33
  • 58
  • Is this question specific to the linux API? What does it have to do with gcc? I suggest removing these tags. – Vladislav Ivanishin Jul 11 '19 at 09:42
  • @VladislavIvanishin It is a Question about `GTK` used on `Linux` compiled with `GCC` – Michi Jul 11 '19 at 09:45
  • As a side-note, GTK+ 2 should not be used in new projects. GTK+ 3 has been the stable version for years, and once GTK+ 4 will be released later this year, support for GTK+ 2 will completely stop (even security issues). Do yourself a favor, and use GTK+ 3, and forward this information to people asking you to do some coding using GTK+ 2. – liberforce Jul 22 '19 at 11:59
  • @liberforce I all ready work with `GTK4`, but I was need it in `GTK2`. Please do not ask why :) – Michi Jul 22 '19 at 12:44

1 Answers1

0

After a lot of search and trying different things which did not helped I searched help by Gnome-Team and managed to fix it.

I decided to share this here two, because it could help in the future other too. Here is an working example:

#include <gtk/gtk.h>

typedef struct
{
    GtkWidget *entry;
    GtkWidget *textview;
} Widgets;

void chatMSG ( GtkButton *, Widgets * );
void scroll_value_changed ( GtkAdjustment *adjustment, gpointer user_data );
void scroll_bottom_gravity ( GtkWidget    *scrolled_window, gpointer user_data );

int main ( void )
{
    GtkWidget *window, *scrolled_win, *hbox, *vbox, *button;
    Widgets *widg = g_slice_new ( Widgets );
    double from_bottom = 0.0;
    /// ***
    gtk_init ( NULL, NULL );
    /// ***
    window = gtk_window_new ( GTK_WINDOW_TOPLEVEL );
    g_signal_connect ( G_OBJECT ( window ), "delete_event", gtk_main_quit, NULL );
    gtk_window_set_title ( GTK_WINDOW ( window ), "WhatsChat" );
    gtk_container_set_border_width ( GTK_CONTAINER ( window ), 10 );
    gtk_widget_set_size_request ( window, 250, 200 );
    /// ***
    widg->textview = gtk_text_view_new();
    gtk_text_view_set_editable ( GTK_TEXT_VIEW ( widg->textview ), FALSE );
    gtk_text_view_set_cursor_visible ( GTK_TEXT_VIEW ( widg->textview ), FALSE );
    /// ***
    widg->entry = gtk_entry_new();
    button = gtk_button_new_with_label ( "Send" );
    /// ***
    g_signal_connect ( G_OBJECT ( button      ), "clicked",  G_CALLBACK ( chatMSG ), ( gpointer ) widg );
    g_signal_connect ( G_OBJECT ( widg->entry ), "activate", G_CALLBACK ( chatMSG ), ( gpointer ) widg );
    /// ***
    scrolled_win = gtk_scrolled_window_new ( NULL, NULL );
    gtk_widget_set_size_request ( scrolled_win, -1, 200 );
    gtk_scrolled_window_set_policy ( GTK_SCROLLED_WINDOW ( scrolled_win ), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC );
    GtkAdjustment *adjustment = gtk_scrolled_window_get_vadjustment ( GTK_SCROLLED_WINDOW ( scrolled_win ) );
    g_signal_connect ( scrolled_win, "size-allocate", ( GCallback ) scroll_bottom_gravity, &from_bottom );
    g_signal_connect ( adjustment, "value-changed", ( GCallback ) scroll_value_changed, &from_bottom );
    gtk_container_add ( GTK_CONTAINER ( scrolled_win ), widg->textview );
    /// ***
    hbox = gtk_hbox_new ( FALSE, 5 );
    gtk_box_pack_start_defaults ( GTK_BOX ( hbox ), widg->entry );
    gtk_box_pack_start_defaults ( GTK_BOX ( hbox ), button );
    /// ***
    vbox = gtk_vbox_new ( FALSE, 5 );
    gtk_box_pack_start ( GTK_BOX ( vbox ), scrolled_win, TRUE, TRUE, 0 );
    gtk_box_pack_start ( GTK_BOX ( vbox ), hbox, FALSE, TRUE, 0 );
    /// ***
    gtk_container_add ( GTK_CONTAINER ( window ), vbox );
    gtk_widget_show_all ( window );
    gtk_main();
}

void chatMSG ( GtkButton *button, Widgets *widg )
{
    ( void ) button;
    GtkTextMark *mark;
    GtkTextIter iter;
    /// ***
    GtkTextBuffer *buffer = gtk_text_view_get_buffer ( GTK_TEXT_VIEW ( widg->textview ) );
    const gchar *text     = gtk_entry_get_text ( GTK_ENTRY ( widg->entry ) );
    /// ***
    mark = gtk_text_buffer_get_insert ( buffer );
    gtk_text_buffer_get_iter_at_mark ( buffer, &iter, mark );

    if (  gtk_text_buffer_get_char_count ( buffer ) && strlen ( text ) > 0 )
    {
        gtk_text_buffer_insert ( buffer, &iter, "\n", -1 );
    }

    gtk_text_buffer_insert ( buffer, &iter, text, -1 );
    gtk_entry_set_text ( GTK_ENTRY ( widg->entry ), "" );
}

void scroll_bottom_gravity ( GtkWidget *scrolled_window,  gpointer user_data )
{
    GtkAdjustment *adjustment = gtk_scrolled_window_get_vadjustment ( GTK_SCROLLED_WINDOW ( scrolled_window ) );
    double *from_bottom = user_data;
    double upper = gtk_adjustment_get_upper ( adjustment );
    double page_size = gtk_adjustment_get_page_size ( adjustment );
    gtk_adjustment_set_value ( adjustment, upper - page_size - *from_bottom );
}

void scroll_value_changed ( GtkAdjustment *adjustment, gpointer user_data )
{
    double *from_bottom = user_data;
    double value = gtk_adjustment_get_value ( adjustment );
    double upper = gtk_adjustment_get_upper ( adjustment );
    double page_size = gtk_adjustment_get_page_size ( adjustment );
    *from_bottom = upper - page_size - value;
}
Michi
  • 5,175
  • 7
  • 33
  • 58