ANNOUNCEMENT: Live Wireshark University & Allegro Packets online APAC Wireshark Training Session
July 17th, 2024 | 10:00am-11:55am SGT (UTC+8) | Online

Ethereal-dev: Re: [ethereal-dev] Right button menus

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Guy Harris <gharris@xxxxxxxxxxxx>
Date: Wed, 29 Dec 1999 23:59:38 -0800
> Here are three patches, which all provide right click menus.  The first one
> is just a static menu, which is attached to the packet list and the tree
> view.  The second one does automagic adding of menu items when they are set
> sensitive, but it could cause confusion with the ordering of menu items,
> depending on how it's called.  The third has seperate static menus for each pane.

I'm inclined to prefer the first or third, from the short tests I tried.

I'm not certain which of those two I'd prefer; I'm not sure if it'd make
sense to have different context menus for the different panes or not -
one could argue that "Match Selected", say, belongs only in the pane in
which you'd select an item, but I'm not sure whether it's confusing to
have it in, say, the summary pane.

I tried checking the Mac UI guidelines online to see what they had to
say about right-button context menus, but shortly realized that I was
being an idiot for doing so. :-)  (Hint: how many mouse buttons do most
Macs have?)

The online Windows UI guidelines appear to have disappeared (they
mention a book version); I checked out a couple of books I have:

	Developing User Interfaces for Microsoft Windows

which suggests only if something is available in a context menu, make it
available elsewhere as well (as they're not visible, unlike, say,
menu-bar menus - although only the name of the menu-bar menu is visible
until you pull the menu down, and it might not necessarily be obvious
*which* menu has the operation you want, although one could argue that
means your menus are ill-designed) and seems to imply that the
context-menu items should apply only to the item the mouse is over when
they're selected (one might have "Match" instead of "Match Selected", to
match whatever the mouse is over - but that wouldn't make sense in the
menu bar, so I think we may have Dueling Guidelines here; perhaps they'd
think that "Match Selected" would be in the menu, with "Match" being the
equivalent in the context menu, doing a match on the item the mouse is
over), and

	About Face: The Essentials of User Interface Design

which doesn't discuss context menus directly, but mentions them under
the heading of "the right mouse button", also hinting that they're for
getting properties of, or doing things to, the item under the mouse.

As I remember, Network Monitor offered context-menu items in the
protocol-tree pane such as "Find" (or something such as that), which
finds the next packet where that field has that value, and something to
pop up documentation on the field (which works, as I remember, only for
SMB, as that's the only protocol documentation in the version of NetMon
that I have).

> All three have the problem that the cursor must be above a top-level tree
> item to popup the window.  I suppose that one could attach the menu to the
> lower widgets also, but I didn't try it.  Trying to attach the menu to the
> tv_scrollw had some funky results...

With the latest code, using a CTree, the menus appear to pop up no
matter where you are, and the right mouse button doesn't have the
side-effect of closing a tree item.

I've attached versions of the three patches that apply to the current
CVS tree (which is also the 0.8.0 tree).
Index: gtk/main.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/gtk/main.c,v
retrieving revision 1.77
diff -c -r1.77 main.c
*** main.c	1999/12/29 20:10:10	1.77
--- main.c	1999/12/30 08:01:15
***************
*** 1269,1274 ****
--- 1269,1276 ----
  						pl_style->font);
    }
    gtk_widget_set_usize(packet_list, -1, pl_size);
+   gtk_signal_connect_object(GTK_OBJECT(packet_list), "button_press_event",
+     GTK_SIGNAL_FUNC(popup_menu_handler), GTK_OBJECT(popup_menu_object));
    gtk_widget_show(packet_list);
    
    /* Tree view */
***************
*** 1288,1293 ****
--- 1290,1297 ----
      GTK_SIGNAL_FUNC(tree_view_select_row_cb), NULL);
    gtk_signal_connect(GTK_OBJECT(tree_view), "tree-unselect-row",
      GTK_SIGNAL_FUNC(tree_view_unselect_row_cb), NULL);
+   gtk_signal_connect_object(GTK_OBJECT(tree_view), "button_press_event",
+     GTK_SIGNAL_FUNC(popup_menu_handler), GTK_OBJECT(popup_menu_object));
    gtk_widget_show(tree_view);
  
    item_style = gtk_style_new();
