/* Nonzero means a menu is currently active. */
static int popup_activated_flag;
+static NSModalSession popupSession;
/* 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)
{
since key equivalents are handled through emacs.
On Leopard, even keystroke events generate SystemDefined events, but
their subtype is 8. */
- if ([event type] != NSSystemDefined || [event subtype] == 8)
+ if ([event type] != NSSystemDefined || [event subtype] == 8
+ /* Also, don't try this if from an event picked up asynchronously,
+ as lots of lisp evaluation happens in ns_update_menubar. */
+ || handling_signal != 0)
return;
/*fprintf (stderr, "Updating menu '%s'\n", [[self title] UTF8String]); NSLog (@"%@\n", event); */
ns_update_menubar (frame, 1, self);
}
-/* 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]];
}
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];
if (wv->contents)
{
- EmacsMenu *submenu = [[EmacsMenu alloc] initWithTitle: @"Submenu"];
+ EmacsMenu *submenu = [[EmacsMenu alloc] initWithTitle: [item title]];
[self setSubmenu: submenu forItem: item];
[submenu fillWithWidgetValue: wv->contents];
========================================================================== */
+
+static Lisp_Object
+pop_down_menu (Lisp_Object arg)
+{
+ struct Lisp_Save_Value *p = XSAVE_VALUE (arg);
+ popup_activated_flag = 0;
+ BLOCK_INPUT;
+ [NSApp endModalSession: popupSession];
+ [((EmacsDialogPanel *) (p->pointer)) close];
+ [[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow];
+ UNBLOCK_INPUT;
+ return Qnil;
+}
+
+
Lisp_Object
ns_popup_dialog (Lisp_Object position, Lisp_Object contents, Lisp_Object header)
{
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;
+
+ BLOCK_INPUT;
dialog = [[EmacsDialogPanel alloc] initFromContents: contents
isQuestion: isQ];
- popup_activated_flag = 1;
- tem = [dialog runDialogAt: p];
- popup_activated_flag = 0;
+ {
+ int specpdl_count = SPECPDL_INDEX ();
+ record_unwind_protect (pop_down_menu, make_save_value (dialog, 0));
+ popup_activated_flag = 1;
+ tem = [dialog runDialogAt: p];
+ popup_activated_flag = 0;
+ unbind_to (specpdl_count, Qnil);
+ }
[dialog close];
-
[[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow];
+ UNBLOCK_INPUT;
+
return tem;
}
- (Lisp_Object)runDialogAt: (NSPoint)p
{
- NSEvent *e;
- NSModalSession session;
int ret;
- [self center]; /*XXX p ignored? */
- [self orderFront: NSApp];
-
- session = [NSApp beginModalSessionForWindow: self];
- while ((ret = [NSApp runModalSession: session]) == NSRunContinuesResponse)
+ popupSession = [NSApp beginModalSessionForWindow: self];
+ while (popup_activated_flag
+ && (ret = [NSApp runModalSession: popupSession])
+ == NSRunContinuesResponse)
{
- (e = [NSApp nextEventMatchingMask: NSAnyEventMask
- untilDate: [NSDate distantFuture]
- inMode: NSEventTrackingRunLoopMode
- dequeue: NO]);
-/*fprintf (stderr, "ret = %d\te = %p\n", ret, e); */
+ /* Run this for timers.el, indep of atimers; might not return.
+ TODO: use return value to avoid calling every iteration. */
+ timer_check (1);
+ [NSThread sleepUntilDate: [NSDate dateWithTimeIntervalSinceNow: 0.1]];
}
- [NSApp endModalSession: session];
+ [NSApp endModalSession: popupSession];
- { // FIXME: BIG UGLY HACK!!!
+ { /* FIXME: BIG UGLY HACK!!! */
Lisp_Object tmp;
*(EMACS_INT*)(&tmp) = ret;
return tmp;
@end
-
/* ==========================================================================
Lisp definitions