comparison src/menubar-gtk.c @ 2081:e8db6a10ad42

[xemacs-hg @ 2004-05-15 07:31:43 by malcolmp] Added support for Gtk menu bar, menu item and dialog button mnemonics.
author malcolmp
date Sat, 15 May 2004 07:31:49 +0000
parents 91d4c8c65a0f
children 95fee4a1420e
comparison
equal deleted inserted replaced
2080:ebba17579ace 2081:e8db6a10ad42
1 /* Implements an elisp-programmable menubar -- X interface. 1 /* Implements an elisp-programmable menubar -- Gtk interface.
2 Copyright (C) 1993, 1994 Free Software Foundation, Inc. 2 Copyright (C) 1993, 1994 Free Software Foundation, Inc.
3 Copyright (C) 1995 Tinker Systems and INS Engineering Corp. 3 Copyright (C) 1995 Tinker Systems and INS Engineering Corp.
4 Copyright (C) 2002, 2003 Ben Wing. 4 Copyright (C) 2002, 2003 Ben Wing.
5 5
6 This file is part of XEmacs. 6 This file is part of XEmacs.
47 47
48 #define MENUBAR_TYPE 0 48 #define MENUBAR_TYPE 0
49 #define SUBMENU_TYPE 1 49 #define SUBMENU_TYPE 1
50 #define POPUP_TYPE 2 50 #define POPUP_TYPE 2
51 51
52 static GtkWidget *menu_descriptor_to_widget_1 (Lisp_Object descr); 52 static GtkWidget *menu_descriptor_to_widget_1 (Lisp_Object descr, GtkAccelGroup* accel_group);
53 53
54 #define FRAME_GTK_MENUBAR_DATA(f) (FRAME_GTK_DATA (f)->menubar_data) 54 #define FRAME_GTK_MENUBAR_DATA(f) (FRAME_GTK_DATA (f)->menubar_data)
55 #define XFRAME_GTK_MENUBAR_DATA_LASTBUFF(f) XCAR (FRAME_GTK_MENUBAR_DATA (f)) 55 #define XFRAME_GTK_MENUBAR_DATA_LASTBUFF(f) XCAR (FRAME_GTK_MENUBAR_DATA (f))
56 #define XFRAME_GTK_MENUBAR_DATA_UPTODATE(f) XCDR (FRAME_GTK_MENUBAR_DATA (f)) 56 #define XFRAME_GTK_MENUBAR_DATA_UPTODATE(f) XCDR (FRAME_GTK_MENUBAR_DATA (f))
57 57
111 } 111 }
112 112
113 return xemacs_menubar_type; 113 return xemacs_menubar_type;
114 } 114 }
115 115
116 static GtkWidgetClass *parent_class; 116 static GtkWidgetClass *menubar_parent_class;
117 117
118 static void 118 static void
119 gtk_xemacs_menubar_class_init (GtkXEmacsMenubarClass *klass) 119 gtk_xemacs_menubar_class_init (GtkXEmacsMenubarClass *klass)
120 { 120 {
121 GtkWidgetClass *widget_class; 121 GtkWidgetClass *widget_class;
122 122
123 widget_class = (GtkWidgetClass*) klass; 123 widget_class = (GtkWidgetClass*) klass;
124 parent_class = (GtkWidgetClass *) gtk_type_class (gtk_menu_bar_get_type ()); 124 menubar_parent_class = (GtkWidgetClass *) gtk_type_class (gtk_menu_bar_get_type ());
125 125
126 widget_class->size_request = gtk_xemacs_menubar_size_request; 126 widget_class->size_request = gtk_xemacs_menubar_size_request;
127 } 127 }
128 128
129 static void 129 static void
135 gtk_xemacs_menubar_size_request (GtkWidget *widget, GtkRequisition *requisition) 135 gtk_xemacs_menubar_size_request (GtkWidget *widget, GtkRequisition *requisition)
136 { 136 {
137 GtkXEmacsMenubar *x = GTK_XEMACS_MENUBAR (widget); 137 GtkXEmacsMenubar *x = GTK_XEMACS_MENUBAR (widget);
138 GtkRequisition frame_size; 138 GtkRequisition frame_size;
139 139
140 parent_class->size_request (widget, requisition); 140 menubar_parent_class->size_request (widget, requisition);
141 141
142 /* #### BILL! 142 /* #### BILL!
143 ** We should really only do this if the menu has not been detached! 143 ** We should really only do this if the menu has not been detached!
144 ** 144 **
145 ** WMP 9/9/2000 145 ** WMP 9/9/2000
158 menubar->frame = f; 158 menubar->frame = f;
159 159
160 return (GTK_WIDGET (menubar)); 160 return (GTK_WIDGET (menubar));
161 } 161 }
162 162
163 /*
164 * Label with XEmacs accelerator character support.
165 *
166 * The default interfaces to GtkAccelLabel does not understand XEmacs
167 * keystroke printing conventions, nor is it convenient in the places where is
168 * it needed. This subclass provides an alternative interface more suited to
169 * XEmacs needs but does not add new functionality.
170 */
171 #define GTK_TYPE_XEMACS_ACCEL_LABEL (gtk_xemacs_accel_label_get_type ())
172 #define GTK_XEMACS_ACCEL_LABEL(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_ACCEL_LABEL, GtkXEmacsAccelLabel))
173 #define GTK_XEMACS_ACCEL_LABEL_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_ACCEL_LABEL, GtkXEmacsAccelLabelClass))
174 #define GTK_IS_XEMACS_ACCEL_LABEL(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_XEMACS_ACCEL_LABEL))
175 #define GTK_IS_XEMACS_ACCEL_LABEL_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_XEMACS_ACCEL_LABEL))
176
177 typedef struct _GtkXEmacsAccelLabel GtkXEmacsAccelLabel;
178 typedef struct _GtkXEmacsAccelLabelClass GtkXEmacsAccelLabelClass;
179
180 /* Instance structure. No additional fields required. */
181 struct _GtkXEmacsAccelLabel
182 {
183 GtkAccelLabel label;
184 };
185
186 /* Class structure. No additional fields required. */
187 struct _GtkXEmacsAccelLabelClass
188 {
189 GtkAccelLabelClass parent_class;
190 };
191
192 static GtkType gtk_xemacs_accel_label_get_type(void);
193 static GtkWidget* gtk_xemacs_accel_label_new(const gchar *string);
194 static void gtk_xemacs_set_accel_keys(GtkXEmacsAccelLabel* l,
195 Lisp_Object keys);
196 static void gtk_xemacs_accel_label_class_init(GtkXEmacsAccelLabelClass *klass);
197 static void gtk_xemacs_accel_label_init(GtkXEmacsAccelLabel *xemacs);
198
199 static GtkType
200 gtk_xemacs_accel_label_get_type(void)
201 {
202 static GtkType xemacs_accel_label_type = 0;
203
204 if (!xemacs_accel_label_type)
205 {
206 static const GtkTypeInfo xemacs_accel_label_info =
207 {
208 "GtkXEmacsAccelLabel",
209 sizeof (GtkXEmacsAccelLabel),
210 sizeof (GtkXEmacsAccelLabelClass),
211 (GtkClassInitFunc) gtk_xemacs_accel_label_class_init,
212 (GtkObjectInitFunc) gtk_xemacs_accel_label_init,
213 /* reserved_1 */ NULL,
214 /* reserved_2 */ NULL,
215 (GtkClassInitFunc) NULL,
216 };
217
218 xemacs_accel_label_type = gtk_type_unique (gtk_accel_label_get_type(), &xemacs_accel_label_info);
219 }
220
221 return xemacs_accel_label_type;
222 }
223
224 static void
225 gtk_xemacs_accel_label_class_init(GtkXEmacsAccelLabelClass *klass)
226 {
227 /* Nothing to do. */
228 }
229
230 static void
231 gtk_xemacs_accel_label_init(GtkXEmacsAccelLabel *xemacs)
232 {
233 /* Nothing to do. */
234 }
235
236 static GtkWidget*
237 gtk_xemacs_accel_label_new (const gchar *string)
238 {
239 GtkXEmacsAccelLabel *xemacs_accel_label;
240
241 xemacs_accel_label = (GtkXEmacsAccelLabel*) gtk_type_new (GTK_TYPE_XEMACS_ACCEL_LABEL);
242
243 if (string && *string)
244 gtk_label_set_text (GTK_LABEL (xemacs_accel_label), string);
245
246 return GTK_WIDGET (xemacs_accel_label);
247 }
248
249 /* Make the string <keys> the accelerator string for the label. */
250 static void
251 gtk_xemacs_set_accel_keys(GtkXEmacsAccelLabel* l, Lisp_Object keys)
252 {
253 g_return_if_fail (l != NULL);
254 g_return_if_fail (GTK_IS_XEMACS_ACCEL_LABEL (l));
255
256 /* Disable the standard way of finding the accelerator string for the
257 label. */
258 gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL(l), NULL);
259
260 /* Set the string straight from the object. */
261 if (STRINGP (keys) && XSTRING_LENGTH (keys))
262 {
263 C_STRING_TO_EXTERNAL_MALLOC(XSTRING_DATA (keys),
264 l->label.accel_string,
265 Qctext);
266 }
267 else
268 {
269 /* l->label.accel_string = NULL;*/
270 }
271 }
272
273
163 /* We now return you to your regularly scheduled menus... */ 274 /* We now return you to your regularly scheduled menus... */
164 275
165 int dockable_menubar; 276 int dockable_menubar;
166 277
167 /* #define TEAR_OFF_MENUS */ 278 /* #define TEAR_OFF_MENUS */
318 /* Signal an error here? The NILP handling is handled a 429 /* Signal an error here? The NILP handling is handled a
319 layer higher where appropriate */ 430 layer higher where appropriate */
320 } 431 }
321 else 432 else
322 { 433 {
323 next = menu_descriptor_to_widget_1 (child); 434 next = menu_descriptor_to_widget_1 (child,
435 gtk_menu_ensure_uline_accel_group (GTK_MENU (item->submenu)));
324 } 436 }
325 437
326 if (!next) 438 if (!next)
327 { 439 {
328 continue; 440 continue;
353 gtk_timeout_remove (mi->timer); 465 gtk_timeout_remove (mi->timer);
354 mi->timer = 0; 466 mi->timer = 0;
355 } 467 }
356 } 468 }
357 469
470 /* Convert the XEmacs menu accelerator representation to Gtk mnemonic form. If
471 no accelerator has been provided, put one at the start of the string (this
472 mirrors the behaviour under X). This algorithm is also found in
473 dialog-gtk.el:gtk-popup-convert-underscores.
474 */
358 static char * 475 static char *
359 remove_underscores(const Ibyte* name) 476 convert_underscores(const Ibyte *name)
360 { 477 {
361 char *rval = (char*) xmalloc_and_zero (strlen((char*) name) + 1); 478 char *rval;
479 int i,j;
480 int found_accel = FALSE;
481 int underscores = 0;
482
483 for (i = 0; name[i]; ++i)
484 if (name[i] == '%' && name[i+1] == '_')
485 {
486 found_accel = TRUE;
487 }
488 else if (name[i] == '_')
489 {
490 underscores++;
491 }
492
493 /* Allocate space for the original string, plus zero byte plus extra space
494 for all quoted underscores plus possible additional leading accelerator. */
495 rval = (char*) xmalloc_and_zero (qxestrlen(name) + 1 + underscores
496 + (found_accel ? 0 : 1));
497
498 if (!found_accel)
499 rval[0] = '_';
500
501 for (i = 0, j = (found_accel ? 0 : 1); name[i]; i++)
502 {
503 if (name[i]=='%')
504 {
505 i++;
506 if (!(name[i]))
507 continue;
508
509 if ((name[i] != '_') && (name[i] != '%'))
510 i--;
511
512 found_accel = TRUE;
513 }
514 else if (name[i] == '_')
515 {
516 rval[j++] = '_';
517 }
518
519 rval[j++] = name[i];
520 }
521
522 return rval;
523 }
524
525 /* Remove the XEmacs menu accellerator representation from a string. */
526 static char *
527 remove_underscores(const Ibyte *name)
528 {
529 char *rval = (char*) xmalloc_and_zero (qxestrlen(name) + 1);
362 int i,j; 530 int i,j;
363 531
364 for (i = 0, j = 0; name[i]; i++) 532 for (i = 0, j = 0; name[i]; i++)
365 { 533 {
366 if (name[i]=='%') { 534 if (name[i]=='%') {
367 i++; 535 i++;
368 if (!(name[i])) 536 if (!(name[i]))
369 continue; 537 continue;
370 538
371 if ((name[i] == '_')) 539 if ((name[i] != '_') && (name[i] != '%'))
540 i--;
541 else
372 continue; 542 continue;
373 } 543 }
374 rval[j++] = name[i]; 544 rval[j++] = name[i];
375 } 545 }
376 return rval; 546 return rval;
379 /* This converts an entire menu into a GtkMenuItem (with an attached 549 /* This converts an entire menu into a GtkMenuItem (with an attached
380 submenu). A menu is a list of (STRING [:keyword value]+ [DESCR]+) 550 submenu). A menu is a list of (STRING [:keyword value]+ [DESCR]+)
381 DESCR is either a list (meaning a submenu), a vector, or nil (if 551 DESCR is either a list (meaning a submenu), a vector, or nil (if
382 you include a :filter keyword) */ 552 you include a :filter keyword) */
383 static GtkWidget * 553 static GtkWidget *
384 menu_convert (Lisp_Object desc, GtkWidget *reuse) 554 menu_convert (Lisp_Object desc, GtkWidget *reuse,
555 GtkAccelGroup* menubar_accel_group)
385 { 556 {
386 GtkWidget *menu_item = NULL; 557 GtkWidget *menu_item = NULL;
387 GtkWidget *submenu = NULL; 558 GtkWidget *submenu = NULL;
388 Lisp_Object key, val; 559 Lisp_Object key, val;
389 Lisp_Object include_p = Qnil, hook_fn = Qnil, config_tag = Qnil; 560 Lisp_Object include_p = Qnil, hook_fn = Qnil, config_tag = Qnil;
396 { 567 {
397 accel = menu_name_to_accelerator (XSTRING_DATA (XCAR (desc))); 568 accel = menu_name_to_accelerator (XSTRING_DATA (XCAR (desc)));
398 569
399 if (!reuse) 570 if (!reuse)
400 { 571 {
401 char *temp_menu_name = remove_underscores (XSTRING_DATA (XCAR (desc))); 572 char *temp_menu_name = convert_underscores (XSTRING_DATA (XCAR (desc)));
402 menu_item = gtk_menu_item_new_with_label (temp_menu_name); 573 GtkWidget* accel_label = gtk_xemacs_accel_label_new(NULL);
574 guint accel_key;
575
576 gtk_misc_set_alignment (GTK_MISC (accel_label), 0.0, 0.5);
577 accel_key = gtk_label_parse_uline (GTK_LABEL (accel_label), temp_menu_name);
578
579 menu_item = gtk_menu_item_new ();
580 gtk_container_add (GTK_CONTAINER (menu_item), accel_label);
581 gtk_widget_show (accel_label);
582
583 if (menubar_accel_group)
584 gtk_widget_add_accelerator (menu_item,
585 "activate_item",
586 menubar_accel_group,
587 accel_key, GDK_MOD1_MASK,
588 GTK_ACCEL_LOCKED);
403 free (temp_menu_name); 589 free (temp_menu_name);
404 } 590 }
405 else 591 else
406 { 592 {
407 menu_item = reuse; 593 menu_item = reuse;
581 /* Convert a single menu item descriptor to a suitable GtkMenuItem */ 767 /* Convert a single menu item descriptor to a suitable GtkMenuItem */
582 /* This function cannot GC. 768 /* This function cannot GC.
583 It is only called from menu_item_descriptor_to_widget_value, which 769 It is only called from menu_item_descriptor_to_widget_value, which
584 prohibits GC. */ 770 prohibits GC. */
585 static GtkWidget * 771 static GtkWidget *
586 menu_descriptor_to_widget_1 (Lisp_Object descr) 772 menu_descriptor_to_widget_1 (Lisp_Object descr, GtkAccelGroup* accel_group)
587 { 773 {
588 if (STRINGP (descr)) 774 if (STRINGP (descr))
589 { 775 {
590 /* It is a separator. Unfortunately GTK does not allow us to 776 /* It is a separator. Unfortunately GTK does not allow us to
591 specify what our separators look like, so we can't do all the 777 specify what our separators look like, so we can't do all the
594 return (gtk_menu_item_new ()); 780 return (gtk_menu_item_new ());
595 } 781 }
596 else if (LISTP (descr)) 782 else if (LISTP (descr))
597 { 783 {
598 /* It is a submenu */ 784 /* It is a submenu */
599 return (menu_convert (descr, NULL)); 785 return (menu_convert (descr, NULL, accel_group));
600 } 786 }
601 else if (VECTORP (descr)) 787 else if (VECTORP (descr))
602 { 788 {
603 /* An actual menu item description! This gets yucky. */ 789 /* An actual menu item description! This gets yucky. */
604 Lisp_Object name = Qnil; 790 Lisp_Object name = Qnil;
615 int length = XVECTOR_LENGTH (descr); 801 int length = XVECTOR_LENGTH (descr);
616 Lisp_Object *contents = XVECTOR_DATA (descr); 802 Lisp_Object *contents = XVECTOR_DATA (descr);
617 int plist_p; 803 int plist_p;
618 int selected_spec = 0, included_spec = 0; 804 int selected_spec = 0, included_spec = 0;
619 GtkWidget *widget = NULL; 805 GtkWidget *widget = NULL;
806 guint accel_key;
620 807
621 if (length < 2) 808 if (length < 2)
622 sferror ("button descriptors must be at least 2 long", descr); 809 sferror ("button descriptors must be at least 2 long", descr);
623 810
624 /* length 2: [ "name" callback ] 811 /* length 2: [ "name" callback ]
710 { 897 {
711 label_buffer = (Ibyte*) ALLOCA (XSTRING_LENGTH (name) + 15); 898 label_buffer = (Ibyte*) ALLOCA (XSTRING_LENGTH (name) + 15);
712 sprintf ((char*) label_buffer, "%s ", XSTRING_DATA (name)); 899 sprintf ((char*) label_buffer, "%s ", XSTRING_DATA (name));
713 } 900 }
714 901
715 temp_label = remove_underscores (label_buffer); 902 temp_label = convert_underscores (label_buffer);
716 main_label = gtk_accel_label_new (temp_label); 903 main_label = gtk_xemacs_accel_label_new (NULL);
904 accel_key = gtk_label_parse_uline (GTK_LABEL (main_label), temp_label);
717 free (temp_label); 905 free (temp_label);
718 } 906 }
719 907
720 /* Evaluate the selected and active items now */ 908 /* Evaluate the selected and active items now */
721 if (selected_spec) 909 if (selected_spec)
835 1023
836 gtk_signal_connect (GTK_OBJECT (widget), "activate", 1024 gtk_signal_connect (GTK_OBJECT (widget), "activate",
837 GTK_SIGNAL_FUNC (__generic_button_callback), 1025 GTK_SIGNAL_FUNC (__generic_button_callback),
838 LISP_TO_VOID (callback)); 1026 LISP_TO_VOID (callback));
839 1027
840 /* We cheat here... GtkAccelLabel usually builds its 1028 /* Now that all the information about the menu item is know, set the
841 `accel_string' from the widget it is attached to, but we do 1029 remaining properties.
842 not want to go thru the overhead of converting our nice
843 string back into the modifier + key format that requires,
844 just so that they can convert it back into a (possibly
845 different/wrong) string
846
847 We set the label string manually, and things should 'just
848 work'
849
850 In an ideal world we would just subclass GtkLabel ourselves,
851 but I have known for a very long time that this is not an
852 ideal world.
853
854 #### Should do menu shortcuts `correctly' one of these days.
855 */ 1030 */
856 1031
857 if (main_label) 1032 if (main_label)
858 { 1033 {
859 GtkAccelLabel *l = GTK_ACCEL_LABEL (main_label);
860
861 gtk_container_add (GTK_CONTAINER (widget), main_label); 1034 gtk_container_add (GTK_CONTAINER (widget), main_label);
862 1035
863 gtk_accel_label_set_accel_widget (l, NULL); 1036 gtk_misc_set_alignment (GTK_MISC (main_label), 0.0, 0.5);
864 gtk_misc_set_alignment (GTK_MISC (l), 0.0, 0.5); 1037 gtk_xemacs_set_accel_keys(GTK_XEMACS_ACCEL_LABEL(main_label), keys);
865 1038
866 if (STRINGP (keys) && XSTRING_LENGTH (keys)) 1039 if (accel_group)
867 { 1040 gtk_widget_add_accelerator (widget,
868 C_STRING_TO_EXTERNAL_MALLOC (XSTRING_DATA (keys), l->accel_string, 1041 "activate_item",
869 Qctext); 1042 accel_group,
870 stderr_out ("accel: %s\n", l->accel_string); 1043 accel_key, 0,
871 } 1044 GTK_ACCEL_LOCKED);
872 else
873 {
874 /* l->accel_string = ""; */
875 }
876 } 1045 }
877 1046
878 return (widget); 1047 return (widget);
879 } 1048 }
880 else 1049 else
883 /* abort (); ???? */ 1052 /* abort (); ???? */
884 } 1053 }
885 } 1054 }
886 1055
887 static GtkWidget * 1056 static GtkWidget *
888 menu_descriptor_to_widget (Lisp_Object descr) 1057 menu_descriptor_to_widget (Lisp_Object descr, GtkAccelGroup* accel_group)
889 { 1058 {
890 GtkWidget *rval = NULL; 1059 GtkWidget *rval = NULL;
891 int count = begin_gc_forbidden (); 1060 int count = begin_gc_forbidden ();
892 1061
893 /* Cannot GC from here on out... */ 1062 /* Cannot GC from here on out... */
894 rval = menu_descriptor_to_widget_1 (descr); 1063 rval = menu_descriptor_to_widget_1 (descr, accel_group);
895 unbind_to (count); 1064 unbind_to (count);
896 return (rval); 1065 return (rval);
897 1066
898 } 1067 }
899 1068
900 static gboolean 1069 static gboolean
901 menu_can_reuse_widget (GtkWidget *child, const Ibyte *label) 1070 menu_can_reuse_widget (GtkWidget *child, const Ibyte *label)
902 { 1071 {
903 /* Everything up at the top level was done using 1072 /* Everything up at the top level was done using
904 ** gtk_menu_item_new_with_label(), but we still double check to make 1073 ** gtk_xemacs_accel_label_new(), but we still double check to make
905 ** sure we don't seriously foobar ourselves. 1074 ** sure we don't seriously foobar ourselves.
906 */ 1075 */
907 char *temp_label = NULL; 1076 gpointer possible_child =
908 gpointer possible_child = g_list_nth_data (gtk_container_children (GTK_CONTAINER (child)), 0); 1077 g_list_nth_data (gtk_container_children (GTK_CONTAINER (child)), 0);
1078 gboolean ret_val = FALSE;
909 1079
910 if (possible_child && GTK_IS_LABEL (possible_child)) 1080 if (possible_child && GTK_IS_LABEL (possible_child))
911 { 1081 {
912 if (!temp_label) temp_label = remove_underscores (label); 1082 char *temp_label = remove_underscores (label);
1083
913 if (!strcmp (GTK_LABEL (possible_child)->label, temp_label)) 1084 if (!strcmp (GTK_LABEL (possible_child)->label, temp_label))
914 { 1085 ret_val = TRUE;
915 free (temp_label); 1086
916 return (TRUE); 1087 free (temp_label);
917 } 1088 }
918 } 1089
919 if (temp_label) free (temp_label); 1090 return ret_val;
920 return (FALSE);
921 } 1091 }
922 1092
923 /* Converts a menubar description into a GtkMenuBar... a menubar is a 1093 /* Converts a menubar description into a GtkMenuBar... a menubar is a
924 list of menus or buttons 1094 list of menus or buttons
925 */ 1095 */
931 Lisp_Object value = descr; 1101 Lisp_Object value = descr;
932 Lisp_Object item_descr = Qnil; 1102 Lisp_Object item_descr = Qnil;
933 GtkWidget *menubar = FRAME_GTK_MENUBAR_WIDGET (f); 1103 GtkWidget *menubar = FRAME_GTK_MENUBAR_WIDGET (f);
934 GUI_ID id = (GUI_ID) gtk_object_get_data (GTK_OBJECT (menubar), XEMACS_MENU_GUIID_TAG); 1104 GUI_ID id = (GUI_ID) gtk_object_get_data (GTK_OBJECT (menubar), XEMACS_MENU_GUIID_TAG);
935 guint menu_position = 0; 1105 guint menu_position = 0;
1106 GtkAccelGroup *menubar_accel_group;
936 1107
937 /* Remove any existing protection for old menu items */ 1108 /* Remove any existing protection for old menu items */
938 ungcpro_popup_callbacks (id); 1109 ungcpro_popup_callbacks (id);
939 1110
940 /* GCPRO the whole damn thing */ 1111 /* GCPRO the whole damn thing */
941 gcpro_popup_callbacks (id, descr); 1112 gcpro_popup_callbacks (id, descr);
1113
1114 menubar_accel_group = gtk_accel_group_new();
942 1115
943 EXTERNAL_LIST_LOOP (tail, value) 1116 EXTERNAL_LIST_LOOP (tail, value)
944 { 1117 {
945 gpointer current_child = g_list_nth_data (GTK_MENU_SHELL (menubar)->children, menu_position); 1118 gpointer current_child = g_list_nth_data (GTK_MENU_SHELL (menubar)->children, menu_position);
946 1119
955 else if (VECTORP (item_descr)) 1128 else if (VECTORP (item_descr))
956 { 1129 {
957 /* It is a button description */ 1130 /* It is a button description */
958 GtkWidget *item; 1131 GtkWidget *item;
959 1132
960 item = menu_descriptor_to_widget (item_descr); 1133 item = menu_descriptor_to_widget (item_descr, menubar_accel_group);
961 gtk_widget_set_name (item, "XEmacsMenuButton"); 1134 gtk_widget_set_name (item, "XEmacsMenuButton");
962 1135
963 if (!item) 1136 if (!item)
964 { 1137 {
965 item = gtk_menu_item_new_with_label ("ITEM CREATION ERROR"); 1138 item = gtk_menu_item_new_with_label ("ITEM CREATION ERROR");
977 1150
978 /* We may be able to reuse the widget, let's at least check. */ 1151 /* We may be able to reuse the widget, let's at least check. */
979 if (current_child && menu_can_reuse_widget (GTK_WIDGET (current_child), 1152 if (current_child && menu_can_reuse_widget (GTK_WIDGET (current_child),
980 XSTRING_DATA (XCAR (item_descr)))) 1153 XSTRING_DATA (XCAR (item_descr))))
981 { 1154 {
982 widget = menu_convert (item_descr, GTK_WIDGET (current_child)); 1155 widget = menu_convert (item_descr, GTK_WIDGET (current_child),
1156 menubar_accel_group);
983 reused_p = TRUE; 1157 reused_p = TRUE;
984 } 1158 }
985 else 1159 else
986 { 1160 {
987 widget = menu_convert (item_descr, NULL); 1161 widget = menu_convert (item_descr, NULL, menubar_accel_group);
988 if (current_child) gtk_widget_destroy (GTK_WIDGET (current_child)); 1162 if (current_child) gtk_widget_destroy (GTK_WIDGET (current_child));
989 gtk_menu_bar_insert (GTK_MENU_BAR (menubar), widget, menu_position); 1163 gtk_menu_bar_insert (GTK_MENU_BAR (menubar), widget, menu_position);
990 } 1164 }
991 1165
992 if (widget) 1166 if (widget)
1021 { 1195 {
1022 gtk_widget_destroy (GTK_WIDGET (data)); 1196 gtk_widget_destroy (GTK_WIDGET (data));
1023 } 1197 }
1024 } 1198 }
1025 } 1199 }
1200
1201 /* Attach the new accelerator group to the frame. */
1202 gtk_window_add_accel_group (GTK_WINDOW (FRAME_GTK_SHELL_WIDGET(f)),
1203 menubar_accel_group);
1026 } 1204 }
1027 1205
1028 1206
1029 /* Deal with getting/setting the menubar */ 1207 /* Deal with getting/setting the menubar */
1030 #ifndef GNOME_IS_APP 1208 #ifndef GNOME_IS_APP
1244 menu_desc = Fsymbol_value (menu_desc); 1422 menu_desc = Fsymbol_value (menu_desc);
1245 CHECK_CONS (menu_desc); 1423 CHECK_CONS (menu_desc);
1246 CHECK_STRING (XCAR (menu_desc)); 1424 CHECK_STRING (XCAR (menu_desc));
1247 1425
1248 /* Now lets get down to business... */ 1426 /* Now lets get down to business... */
1249 widget = menu_descriptor_to_widget (menu_desc); 1427 widget = menu_descriptor_to_widget (menu_desc, NULL);
1250 menu = GTK_MENU_ITEM (widget)->submenu; 1428 menu = GTK_MENU_ITEM (widget)->submenu;
1251 gtk_widget_set_name (widget, "XEmacsPopupMenu"); 1429 gtk_widget_set_name (widget, "XEmacsPopupMenu");
1252 id = gtk_object_get_data (GTK_OBJECT (widget), XEMACS_MENU_GUIID_TAG); 1430 id = gtk_object_get_data (GTK_OBJECT (widget), XEMACS_MENU_GUIID_TAG);
1253 1431
1254 __activate_menu (GTK_MENU_ITEM (widget), id); 1432 __activate_menu (GTK_MENU_ITEM (widget), id);
1288 Returns a GTK menu item from MENU, a standard XEmacs menu description. 1466 Returns a GTK menu item from MENU, a standard XEmacs menu description.
1289 See the definition of `popup-menu' for more information on the format of MENU. 1467 See the definition of `popup-menu' for more information on the format of MENU.
1290 */ 1468 */
1291 (menu)) 1469 (menu))
1292 { 1470 {
1293 GtkWidget *w = menu_descriptor_to_widget (menu); 1471 GtkWidget *w = menu_descriptor_to_widget (menu, NULL);
1294 1472
1295 return (w ? build_gtk_object (GTK_OBJECT (w)) : Qnil); 1473 return (w ? build_gtk_object (GTK_OBJECT (w)) : Qnil);
1296 } 1474 }
1297 1475
1298 1476
1331 If non-nil, menus can be torn off into their own top-level windows. 1509 If non-nil, menus can be torn off into their own top-level windows.
1332 */ ); 1510 */ );
1333 #endif 1511 #endif
1334 reinit_vars_of_menubar_gtk (); 1512 reinit_vars_of_menubar_gtk ();
1335 } 1513 }
1514
1515 /*---------------------------------------------------------------------------*/
1516