Search code examples
c++gtkgtk3gtkmmgtkmm3

Show accelerator key in menu


I am using Gtkmm 3.22.30 on Ubuntu and I have been trying to show accelerator keys in my application menu, without success. So far, I have been able to register an accelerator key to my menu items, but for some reason, they don't appear in my menu. I know this is possible, because I have seen it in Inkscape, which I believe is using Gtkmm as well (For example: New is bound to <Control>N:

Inkscape

I have prepared a minimal example to show my problem (and what I have done). Here is the code:

#include <gtkmm.h>
#include <iostream>

class MainWindow : public Gtk::ApplicationWindow
{

public:

    MainWindow();

private:

    void OnActivateSubItem()
    {
        std::cout << "Handler called" << std::endl;
    }
    
    Gtk::MenuBar  m_menuBar;
    Gtk::MenuItem m_mainMenu{"Menu"};
    Gtk::Menu     m_menu;
    Gtk::MenuItem m_subItem{"Item"};  // Menu|Item
 
};

MainWindow::MainWindow()
{
    // Setting the menu up:
    add(m_menuBar);

    m_menuBar.append(m_mainMenu);
    m_mainMenu.set_submenu(m_menu);
    m_menu.append(m_subItem);

    // Adding accelerator:
    auto accel_group = Gtk::AccelGroup::create();
    add_accel_group(accel_group);
    m_menu.set_accel_group(accel_group);

    // I would have believed this to do the trick but, meh...
    m_subItem.add_accelerator("activate",
                              accel_group,
                              GDK_KEY_y,
                              Gdk::ModifierType::CONTROL_MASK,
                              Gtk::ACCEL_VISIBLE);

    m_subItem.signal_activate().connect([this]{OnActivateSubItem();});
}

int main()
{
    auto app = Gtk::Application::create("my.menu.problem");

    MainWindow window;
    window.show_all();

    return app->run(window);
}

which leads to the following:

enter image description here

I was expecting a Ctrl + y entry next to the Item menu item (especially with the Gtk::ACCEL_VISIBLE flag for which I have found no documentation), but nothing is showing except a blank space. When I hit Ctrl + y, "Handler called" appears in the console, so the accelerator works.

I have look through the API but it is very confusing and badly documented (I was not able to find a working example for Gtkmm 3.22.30, not even in the examples coming with the source code).

How can I achieve this?

Notes:

  1. I am looking for an answer which does not involve Gtk::Builder if possible.
  2. The answer can use C code if what I want to do is not possible in Gtkmm, but I would need it to integrate with my Gtkmm code.

Solution

  • add_accel_group(accel_group);
    m_menu.set_accel_group(accel_group);
    

    I think the same AccelGroup cannot be assigned to a window and a menu. I searched the docs for details on this and found nothing, but my tummy feeling says me you have to delete one of these lines. And in this example they use the AccelGroup only in the window, too. I suggest to delete the second line.

    EDIT: i think you are using a different Gtkmm version than i am, because the code you provided works fine on my machine. Could you please compile following c++ program, run it and post its output ?

    #include <gtkmm.h>
    #include <iostream>
    
    int main() {
        cout << gtk_get_major_version() << "." << gtk_get_minor_version() << "." << gtk_get_micro_version();
    }