'How to Scroll a ScrolledWindow with arrow keys in Gtk 3.24.5?

I have a gtk entry right below the scrolled window which has the default focus , left and right keys move the cursor in the entry ,I am able to catch the key press events for up and down arrow keys but don't know how to scroll the scrolled window, referred many websites none of them were clear or explained only in parts.

Below are some of the pages I went through: https://mail.gnome.org/archives/gtk-devel-list/2002-February/msg00104.html

https://developer.gnome.org/gtkmm-tutorial/stable/sec-keyboardevents-overview.html.en

tried using gtk_scrolled_window_set_vadjustment() couldn't get it working. The official page says GTK_SCROLL_STEP_UP is deprecated but doesn't say what should be used instead.

Every answer would be very appreciated.Thanks

bool Method::cb_MPWindow(GtkWidget *wgt, GdkEventKey *event, MethodSelect *ms)
{
    if(event->keyval == GDK_KEY_Up || event->keyval == GDK_KEY_Down)
    {  
  
        g_signal_emit_by_name(ms->ScrolledWindow, "scroll-child",(event->keyval == GDK_KEY_Up)?GTK_SCROLL_STEP_UP:GTK_SCROLL_STEP_DOWN);
//The above line works in gtk 3.14.5 but crashes the app in 3.24.5 
        return TRUE;
    }

    return FALSE;
}


Solution 1:[1]

In order to scroll the window with the keyboard, you need to:

  • Get the scrolled window's vertical or horizontal adjustment with gtk_scrolled_window_get_vadjustment() or gtk_scrolled_window_get_hadjustment().
  • From the adjustment object, get the following properties: value (the current scroll position), step-increment (how much to scroll by line), and page-increment (how much to scroll by page).
  • Then, according to the key that was pressed, you add or subtract the increment to value and then set the new value with gtk_adjustment_set_value().

The the window will scroll when change when you set the value. Typically the line increment is used when navigating with the arrow keys, while the page increment when using the Page Up/Down keys. You add them when scrolling down, and subtract while scrolling down. It is worth noting that the increments change dynamically based on the window size, so you do not need to set them manually.

Here is my code (in C). First setting up the callback:

// Create a scrolled window
GtkWidget *scrolled_window = gtk_scrolled_window_new(NULL, NULL);

// Get the vertical adjustment object
GtkAdjustment *page_vertical_adjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(scrolled_window));

// Connect to the key press event
g_signal_connect(
    GTK_SCROLLED_WINDOW(scrolled_window),
    "key-press-event",
    G_CALLBACK(keyboard_scrolling),
    page_vertical_adjustment
);

And then the callback function:

void keyboard_scrolling(GtkScrolledWindow *widget, GdkEventKey event, GtkAdjustment *adjustment)
{
    // Get the vertical position of the page
    gdouble position = gtk_adjustment_get_value(adjustment);

    // Get the scrolling increments
    gdouble step = gtk_adjustment_get_step_increment(adjustment);  // Amount to be scrolled by the arrows (roughly a line)
    gdouble page = gtk_adjustment_get_page_increment(adjustment);  // Amount to be scrolled by the Page keys (roughly the visible area)

    // printf("step: %f, page: %f, key: %d\n", step, page, event.keyval);

    // Check which key was pressed    
    switch (event.keyval)
    {
    case GDK_KEY_Page_Down:
        gtk_adjustment_set_value(adjustment, position + page);
        break;
    
    case GDK_KEY_Page_Up:
        gtk_adjustment_set_value(adjustment, position - page);
        break;
    
    case GDK_KEY_Down:
        gtk_adjustment_set_value(adjustment, position + step);
        break;
    
    case GDK_KEY_Up:
        gtk_adjustment_set_value(adjustment, position - step);
        break;
    
    default:
        break;
    }
}

For convenience, here is a list of keyboard macros that GTK accepts: https://github.com/GNOME/gtk/blob/main/gdk/gdkkeysyms.h

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Tiago Becerra Paolini