Index: gtk/menu.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/gtk/menu.c,v
retrieving revision 1.12
diff -c -r1.12 menu.c
*** menu.c	1999/12/10 07:04:30	1.12
--- menu.c	1999/12/30 08:01:16
***************
*** 74,79 ****
--- 74,80 ----
                 "<LastBranch>"     -> create a right justified branch 
      */
  
+ /* main menu */
  static GtkItemFactoryEntry menu_items[] =
  {
    {"/_File", NULL, NULL, 0, "<Branch>" },
***************
*** 122,129 ****
--- 123,147 ----
  /* calculate the number of menu_items */
  static int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
  
+ /* packet list popup */
+ static GtkItemFactoryEntry popup_menu_items[] =
+ {
+ 	{"/Match Selected", NULL, GTK_MENU_FUNC(match_selected_cb), 0, NULL},
+ 	{"/Follow TCP Stream", NULL, GTK_MENU_FUNC(follow_stream_cb), 0, NULL},
+ 	{"/Filters...", NULL, GTK_MENU_FUNC(filter_dialog_cb), 0, NULL},
+ 	{"/<separator>", NULL, NULL, 0, "<Separator>"},
+ 	{"/Colorize Display...", NULL, GTK_MENU_FUNC(color_display_cb), 0, NULL},
+ 	{"/Print...", NULL, GTK_MENU_FUNC(file_print_cmd_cb), 0, NULL},
+   	{"/Print Packet", NULL, GTK_MENU_FUNC(file_print_packet_cmd_cb), 0, NULL},
+ 	{"/<separator>", NULL, NULL, 0, "<Separator>"},
+ 	{"/Collapse All", NULL, GTK_MENU_FUNC(collapse_all_cb), 0, NULL},
+ 	{"/Expand All", NULL, GTK_MENU_FUNC(expand_all_cb), 0, NULL}
+ };
+ 
+ 
  static int initialize = TRUE;
  static GtkItemFactory *factory = NULL;
+ static GtkItemFactory *popup_menu_factory;
  
  void
  get_main_menu(GtkWidget ** menubar, GtkAccelGroup ** table) {
***************
*** 147,153 ****
--- 165,174 ----
      initialize = FALSE;
  
      factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", grp);
+     popup_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
      gtk_item_factory_create_items_ac(factory, nmenu_items, menu_items, NULL,2);
+     gtk_item_factory_create_items_ac(popup_menu_factory, sizeof(popup_menu_items)/sizeof(popup_menu_items[0]), popup_menu_items, NULL,2);
+     popup_menu_object = popup_menu_factory->widget;
      set_menu_sensitivity("/File/Close", FALSE);
      set_menu_sensitivity("/File/Save", FALSE);
      set_menu_sensitivity("/File/Save As...", FALSE);
***************
*** 173,189 ****
--- 194,237 ----
  void
  set_menu_sensitivity (gchar *path, gint val) {
    GtkWidget *menu;
+   gchar *shortpath = rindex(path, '/');
  
    if ((menu = gtk_item_factory_get_widget(factory, path)) != NULL)
      gtk_widget_set_sensitive(menu, val);
+   
+   if ((menu = gtk_item_factory_get_widget(popup_menu_factory, shortpath)) != NULL)
+     gtk_widget_set_sensitive(menu, val);
  }
  
  void
  set_menu_object_data (gchar *path, gchar *key, gpointer data) {
    GtkWidget *menu;
+   gchar *shortpath = rindex(path, '/');
    
    if ((menu = gtk_item_factory_get_widget(factory, path)) != NULL)
      gtk_object_set_data(GTK_OBJECT(menu), key, data);
+   
+   if ((menu = gtk_item_factory_get_widget(popup_menu_factory, shortpath)) != NULL)
+     gtk_object_set_data(GTK_OBJECT(menu), key, data);
+     
  }
  
+ void
+ popup_menu_handler(GtkWidget *widget, GdkEvent *event)
+ {
+ 	GtkWidget *menu = NULL;
+ 	GdkEventButton *event_button = NULL;
  
+ 	if(widget == NULL || event == NULL) {
+ 		return;
+ 	}
+ 	
+ 	menu = widget;
+ 	if(event->type == GDK_BUTTON_PRESS) {
+ 		event_button = (GdkEventButton *) event;
+ 		
+ 		if(event_button->button == 3) {
+ 			gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, event_button->button, event_button->time);
+ 		}
+ 	}
+ }
Index: gtk/menu.h
===================================================================
RCS file: /usr/local/cvsroot/ethereal/gtk/menu.h,v
retrieving revision 1.1
diff -c -r1.1 menu.h
*** menu.h	1999/09/01 03:04:23	1.1
--- menu.h	1999/12/30 08:01:16
***************
*** 38,44 ****
--- 38,46 ----
  void set_menu_sensitivity (gchar *, gint);
  void set_menu_object_data (gchar *path, gchar *key, gpointer data);
  void menus_create (GtkMenuEntry *, int);
+ void popup_menu_handler(GtkWidget *widget, GdkEvent *event);
  
+ GtkWidget           *popup_menu_object;
  
  #ifdef __cplusplus
  }
