The Allegro Wiki is migrating to github at

Native Menu Proposal

From Allegro Wiki
Revision as of 21:32, June 29, 2011 by Matthew Leverton (talk | contribs) (Created page with 'Allegro's native dialog add-on provides a way to access basic OS dialogs (message boxes, file selectors, etc). This is a proposal to add support for native menus as part of the a…')
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Allegro's native dialog add-on provides a way to access basic OS dialogs (message boxes, file selectors, etc). This is a proposal to add support for native menus as part of the add-on.

This proposal is a draft. It is likely to change as it is implemented.


<highlightSyntax language="c"> typedef struct ALLEGRO_MENU ALLEGRO_MENU;





 int id;


/* creating/modifying */ ALLEGRO_MENU *al_create_menu(void); int al_append_menu_item(ALLEGRO_MENU *parent, char const *title, int id, int flags, ALLEGRO_MENU *popup); int al_insert_menu_item(ALLEGRO_MENU *parent, int index, char const *title, int id, int flags, ALLEGRO_MENU *popup); void al_remove_menu_item(ALLEGRO_MENU *menu, int index); void al_set_menu_item_flags(ALLEGRO_MENU *menu, int index, int flags); ALLEGRO_MENU *al_clone_menu(ALLEGRO_MENU *menu); void al_destroy_menu(ALLEGRO_MENU *menu);

/* querying */ int al_get_menu_index_by_id(ALLEGRO_MENU *menu, int id); int al_get_menu_index_by_name(ALLEGRO_MENU *menu, int const char *title);

/* events */ ALLEGRO_EVENT_SOURCE *al_get_default_menu_event_source(void); ALLEGRO_EVENT_SOURCE *al_enable_menu_event_source(ALLEGRO_MENU *menu); void al_disable_menu_event_source(ALLEGRO_MENU *menu);

/* displaying */ void al_set_display_menu(ALLEGRO_DISPLAY *display, ALLEGRO_MENU *menu); void al_popup_menu(ALLEGRO_MENU *popup, ALLEGRO_DISPLAY *display, int x, int y); void al_hide_menu(ALLEGRO_MENU *menu);


Basic Use Case

<highlightSyntax language="c"> ALLEGRO_MENU *file = al_create_menu(); al_append_menu_item(file, "Open", OPEN_ID, 0, NULL); al_append_menu_item(file, "Exit", EXIT_ID, 0, NULL);

ALLEGRO_MENU *menu = al_create_menu(); al_append_menu_item(menu, "File", 0, 0, file);

al_set_display_menu(display, menu); </highlightSyntax>

Implementation Notes

  • An ALLEGRO_MENU can only be attached to a single display at a time. A menu that is attached to a display cannot be used as a popup. The al_clone_menu() is intended to be used for the case where the same menu should be displayed on multiple displays.
  • Events are sent via the closest source found in the menu hierarchy. If none is found (al_enable_menu_event_source() was not ever used), then they are sent via a default source.
  • There is no way yet to specify a bitmap icon. If an ALLEGRO_BITMAP is used, then it would have to be converted to the OS's native bitmap format.
  • There is no way yet to specify keyboard triggers.
  • A higher level function like al_build_menu(ALLEGRO_MENU_INFO *info) that takes a complete menu structure could be useful to make the creation process less verbose.


The system menu is always built (with certain default menu items), even if no user menu has been set. So when a user menu is set, those default menu items should be automatically inserted in a transparent manner.

OS X uses a single application menu as opposed to a per window menu. This presents a problem because the API is designed to work with a per-window menu. Some solutions:

  1. Automatically detect when a display gains focus, and update the menu accordingly. If the newly focused display has no menu, then nothing would happen to the existing system menu. If possible, this would be the preferred solution. While it may not be how first-class OS X applications operate, it provides the most transparent cross platform solution.
  2. Always show the most recent menu as set via al_set_display_menu() regardless of the current display. The user would have to explicitly call that function every time a different display gains focus. When a display is destroyed, the user would have to call al_set_display_menu(NULL, NULL). (The first parameter would actually just be ignored, so it could be anything, including the pointer of the destroyed display.)