fix previously cherry-picked commit to be Tracks-only, since Ardour/Mixbus are not...
[ardour.git] / libs / gtkmm2ext / gtkapplication_quartz.mm
1 /* GTK+ application-level integration for the Mac OS X/Cocoa 
2  *
3  * Copyright (C) 2007 Pioneer Research Center USA, Inc.
4  * Copyright (C) 2007 Imendio AB
5  * Copyright (C) 2009 Paul Davis
6  *
7  * This is a reimplementation in Cocoa of the sync-menu.c concept
8  * from Imendio, although without the "set quit menu" API since
9  * a Cocoa app needs to handle termination anyway.
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; version 2.1
14  * of the License.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with this library; if not, write to the
23  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
24  * Boston, MA 02111-1307, USA.
25  */
26
27 #include <sigc++/signal.h>
28 #include <sigc++/slot.h>
29
30 #include <string.h>
31 #include <gtk/gtk.h>
32 #include <gdk/gdkkeysyms.h>
33 #include <gtkmm2ext/gtkapplication.h>
34 #include <gtkmm2ext/gtkapplication-private.h>
35
36 #import <AppKit/NSMenu.h>
37 #import <AppKit/NSMenuItem.h>
38 #import <AppKit/NSCell.h>
39 #import <AppKit/NSEvent.h>
40 #import <AppKit/NSApplication.h>
41 #import <Foundation/NSString.h>
42 #import <Foundation/NSNotification.h>
43
44 #define UNUSED_PARAMETER(a) (void) (a)
45
46 // #define DEBUG(format, ...) g_printerr ("%s: " format, G_STRFUNC, ## __VA_ARGS__)
47 #define DEBUG(format, ...)
48
49 /* TODO
50  *
51  * - Sync adding/removing/reordering items
52  * - Create on demand? (can this be done with gtk+? ie fill in menu
53      items when the menu is opened)
54  * - Figure out what to do per app/window...
55  *
56  */
57
58 static gint _exiting = 0;
59
60 static guint
61 gdk_quartz_keyval_to_ns_keyval (guint keyval)
62 {
63         switch (keyval) {
64         case GDK_BackSpace:
65                 return NSBackspaceCharacter;
66         case GDK_Delete:
67                 return NSDeleteFunctionKey;
68         case GDK_Pause:
69                 return NSPauseFunctionKey;
70         case GDK_Scroll_Lock:
71                 return NSScrollLockFunctionKey;
72         case GDK_Sys_Req:
73                 return NSSysReqFunctionKey;
74         case GDK_Home:
75                 return NSHomeFunctionKey;
76         case GDK_Left:
77         case GDK_leftarrow:
78                 return NSLeftArrowFunctionKey;
79         case GDK_Up:
80         case GDK_uparrow:
81                 return NSUpArrowFunctionKey;
82         case GDK_Right:
83         case GDK_rightarrow:
84                 return NSRightArrowFunctionKey;
85         case GDK_Down:
86         case GDK_downarrow:
87                 return NSDownArrowFunctionKey;
88         case GDK_Page_Up:
89                 return NSPageUpFunctionKey;
90         case GDK_Page_Down:
91                 return NSPageDownFunctionKey;
92         case GDK_End:
93                 return NSEndFunctionKey;
94         case GDK_Begin:
95                 return NSBeginFunctionKey;
96         case GDK_Select:
97                 return NSSelectFunctionKey;
98         case GDK_Print:
99                 return NSPrintFunctionKey;
100         case GDK_Execute:
101                 return NSExecuteFunctionKey;
102         case GDK_Insert:
103                 return NSInsertFunctionKey;
104         case GDK_Undo:
105                 return NSUndoFunctionKey;
106         case GDK_Redo:
107                 return NSRedoFunctionKey;
108         case GDK_Menu:
109                 return NSMenuFunctionKey;
110         case GDK_Find:
111                 return NSFindFunctionKey;
112         case GDK_Help:
113                 return NSHelpFunctionKey;
114         case GDK_Break:
115                 return NSBreakFunctionKey;
116         case GDK_Mode_switch:
117                 return NSModeSwitchFunctionKey;
118         case GDK_F1:
119                 return NSF1FunctionKey;
120         case GDK_F2:
121                 return NSF2FunctionKey;
122         case GDK_F3:
123                 return NSF3FunctionKey;
124         case GDK_F4:
125                 return NSF4FunctionKey;
126         case GDK_F5:
127                 return NSF5FunctionKey;
128         case GDK_F6:
129                 return NSF6FunctionKey;
130         case GDK_F7:
131                 return NSF7FunctionKey;
132         case GDK_F8:
133                 return NSF8FunctionKey;
134         case GDK_F9:
135                 return NSF9FunctionKey;
136         case GDK_F10:
137                 return NSF10FunctionKey;
138         case GDK_F11:
139                 return NSF11FunctionKey;
140         case GDK_F12:
141                 return NSF12FunctionKey;
142         case GDK_F13:
143                 return NSF13FunctionKey;
144         case GDK_F14:
145                 return NSF14FunctionKey;
146         case GDK_F15:
147                 return NSF15FunctionKey;
148         case GDK_F16:
149                 return NSF16FunctionKey;
150         case GDK_F17:
151                 return NSF17FunctionKey;
152         case GDK_F18:
153                 return NSF18FunctionKey;
154         case GDK_F19:
155                 return NSF19FunctionKey;
156         case GDK_F20:
157                 return NSF20FunctionKey;
158         case GDK_F21:
159                 return NSF21FunctionKey;
160         case GDK_F22:
161                 return NSF22FunctionKey;
162         case GDK_F23:
163                 return NSF23FunctionKey;
164         case GDK_F24:
165                 return NSF24FunctionKey;
166         case GDK_F25:
167                 return NSF25FunctionKey;
168         case GDK_F26:
169                 return NSF26FunctionKey;
170         case GDK_F27:
171                 return NSF27FunctionKey;
172         case GDK_F28:
173                 return NSF28FunctionKey;
174         case GDK_F29:
175                 return NSF29FunctionKey;
176         case GDK_F30:
177                 return NSF30FunctionKey;
178         case GDK_F31:
179                 return NSF31FunctionKey;
180         case GDK_F32:
181                 return NSF32FunctionKey;
182         case GDK_F33:
183                 return NSF33FunctionKey;
184         case GDK_F34:
185                 return NSF34FunctionKey;
186         case GDK_F35:
187                 return NSF35FunctionKey;
188         default:
189                 break;
190         }
191
192         return 0;
193 }
194
195 static gboolean
196 keyval_is_keypad (guint keyval)
197 {
198         switch (keyval) {
199         case GDK_KP_F1:
200         case GDK_KP_F2:
201         case GDK_KP_F3:
202         case GDK_KP_F4:
203         case GDK_KP_Home:
204         case GDK_KP_Left:
205         case GDK_KP_Up:
206         case GDK_KP_Right:
207         case GDK_KP_Down:
208         case GDK_KP_Page_Up:
209         case GDK_KP_Page_Down:
210         case GDK_KP_End:
211         case GDK_KP_Begin:
212         case GDK_KP_Insert:
213         case GDK_KP_Delete:
214         case GDK_KP_Equal:
215         case GDK_KP_Multiply:
216         case GDK_KP_Add:
217         case GDK_KP_Separator:
218         case GDK_KP_Subtract:
219         case GDK_KP_Decimal:
220         case GDK_KP_Divide:
221         case GDK_KP_0:
222         case GDK_KP_1:
223         case GDK_KP_2:
224         case GDK_KP_3:
225         case GDK_KP_4:
226         case GDK_KP_5:
227         case GDK_KP_6:
228         case GDK_KP_7:
229         case GDK_KP_8:
230         case GDK_KP_9:
231                 return TRUE;
232                 break;
233         default:
234                 break;
235         }
236         return FALSE;
237 }
238
239 static guint
240 keyval_keypad_nonkeypad_equivalent (guint keyval)
241 {
242         switch (keyval) {
243         case GDK_KP_F1:
244                 return GDK_F1;
245         case GDK_KP_F2:
246                 return GDK_F2;
247         case GDK_KP_F3:
248                 return GDK_F3;
249         case GDK_KP_F4:
250                 return GDK_F4;
251         case GDK_KP_Home:
252                 return GDK_Home;
253         case GDK_KP_Left:
254                 return GDK_Left;
255         case GDK_KP_Up:
256                 return GDK_Up;
257         case GDK_KP_Right:
258                 return GDK_Right;
259         case GDK_KP_Down:
260                 return GDK_Down;
261         case GDK_KP_Page_Up:
262                 return GDK_Page_Up;
263         case GDK_KP_Page_Down:
264                 return GDK_Page_Down;
265         case GDK_KP_End:
266                 return GDK_End;
267         case GDK_KP_Begin:
268                 return GDK_Begin;
269         case GDK_KP_Insert:
270                 return GDK_Insert;
271         case GDK_KP_Delete:
272                 return GDK_Delete;
273         case GDK_KP_Equal:
274                 return GDK_equal;
275         case GDK_KP_Multiply:
276                 return GDK_asterisk;
277         case GDK_KP_Add:
278                 return GDK_plus;
279         case GDK_KP_Subtract:
280                 return GDK_minus;
281         case GDK_KP_Decimal:
282                 return GDK_period;
283         case GDK_KP_Divide:
284                 return GDK_slash;
285         case GDK_KP_0:
286                 return GDK_0;
287         case GDK_KP_1:
288                 return GDK_1;
289         case GDK_KP_2:
290                 return GDK_2;
291         case GDK_KP_3:
292                 return GDK_3;
293         case GDK_KP_4:
294                 return GDK_4;
295         case GDK_KP_5:
296                 return GDK_5;
297         case GDK_KP_6:
298                 return GDK_6;
299         case GDK_KP_7:
300                 return GDK_7;
301         case GDK_KP_8:
302                 return GDK_8;
303         case GDK_KP_9:
304                 return GDK_9;
305         default:
306                 break;
307         }
308
309         return GDK_VoidSymbol;
310 }
311
312 static const gchar* 
313 gdk_quartz_keyval_to_string (guint keyval)
314 {
315         switch (keyval) {
316         case GDK_space:
317                 return " ";
318         case GDK_exclam:
319                 return "!";
320         case GDK_quotedbl:
321                 return "\"";
322         case GDK_numbersign:
323                 return "#";
324         case GDK_dollar:
325                 return "$";
326         case GDK_percent:
327                 return "%";
328         case GDK_ampersand:
329                 return "&";
330         case GDK_apostrophe:
331                 return "'";
332         case GDK_parenleft:
333                 return "(";
334         case GDK_parenright:
335                 return ")";
336         case GDK_asterisk:
337                 return "*";
338         case GDK_plus:
339                 return "+";
340         case GDK_comma:
341                 return ",";
342         case GDK_minus:
343                 return "-";
344         case GDK_period:
345                 return ".";
346         case GDK_slash:
347                 return "/";
348         case GDK_0:
349                 return "0";
350         case GDK_1:
351                 return "1";
352         case GDK_2:
353                 return "2";
354         case GDK_3:
355                 return "3";
356         case GDK_4:
357                 return "4";
358         case GDK_5:
359                 return "5";
360         case GDK_6:
361                 return "6";
362         case GDK_7:
363                 return "7";
364         case GDK_8:
365                 return "8";
366         case GDK_9:
367                 return "9";
368         case GDK_colon:
369                 return ":";
370         case GDK_semicolon:
371                 return ";";
372         case GDK_less:
373                 return "<";
374         case GDK_equal:
375                 return "=";
376         case GDK_greater:
377                 return ">";
378         case GDK_question:
379                 return "?";
380         case GDK_at:
381                 return "@";
382         case GDK_A:
383         case GDK_a:
384                 return "a";
385         case GDK_B:
386         case GDK_b:
387                 return "b";
388         case GDK_C:
389         case GDK_c:
390                 return "c";
391         case GDK_D:
392         case GDK_d:
393                 return "d";
394         case GDK_E:
395         case GDK_e:
396                 return "e";
397         case GDK_F:
398         case GDK_f:
399                 return "f";
400         case GDK_G:
401         case GDK_g:
402                 return "g";
403         case GDK_H:
404         case GDK_h:
405                 return "h";
406         case GDK_I:
407         case GDK_i:
408                 return "i";
409         case GDK_J:
410         case GDK_j:
411                 return "j";
412         case GDK_K:
413         case GDK_k:
414                 return "k";
415         case GDK_L:
416         case GDK_l:
417                 return "l";
418         case GDK_M:
419         case GDK_m:
420                 return "m";
421         case GDK_N:
422         case GDK_n:
423                 return "n";
424         case GDK_O:
425         case GDK_o:
426                 return "o";
427         case GDK_P:
428         case GDK_p:
429                 return "p";
430         case GDK_Q:
431         case GDK_q:
432                 return "q";
433         case GDK_R:
434         case GDK_r:
435                 return "r";
436         case GDK_S:
437         case GDK_s:
438                 return "s";
439         case GDK_T:
440         case GDK_t:
441                 return "t";
442         case GDK_U:
443         case GDK_u:
444                 return "u";
445         case GDK_V:
446         case GDK_v:
447                 return "v";
448         case GDK_W:
449         case GDK_w:
450                 return "w";
451         case GDK_X:
452         case GDK_x:
453                 return "x";
454         case GDK_Y:
455         case GDK_y:
456                 return "y";
457         case GDK_Z:
458         case GDK_z:
459                 return "z";
460         case GDK_bracketleft:
461                 return "[";
462         case GDK_backslash:
463                 return "\\";
464         case GDK_bracketright:
465                 return "]";
466         case GDK_asciicircum:
467                 return "^";
468         case GDK_underscore:
469                 return "_";
470         case GDK_grave:
471                 return "`";
472         case GDK_braceleft:
473                 return "{";
474         case GDK_bar:
475                 return "|";
476         case GDK_braceright:
477                 return "}";
478         case GDK_asciitilde:
479                 return "~";
480         default:
481                 break;
482         }
483         return NULL;
484 };
485
486 static gboolean
487 keyval_is_uppercase (guint keyval)
488 {
489         switch (keyval) {
490         case GDK_A:
491         case GDK_B:
492         case GDK_C:
493         case GDK_D:
494         case GDK_E:
495         case GDK_F:
496         case GDK_G:
497         case GDK_H:
498         case GDK_I:
499         case GDK_J:
500         case GDK_K:
501         case GDK_L:
502         case GDK_M:
503         case GDK_N:
504         case GDK_O:
505         case GDK_P:
506         case GDK_Q:
507         case GDK_R:
508         case GDK_S:
509         case GDK_T:
510         case GDK_U:
511         case GDK_V:
512         case GDK_W:
513         case GDK_X:
514         case GDK_Y:
515         case GDK_Z:
516                 return TRUE;
517         default:
518                 return FALSE;
519         }
520         return FALSE;
521 }
522
523 /* gtk/osx has a problem in that mac main menu events
524    are handled using an "internal" event handling system that 
525    doesn't pass things back to the glib/gtk main loop. if we call
526    gtk_main_iteration() block while in a menu event handler, then
527    glib gets confused and thinks there are two threads running
528    g_main_poll_func(). apps call call gdk_quartz_in_menu_event_handler()
529    if they need to check this.
530  */
531
532 static int _in_menu_event_handler = 0;
533
534 int 
535 gdk_quartz_in_menu_event_handler ()
536 {
537         return _in_menu_event_handler;
538 }
539
540 static gboolean
541 idle_call_activate (gpointer data)
542 {
543         gtk_menu_item_activate ((GtkMenuItem*) data);
544         return FALSE;
545 }
546
547 @interface GNSMenuItem : NSMenuItem
548 {
549     @public
550         GtkMenuItem* gtk_menu_item;
551         GClosure      *accel_closure;
552 }
553 - (id) initWithTitle:(NSString*) title andGtkWidget:(GtkMenuItem*) w;
554 - (void) activate:(id) sender;
555 @end
556
557 @implementation GNSMenuItem
558 - (id) initWithTitle:(NSString*) title andGtkWidget:(GtkMenuItem*) w
559 {
560         /* All menu items have the action "activate", which will be handled by this child class
561          */
562
563         self = [ super initWithTitle:title action:@selector(activate:) keyEquivalent:@"" ];
564
565         if (self) {
566                 /* make this handle its own action */
567                 [ self setTarget:self ];
568                 gtk_menu_item = w;
569                 accel_closure = 0;
570         }
571         return self;
572 }
573 - (void) activate:(id) sender
574 {
575         UNUSED_PARAMETER(sender);
576 #ifdef USE_TRACKS_CODE_FEATURES
577         // Hot Fix. Increase Priority.
578         g_idle_add_full (G_PRIORITY_HIGH_IDLE, idle_call_activate, gtk_menu_item, NULL);
579 #else
580         g_idle_add (idle_call_activate, gtk_menu_item);
581 #endif
582 }
583 @end
584
585 static void push_menu_shell_to_nsmenu (GtkMenuShell *menu_shell,
586                                        NSMenu       *menu,
587                                        gboolean      toplevel,
588                                        gboolean      debug);
589
590 /*
591  * utility functions
592  */
593
594 static GtkWidget *
595 find_menu_label (GtkWidget *widget)
596 {
597   GtkWidget *label = NULL;
598
599   if (GTK_IS_LABEL (widget))
600     return widget;
601
602   if (GTK_IS_CONTAINER (widget))
603     {
604       GList *children;
605       GList *l;
606
607       children = gtk_container_get_children (GTK_CONTAINER (widget));
608
609       for (l = children; l; l = l->next)
610         {
611           label = find_menu_label ((GtkWidget*) l->data);
612           if (label)
613             break;
614         }
615
616       g_list_free (children);
617     }
618
619   return label;
620 }
621
622 static const gchar *
623 get_menu_label_text (GtkWidget  *menu_item,
624                      GtkWidget **label)
625 {
626   GtkWidget *my_label;
627
628   my_label = find_menu_label (menu_item);
629   if (label)
630     *label = my_label;
631
632   if (my_label)
633     return gtk_label_get_text (GTK_LABEL (my_label));
634
635   return NULL;
636 }
637
638 static gboolean
639 accel_find_func (GtkAccelKey * /*key*/,
640                  GClosure    *closure,
641                  gpointer     data)
642 {
643   return (GClosure *) data == closure;
644 }
645
646
647 /*
648  * CocoaMenu functions
649  */
650
651 static GQuark cocoa_menu_quark = 0;
652
653 static NSMenu *
654 cocoa_menu_get (GtkWidget *widget)
655 {
656   return (NSMenu*) g_object_get_qdata (G_OBJECT (widget), cocoa_menu_quark);
657 }
658
659 static void
660 cocoa_menu_free (gpointer *ptr)
661 {
662         NSMenu* menu = (NSMenu*) ptr;
663         [menu release];
664 }
665
666 static void
667 cocoa_menu_connect (GtkWidget *menu,
668                     NSMenu*    cocoa_menu)
669 {
670         [cocoa_menu retain];
671
672         if (cocoa_menu_quark == 0)
673                 cocoa_menu_quark = g_quark_from_static_string ("NSMenu");
674         
675         g_object_set_qdata_full (G_OBJECT (menu), cocoa_menu_quark,
676                                  cocoa_menu,
677                                  (GDestroyNotify) cocoa_menu_free);
678 }
679
680 /*
681  * NSMenuItem functions
682  */
683
684 static GQuark cocoa_menu_item_quark = 0;
685 static void cocoa_menu_item_connect (GtkWidget*   menu_item,
686                                      GNSMenuItem* cocoa_menu_item,
687                                      GtkWidget     *label);
688
689 static void
690 cocoa_menu_item_free (gpointer *ptr)
691 {
692         GNSMenuItem* item = (GNSMenuItem*) ptr;
693         [item release];
694 }
695
696 static GNSMenuItem *
697 cocoa_menu_item_get (GtkWidget *widget)
698 {
699   return (GNSMenuItem*) g_object_get_qdata (G_OBJECT (widget), cocoa_menu_item_quark);
700 }
701
702 static void
703 cocoa_menu_item_update_state (NSMenuItem* cocoa_item,
704                               GtkWidget      *widget)
705 {
706   gboolean sensitive;
707   gboolean visible;
708
709   g_object_get (widget,
710                 "sensitive", &sensitive,
711                 "visible",   &visible,
712                 NULL);
713
714   if (!sensitive)
715           [cocoa_item setEnabled:NO];
716   else
717           [cocoa_item setEnabled:YES];
718
719 #if 0
720   // requires OS X 10.5 or later
721   if (!visible)
722           [cocoa_item setHidden:YES];
723   else
724           [cocoa_item setHidden:NO];
725 #endif
726 }
727
728 static void
729 cocoa_menu_item_update_active (NSMenuItem *cocoa_item,
730                                 GtkWidget  *widget)
731 {
732   gboolean active;
733
734   g_object_get (widget, "active", &active, NULL);
735
736   if (active) 
737     [cocoa_item setState:NSOnState];
738   else
739     [cocoa_item setState:NSOffState];
740 }
741
742 static void
743 cocoa_menu_item_update_submenu (NSMenuItem *cocoa_item,
744                                 GtkWidget      *widget)
745 {
746   GtkWidget *submenu;
747   
748   g_return_if_fail (cocoa_item != NULL);
749   g_return_if_fail (widget != NULL);
750
751   submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget));
752
753   if (submenu)
754     {
755       GtkWidget* label = NULL;
756       const gchar *label_text;
757       NSMenu* cocoa_submenu;
758
759       label_text = get_menu_label_text (widget, &label);
760
761       /* create a new nsmenu to hold the GTK menu */
762
763       if (label_text) 
764               cocoa_submenu = [ [ NSMenu alloc ] initWithTitle:[ [ NSString alloc] initWithCString:label_text encoding:NSUTF8StringEncoding]];
765       else
766               cocoa_submenu = [ [ NSMenu alloc ] initWithTitle:@""];
767
768       [cocoa_submenu setAutoenablesItems:NO];
769       cocoa_menu_connect (submenu, cocoa_submenu);
770
771       /* connect the new nsmenu to the passed-in item (which lives in
772          the parent nsmenu)
773          (Note: this will release any pre-existing version of this submenu)
774       */
775       [ cocoa_item setSubmenu:cocoa_submenu];
776
777       /* and push the GTK menu into the submenu */
778       push_menu_shell_to_nsmenu (GTK_MENU_SHELL (submenu), cocoa_submenu, FALSE, FALSE);
779
780       [ cocoa_submenu release ];
781     }
782 }
783
784 static void
785 cocoa_menu_item_update_label (NSMenuItem *cocoa_item,
786                                GtkWidget      *widget)
787 {
788   const gchar *label_text;
789
790   g_return_if_fail (cocoa_item != NULL);
791   g_return_if_fail (widget != NULL);
792
793   label_text = get_menu_label_text (widget, NULL);
794   if (label_text)
795           [cocoa_item setTitle:[ [ NSString alloc] initWithCString:label_text encoding:NSUTF8StringEncoding]];
796   else 
797           [cocoa_item setTitle:@""];
798 }
799
800 static void
801 cocoa_menu_item_update_accelerator (NSMenuItem *cocoa_item,
802                                      GtkWidget *widget)
803 {
804   GtkWidget *label;
805
806   g_return_if_fail (cocoa_item != NULL);
807   g_return_if_fail (widget != NULL);
808
809   /* important note: this function doesn't do anything to actually change
810      key handling. Its goal is to get Cocoa to display the correct
811      accelerator as part of a menu item. Actual accelerator handling
812      is still done by GTK, so this is more cosmetic than it may 
813      appear.
814   */
815
816   get_menu_label_text (widget, &label);  
817
818   if (GTK_IS_ACCEL_LABEL (label) &&
819             GTK_ACCEL_LABEL (label)->accel_closure)
820         {
821                 GtkAccelKey *key;
822                 
823                 key = gtk_accel_group_find (GTK_ACCEL_LABEL (label)->accel_group,
824                                             accel_find_func,
825                                   GTK_ACCEL_LABEL (label)->accel_closure);
826                 
827                 if (key            &&
828                     key->accel_key &&
829                     key->accel_flags & GTK_ACCEL_VISIBLE)
830                 {
831                         guint modifiers = 0; 
832                         const gchar* str = NULL;
833                         guint actual_key = key->accel_key; 
834                         
835                         if (keyval_is_keypad (actual_key)) {
836                                 if ((actual_key = keyval_keypad_nonkeypad_equivalent (actual_key)) == GDK_VoidSymbol) {
837                                         /* GDK_KP_Separator */
838                                         [cocoa_item setKeyEquivalent:@""];
839                                         return;
840                                 }
841                                 modifiers |= NSNumericPadKeyMask;
842                         }
843                         
844                         /* if we somehow got here with GDK_A ... GDK_Z rather than GDK_a ... GDK_z, then take note
845                            of that and make sure we use a shift modifier.
846                         */
847                         
848                         if (keyval_is_uppercase (actual_key)) {
849                                 modifiers |= NSShiftKeyMask;
850                         }
851                         
852                         str = gdk_quartz_keyval_to_string (actual_key);
853                         
854                         if (str) {
855                                 unichar ukey = str[0];
856                                 [cocoa_item setKeyEquivalent:[NSString stringWithCharacters:&ukey length:1]];
857                         } else {
858                                 unichar ukey = gdk_quartz_keyval_to_ns_keyval (actual_key);
859                                 if (ukey != 0) {
860                                         [cocoa_item setKeyEquivalent:[NSString stringWithCharacters:&ukey length:1]];
861                                 } else {
862                                         /* cannot map this key to Cocoa key equivalent */
863                                         [cocoa_item setKeyEquivalent:@""];
864                                         return;
865                                 }
866                         } 
867                         
868                         if (key->accel_mods || modifiers)
869                         {
870                                 if (key->accel_mods & GDK_SHIFT_MASK) {
871                                         modifiers |= NSShiftKeyMask;
872                                 }
873                                 
874                                 /* gdk/quartz maps Alt/Option to Mod1 */
875                                 
876                                 if (key->accel_mods & (GDK_MOD1_MASK)) {
877                                         modifiers |= NSAlternateKeyMask;
878                                 }
879                                 
880                                 if (key->accel_mods & GDK_CONTROL_MASK) {
881                                         modifiers |= NSControlKeyMask;
882                                 }
883                                 
884                                 /* gdk/quartz maps Command to Meta (XXX check this - it may move to SUPER at some point) */
885                                 
886                                 if (key->accel_mods & GDK_META_MASK) {
887                                         modifiers |= NSCommandKeyMask;
888                                 }
889                         }  
890                         
891                         [cocoa_item setKeyEquivalentModifierMask:modifiers];
892                         return;
893                 }
894         }
895
896         /*  otherwise, clear the menu shortcut  */
897         [cocoa_item setKeyEquivalent:@""];
898 }
899
900 static void
901 cocoa_menu_item_accel_changed (GtkAccelGroup*   /*accel_group*/,
902                                guint            /*keyval*/,
903                                 GdkModifierType /*modifier*/,
904                                 GClosure        *accel_closure,
905                                 GtkWidget       *widget)
906 {
907   GNSMenuItem *cocoa_item;
908   GtkWidget      *label;
909
910   if (_exiting) 
911     return;
912
913   cocoa_item = cocoa_menu_item_get (widget);
914   get_menu_label_text (widget, &label);
915
916   if (GTK_IS_ACCEL_LABEL (label) &&
917       GTK_ACCEL_LABEL (label)->accel_closure == accel_closure)
918     cocoa_menu_item_update_accelerator (cocoa_item, widget);
919 }
920
921 static void
922 cocoa_menu_item_update_accel_closure (GNSMenuItem *cocoa_item,
923                                       GtkWidget      *widget)
924 {
925   GtkAccelGroup *group;
926   GtkWidget     *label;
927
928   get_menu_label_text (widget, &label);
929
930   if (cocoa_item->accel_closure)
931     {
932       group = gtk_accel_group_from_accel_closure (cocoa_item->accel_closure);
933
934       g_signal_handlers_disconnect_by_func (group,
935                                             (void*) cocoa_menu_item_accel_changed,
936                                             widget);
937
938       g_closure_unref (cocoa_item->accel_closure);
939       cocoa_item->accel_closure = NULL;
940     }
941
942   if (GTK_IS_ACCEL_LABEL (label)) {
943     cocoa_item->accel_closure = GTK_ACCEL_LABEL (label)->accel_closure;
944   }
945
946   if (cocoa_item->accel_closure)
947     {
948       g_closure_ref (cocoa_item->accel_closure);
949
950       group = gtk_accel_group_from_accel_closure (cocoa_item->accel_closure);
951
952       g_signal_connect_object (group, "accel-changed",
953                                G_CALLBACK (cocoa_menu_item_accel_changed),
954                                widget, (GConnectFlags) 0);
955     }
956
957   cocoa_menu_item_update_accelerator (cocoa_item, widget);
958 }
959
960 static void
961 cocoa_menu_item_notify_label (GObject    *object,
962                               GParamSpec *pspec,
963                               gpointer)
964 {
965   GNSMenuItem *cocoa_item;
966
967   if (_exiting) 
968     return;
969
970   cocoa_item = cocoa_menu_item_get (GTK_WIDGET (object));
971
972   if (!strcmp (pspec->name, "label"))
973     {
974       cocoa_menu_item_update_label (cocoa_item,
975                                      GTK_WIDGET (object));
976     }
977   else if (!strcmp (pspec->name, "accel-closure"))
978     {
979       cocoa_menu_item_update_accel_closure (cocoa_item,
980                                              GTK_WIDGET (object));
981     }
982 }
983
984 static void
985 cocoa_menu_item_notify (GObject        *object,
986                         GParamSpec     *pspec,
987                         NSMenuItem *cocoa_item)
988 {
989   if (_exiting)
990     return;
991
992   if (!strcmp (pspec->name, "sensitive") ||
993       !strcmp (pspec->name, "visible"))
994     {
995       cocoa_menu_item_update_state (cocoa_item, GTK_WIDGET (object));
996     }
997   else if (!strcmp (pspec->name, "active"))
998     {
999       cocoa_menu_item_update_active (cocoa_item, GTK_WIDGET (object));
1000     }
1001   else if (!strcmp (pspec->name, "submenu"))
1002     {
1003       cocoa_menu_item_update_submenu (cocoa_item, GTK_WIDGET (object));
1004     }
1005 }
1006
1007 static void
1008 cocoa_menu_item_connect (GtkWidget*   menu_item,
1009                          GNSMenuItem* cocoa_item,
1010                          GtkWidget     *label)
1011 {
1012         GNSMenuItem* old_item = cocoa_menu_item_get (menu_item);
1013
1014         [cocoa_item retain];
1015
1016         if (cocoa_menu_item_quark == 0)
1017                 cocoa_menu_item_quark = g_quark_from_static_string ("NSMenuItem");
1018
1019         g_object_set_qdata_full (G_OBJECT (menu_item), cocoa_menu_item_quark,
1020                                  cocoa_item,
1021                                  (GDestroyNotify) cocoa_menu_item_free);
1022         
1023         if (!old_item) {
1024
1025                 g_signal_connect (menu_item, "notify",
1026                                   G_CALLBACK (cocoa_menu_item_notify),
1027                                   cocoa_item);
1028                 
1029                 if (label)
1030                         g_signal_connect_swapped (label, "notify::label",
1031                                                   G_CALLBACK (cocoa_menu_item_notify_label),
1032                                                   menu_item);
1033         }
1034 }
1035
1036 static void
1037 add_menu_item (NSMenu* cocoa_menu, GtkWidget* menu_item, int index)
1038 {
1039         GtkWidget* label      = NULL;
1040         GNSMenuItem *cocoa_item;
1041         
1042         DEBUG ("add %s to menu %s separator ? %d\n", get_menu_label_text (menu_item, NULL), 
1043                [[cocoa_menu title] cStringUsingEncoding:NSUTF8StringEncoding],
1044                GTK_IS_SEPARATOR_MENU_ITEM(menu_item));
1045
1046         cocoa_item = cocoa_menu_item_get (menu_item);
1047
1048         if (cocoa_item) 
1049                 return;
1050
1051         if (GTK_IS_SEPARATOR_MENU_ITEM (menu_item)) {
1052                 cocoa_item = [NSMenuItem separatorItem];
1053                 DEBUG ("\ta separator\n");
1054         } else {
1055
1056                 if (!GTK_WIDGET_VISIBLE (menu_item)) {
1057                         DEBUG ("\tnot visible\n");
1058                         return;
1059                 }
1060
1061                 const gchar* label_text = get_menu_label_text (menu_item, &label);
1062                 
1063                 if (label_text)
1064                         cocoa_item = [ [ GNSMenuItem alloc] initWithTitle:[ [ NSString alloc] initWithCString:label_text encoding:NSUTF8StringEncoding]
1065                                        andGtkWidget:(GtkMenuItem*)menu_item];
1066                 else
1067                         cocoa_item = [ [ GNSMenuItem alloc] initWithTitle:@"" andGtkWidget:(GtkMenuItem*)menu_item];
1068                 DEBUG ("\tan item\n");
1069         }
1070         
1071         /* connect GtkMenuItem and NSMenuItem so that we can notice changes to accel/label/submenu etc. */
1072         cocoa_menu_item_connect (menu_item, (GNSMenuItem*) cocoa_item, label);
1073         
1074         [ cocoa_item setEnabled:YES];
1075         if (index >= 0) 
1076                 [ cocoa_menu insertItem:cocoa_item atIndex:index];
1077         else 
1078                 [ cocoa_menu addItem:cocoa_item];
1079         
1080         if (!GTK_WIDGET_IS_SENSITIVE (menu_item))
1081                 [cocoa_item setState:NSOffState];
1082
1083 #if MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_4
1084         if (!GTK_WIDGET_VISIBLE (menu_item))
1085                 [cocoa_item setHidden:YES];
1086 #endif
1087         
1088         if (GTK_IS_CHECK_MENU_ITEM (menu_item))
1089                 cocoa_menu_item_update_active (cocoa_item, menu_item);
1090         
1091         if (!GTK_IS_SEPARATOR_MENU_ITEM (menu_item))
1092                 cocoa_menu_item_update_accel_closure (cocoa_item, menu_item);
1093         
1094         if (gtk_menu_item_get_submenu (GTK_MENU_ITEM (menu_item))) 
1095                 cocoa_menu_item_update_submenu (cocoa_item, menu_item);
1096
1097         [ cocoa_item release];
1098 }
1099         
1100 static void
1101 push_menu_shell_to_nsmenu (GtkMenuShell *menu_shell,
1102                            NSMenu*       cocoa_menu,
1103                            gboolean      /*toplevel*/,
1104                            gboolean      /*debug*/)
1105 {
1106   GList         *children;
1107   GList         *l;
1108
1109   children = gtk_container_get_children (GTK_CONTAINER (menu_shell));
1110
1111   for (l = children; l; l = l->next)
1112     {
1113       GtkWidget   *menu_item = (GtkWidget*) l->data;
1114
1115       if (GTK_IS_TEAROFF_MENU_ITEM (menu_item))
1116         continue;
1117
1118       if (g_object_get_data (G_OBJECT (menu_item), "gtk-empty-menu-item"))
1119         continue;
1120
1121       add_menu_item (cocoa_menu, menu_item, -1);
1122     }
1123   
1124   g_list_free (children);
1125 }
1126
1127
1128 static gulong emission_hook_id = 0;
1129
1130 static gboolean
1131 parent_set_emission_hook (GSignalInvocationHint* /*ihint*/,
1132                           guint                  /*n_param_values*/,
1133                           const GValue*          param_values,
1134                           gpointer               data)
1135 {
1136   GtkWidget *instance = (GtkWidget*) g_value_get_object (param_values);
1137
1138   if (GTK_IS_MENU_ITEM (instance))
1139     {
1140       GtkWidget *previous_parent = (GtkWidget*) g_value_get_object (param_values + 1);
1141       GtkWidget *menu_shell      = NULL;
1142
1143       if (GTK_IS_MENU_SHELL (previous_parent))
1144         {
1145           menu_shell = previous_parent;
1146         }
1147       else if (GTK_IS_MENU_SHELL (instance->parent))
1148         {
1149           menu_shell = instance->parent;
1150         }
1151
1152       if (menu_shell)
1153         {
1154           NSMenu *cocoa_menu = cocoa_menu_get (menu_shell);
1155
1156           if (cocoa_menu)
1157             {
1158               push_menu_shell_to_nsmenu (GTK_MENU_SHELL (menu_shell),
1159                                          cocoa_menu,
1160                                          cocoa_menu == (NSMenu*) data,
1161                                          FALSE);
1162             }
1163         }
1164     }
1165
1166   return TRUE;
1167 }
1168
1169 static void
1170 parent_set_emission_hook_remove (GtkWidget*, gpointer)
1171 {
1172         g_signal_remove_emission_hook (g_signal_lookup ("parent-set", GTK_TYPE_WIDGET),
1173                                        emission_hook_id);
1174 }
1175
1176 /* Building "standard" Cocoa/OS X menus */
1177
1178 #warning You can safely ignore the next warning about a duplicate interface definition
1179 @interface NSApplication(NSWindowsMenu)
1180         - (void)setAppleMenu:(NSMenu *)aMenu;
1181 @end
1182
1183 static NSMenu* _main_menubar = 0;
1184 static NSMenu* _window_menu = 0;
1185 static NSMenu* _app_menu = 0;
1186
1187 static int
1188 add_to_menubar (NSMenu *menu)
1189 {
1190         NSMenuItem *dummyItem = [[NSMenuItem alloc] initWithTitle:@""
1191                                  action:nil keyEquivalent:@""];
1192         [dummyItem setSubmenu:menu];
1193         [_main_menubar addItem:dummyItem];
1194         [dummyItem release];
1195         return 0;
1196 }
1197
1198 #if 0
1199 static int
1200 add_to_app_menu (NSMenu *menu)
1201 {
1202         NSMenuItem *dummyItem = [[NSMenuItem alloc] initWithTitle:@""
1203                                  action:nil keyEquivalent:@""];
1204         [dummyItem setSubmenu:menu];
1205         [_app_menu addItem:dummyItem];
1206         [dummyItem release];
1207         return 0;
1208 }
1209 #endif
1210
1211 static int
1212 create_apple_menu ()
1213 {
1214         NSMenuItem *menuitem;
1215         // Create the application (Apple) menu.
1216         _app_menu = [[NSMenu alloc] initWithTitle: @"Apple Menu"];
1217
1218         NSMenu *menuServices = [[NSMenu alloc] initWithTitle: @"Services"];
1219         [NSApp setServicesMenu:menuServices];
1220
1221         [_app_menu addItem: [NSMenuItem separatorItem]];
1222         menuitem = [[NSMenuItem alloc] initWithTitle: @"Services"
1223                     action:nil keyEquivalent:@""];
1224         [menuitem setSubmenu:menuServices];
1225         [_app_menu addItem: menuitem];
1226         [menuitem release];
1227         [_app_menu addItem: [NSMenuItem separatorItem]];
1228         menuitem = [[NSMenuItem alloc] initWithTitle:@"Hide"
1229                     action:@selector(hide:) keyEquivalent:@"h"];
1230         [menuitem setTarget: NSApp];
1231         [_app_menu addItem: menuitem];
1232         [menuitem release];
1233         menuitem = [[NSMenuItem alloc] initWithTitle:@"Hide Others"
1234                     action:@selector(hideOtherApplications:) keyEquivalent:@""];
1235         [menuitem setTarget: NSApp];
1236         [_app_menu addItem: menuitem];
1237         [menuitem release];
1238         menuitem = [[NSMenuItem alloc] initWithTitle:@"Show All"
1239                     action:@selector(unhideAllApplications:) keyEquivalent:@""];
1240         [menuitem setTarget: NSApp];
1241         [_app_menu addItem: menuitem];
1242         [menuitem release];
1243         [_app_menu addItem: [NSMenuItem separatorItem]];
1244         menuitem = [[NSMenuItem alloc] initWithTitle:@"Quit"
1245                     action:@selector(terminate:) keyEquivalent:@"q"];
1246         [menuitem setTarget: NSApp];
1247         [_app_menu addItem: menuitem];
1248         [menuitem release];
1249
1250         [NSApp setAppleMenu:_app_menu];
1251         add_to_menubar (_app_menu);
1252
1253         return 0;
1254 }
1255
1256 #if 0
1257 static int
1258 add_to_window_menu (NSMenu *menu)
1259 {
1260         NSMenuItem *dummyItem = [[NSMenuItem alloc] initWithTitle:@""
1261                                  action:nil keyEquivalent:@""];
1262         [dummyItem setSubmenu:menu];
1263         [_window_menu addItem:dummyItem];
1264         [dummyItem release];
1265         return 0;
1266 }
1267
1268 static int
1269 create_window_menu ()
1270 {   
1271         _window_menu = [[NSMenu alloc] initWithTitle: @"Window"];
1272
1273         [_window_menu addItemWithTitle:@"Minimize"
1274          action:@selector(performMiniaturize:) keyEquivalent:@""];
1275         [_window_menu addItem: [NSMenuItem separatorItem]];
1276         [_window_menu addItemWithTitle:@"Bring All to Front"
1277          action:@selector(arrangeInFront:) keyEquivalent:@""];
1278
1279         [NSApp setWindowsMenu:_window_menu];
1280         add_to_menubar(_window_menu);
1281
1282         return 0;
1283 }  
1284 #endif
1285
1286 /*
1287  * public functions
1288  */
1289
1290 extern "C" void
1291 gtk_application_set_menu_bar (GtkMenuShell *menu_shell)
1292 {
1293   NSMenu* cocoa_menubar;
1294
1295   g_return_if_fail (GTK_IS_MENU_SHELL (menu_shell));
1296
1297   if (cocoa_menu_quark == 0)
1298     cocoa_menu_quark = g_quark_from_static_string ("NSMenu");
1299
1300   if (cocoa_menu_item_quark == 0)
1301     cocoa_menu_item_quark = g_quark_from_static_string ("NSMenuItem");
1302
1303   cocoa_menubar = [ [ NSApplication sharedApplication] mainMenu];
1304
1305   /* turn off auto-enabling for the menu - its silly and slow and
1306      doesn't really make sense for a Gtk/Cocoa hybrid menu.
1307    */
1308
1309   [cocoa_menubar setAutoenablesItems:NO];
1310
1311   emission_hook_id =
1312     g_signal_add_emission_hook (g_signal_lookup ("parent-set",
1313                                                  GTK_TYPE_WIDGET),
1314                                 0,
1315                                 parent_set_emission_hook,
1316                                 cocoa_menubar, NULL);
1317
1318
1319   g_signal_connect (menu_shell, "destroy",
1320                     G_CALLBACK (parent_set_emission_hook_remove),
1321                     NULL);
1322
1323   push_menu_shell_to_nsmenu (menu_shell, cocoa_menubar, TRUE, FALSE);
1324 }
1325
1326 extern "C" void
1327 gtk_application_add_app_menu_item (GtkApplicationMenuGroup *group,
1328                                    GtkMenuItem     *menu_item)
1329 {
1330   // we know that the application menu is always the submenu of the first item in the main menu
1331   NSMenu* mainMenu;
1332   NSMenu *appMenu;
1333   NSMenuItem *firstItem;
1334   GList   *list;
1335   gint     index = 0;
1336
1337   mainMenu = [NSApp mainMenu];
1338   firstItem = [ mainMenu itemAtIndex:0];
1339   appMenu = [ firstItem submenu ];
1340
1341   g_return_if_fail (group != NULL);
1342   g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
1343
1344   for (list = _gtk_application_menu_groups; list; list = g_list_next (list))
1345     {
1346       GtkApplicationMenuGroup *list_group = (GtkApplicationMenuGroup*) list->data;
1347
1348       index += g_list_length (list_group->items);
1349
1350       /*  adjust index for the separator between groups, but not
1351        *  before the first group
1352        */
1353       if (list_group->items && list->prev)
1354         index++;
1355
1356       if (group == list_group)
1357         {
1358                 /*  add a separator before adding the first item, but not
1359                  *  for the first group
1360                  */
1361                 
1362                 if (!group->items && list->prev)
1363                    {
1364                            [appMenu insertItem:[NSMenuItem separatorItem] atIndex:index+1];
1365                            index++;
1366                    }
1367                 DEBUG ("Add to APP menu bar %s\n", get_menu_label_text (GTK_WIDGET(menu_item), NULL));
1368                 add_menu_item (appMenu, GTK_WIDGET(menu_item), index+1);
1369
1370                 group->items = g_list_append (group->items, menu_item);
1371                 gtk_widget_hide (GTK_WIDGET (menu_item));
1372                 return;
1373         }
1374     }
1375
1376   if (!list)
1377     g_warning ("%s: app menu group %p does not exist",
1378                G_STRFUNC, group);
1379 }
1380
1381 /* application delegate, currently in C++ */
1382
1383 #include <gtkmm2ext/application.h>
1384 #include <glibmm/ustring.h>
1385
1386 namespace Gtk {
1387         namespace Application {
1388                 sigc::signal<void,bool> ActivationChanged;
1389                 sigc::signal<void,const Glib::ustring&> ShouldLoad;
1390                 sigc::signal<void> ShouldQuit;
1391         }
1392 }
1393
1394 @interface GtkApplicationNotificationObject : NSObject {}
1395 - (GtkApplicationNotificationObject*) init; 
1396 @end
1397
1398 @implementation GtkApplicationNotificationObject
1399 - (GtkApplicationNotificationObject*) init
1400 {
1401         self = [ super init ];
1402
1403         if (self) {
1404                 [[NSNotificationCenter defaultCenter] addObserver:self
1405                  selector:@selector(appDidBecomeActive:)
1406                  name:NSApplicationDidBecomeActiveNotification
1407                  object:[NSApplication sharedApplication]];
1408
1409                 [[NSNotificationCenter defaultCenter] addObserver:self
1410                  selector:@selector(appDidBecomeInactive:)
1411                  name:NSApplicationWillResignActiveNotification 
1412                  object:[NSApplication sharedApplication]];
1413         }
1414
1415         return self;
1416 }
1417
1418 - (void)appDidBecomeActive:(NSNotification *) notification
1419 {
1420         UNUSED_PARAMETER(notification);
1421         Gtkmm2ext::Application::instance()->ActivationChanged (true);
1422 }
1423
1424 - (void)appDidBecomeInactive:(NSNotification *) notification
1425 {
1426         UNUSED_PARAMETER(notification);
1427         Gtkmm2ext::Application::instance()->ActivationChanged (false);
1428 }
1429
1430 @end
1431
1432 @interface GtkApplicationDelegate : NSObject
1433 -(BOOL) application:(NSApplication*) app openFile:(NSString*) file;
1434 - (NSApplicationTerminateReply) applicationShouldTerminate:(NSApplication *) app;
1435 - (void) startApp;
1436 @end
1437
1438 @implementation GtkApplicationDelegate
1439 -(BOOL) application:(NSApplication*) app openFile:(NSString*) file
1440 {
1441         UNUSED_PARAMETER(app);
1442         Glib::ustring utf8_path ([file UTF8String]);
1443         Gtkmm2ext::Application::instance()->ShouldLoad (utf8_path);
1444         return 1;
1445 }
1446 - (NSApplicationTerminateReply) applicationShouldTerminate:(NSApplication *) app
1447 {
1448         UNUSED_PARAMETER(app);
1449         Gtkmm2ext::Application::instance()->ShouldQuit ();
1450         return NSTerminateCancel;
1451 }
1452 @end
1453
1454
1455 /* Basic setup */
1456
1457 extern "C" int
1458 gtk_application_init ()
1459 {
1460         _main_menubar = [[NSMenu alloc] initWithTitle: @""];
1461
1462         if (!_main_menubar) 
1463                 return -1;
1464
1465         [NSApp setMainMenu: _main_menubar];
1466         create_apple_menu ();
1467         // create_window_menu ();
1468
1469         /* this will stick around for ever ... is that OK ? */
1470
1471         [ [GtkApplicationNotificationObject alloc] init];
1472         [ NSApp setDelegate: [GtkApplicationDelegate new]];
1473
1474         return 0;
1475 }
1476
1477 extern "C" void
1478 gtk_application_ready ()
1479 {
1480         [ NSApp finishLaunching ];
1481         [[NSApplication sharedApplication] activateIgnoringOtherApps : YES];
1482 }
1483
1484 extern "C" void
1485 gtk_application_hide ()
1486 {
1487     [NSApp performSelector:@selector(hide:)];
1488 }
1489
1490 extern "C" void
1491 gtk_application_cleanup()
1492 {
1493         _exiting = 1;
1494
1495         if (_window_menu) {
1496                 [ _window_menu release ];
1497                 _window_menu = 0;
1498         }
1499         if (_app_menu) {
1500                 [ _app_menu release ];
1501                 _app_menu = 0;
1502         }
1503         if (_main_menubar) {
1504                 [ _main_menubar release ];
1505                 _main_menubar = 0;
1506         }
1507 }