Index: file.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/file.c,v
retrieving revision 1.143
diff -c -r1.143 file.c
*** file.c	1999/12/29 20:09:45	1.143
--- file.c	1999/12/30 08:02:19
***************
*** 323,330 ****
    cf->fh = filed_open(cf->filed, "r");
    cf->unfiltered_count = cf->count;
    cf->current_frame = cf->first_displayed;
-   /* Make the first row the selected row. */
-   gtk_clist_select_row(GTK_CLIST(packet_list), 0, -1);
    thaw_clist(cf);
  
    gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
--- 323,328 ----
***************
*** 349,354 ****
--- 347,355 ----
    set_menu_sensitivity("/Display/Go To Frame...", TRUE);
    set_menu_sensitivity("/Tools/Graph", TRUE);
    set_menu_sensitivity("/Tools/Summary", TRUE);
+ 
+   /* Make the first row the selected row. */
+   gtk_signal_emit_by_name(GTK_OBJECT(packet_list), "select_row", 0);
  
    if (!success) {
      /* Put up a message box noting that the read failed somewhere along
Index: gtk/main.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/gtk/main.c,v
retrieving revision 1.77
diff -c -r1.77 main.c
*** main.c	1999/12/29 20:10:10	1.77
--- main.c	1999/12/30 08:02:23
***************
*** 1269,1274 ****
--- 1269,1276 ----
  						pl_style->font);
    }
    gtk_widget_set_usize(packet_list, -1, pl_size);
+   gtk_signal_connect_object(GTK_OBJECT(packet_list), "button_press_event",
+     GTK_SIGNAL_FUNC(popup_menu_handler), GTK_OBJECT(popup_menu_object));
    gtk_widget_show(packet_list);
    
    /* Tree view */
***************
*** 1288,1293 ****
--- 1290,1297 ----
      GTK_SIGNAL_FUNC(tree_view_select_row_cb), NULL);
    gtk_signal_connect(GTK_OBJECT(tree_view), "tree-unselect-row",
      GTK_SIGNAL_FUNC(tree_view_unselect_row_cb), NULL);
+   gtk_signal_connect_object(GTK_OBJECT(tree_view), "button_press_event",
+     GTK_SIGNAL_FUNC(popup_menu_handler), GTK_OBJECT(popup_menu_object));
    gtk_widget_show(tree_view);
  
    item_style = gtk_style_new();
Index: gtk/menu.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/gtk/menu.c,v
retrieving revision 1.12
diff -c -r1.12 menu.c
*** menu.c	1999/12/10 07:04:30	1.12
--- menu.c	1999/12/30 08:02:24
***************
*** 74,79 ****
--- 74,80 ----
                 "<LastBranch>"     -> create a right justified branch 
      */
  
