Re: [AD] native menus

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


On Wed, Jul 6, 2011 at 2:29 AM, Matthew Leverton <meffer@xxxxxxxxxx> wrote:
> I poked around the GTK code and it looked like too much hassle for me
> to bother with at the moment
>
Attached is a limited test implementation for GTK. It works with
ex_menu.c to show/hide the main menu bar.

But I don't know enough about how the window/display code works under
Linux... Is there even an easy way to attach a GTK menu to the window?
My test code just pops up a new detached window that contains the
menu.

Would we need something like: ALLEGRO_DISPLAY
*al_create_native_display(w,h) that under Linux would return something
that is a GTK window?

--
Matthew Leverton
Index: addons/native_dialog/gtk_dialog.c
===================================================================
--- addons/native_dialog/gtk_dialog.c	(revision 14832)
+++ addons/native_dialog/gtk_dialog.c	(working copy)
@@ -534,25 +534,32 @@
    textlog->async_queue = NULL;
 }
 
+/*---------------------------------------------------------------------------*/
+/* Menus                                                                     */
+/*---------------------------------------------------------------------------*/
+
+/* [user thread] */
 bool _al_init_menu(ALLEGRO_MENU *menu)
 {
    (void) menu;
-   return false;
+   return true;
 }
 
+/* [user thread] */
 bool _al_init_popup_menu(ALLEGRO_MENU *menu)
 {
-   (void) menu;
-   return false;
+   return _al_init_menu(menu);
 }
 
+/* [user thread] */
 bool _al_insert_menu_item_at(ALLEGRO_MENU_ITEM *item, int i)
 {
    (void) item;
    (void) i;
-   return false;
+   return true;
 }
 
+/* [user thread] */
 bool _al_destroy_menu_item_at(ALLEGRO_MENU_ITEM *item, int i)
 {
    (void) item;
@@ -560,6 +567,7 @@
    return false;
 }
 
+/* [user thread] */
 bool _al_update_menu_item_at(ALLEGRO_MENU_ITEM *item, int i)
 {
    (void) item;
@@ -567,20 +575,126 @@
    return false;
 }
 
+typedef struct DISPLAY_MENU_ARGS DISPLAY_MENU_ARGS;
+struct DISPLAY_MENU_ARGS
+{
+   ALLEGRO_DISPLAY *display;
+   ALLEGRO_MENU *menu;
+};
+
+/* [gtk thread] */
+static void menuitem_response(ALLEGRO_MENU_ITEM *menu_item)
+{
+   if (menu_item->parent)
+      _al_emit_menu_event(menu_item->parent->display, menu_item->id);
+}
+
+/* [gtk thread] */
+GtkWidget *build_menu(GtkWidget *gmenu, ALLEGRO_MENU *amenu)
+{
+   size_t i;
+   
+   for (i = 0; i < _al_vector_size(&amenu->items); ++i) {
+      ALLEGRO_MENU_ITEM *aitem = * (ALLEGRO_MENU_ITEM **) _al_vector_ref(&amenu->items, i);
+      GtkWidget *gitem = gtk_menu_item_new_with_label(al_cstr(aitem->caption));
+      
+      if (aitem->popup) {
+         GtkWidget *gsubmenu = gtk_menu_new();
+         build_menu(gsubmenu, aitem->popup);
+         gtk_widget_show(gsubmenu);
+         gtk_menu_item_set_submenu(GTK_MENU_ITEM(gitem), gsubmenu);
+      }
+      else if (aitem->id) {
+         g_signal_connect_swapped (gitem, "activate",
+            G_CALLBACK(menuitem_response), (gpointer) aitem);
+      }
+      
+      gtk_widget_show(gitem);
+      gtk_menu_shell_append(GTK_MENU_SHELL(gmenu), gitem);
+   }
+   
+   return NULL;
+}
+
+/* [gtk thread] */
+static gboolean do_show_display_menu(gpointer data)
+{
+   DISPLAY_MENU_ARGS *args = (DISPLAY_MENU_ARGS *) data;
+   
+   if (!args->menu->extra1) {
+      GtkWidget *gtk_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+      GtkWidget *menu_bar = gtk_menu_bar_new();
+   
+      build_menu(menu_bar, args->menu);
+       
+      gtk_container_add(GTK_CONTAINER(gtk_window), menu_bar);
+      gtk_widget_show(menu_bar);
+   
+      gtk_window_set_default_size(GTK_WINDOW(gtk_window), 320, 32);
+      args->menu->extra1 = gtk_window;
+   }
+   
+   gtk_widget_show(args->menu->extra1);
+   
+   al_free(args);
+   
+   return FALSE;
+}
+
+/* [user thread] */
 bool _al_show_display_menu(ALLEGRO_DISPLAY *display, ALLEGRO_MENU *menu)
 {
-   (void) display;
-   (void) menu;
-   return false;
+   DISPLAY_MENU_ARGS *args;
+   
+   if (!ensure_gtk_thread()) {
+      return false;
+   }
+   
+   args = al_malloc(sizeof(*args));
+   if (!args) {
+      return false;
+   }
+   
+   args->display = display;
+   args->menu = menu;
+   
+   g_timeout_add(0, do_show_display_menu, args);
+   
+   return true;
 }
 
+/* [gtk thread] */
+static gboolean do_hide_display_menu(gpointer data)
+{
+   DISPLAY_MENU_ARGS *args = (DISPLAY_MENU_ARGS *) data;
+   
+   gtk_widget_destroy(GTK_WIDGET(args->menu->extra1));
+   args->menu->extra1 = NULL;
+   
+   al_free(args);
+   
+   return FALSE;
+}
+
+/* [user thread] */
 bool _al_hide_display_menu(ALLEGRO_DISPLAY *display, ALLEGRO_MENU *menu)
 {
-   (void) display;
-   (void) menu;
-   return false;
+   DISPLAY_MENU_ARGS *args;
+   
+   args = al_malloc(sizeof(*args));
+   if (!args) {
+      return false;
+   }
+   
+   args->display = display;
+   args->menu = menu;
+   
+   g_timeout_add(0, do_hide_display_menu, args);
+   
+   return true;
 }
 
+
 bool _al_show_popup_menu(ALLEGRO_DISPLAY *display, ALLEGRO_MENU *menu,
    int x, int y, int flags)
 {


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/