Index: src/menu.c =================================================================== RCS file: /cvsroot/xfce/xfce-devel/xfdesktop/src/menu.c,v retrieving revision 1.27 diff -u -u -r1.27 menu.c --- src/menu.c 8 Oct 2003 08:21:24 -0000 1.27 +++ src/menu.c 21 Oct 2003 09:47:35 -0000 @@ -58,13 +58,20 @@ SYSCONFDIR G_DIR_SEPARATOR_S "xfce4" G_DIR_SEPARATOR_S "%F.%l:"\ SYSCONFDIR G_DIR_SEPARATOR_S "xfce4" G_DIR_SEPARATOR_S "%F") +/* search path for menu icons */ +#define ICONSEARCHPATH { "/usr/share/pixmaps", "/usr/local/share/pixmaps", \ + "/usr/share/icons", "/usr/local/share/icons", NULL } + +/* icon suffixes to use when we aren't supplied with one */ +#define ICONSUFFIXES { "png", "xpm", "gif", "jpg", NULL }; + /* a bit hackish, but works well enough */ static gboolean is_using_system_rc = TRUE; static NetkScreen *netk_screen = NULL; static GList *MainMenuData; /* TODO: Free this at some point */ static gboolean EditMode = FALSE; -static GtkItemFactory *ifactory = NULL; /* TODO: Is this really necessary? */ +static GtkWidget *TheMainMenu = NULL; /* User menu * --------- @@ -75,7 +82,8 @@ MI_SEPARATOR, MI_SUBMENU, MI_TITLE, - MI_BUILTIN + MI_BUILTIN, + MI_SUBMENU_END } MenuItemType; @@ -89,12 +97,6 @@ } MenuItem; -void remove_factory_item(MenuItem *mi, GtkItemFactory *ifact) -{ - TRACE("dummy"); - gtk_item_factory_delete_item(ifact, mi->path); -} - void free_menu_data(GList * menu_data) { MenuItem *mi; @@ -116,6 +118,10 @@ g_free(mi->cmd); } g_free(mi); + if(mi->icon) + { + g_object_unref(mi->icon); + } } } g_list_free(menu_data); @@ -125,6 +131,7 @@ void do_exec(gpointer callback_data, guint callback_action, GtkWidget * widget) { TRACE("dummy"); + g_spawn_command_line_async((char *)callback_data, NULL); } @@ -154,9 +161,11 @@ EditMode = (EditMode ? FALSE : TRUE); /* Need to rebuild menu, so destroy the current one */ - g_list_foreach(MainMenuData, (GFunc)remove_factory_item, ifactory); + if(TheMainMenu) { + gtk_widget_destroy(TheMainMenu); + TheMainMenu = NULL; + } free_menu_data(MainMenuData); - ifactory = NULL; MainMenuData = NULL; } else if (!strcmp(builtin, "quit")) @@ -171,9 +180,11 @@ EditMode = FALSE; /* Need to rebuild menu, so destroy the current one */ - g_list_foreach(MainMenuData, (GFunc)remove_factory_item, ifactory); + if(TheMainMenu) { + gtk_widget_destroy(TheMainMenu); + TheMainMenu = NULL; + } free_menu_data(MainMenuData); - ifactory = NULL; MainMenuData = NULL; } @@ -227,6 +238,7 @@ xmlChar *cmd = NULL; xmlChar *term = NULL; xmlChar *visible = NULL; + xmlChar *icon = NULL; TRACE("dummy"); @@ -270,8 +282,56 @@ mi->term = FALSE; } + icon = xmlGetProp(cur, "icon"); + if(icon) { + char iconfile[1024]; + *iconfile = 0; + + if(icon[0]!='/') { + char *iconpaths[] = ICONSEARCHPATH; + int i; + struct stat st; + + for(i=0; iconpaths[i]; i++) { + if(!strchr(icon, '.')) { + char *iconsuffixes[] = ICONSUFFIXES; + int j; + + for(j=0; iconsuffixes[j]; j++) { + snprintf(iconfile, 1024, "%s/%s.%s", iconpaths[i], icon, iconsuffixes[j]); + if(!stat(iconfile, &st)) + break; + else + *iconfile = 0; + } + if(*iconfile) + break; + } else { + snprintf(iconfile, 1024, "%s/%s", iconpaths[i], icon); + if(!stat(iconfile, &st)) + break; + else + *iconfile = 0; + } + } + } else { + struct stat st; + snprintf(iconfile, 1024, icon); + if(stat(iconfile, &st)) + *iconfile = 0; + } + + if(!*iconfile) + mi->icon = NULL; + else { + GdkPixbuf *tmp = gdk_pixbuf_new_from_file(iconfile, NULL); + mi->icon = gdk_pixbuf_scale_simple(tmp, 16, 16, GDK_INTERP_BILINEAR); + g_object_unref(G_OBJECT(tmp)); + } + } else + mi->icon = NULL; + mi->type = type; - mi->icon = NULL; /* TODO: Load a pixbuf from icon filename */ /* clean up */ if(visible) @@ -285,6 +345,9 @@ if(term) xmlFree(term); + + if(icon) + xmlFree(icon); return mi; } @@ -304,10 +367,16 @@ mi = parse_node_attr(MI_SUBMENU, doc, cur, path); if(mi) { + MenuItem *mi1; + menu_data = g_list_append(menu_data, mi); /* recurse */ menu_data = parse_menu_node(doc, cur, mi->path, menu_data); + + mi1 = g_new0(MenuItem, 1); + mi1->type = MI_SUBMENU_END; + menu_data = g_list_append(menu_data, mi1); } } if((!xmlStrcmp(cur->name, (const xmlChar *)"app"))) @@ -398,72 +467,72 @@ return menu_data; } -GtkItemFactoryEntry parse_item(MenuItem * item) +static GtkWidget *create_submenu(GList **menu_data) { - GtkItemFactoryEntry t; - - DBG("%s (type=%d) (term=%d)\n", item->path, item->type, item->term); - - t.path = item->path; - t.accelerator = NULL; - t.callback_action = 1; /* non-zero ! */ - - /* disable for now - t.extra_data = item->icon; */ - - if (!EditMode) - { - switch (item->type) - { - case MI_APP: - t.callback = (item->term ? do_term_exec : do_exec); - t.item_type = ""; - break; - case MI_SEPARATOR: - t.callback = NULL; - t.item_type = ""; - break; - case MI_SUBMENU: - t.callback = NULL; - t.item_type = ""; - break; - case MI_TITLE: - t.callback = NULL; - t.item_type = ""; - break; - case MI_BUILTIN: - t.callback = do_builtin; - t.item_type = "<Item>"; - break; - default: - break; - } - } - else - { - t.callback = do_edit; - - if (item->type == MI_SUBMENU) - t.item_type = "<Branch>"; - else - t.item_type = "<Item>"; - - if (item->type == MI_SEPARATOR) - { - gchar *parent_menu; - - parent_menu = g_path_get_dirname(item->path); - g_free(item->path); - item->path = g_strconcat(parent_menu, "--- seperator ---", NULL); - t.path = item->path; - - g_free(parent_menu); - } - } - - return t; + GtkWidget *submenu = gtk_menu_new(); + MenuItem *item = NULL; + GList *li; + GtkWidget *lastitem = NULL; + gboolean new_submenu = FALSE; + + if(!menu_data || !*menu_data) + return NULL; + + for(li=*menu_data; li; li=li->next) { + GtkWidget *mi = NULL; + gchar *itemname = NULL; + + item = (MenuItem *) li->data; + + g_assert(item != NULL); + + if(item->type==MI_SUBMENU_END) { + /* we've hit the end of this submenu, return what we've got */ + DBG("(end of submenu) (type=%d) (term=%d)\n", item->type, item->term); + *menu_data = li; + break; + } else { + DBG("%s (type=%d) (term=%d)\n", item->path, item->type, item->term); + + itemname = g_strrstr(item->path, "/") + 1; + if(itemname==(gchar *)1 || !*itemname) + continue; + + if(item->type==MI_SUBMENU) { + /* submenu, recurse */ + mi = gtk_menu_item_new_with_label(itemname); + *menu_data = li->next; + gtk_menu_item_set_submenu(GTK_MENU_ITEM(mi), create_submenu(menu_data)); + li = *menu_data; + } else if(item->type==MI_SEPARATOR) + mi = gtk_separator_menu_item_new(); + else if(item->icon) { + GtkWidget *img; + mi = gtk_image_menu_item_new_with_label(itemname); + img = gtk_image_new_from_pixbuf(item->icon); + gtk_widget_show(img); + gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(mi), img); + } else + mi = gtk_menu_item_new_with_label(itemname); + + if(item->type==MI_APP) + g_signal_connect_swapped(G_OBJECT(mi), "activate", + G_CALLBACK((item->term ? do_term_exec : do_exec)), + item->cmd); + else if(item->type==MI_BUILTIN) + g_signal_connect_swapped(G_OBJECT(mi), "activate", + G_CALLBACK(do_builtin), item->cmd); + else if(item->type==MI_TITLE) + gtk_widget_set_sensitive(mi, FALSE); + } + + gtk_widget_show(mi); + gtk_menu_shell_append(GTK_MENU_SHELL(submenu), mi); + } + + return submenu; } - + /* returns the menu widget */ static GtkWidget *create_desktop_menu(void) { @@ -501,20 +570,17 @@ return NULL; } - if (!ifactory || !MainMenuData || ctime < st.st_ctime) + if (!TheMainMenu || !MainMenuData || ctime < st.st_ctime) { - GtkItemFactoryEntry entry; - MenuItem *item = NULL; - GList *li, *menu_data = NULL; + GList *menu_data = NULL; - if (!ifactory) - ifactory = gtk_item_factory_new(GTK_TYPE_MENU, "<popup>", NULL); + if(TheMainMenu) { + gtk_widget_destroy(TheMainMenu); + TheMainMenu = NULL; + } if (MainMenuData) - { - g_list_foreach(MainMenuData, (GFunc)remove_factory_item, ifactory); free_menu_data(MainMenuData); - } /* * TODO: Replace the following line with code to call multiple @@ -527,34 +593,18 @@ PACKAGE, filename); } - for(li = menu_data; li; li = li->next) - { - /* parse current item */ - item = (MenuItem *) li->data; - - g_assert(item != NULL); - - entry = parse_item(item); - - if (!EditMode) - { - gtk_item_factory_create_item(ifactory, &entry, item->cmd, 1); - } - else - { - gtk_item_factory_create_item(ifactory, &entry, item, 1); - } - } - + /* create the menu */ + MainMenuData = menu_data; + TheMainMenu = create_submenu(&menu_data); + /* clean up */ /* free_menu_data(menu_data); */ /* Hmmm ... if you do this the menus don't work */ /* Lets save it in a global var and worry about it later */ - MainMenuData = menu_data; ctime = st.st_ctime; } - return gtk_item_factory_get_widget(ifactory, "<popup>"); + return TheMainMenu; } /* Window list menu