+ /* main menu */
  static GtkItemFactoryEntry menu_items[] =
  {
    {"/_File", NULL, NULL, 0, "<Branch>" },
***************
*** 122,129 ****
--- 123,145 ----
  /* calculate the number of menu_items */
  static int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
  
+ /* packet list popup */
+ static GtkItemFactoryEntry popup_menu_items[] =
+ {
+ 	{"/Match Selected", NULL, GTK_MENU_FUNC(match_selected_cb), 0, NULL},
+ 	{"/Follow TCP Stream", NULL, GTK_MENU_FUNC(follow_stream_cb), 0, NULL},
+ 	{"/Filters...", NULL, GTK_MENU_FUNC(filter_dialog_cb), 0, NULL},
+ 	{"/Colorize Display...", NULL, GTK_MENU_FUNC(color_display_cb), 0, NULL},
+ 	{"/Print...", NULL, GTK_MENU_FUNC(file_print_cmd_cb), 0, NULL},
+   	{"/Print Packet", NULL, GTK_MENU_FUNC(file_print_packet_cmd_cb), 0, NULL},
+ 	{"/Collapse All", NULL, GTK_MENU_FUNC(collapse_all_cb), 0, NULL},
+ 	{"/Expand All", NULL, GTK_MENU_FUNC(expand_all_cb), 0, NULL}
+ };
+ 
+ 
  static int initialize = TRUE;
  static GtkItemFactory *factory = NULL;
+ static GtkItemFactory *popup_menu_factory;
  
  void
  get_main_menu(GtkWidget ** menubar, GtkAccelGroup ** table) {
***************
*** 146,151 ****
--- 162,171 ----
    if (initialize) {
      initialize = FALSE;
  
+     /* popup */
+     popup_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
+     popup_menu_object = popup_menu_factory->widget;
+     
      factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", grp);
      gtk_item_factory_create_items_ac(factory, nmenu_items, menu_items, NULL,2);
      set_menu_sensitivity("/File/Close", FALSE);
***************
*** 167,189 ****
--- 187,254 ----
      set_menu_sensitivity("/Tools/Follow TCP Stream", FALSE);
      set_menu_sensitivity("/Tools/Graph", FALSE);
      set_menu_sensitivity("/Tools/Summary", FALSE);
+     /* popup items have to be explicitly set to true */
+     set_menu_sensitivity("/Edit/Filters...", TRUE);
    }
  }
  
  void
  set_menu_sensitivity (gchar *path, gint val) {
    GtkWidget *menu;
+   gchar *shortpath = rindex(path, '/');
  
    if ((menu = gtk_item_factory_get_widget(factory, path)) != NULL)
      gtk_widget_set_sensitive(menu, val);
+   
+   if ((menu = gtk_item_factory_get_widget(popup_menu_factory, shortpath)) != NULL) {
+   	if(val == FALSE) {
+ 		gtk_item_factory_delete_item(popup_menu_factory, shortpath);
+ 	} else {
+ 		gtk_widget_set_sensitive(menu, val);
+ 	}
+   } else if (val == TRUE) {
+   	GtkItemFactoryEntry *newitem = NULL;
+ 	int i = 0;
+ 
+ 	for (i = 0; i < (sizeof(popup_menu_items)/sizeof(popup_menu_items[0])); i++) {
+ 		newitem = &popup_menu_items[i];
+ 		if(strcmp(shortpath, newitem->path) == 0) {
+ 			gtk_item_factory_create_item(popup_menu_factory, newitem, NULL, 2);
+ 			break;
+ 		}
+ 	}
+   }
  }
  
  void
  set_menu_object_data (gchar *path, gchar *key, gpointer data) {
    GtkWidget *menu;
+   gchar *shortpath = rindex(path, '/');
    
    if ((menu = gtk_item_factory_get_widget(factory, path)) != NULL)
      gtk_object_set_data(GTK_OBJECT(menu), key, data);
+   
+   if ((menu = gtk_item_factory_get_widget(popup_menu_factory, shortpath)) != NULL)
+     gtk_object_set_data(GTK_OBJECT(menu), key, data);
+     
  }
  
+ void
+ popup_menu_handler(GtkWidget *widget, GdkEvent *event)
+ {
+ 	GtkWidget *menu = NULL;
+ 	GdkEventButton *event_button = NULL;
  
+ 	if(widget == NULL || event == NULL) {
+ 		return;
+ 	}
+ 	
+ 	menu = widget;
+ 	if(event->type == GDK_BUTTON_PRESS) {
+ 		event_button = (GdkEventButton *) event;
+ 		
+ 		if(event_button->button == 3) {
+ 			gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, event_button->button, event_button->time);
+ 		}
+ 	}
+ }
Index: gtk/menu.h
===================================================================
RCS file: /usr/local/cvsroot/ethereal/gtk/menu.h,v
retrieving revision 1.1
diff -c -r1.1 menu.h
*** menu.h	1999/09/01 03:04:23	1.1
--- menu.h	1999/12/30 08:02:24
***************
*** 38,44 ****
--- 38,46 ----
  void set_menu_sensitivity (gchar *, gint);
  void set_menu_object_data (gchar *path, gchar *key, gpointer data);
  void menus_create (GtkMenuEntry *, int);
