Hi!
I am trying to implement simple popup (context) menu using Gtk4 (Ubuntu 22.04). My code (compiled with: g++ pkg-config --cflags gtk4
-o test main.cpp pkg-config --libs gtk4
):
#include <gtk/gtk.h>
GtkApplication * app = NULL;
GtkWidget * window = NULL;
GtkWidget * area = NULL;
void item_1_activated( GSimpleAction * action, GVariant * parameter, gpointer user_data )
{
printf( "Item 1\n" );
}
void item_2_activated( GSimpleAction * action, GVariant * parameter, gpointer user_data )
{
printf( "Item 2\n" );
}
void popover_closed_callback( GtkPopover * popover, gpointer user_data )
{
gtk_widget_unparent( GTK_WIDGET( popover ));
}
void PopUpMenu( int x, int y )
{
GMenu * menu = g_menu_new();
const GActionEntry entries[] =
{
{ "item_1_action", item_1_activated, NULL, NULL, NULL, { 0, 0, 0 }},
{ "item_2_action", item_2_activated, NULL, NULL, NULL, { 0, 0, 0 }}
};
g_action_map_add_action_entries( G_ACTION_MAP( window ), entries, G_N_ELEMENTS ( entries ), NULL );
g_menu_insert( menu, 0, "item 1", "win.item_1_action" );
g_menu_insert( menu, 1, "item 2", "win.item_2_action" );
GtkWidget * popover = gtk_popover_menu_new_from_model_full( G_MENU_MODEL( menu ), GTK_POPOVER_MENU_NESTED );
g_object_unref( menu );
gtk_widget_set_parent( popover, area );
gtk_popover_set_has_arrow( GTK_POPOVER( popover ), FALSE );
GdkRectangle rectangle = { x, y, 1, 1 };
gtk_popover_set_pointing_to( GTK_POPOVER( popover ), &rectangle );
g_signal_connect( popover, "closed", G_CALLBACK( popover_closed_callback ), NULL );
gtk_popover_popup( GTK_POPOVER( popover ));
}
void mouse_button_pressed_callback( GtkGestureClick * gesture, int, double x, double y, gpointer user_data )
{
if ( gtk_gesture_single_get_current_button(( GtkGestureSingle * ) gesture ) == GDK_BUTTON_SECONDARY )
PopUpMenu( x, y );
}
void activate( GtkApplication *, gpointer user_data )
{
window = gtk_application_window_new( app );
gtk_window_set_title( GTK_WINDOW( window ), "Popover example" );
gtk_window_set_default_size( GTK_WINDOW( window ), 400, 400 );
area = gtk_drawing_area_new();
gtk_window_set_child( GTK_WINDOW( window ), area );
GtkGesture * gesture = gtk_gesture_click_new();
gtk_gesture_single_set_button( GTK_GESTURE_SINGLE( gesture ), 0 );
g_signal_connect( gesture, "pressed", G_CALLBACK( mouse_button_pressed_callback ), NULL );
gtk_widget_add_controller( area, GTK_EVENT_CONTROLLER( gesture ));
gtk_widget_show( window );
}
int main( int argc, char ** argv )
{
app = gtk_application_new( NULL, G_APPLICATION_FLAGS_NONE );
g_signal_connect( app, "activate", G_CALLBACK( activate ), NULL );
int status = g_application_run( G_APPLICATION( app ), 0, NULL );
g_object_unref( app );
return status;
}
The problem: if I keep call to “gtk_widget_unparent” then I am not receive activate signal from actions; If I comment the call to “gtk_widget_unparent”, then I receive the signals, but on exit I get:
(test:6653): Gtk-WARNING **: 13:08:01.640: Finalizing GtkDrawingArea 0x55964e60a4b0, but it still has children left:
(test:6653): Gtk-WARNING **: 13:08:01.640: - GtkPopoverMenu 0x559650ca6200
And, if I run this code in WSL then after receiving the signal the UI is hang.
Any ideas what I did wrong?
Thank you in advance