This is a minimal example that displays Popovermenu with scrollbars…
#include <gtk/gtk.h>
static GtkWidget* popoverMenu = nullptr;
static GMenu* subMenu = nullptr;
void createContextMenu()
{
subMenu = g_menu_new();
GMenu* section = g_menu_new();
const char* pID = "f";
//GSimpleAction* sa = g_simple_action_new ("saSetFront", NULL);
//g_action_map_add_action (G_ACTION_MAP (app), G_ACTION (sa));
//g_signal_connect (sa, "activate", G_CALLBACK (itemActivated), &item);
GMenuItem* gMI = g_menu_item_new ("SetFront", pID);
g_menu_append_item (section, gMI);
g_object_unref (gMI);
pID = "b";
//sa = g_simple_action_new ("saSetBack", NULL);
//g_action_map_add_action (G_ACTION_MAP (app), G_ACTION (sa));
//g_signal_connect (sa, "activate", G_CALLBACK (itemActivated), &item);
gMI = g_menu_item_new ("SetBack", pID);
g_menu_append_item (section, gMI);
g_object_unref (gMI);
//complete first section (2 items)
g_menu_append_section (subMenu, NULL, G_MENU_MODEL(section));
//add second section (1 item)
section = g_menu_new();
pID = nullptr;
//sa = g_simple_action_new ("saOptions", NULL);
// g_action_map_add_action (G_ACTION_MAP (app), G_ACTION (sa));
// g_signal_connect (sa, "activate", G_CALLBACK (itemActivated), &item);
gMI = g_menu_item_new ("Options", pID);
g_menu_append_item (section, gMI);
g_object_unref (gMI);
//complete second section
g_menu_append_section (subMenu, NULL, G_MENU_MODEL(section));
}
void handleMenu(GtkWidget* parent, int x, int y)
{
if(!subMenu)
createContextMenu();
GMenuModel* model = G_MENU_MODEL(subMenu);
if (!popoverMenu)
{
popoverMenu = gtk_popover_menu_new_from_model_full(model, GTK_POPOVER_MENU_NESTED);
gtk_widget_set_parent(popoverMenu, parent);
GtkPopover* popover = GTK_POPOVER (popoverMenu);
gtk_popover_set_position (popover, GTK_POS_BOTTOM);
gtk_popover_set_has_arrow (popover, FALSE);
gtk_widget_set_halign (popoverMenu, GTK_ALIGN_START);
gtk_widget_set_valign(popoverMenu, GTK_ALIGN_START);
}
GtkPopover* popOver = GTK_POPOVER(popoverMenu);
GdkRectangle rect = { x, y, 1, 1 };
gtk_popover_set_pointing_to (popOver, &rect);
gtk_popover_popup (popOver);
}
static void onRightClick(GtkGestureClick *gesture, gint n_press, gdouble x, gdouble y, gpointer user_data)
{
if (n_press == 1 && gtk_gesture_single_get_current_button(GTK_GESTURE_SINGLE(gesture)) == GDK_BUTTON_SECONDARY)
{
GtkWidget *parent = (GtkWidget *) user_data;
handleMenu(parent, (int) x, (int) y);
}
}
static void activate (GtkApplication* app, gpointer user_data)
{
GtkWidget *window;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window");
gtk_window_set_default_size (GTK_WINDOW (window), 800, 600);
// Create a GtkGestureClick controller for right-clicks
GtkGesture* rightClick = gtk_gesture_click_new();
gtk_gesture_single_set_button(GTK_GESTURE_SINGLE(rightClick), GDK_BUTTON_SECONDARY);
gtk_widget_add_controller (window, GTK_EVENT_CONTROLLER(rightClick));
g_signal_connect (rightClick, "pressed", G_CALLBACK (onRightClick), window);
gtk_window_present (GTK_WINDOW (window));
}
int main (int argc, char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new ("org.gtk.example", G_APPLICATION_DEFAULT_FLAGS);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return status;
}