+ void popup_menu_handler(GtkWidget *widget, GdkEvent *event);
  
+ GtkWidget           *popup_menu_object;
  
  #ifdef __cplusplus
  }
Index: file.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/file.c,v
retrieving revision 1.143
diff -c -r1.143 file.c
*** file.c	1999/12/29 20:09:45	1.143
--- file.c	1999/12/30 08:03:49
***************
*** 323,330 ****
    cf->fh = filed_open(cf->filed, "r");
    cf->unfiltered_count = cf->count;
    cf->current_frame = cf->first_displayed;
-   /* Make the first row the selected row. */
-   gtk_clist_select_row(GTK_CLIST(packet_list), 0, -1);
    thaw_clist(cf);
  
    gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
--- 323,328 ----
***************
*** 349,354 ****
--- 347,355 ----
    set_menu_sensitivity("/Display/Go To Frame...", TRUE);
    set_menu_sensitivity("/Tools/Graph", TRUE);
    set_menu_sensitivity("/Tools/Summary", TRUE);
+ 
+   /* Make the first row the selected row. */
+   gtk_signal_emit_by_name(GTK_OBJECT(packet_list), "select_row", 0);
  
    if (!success) {
      /* Put up a message box noting that the read failed somewhere along
Index: gtk/keys.h
===================================================================
RCS file: /usr/local/cvsroot/ethereal/gtk/keys.h,v
retrieving revision 1.8
diff -c -r1.8 keys.h
*** keys.h	1999/12/09 20:41:41	1.8
--- keys.h	1999/12/30 08:03:50
***************
*** 41,44 ****
--- 41,48 ----
  
  #define PLUGINS_DFILTER_TE        "plugins_dfilter_te"
  
+ #define PM_MENU_LIST_KEY	  "popup_menu_menu_list"
+ #define PM_PACKET_LIST_KEY	  "popup_menu_packet_list"
+ #define PM_TREE_VIEW_KEY	  "popup_menu_tree_view"
+ 
  #endif
Index: gtk/main.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/gtk/main.c,v
retrieving revision 1.77
diff -c -r1.77 main.c
*** main.c	1999/12/29 20:10:10	1.77
--- main.c	1999/12/30 08:03:53
***************
*** 1269,1274 ****
--- 1269,1276 ----
  						pl_style->font);
    }
    gtk_widget_set_usize(packet_list, -1, pl_size);
+   gtk_signal_connect_object(GTK_OBJECT(packet_list), "button_press_event",
+     GTK_SIGNAL_FUNC(popup_menu_handler), gtk_object_get_data(GTK_OBJECT(popup_menu_object), PM_PACKET_LIST_KEY));
    gtk_widget_show(packet_list);
    
    /* Tree view */
***************
*** 1288,1293 ****
--- 1290,1297 ----
      GTK_SIGNAL_FUNC(tree_view_select_row_cb), NULL);
    gtk_signal_connect(GTK_OBJECT(tree_view), "tree-unselect-row",
      GTK_SIGNAL_FUNC(tree_view_unselect_row_cb), NULL);
+   gtk_signal_connect_object(GTK_OBJECT(tree_view), "button_press_event",
+     GTK_SIGNAL_FUNC(popup_menu_handler), gtk_object_get_data(GTK_OBJECT(popup_menu_object), PM_TREE_VIEW_KEY));
    gtk_widget_show(tree_view);
  
    item_style = gtk_style_new();
Index: gtk/menu.c
===================================================================
RCS file: /usr/local/cvsroot/ethereal/gtk/menu.c,v
retrieving revision 1.12
diff -c -r1.12 menu.c
*** menu.c	1999/12/10 07:04:30	1.12
--- menu.c	1999/12/30 08:03:54
***************
*** 28,33 ****
--- 28,34 ----
  #endif
  
  #include <gtk/gtk.h>
+ #include <glib.h>
  
  #include <string.h>
  #include <stdio.h>
***************
*** 48,53 ****
--- 49,55 ----
  #include "print.h"
  #include "follow.h"
  #include "colors.h"
+ #include "keys.h"
  
  
  GtkAccelGroup *grp;
***************
*** 74,79 ****
--- 76,82 ----
                 "<LastBranch>"     -> create a right justified branch 
      */
  
