/* NeXT/Open/GNUstep and MacOSX Cocoa menu and toolbar module.
- Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc.
This file is part of GNU Emacs.
Christian Limpach, Scott Bender, Christophe de Dinechin) and code in the
Carbon version by Yamamoto Mitsuharu. */
+/* This should be the first include, as it may set up #defines affecting
+ interpretation of even the system includes. */
#include "config.h"
+
#include "lisp.h"
#include "window.h"
#include "buffer.h"
#include "termhooks.h"
#include "keyboard.h"
-/* for profiling */
+#define NSMENUPROFILE 0
+
+#if NSMENUPROFILE
#include <sys/timeb.h>
#include <sys/types.h>
+#endif
#define MenuStagger 10.0
#include "nsmenu_common.c"
#endif
-extern struct widget_value;
-
extern Lisp_Object Qundefined, Qmenu_enable, Qmenu_bar_update_hook;
extern Lisp_Object QCtoggle, QCradio;
Qoverriding_local_map, Qoverriding_terminal_local_map;
extern long context_menu_value;
-EmacsMenu *mainMenu, *svcsMenu;
+EmacsMenu *mainMenu, *svcsMenu, *dockMenu;
+
+/* Nonzero means a menu is currently active. */
+static int popup_activated_flag;
/* NOTE: toolbar implementation is at end,
following complete menu implementation. */
========================================================================== */
-/*23: FIXME: not currently used, but should normalize with other terms. */
+/* FIXME: not currently used, but should normalize with other terms. */
void
x_activate_menubar (struct frame *f)
{
}
+int
+popup_activated ()
+{
+ return popup_activated_flag;
+}
+
+
/* --------------------------------------------------------------------------
Update menubar. Three cases:
1) deep_p = 0, submenu = nil: Fresh switch onto a frame -- either set up
2) deep_p = 1, submenu = nil: Recompute all submenus.
3) deep_p = 1, submenu = non-nil: Update contents of a single submenu.
-------------------------------------------------------------------------- */
-/*#define NSMENUPROFILE 1 */
void
ns_update_menubar (struct frame *f, int deep_p, EmacsMenu *submenu)
{
widget_value *wv, *first_wv, *prev_wv = 0;
int i;
-#ifdef NSMENUPROFILE
+#if NSMENUPROFILE
struct timeb tb;
long t;
#endif
[attMenu close];
}
-#ifdef NSMENUPROFILE
+#if NSMENUPROFILE
ftime (&tb);
t = -(1000*tb.time+tb.millitm);
#endif
{
/* No change.. */
-#ifdef NSMENUPROFILE
+#if NSMENUPROFILE
ftime (&tb);
t += 1000*tb.time+tb.millitm;
fprintf (stderr, "NO CHANGE! CUTTING OUT after %ld msec.\n", t);
free_menubar_widget_value_tree (first_wv);
-#ifdef NSMENUPROFILE
+#if NSMENUPROFILE
ftime (&tb);
t += 1000*tb.time+tb.millitm;
fprintf (stderr, "Menu update took %ld msec.\n", t);
}
-/* parse a wdiget_value's key rep (examples: 's-p', 's-S', '(C-x C-s)', '<f13>')
- into an accelerator string */
+/* Parse a widget_value's key rep (examples: 's-p', 's-S', '(C-x C-s)', '<f13>')
+ into an accelerator string. We are only able to display a single character
+ for an accelerator, together with an optional modifier combination. (Under
+ Carbon more control was possible, but in Cocoa multi-char strings passed to
+ NSMenuItem get ignored. For now we try to display a super-single letter
+ combo, and return the others as strings to be appended to the item title.
+ (This is signaled by setting keyEquivModMask to 0 for now.) */
-(NSString *)parseKeyEquiv: (char *)key
{
char *tpos = key;
- keyEquivModMask = 0;
- /* currently we just parse 'super' combinations;
- later we'll set keyEquivModMask */
+ keyEquivModMask = NSCommandKeyMask;
+
if (!key || !strlen (key))
return @"";
while (*tpos == ' ' || *tpos == '(')
tpos++;
- if (*tpos != 's'/* || tpos[3] != ')'*/)
- return @"";
+ if (*tpos != 's') {
+ keyEquivModMask = 0; /* signal */
+ return [NSString stringWithUTF8String: tpos];
+ }
return [NSString stringWithFormat: @"%c", tpos[2]];
}
-- (id <NSMenuItem>)addItemWithWidgetValue: (void *)wvptr
+
+- (NSMenuItem *)addItemWithWidgetValue: (void *)wvptr
{
- id <NSMenuItem> item;
+ NSMenuItem *item;
widget_value *wv = (widget_value *)wvptr;
if (name_is_separator (wv->name))
title = @"< ? >"; /* (get out in the open so we know about it) */
keyEq = [self parseKeyEquiv: wv->key];
+ if (keyEquivModMask == 0)
+ title = [title stringByAppendingFormat: @" (%@)", keyEq];
item = [self addItemWithTitle: (NSString *)title
action: @selector (menuDown:)
keyEquivalent: keyEq];
- if (keyEquivModMask)
- [item setKeyEquivalentModifierMask: keyEquivModMask];
+ [item setKeyEquivalentModifierMask: keyEquivModMask];
[item setEnabled: wv->enabled];
/* add new contents */
for (; wv != NULL; wv = wv->next)
{
- id <NSMenuItem> item = [self addItemWithWidgetValue: wv];
+ NSMenuItem *item = [self addItemWithWidgetValue: wv];
if (wv->contents)
{
- (EmacsMenu *)addSubmenuWithTitle: (char *)title forFrame: (struct frame *)f
{
NSString *titleStr = [NSString stringWithUTF8String: title];
- id <NSMenuItem> item
- = [self addItemWithTitle: titleStr
- action: nil /*@selector (menuDown:) */
- keyEquivalent: @""];
+ NSMenuItem *item = [self addItemWithTitle: titleStr
+ action: nil /*@selector (menuDown:) */
+ keyEquivalent: @""];
EmacsMenu *submenu = [[EmacsMenu alloc] initWithTitle: titleStr frame: f];
[self setSubmenu: submenu forItem: item];
[submenu release];
#endif
wv_title->name = (char *) SDATA (title);
- wv_title->enabled = NULL;
+ wv_title->enabled = NO;
wv_title->button_type = BUTTON_TYPE_NONE;
wv_title->help = Qnil;
wv_title->next = wv_sep;
free_menubar_widget_value_tree (first_wv);
unbind_to (specpdl_count2, Qnil);
+ popup_activated_flag = 1;
tem = [pmenu runMenuAt: p forFrame: f keymaps: keymaps];
+ popup_activated_flag = 0;
[[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow];
UNBLOCK_INPUT;
+ discard_menu_items ();
unbind_to (specpdl_count, Qnil);
UNGCPRO;
isQ = NILP (header);
- if (EQ (position, Qt))
+ if (EQ (position, Qt)
+ || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar)
+ || EQ (XCAR (position), Qtool_bar))))
{
window = selected_window;
}
window = Fcar (tem); /* POSN_WINDOW (tem) */
}
}
- else if (FRAMEP (position))
+ else if (WINDOWP (position) || FRAMEP (position))
{
window = position;
}
else
- {
- CHECK_LIVE_WINDOW (position);
- window = position;
- }
-
+ window = Qnil;
+
if (FRAMEP (window))
f = XFRAME (window);
- else
+ else if (WINDOWP (window))
{
CHECK_LIVE_WINDOW (window);
f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
}
+ else
+ CHECK_WINDOW (window);
+
p.x = (int)f->left_pos + ((int)FRAME_COLUMN_WIDTH (f) * f->text_cols)/2;
p.y = (int)f->top_pos + (FRAME_LINE_HEIGHT (f) * f->text_lines)/2;
dialog = [[EmacsDialogPanel alloc] initFromContents: contents
isQuestion: isQ];
-
+ popup_activated_flag = 1;
tem = [dialog runDialogAt: p];
+ popup_activated_flag = 0;
[dialog close];
return self;
seltag = [[sellist objectAtIndex: 0] tag];
- if (seltag == XHASH (Qundefined)) // FIXME: BIG UGLY HACK!!
+ if (seltag != XHASH (Qundefined)) // FIXME: BIG UGLY HACK!!
[NSApp stopModalWithCode: seltag];
return self;
}
{
(e = [NSApp nextEventMatchingMask: NSAnyEventMask
untilDate: [NSDate distantFuture]
- inMode: NSEventTrackingRunLoopMode
+ inMode: NSModalPanelRunLoopMode
dequeue: NO]);
-/*fprintf (stderr, "ret = %d\te = %p\n", ret, e); */
+/*fprintf (stderr, "ret = %d\te = %p\n", ret, e);*/
}
[NSApp endModalSession: session];
return ns_popup_dialog (position, contents, header);
}
+DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, Smenu_or_popup_active_p, 0, 0, 0,
+ doc: /* Return t if a menu or popup dialog is active. */)
+ ()
+{
+ return popup_activated () ? Qt : Qnil;
+}
/* ==========================================================================
defsubr (&Sx_popup_menu);
defsubr (&Sx_popup_dialog);
defsubr (&Sns_reset_menu);
+ defsubr (&Smenu_or_popup_active_p);
staticpro (&menu_items);
menu_items = Qnil;