Search code examples
gtk3glibvala

GLib.Menu Action not working


I'm trying to learn vala at the moment. With my sample app i have a problem with the GLib.Menu actions.

I declared a new action quit_action which should quit the app. The compiler runs without any warnings or errors, but when i run the app i can open the menu, but the item "quit" is greyed-out.

/* main.vala */

using Gtk;

class mainWindow : Gtk.ApplicationWindow {
        public mainWindow (Application app) {

            // Window Properties
            this.set_default_size (800, 600);
            this.window_position = Gtk.WindowPosition.CENTER;
        this.destroy.connect (Gtk.main_quit);

            // HeaderBar
            var headerBar = new Gtk.HeaderBar ();
            headerBar.set_title ("Test Title");
            headerBar.set_subtitle ("Test Subtitle");
            headerBar.set_show_close_button (true);

            // Menu
            var menuButton = new Gtk.Button.from_icon_name ("open-menu-symbolic", Gtk.IconSize.SMALL_TOOLBAR);
            headerBar.pack_end (menuButton);

            var menu = new GLib.Menu ();
        menu.append ("Quit", "app.quit");

            var popover = new Gtk.Popover (menuButton);
            popover.bind_model (menu, "app");

            menuButton.clicked.connect (() =>  {
                popover.popup ();
                popover.show_all ();
            });

            this.set_titlebar (headerBar);

            this.show_all ();
        }
}

public class Application : Gtk.Application {
    public Application () {
        Object (application_id: "org.example.application", flags: 0);
    }

    protected override void activate () {
        // Create a new window for this application.
        mainWindow win = new mainWindow (this);
        win.show_all ();
        Gtk.main ();
    }

    protected override void startup () {
        base.startup ();

        var quit_action = new GLib.SimpleAction ("quit", null);
        quit_action.activate.connect (this.quit);
        this.add_action (quit_action);
    }
}

int main (string[] args) {
    Gtk.init (ref args);
    return new Application ().run (args);
}

Solution

  • There are two things wrong here:

    1. You have to assign the Application to the ApplicationWindow (this is normally done in the constructor, but since it's a GLib style constructor you can't call the inherited constructor):

      this.application = app;
      
    2. The action names have to match, if you want to use app.quit it has to be called that way in both places.

    The fully working code:

    /* main.vala */
    
    using Gtk;
    
    class mainWindow : Gtk.ApplicationWindow {
      public mainWindow (Application app) {
        this.application = app;
        // Window Properties
        this.set_default_size (800, 600);
        this.window_position = Gtk.WindowPosition.CENTER;
        this.destroy.connect (Gtk.main_quit);
    
        // HeaderBar
        var headerBar = new Gtk.HeaderBar ();
        headerBar.set_title ("Test Title");
        headerBar.set_subtitle ("Test Subtitle");
        headerBar.set_show_close_button (true);
    
        // Menu
        var menuButton = new Gtk.Button.from_icon_name ("open-menu-symbolic", Gtk.IconSize.SMALL_TOOLBAR);
        headerBar.pack_end (menuButton);
    
        var menu = new GLib.Menu ();
        menu.append ("Quit", "app.quit");
    
        var popover = new Gtk.Popover (menuButton);
        popover.bind_model (menu, "app");
    
        menuButton.clicked.connect (() =>  {
          //popover.popdown ();
          popover.show_all ();
        });
    
        this.set_titlebar (headerBar);
    
        this.show_all ();
      }
    }
    
    public class Application : Gtk.Application {
      public Application () {
        Object (application_id: "org.example.application", flags: 0);
      }
    
      protected override void activate () {
        // Create a new window for this application.
        mainWindow win = new mainWindow (this);
        win.show_all ();
        Gtk.main ();
      }
    
      protected override void startup () {
        base.startup ();
    
        var quit_action = new GLib.SimpleAction ("app.quit", null);
        quit_action.activate.connect (this.quit);
        this.add_action (quit_action);
      }
    }
    
    int main (string[] args) {
        Gtk.init (ref args);
        return new Application ().run (args);
    }