+ /* main menu */
  static GtkItemFactoryEntry menu_items[] =
  {
    {"/_File", NULL, NULL, 0, "<Branch>" },
***************
*** 122,137 ****
  /* calculate the number of menu_items */
  static int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
  
  static int initialize = TRUE;
  static GtkItemFactory *factory = NULL;
  
  void
  get_main_menu(GtkWidget ** menubar, GtkAccelGroup ** table) {
  
    grp = gtk_accel_group_new();
  
!   if (initialize)
      menus_init();
  
    if (menubar)
      *menubar = factory->widget;
--- 125,172 ----
  /* calculate the number of menu_items */
  static int nmenu_items = sizeof(menu_items) / sizeof(menu_items[0]);
  
+ /* packet list popup */
+ static GtkItemFactoryEntry packet_list_menu_items[] =
+ {
+ 	{"/Match Selected", NULL, GTK_MENU_FUNC(match_selected_cb), 0, NULL},
+ 	{"/Follow TCP Stream", NULL, GTK_MENU_FUNC(follow_stream_cb), 0, NULL},
+ 	{"/Filters...", NULL, GTK_MENU_FUNC(filter_dialog_cb), 0, NULL},
+ 	{"/<separator>", NULL, NULL, 0, "<Separator>"},
+ 	{"/Colorize Display...", NULL, GTK_MENU_FUNC(color_display_cb), 0, NULL},
+ 	{"/Print...", NULL, GTK_MENU_FUNC(file_print_cmd_cb), 0, NULL},
+   	{"/Print Packet", NULL, GTK_MENU_FUNC(file_print_packet_cmd_cb), 0, NULL},
+ 	{"/<separator>", NULL, NULL, 0, "<Separator>"},
+ 	{"/Collapse All", NULL, GTK_MENU_FUNC(collapse_all_cb), 0, NULL},
+ 	{"/Expand All", NULL, GTK_MENU_FUNC(expand_all_cb), 0, NULL}
+ };
+ 
+ static GtkItemFactoryEntry tree_view_menu_items[] =
+ {
+ 	{"/Match Selected", NULL, GTK_MENU_FUNC(match_selected_cb), 0, NULL},
+ 	{"/Follow TCP Stream", NULL, GTK_MENU_FUNC(follow_stream_cb), 0, NULL},
+ 	{"/Filters...", NULL, GTK_MENU_FUNC(filter_dialog_cb), 0, NULL},
+ 	{"/<separator>", NULL, NULL, 0, "<Separator>"},
+ 	{"/Collapse All", NULL, GTK_MENU_FUNC(collapse_all_cb), 0, NULL},
+ 	{"/Expand All", NULL, GTK_MENU_FUNC(expand_all_cb), 0, NULL}
+ };
+ 
+ 
  static int initialize = TRUE;
  static GtkItemFactory *factory = NULL;
+ static GtkItemFactory *packet_list_menu_factory = NULL;
+ static GtkItemFactory *tree_view_menu_factory = NULL;
  
+ static GSList *popup_menu_list = NULL;
+ 
  void
  get_main_menu(GtkWidget ** menubar, GtkAccelGroup ** table) {
  
    grp = gtk_accel_group_new();
  
!   if (initialize) {
!     popup_menu_object = gtk_widget_new(GTK_TYPE_WIDGET, NULL);
      menus_init();
+   }
  
    if (menubar)
      *menubar = factory->widget;
***************
*** 146,151 ****
--- 181,198 ----
    if (initialize) {
      initialize = FALSE;
  
+     /* popup */
+ 
+     packet_list_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
+     gtk_item_factory_create_items_ac(packet_list_menu_factory, sizeof(packet_list_menu_items)/sizeof(packet_list_menu_items[0]), packet_list_menu_items, NULL, 2);
+     gtk_object_set_data(GTK_OBJECT(popup_menu_object), PM_PACKET_LIST_KEY, packet_list_menu_factory->widget);
+     popup_menu_list = g_slist_append((GSList *)popup_menu_list, packet_list_menu_factory);
+ 
+     tree_view_menu_factory = gtk_item_factory_new(GTK_TYPE_MENU, "<main>", NULL);
+     gtk_item_factory_create_items_ac(tree_view_menu_factory, sizeof(tree_view_menu_items)/sizeof(tree_view_menu_items[0]), tree_view_menu_items, NULL, 2);
+     gtk_object_set_data(GTK_OBJECT(popup_menu_object), PM_TREE_VIEW_KEY, packet_list_menu_factory->widget);
+     popup_menu_list = g_slist_append((GSList *)popup_menu_list, tree_view_menu_factory);
+     
      factory = gtk_item_factory_new(GTK_TYPE_MENU_BAR, "<main>", grp);
      gtk_item_factory_create_items_ac(factory, nmenu_items, menu_items, NULL,2);
      set_menu_sensitivity("/File/Close", FALSE);
***************
*** 171,189 ****
  }
  
  void
  set_menu_sensitivity (gchar *path, gint val) {
!   GtkWidget *menu;
  
!   if ((menu = gtk_item_factory_get_widget(factory, path)) != NULL)
!     gtk_widget_set_sensitive(menu, val);
  }
  
  void
  set_menu_object_data (gchar *path, gchar *key, gpointer data) {
!   GtkWidget *menu;
    
!   if ((menu = gtk_item_factory_get_widget(factory, path)) != NULL)
!     gtk_object_set_data(GTK_OBJECT(menu), key, data);
  }
  
  
--- 218,283 ----
  }
  
  void
+ set_menu_sensitivity_meat(GtkItemFactory *ifactory, gchar *path, gint val) {
+ 	GtkWidget *menu = NULL;
+ 	
+ 	if((menu = gtk_item_factory_get_widget(ifactory, path)) != NULL) {
+ 		gtk_widget_set_sensitive(menu,val);
+ 	}
+ }
+ 
+ void
  set_menu_sensitivity (gchar *path, gint val) {
!   GSList *menu_list = popup_menu_list;
!   gchar *shortpath = rindex(path, '/');
! 
!   set_menu_sensitivity_meat(factory, path, val);
  
!   while (menu_list != NULL) {
!   	set_menu_sensitivity_meat(menu_list->data, shortpath, val);
! 	menu_list = g_slist_next(menu_list);
!   }
!   
  }
  
  void
+ set_menu_object_data_meat(GtkItemFactory *ifactory, gchar *path, gchar *key, gpointer data)
+ {
+ 	GtkWidget *menu = NULL;
+ 	
+ 	if ((menu = gtk_item_factory_get_widget(ifactory, path)) != NULL)
+ 		gtk_object_set_data(GTK_OBJECT(menu), key, data);
+ }
+ 
+ void
  set_menu_object_data (gchar *path, gchar *key, gpointer data) {
!   GSList *menu_list = popup_menu_list;
!   gchar *shortpath = rindex(path, '/');
    
!   set_menu_object_data_meat(factory, path, key, data);
! 
!   while (menu_list != NULL) {
!   	set_menu_object_data_meat(menu_list->data, shortpath, key, data);
! 	menu_list = g_slist_next(menu_list);
!   }
  }
  
+ void
+ popup_menu_handler(GtkWidget *widget, GdkEvent *event)
+ {
+ 	GtkWidget *menu = NULL;
+ 	GdkEventButton *event_button = NULL;
  
+ 	if(widget == NULL || event == NULL) {
+ 		return;
+ 	}
+ 	
+ 	menu = widget;
+ 	if(event->type == GDK_BUTTON_PRESS) {
+ 		event_button = (GdkEventButton *) event;
+ 		
+ 		if(event_button->button == 3) {
+ 			gtk_menu_popup(GTK_MENU(menu), NULL, NULL, NULL, NULL, event_button->button, event_button->time);
+ 		}
+ 	}
+ }
Index: gtk/menu.h
===================================================================
RCS file: /usr/local/cvsroot/ethereal/gtk/menu.h,v
retrieving revision 1.1
diff -c -r1.1 menu.h
*** menu.h	1999/09/01 03:04:23	1.1
--- menu.h	1999/12/30 08:03:54
***************
*** 38,44 ****
--- 38,46 ----
  void set_menu_sensitivity (gchar *, gint);
  void set_menu_object_data (gchar *path, gchar *key, gpointer data);
  void menus_create (GtkMenuEntry *, int);
+ void popup_menu_handler(GtkWidget *widget, GdkEvent *event);
  
+ GtkWidget           *popup_menu_object;
  
  #ifdef __cplusplus
  }