Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
521 views
in Technique[技术] by (71.8m points)

gtk - Border area of context menu for tree view is cut off

I am trying to port a context menu functionality for a tree view from Gtk3 to Gtk4. I've managed up to the point that the menu is shown, but the outer parts are cut off so that the menu is shown incomplete. It looks like this:

enter image description here

Example program to reproduce the effect is here:

#include <gtk/gtk.h>

GtkApplication *app;
GtkWidget *window;
GtkWidget *treeview;
GMenu *context_menu;
GtkWidget *popover;

static void general_initialisiation (gchar *argument);
static void mouse_pressed (GtkGestureClick *gesture, int n_press, double x, double y);

int main (gint argc, gchar *argv[])
{
    app = gtk_application_new ("this.is.a.test", G_APPLICATION_FLAGS_NONE);
    gint status;

    g_signal_connect_swapped (app, "activate", G_CALLBACK (general_initialisiation), NULL);

    status = g_application_run (G_APPLICATION (app), 0, NULL);

    g_object_unref (app);

    return status;
}

static void general_initialisiation (gchar *argument)
{
    window = gtk_application_window_new (GTK_APPLICATION (app));

    GtkTreeStore *treestore;
    GtkTreeModel *model;
    GtkTreeViewColumn *column;
    GtkCellRenderer *renderer;

    treeview = gtk_tree_view_new ();
    treestore = gtk_tree_store_new (1, GDK_TYPE_PIXBUF);
    gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), GTK_TREE_MODEL (treestore));
    model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview));
    g_object_unref (treestore);

    column = gtk_tree_view_column_new ();
    gtk_tree_view_column_set_title (column, "Pix");

    renderer = gtk_cell_renderer_pixbuf_new ();
    gtk_tree_view_column_pack_start (column, renderer, FALSE);
    gtk_tree_view_column_set_attributes (column, renderer, "pixbuf", 0, NULL);

    gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);

    gtk_window_set_child (GTK_WINDOW (window), treeview);

    GtkIconTheme *icon_theme;
    GdkPixbuf *pixbuf_smaller[2];
    GError *error = NULL;

    icon_theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (window));
    for (gint i = 0; i < 2; i++) {
        g_autoptr(GtkIconPaintable) icon;
        g_autoptr(GFile) file;
        g_autofree gchar *file_path;
        g_autoptr(GdkPixbuf) pixbuf;

        icon = gtk_icon_theme_lookup_icon (icon_theme,
                                           (i == 0) ? "dialog-question" : "image-missing", // icon name
                                           NULL, 
                                           48, // icon size
                                           1,  // scale
                                           GTK_TEXT_DIR_LTR, 
                                           0  // flags
                                           );
        file = gtk_icon_paintable_get_file (icon);
        file_path = g_file_get_path (file);

        pixbuf = gdk_pixbuf_new_from_file (file_path, &error);

        pixbuf_smaller[i] = gdk_pixbuf_scale_simple (pixbuf, 39, 39, GDK_INTERP_BILINEAR);
    }

    GtkTreeIter new_iter;

    gtk_tree_store_insert_with_values (treestore, &new_iter, NULL, -1, 0, pixbuf_smaller[0], -1);
    gtk_tree_store_insert_with_values (treestore, &new_iter, NULL, -1, 0, pixbuf_smaller[1], -1);

    context_menu = g_menu_new ();
    popover = gtk_popover_menu_new_from_model_full (G_MENU_MODEL (context_menu), GTK_POPOVER_MENU_NESTED);
    gtk_popover_set_has_arrow (GTK_POPOVER (popover), FALSE);
    gtk_widget_set_parent (popover, treeview);

    GtkGesture *gesture = gtk_gesture_click_new ();
    gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), GDK_BUTTON_SECONDARY);
    GtkEventController *controller = GTK_EVENT_CONTROLLER (gesture);
    g_signal_connect (controller, "pressed", G_CALLBACK (mouse_pressed), NULL);
    gtk_widget_add_controller (treeview, controller);

    gtk_widget_show (window);
}

static void mouse_pressed (GtkGestureClick *gesture, int n_press, double x, double y)
{
    g_autoptr(GtkTreePath) path;

    gint x_bin_window, y_bin_window;

    gtk_tree_view_convert_widget_to_bin_window_coords (GTK_TREE_VIEW (treeview), (gint) x, (gint) y, &x_bin_window, &y_bin_window);

    gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (treeview), x_bin_window, y_bin_window, &path, NULL, NULL, NULL);
    if (!path) {
        return;
    }

    g_menu_remove_all (context_menu);

    GMenu *items1 = g_menu_new ();
    g_menu_append (items1, "Item 1a", NULL);
    g_menu_append (items1, "Item 1b", NULL);

    g_menu_append_section (context_menu, "Headline 1", G_MENU_MODEL (items1));
    g_object_unref (items1);

    GMenu *items2 = g_menu_new ();
    g_menu_append (items2, "Item 2a", NULL);
    g_menu_append (items2, "Item 2b", NULL);

    g_menu_append_section (context_menu, "Headline 2", G_MENU_MODEL (items2));
    g_object_unref (items2);

    GdkRectangle rectangle;
    rectangle.x = x;
    rectangle.y = y;
    rectangle.width = 1;
    rectangle.height = 1;

    gtk_popover_set_pointing_to (GTK_POPOVER (popover), &rectangle);

    gtk_popover_popup (GTK_POPOVER (popover));
}

As for

rectangle.width = 1;
rectangle.height = 1;

I took this from example code, but whatever I set there results in the same effect.

I receive warnings/error messages like the following in the terminal:

  • gtk_css_node_insert_after: assertion 'previous_sibling == NULL || previous_sibling->parent == parent' failed
  • Gtk-WARNING **: 21:05:17.956: Allocating size to GtkPopoverMenu 0x55cf605001f0 without calling gtk_widget_measure(). How does the code know the size to allocate?
  • Allocation height too small. Tried to allocate 89x132, but GtkPopoverMenu 0x55cf605001f0 needs at least 89x201.

What do I need to change so the context menu is shown properly? I've checked in two different Linux distributions, Manjaro and OpenSuse Tumbleweed.

EDIT

After reading Create popover that can overpass window area, I thought I had found the solution and created a large enough window, but other than the messages about allocation problems going away the problem remains. I've noticed though that if I leave out the headlines for the sections, the menu is displayed properly. Adding the section headlines leads to an undersized menu again.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...