Strange behavior of a pop-up menu

I am confused by the attached code. It uses Menu.popup…() and MenuItem.activate() to explicitly invoke a menu item. What I don’t understand is that the pop-up menu persists on the screen unless the MenuItem callback opens a dialog box. Why should it matter whether or not the menu item opens a dialog?

The program (python2, gtk+3) has a button that creates the popup menu, and an “Auto” button that invokes the menu automatically. If the “auto popdown” toggle button is active, the “Auto” button will explicitly pop-down the menu. If the “auto dialog” button is active, the “Auto” button will invoke the menu item that opens a dialog. Since the “Auto” button invokes a menu item in both cases, I don’t expect the menu to remain on the screen in any case, but it does. (If I’m wrong that invoking a menu item should close a menu, then why does the menu go away when the menu item opens the dialog?)

Thanks.
– Steve

import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, Gdk, GObject

def make_popup():
    menu = Gtk.Menu()

    # MenuItem that doesn't open a dialog window
    menuitem = Gtk.MenuItem("no dialog")
    menu.append(menuitem)
    menuitem.connect('activate', do_noDialog)

    # MenuItem that does open a dialog window
    menuitem = Gtk.MenuItem("dialog")
    menu.append(menuitem)
    menuitem.connect('activate', do_dialog)
    
    menu.show_all()
    return menu

def do_popup(button):
    menu = make_popup()
    menu.popup_at_widget(button, Gdk.Gravity.SOUTH_WEST, Gdk.Gravity.NORTH_WEST,
                         None)

# MenuItem callback that doesn't open a dialog
def do_noDialog(menuitem):
    print "no dialog"

# MenuItem callback that does open a dialog
def do_dialog(menuitem):
    dialog = Gtk.Dialog()
    button = dialog.add_button("Push here", 0)
    response = dialog.run()
    print "dialog"
    dialog.close()

# Automatically open the popup menu and activate a MenuItem
def do_auto(button):
    menu = make_popup()
    menu.popup_at_widget(button, Gdk.Gravity.SOUTH_WEST, Gdk.Gravity.NORTH_WEST,
                         None)
    if autodialog.get_active():
        menu.get_children()[1].activate() # opens a dialog
    else:
        menu.get_children()[0].activate() # does not open a dialog

    # If the menu item does not open a dialog, then the menu must be
    # removed explicitly. ???
    if autodown.get_active():
        menu.popdown()

window = Gtk.Window(Gtk.WindowType.TOPLEVEL)
window.connect('delete-event', Gtk.main_quit)
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=2)
window.add(box)

button = Gtk.Button("Pop-up Menu")
button.connect("clicked", do_popup)
box.pack_start(button, expand=True, fill=True, padding=0)

box.pack_start(Gtk.Separator(orientation=Gtk.Orientation.HORIZONTAL),
               expand=False, fill=False, padding=2)

button = Gtk.Button("Auto")
button.connect("clicked", do_auto)
box.pack_start(button, expand=True, fill=True, padding=0)

autodown = Gtk.ToggleButton.new_with_label("auto popdown")
box.pack_start(autodown, expand=True, fill=True, padding=0)
autodialog = Gtk.ToggleButton.new_with_label("auto dialog")
box.pack_start(autodialog, expand=True, fill=True, padding=0)

window.show_all()
window.present()
Gtk.main()
1 Like

I doubt it does.

The menu closing is probably just the result of it losing focus, clicking away from it should have the same effect.

That said, I’m don’t why when you activate/select an item from code it is necessary to also close the menu, but I know I’ve had to do the same thing.

I think the question is why it doesn’t behave the same as if it were clicked by the user.

Which is probably due to a lack of events, and maybe why popdown is even a thing.

Hopefully one of the Gtk guys knows for sure.

That sounds plausible, but it’s not the full answer. I added a GtkEntry to the main window, and a call to entry.grab_focus() inside the callback for the menu item that doesn’t open a dialog (the do_noDialog function in the example). The pop-up menu still doesn’t disappear.

– Steve

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.