From 8500675125ef2d5d1835d89828154c7781291cf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABl=20Bonithon?= Date: Sat, 12 Feb 2022 13:18:17 +0100 Subject: [PATCH] Stick process view at the top in the absence of user action Until the user manually scrolls down by some means, the view remains stuck at the top. When the view subsequently returns to this position, it automatically sticks again, pending further user action. Closes: #18 MR: !30 --- src/process-tree-view.c | 3 ++ src/process-window.c | 65 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 67 insertions(+), 1 deletion(-) diff --git a/src/process-tree-view.c b/src/process-tree-view.c index 8b6392d..1608975 100644 --- a/src/process-tree-view.c +++ b/src/process-tree-view.c @@ -839,6 +839,9 @@ xtm_process_tree_view_highlight_pid (XtmProcessTreeView *treeview, GPid pid) { { path = gtk_tree_model_get_path (model, &iter); gtk_tree_selection_select_path (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)), path); + + /* set cursor before scrolling to unstick the view from top if needed */ + gtk_tree_view_set_cursor (GTK_TREE_VIEW (treeview), path, NULL, FALSE); gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (treeview), path, NULL, TRUE, 0.5, 0); gtk_tree_path_free (path); break; diff --git a/src/process-window.c b/src/process-window.c index 1e63e9a..e937a8e 100644 --- a/src/process-window.c +++ b/src/process-window.c @@ -66,6 +66,7 @@ struct _XtmProcessWindow gint width; gint height; gulong handler; + gboolean view_stuck; }; G_DEFINE_TYPE (XtmProcessWindow, xtm_process_window, GTK_TYPE_WIDGET) @@ -230,6 +231,52 @@ show_settings_dialog (GtkButton *button, gpointer user_data) g_signal_handler_unblock (G_OBJECT (window->window), window->handler); } +static void +xtm_process_window_stick_view (GtkAdjustment *adjustment, XtmProcessWindow *window) +{ + if (window->view_stuck) + gtk_adjustment_set_value (adjustment, 0); + else if (gtk_adjustment_get_value (adjustment) == 0) + window->view_stuck = TRUE; +} + +static gboolean +xtm_process_window_unstick_view_event (GtkWidget *widget, GdkEvent *event, XtmProcessWindow *window) +{ + GdkScrollDirection dir; + gdouble y; + + if (! window->view_stuck) + return FALSE; + + if (event->type == GDK_SCROLL && ( + (gdk_event_get_scroll_direction (event, &dir) && dir == GDK_SCROLL_UP) + || (gdk_event_get_scroll_deltas (event, NULL, &y) && y <= 0) + )) + return FALSE; + + window->view_stuck = FALSE; + + return FALSE; +} + +static void +xtm_process_window_unstick_view_cursor (GtkTreeView *tree_view, XtmProcessWindow *window) +{ + GtkTreePath *cursor, *end; + + if (! window->view_stuck) + return; + + gtk_tree_view_get_cursor (tree_view, &cursor, NULL); + gtk_tree_view_get_visible_range (tree_view, NULL, &end); + if (gtk_tree_path_compare (cursor, end) >= 0) + window->view_stuck = FALSE; + + gtk_tree_path_free (cursor); + gtk_tree_path_free (end); +} + static void xtm_process_window_init (XtmProcessWindow *window) { @@ -297,7 +344,23 @@ xtm_process_window_init (XtmProcessWindow *window) window->treeview = xtm_process_tree_view_new (); gtk_widget_show (window->treeview); - gtk_container_add (GTK_CONTAINER (gtk_builder_get_object (window->builder, "scrolledwindow")), window->treeview); + { + GtkScrolledWindow *s_window; + GtkWidget *bar; + GtkAdjustment *adjust; + + s_window = GTK_SCROLLED_WINDOW (gtk_builder_get_object (window->builder, "scrolledwindow")); + bar = gtk_scrolled_window_get_vscrollbar (s_window); + adjust = gtk_scrolled_window_get_vadjustment (s_window); + window->view_stuck = TRUE; + + gtk_container_add (GTK_CONTAINER (s_window), window->treeview); + g_signal_connect (adjust, "value-changed", G_CALLBACK (xtm_process_window_stick_view), window); + g_signal_connect (bar, "button-press-event", G_CALLBACK (xtm_process_window_unstick_view_event), window); + g_signal_connect (bar, "scroll-event", G_CALLBACK (xtm_process_window_unstick_view_event), window); + g_signal_connect (window->treeview, "scroll-event", G_CALLBACK (xtm_process_window_unstick_view_event), window); + g_signal_connect (window->treeview, "cursor-changed", G_CALLBACK (xtm_process_window_unstick_view_cursor), window); + } g_object_bind_property(window->settings, "show-legend", gtk_builder_get_object(window->builder, "legend"), "visible",