/* NeXT/Open/GNUstep and MacOSX Cocoa menu and toolbar module.
- Copyright (C) 2007-2013 Free Software Foundation, Inc.
+ Copyright (C) 2007-2015 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include "nsmenu_common.c"
#endif
-extern Lisp_Object Qundefined, Qmenu_enable, Qmenu_bar_update_hook;
-extern Lisp_Object QCtoggle, QCradio;
-
-Lisp_Object Qdebug_on_next_call;
-extern Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
-
extern long context_menu_value;
EmacsMenu *mainMenu, *svcsMenu, *dockMenu;
/* parse stage 2: insert into lucid 'widget_value' structures
[comments in other terms say not to evaluate lisp code here] */
- wv = xmalloc_widget_value ();
- wv->name = "menubar";
- wv->value = 0;
- wv->enabled = 1;
+ wv = make_widget_value ("menubar", NULL, true, Qnil);
wv->button_type = BUTTON_TYPE_NONE;
- wv->help = Qnil;
first_wv = wv;
for (i = 0; i < 4*n; i += 4)
}
else
{
- [menu fillWithWidgetValue: first_wv->contents];
+ [menu fillWithWidgetValue: first_wv->contents frame: f];
}
}
int n;
Lisp_Object string;
- wv = xmalloc_widget_value ();
- wv->name = "menubar";
- wv->value = 0;
- wv->enabled = 1;
+ wv = make_widget_value ("menubar", NULL, true, Qnil);
wv->button_type = BUTTON_TYPE_NONE;
- wv->help = Qnil;
first_wv = wv;
/* Make widget-value tree w/ just the top level menu bar strings */
memcpy (previous_strings[i/4], SDATA (string),
min (10, SBYTES (string) + 1));
- wv = xmalloc_widget_value ();
- wv->name = SSDATA (string);
- wv->value = 0;
- wv->enabled = 1;
+ wv = make_widget_value (SSDATA (string), NULL, true, Qnil);
wv->button_type = BUTTON_TYPE_NONE;
- wv->help = Qnil;
wv->call_data = (void *) (intptr_t) (-1);
#ifdef NS_IMPL_COCOA
x_activate_menubar (struct frame *f)
{
#ifdef NS_IMPL_COCOA
- NSArray *a = [[NSApp mainMenu] itemArray];
- /* Update each submenu separately so ns_update_menubar doesn't reset
- the delegate. */
- int i = 0;
- while (i < [a count])
- {
- EmacsMenu *menu = (EmacsMenu *)[[a objectAtIndex:i] submenu];
- const char *title = [[menu title] UTF8String];
- if (strcmp (title, ns_get_pending_menu_title ()) == 0)
- {
- ns_update_menubar (f, true, menu);
- break;
- }
- ++i;
- }
+ ns_update_menubar (f, true, nil);
ns_check_pending_open_menu ();
#endif
}
/* override designated initializer */
- initWithTitle: (NSString *)title
{
+ frame = 0;
if ((self = [super initWithTitle: title]))
[self setAutoenablesItems: NO];
return self;
frame = f;
}
-#ifdef NS_IMPL_COCOA
-#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
-extern NSString *NSMenuDidBeginTrackingNotification;
-#endif
-#endif
-
#ifdef NS_IMPL_COCOA
-(void)trackingNotification:(NSNotification *)notification
{
/* Update menu in menuNeedsUpdate only while tracking menus. */
trackingMenu = ([notification name] == NSMenuDidBeginTrackingNotification
? 1 : 0);
+ if (! trackingMenu) ns_check_menu_open (nil);
}
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
- (void)menuWillOpen:(NSMenu *)menu
{
- ns_check_menu_open (menu);
-}
-#endif
+ ++trackingMenu;
+#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
+ // On 10.6 we get repeated calls, only the one for NSSystemDefined is "real".
+ if ([[NSApp currentEvent] type] != NSSystemDefined) return;
#endif
+ /* When dragging from one menu to another, we get willOpen followed by didClose,
+ i.e. trackingMenu == 3 in willOpen and then 2 after didClose.
+ We have updated all menus, so avoid doing it when trackingMenu == 3. */
+ if (trackingMenu == 2)
+ ns_check_menu_open (menu);
+}
+
+- (void)menuDidClose:(NSMenu *)menu
+{
+ --trackingMenu;
+}
+
+#endif /* NS_IMPL_COCOA */
+
/* delegate method called when a submenu is being opened: run a 'deep' call
to set_frame_menubar */
- (void)menuNeedsUpdate: (NSMenu *)menu
if (trackingMenu == 0)
return;
/*fprintf (stderr, "Updating menu '%s'\n", [[self title] UTF8String]); NSLog (@"%@\n", event); */
-#if ! defined(NS_IMPL_COCOA) || \
- MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
+#ifdef NS_IMPL_GNUSTEP
/* Don't know how to do this for anything other than OSX >= 10.5
This is wrong, as it might run Lisp code in the event loop. */
ns_update_menubar (frame, true, self);
{
NSMenuItem *item = [self itemAtIndex: n];
NSString *title = [item title];
- if (([title length] == 0 /* OSX 10.5 */
- || [ns_app_name isEqualToString: title] /* from 10.6 on */
- || [@"Apple" isEqualToString: title]) /* older */
+ if ([ns_app_name isEqualToString: title]
&& ![item isSeparatorItem])
continue;
[self removeItemAtIndex: n];
- (void)fillWithWidgetValue: (void *)wvptr
+{
+ [self fillWithWidgetValue: wvptr frame: (struct frame *)nil];
+}
+
+- (void)fillWithWidgetValue: (void *)wvptr frame: (struct frame *)f
{
widget_value *wv = (widget_value *)wvptr;
if (wv->contents)
{
- EmacsMenu *submenu = [[EmacsMenu alloc] initWithTitle: [item title]];
+ EmacsMenu *submenu;
+
+ if (f)
+ submenu = [[EmacsMenu alloc] initWithTitle: [item title] frame:f];
+ else
+ submenu = [[EmacsMenu alloc] initWithTitle: [item title]];
[self setSubmenu: submenu forItem: item];
[submenu fillWithWidgetValue: wv->contents];
========================================================================== */
Lisp_Object
-ns_menu_show (FRAME_PTR f, int x, int y, bool for_click, bool keymaps,
+ns_menu_show (struct frame *f, int x, int y, int menuflags,
Lisp_Object title, const char **error)
{
EmacsMenu *pmenu;
Lisp_Object tem;
ptrdiff_t specpdl_count = SPECPDL_INDEX ();
widget_value *wv, *first_wv = 0;
+ bool keymaps = (menuflags & MENU_KEYMAPS);
+
+ block_input ();
p.x = x; p.y = y;
/* now parse stage 2 as in ns_update_menubar */
- wv = xmalloc_widget_value ();
- wv->name = "contextmenu";
- wv->value = 0;
- wv->enabled = 1;
+ wv = make_widget_value ("contextmenu", NULL, true, Qnil);
wv->button_type = BUTTON_TYPE_NONE;
- wv->help = Qnil;
first_wv = wv;
#if 0
with its items as a submenu beneath it. */
if (!keymaps && strcmp (pane_string, ""))
{
- wv = xmalloc_widget_value ();
+ wv = make_widget_value (pane_string, NULL, true, Qnil);
if (save_wv)
save_wv->next = wv;
else
first_wv->contents = wv;
- wv->name = pane_string;
if (keymaps && !NILP (prefix))
wv->name++;
- wv->value = 0;
- wv->enabled = 1;
wv->button_type = BUTTON_TYPE_NONE;
- wv->help = Qnil;
save_wv = wv;
prev_wv = 0;
}
}
#endif /* not HAVE_MULTILINGUAL_MENU */
- wv = xmalloc_widget_value ();
+ wv = make_widget_value (SSDATA (item_name), NULL, !NILP (enable),
+ STRINGP (help) ? help : Qnil);
if (prev_wv)
prev_wv->next = wv;
else
save_wv->contents = wv;
- wv->name = SSDATA (item_name);
if (!NILP (descrip))
wv->key = SSDATA (descrip);
- wv->value = 0;
/* If this item has a null value,
make the call_data null so that it won't display a box
when the mouse is on it. */
wv->call_data = !NILP (def) ? aref_addr (menu_items, i) : 0;
- wv->enabled = !NILP (enable);
if (NILP (type))
wv->button_type = BUTTON_TYPE_NONE;
wv->selected = !NILP (selected);
- if (! STRINGP (help))
- help = Qnil;
-
- wv->help = help;
-
prev_wv = wv;
i += MENU_ITEMS_ITEM_LENGTH;
if (!NILP (title))
{
- widget_value *wv_title = xmalloc_widget_value ();
- widget_value *wv_sep = xmalloc_widget_value ();
+ widget_value *wv_title;
+ widget_value *wv_sep = make_widget_value ("--", NULL, false, Qnil);
/* Maybe replace this separator with a bitmap or owner-draw item
so that it looks better. Having two separators looks odd. */
- wv_sep->name = "--";
wv_sep->next = first_wv->contents;
- wv_sep->help = Qnil;
#ifndef HAVE_MULTILINGUAL_MENU
if (STRING_MULTIBYTE (title))
title = ENCODE_MENU_STRING (title);
#endif
-
- wv_title->name = SSDATA (title);
- wv_title->enabled = NO;
+ wv_title = make_widget_value (SSDATA (title), NULL, false, Qnil);
wv_title->button_type = BUTTON_TYPE_NONE;
- wv_title->help = Qnil;
wv_title->next = wv_sep;
first_wv->contents = wv_title;
}
popup_activated_flag = 0;
[[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow];
+ unblock_input ();
return tem;
}
========================================================================== */
void
-free_frame_tool_bar (FRAME_PTR f)
+free_frame_tool_bar (struct frame *f)
/* --------------------------------------------------------------------------
Under NS we just hide the toolbar until it might be needed again.
-------------------------------------------------------------------------- */
{
+ EmacsView *view = FRAME_NS_VIEW (f);
block_input ();
- [[FRAME_NS_VIEW (f) toolbar] setVisible: NO];
+ view->wait_for_tool_bar = NO;
+ [[view toolbar] setVisible: NO];
FRAME_TOOLBAR_HEIGHT (f) = 0;
unblock_input ();
}
void
-update_frame_tool_bar (FRAME_PTR f)
+update_frame_tool_bar (struct frame *f)
/* --------------------------------------------------------------------------
Update toolbar contents
-------------------------------------------------------------------------- */
EmacsView *view = FRAME_NS_VIEW (f);
NSWindow *window = [view window];
EmacsToolbar *toolbar = [view toolbar];
+ int oldh;
+ if (view == nil || toolbar == nil) return;
block_input ();
+ oldh = FRAME_TOOLBAR_HEIGHT (f);
+
#ifdef NS_IMPL_COCOA
[toolbar clearActive];
#else
/* Check if this is a separator. */
if (EQ (TOOLPROP (TOOL_BAR_ITEM_TYPE), Qt))
{
- /* Skip separators. Newer OSX don't show them, and on GNUStep they
+ /* Skip separators. Newer OSX don't show them, and on GNUstep they
are wide as a button, thus overflowing the toolbar most of
the time. */
continue;
FRAME_TOOLBAR_HEIGHT (f) =
NSHeight ([window frameRectForContentRect: NSMakeRect (0, 0, 0, 0)])
- FRAME_NS_TITLEBAR_HEIGHT (f);
- if (FRAME_TOOLBAR_HEIGHT (f) < 0) // happens if frame is fullscreen.
- FRAME_TOOLBAR_HEIGHT (f) = 0;
- unblock_input ();
+ if (FRAME_TOOLBAR_HEIGHT (f) < 0) // happens if frame is fullscreen.
+ FRAME_TOOLBAR_HEIGHT (f) = 0;
+
+ if (oldh != FRAME_TOOLBAR_HEIGHT (f))
+ [view updateFrameSize:YES];
+ if (view->wait_for_tool_bar && FRAME_TOOLBAR_HEIGHT (f) > 0)
+ {
+ view->wait_for_tool_bar = NO;
+ [view setNeedsDisplay: YES];
+ }
+
+ unblock_input ();
}
{
/* 1) come up w/identifier */
NSString *identifier
- = [NSString stringWithFormat: @"%u", [img hash]];
+ = [NSString stringWithFormat: @"%lu", (unsigned long)[img hash]];
[activeIdentifiers addObject: identifier];
/* 2) create / reuse item */
#ifdef NS_IMPL_GNUSTEP
[self insertItemWithItemIdentifier: identifier atIndex: idx];
#endif
-
+
[item setTag: tag];
[item setEnabled: enabled];
EmacsDialogPanel *dialog;
};
-static Lisp_Object
-pop_down_menu (Lisp_Object arg)
+static void
+pop_down_menu (void *arg)
{
- struct Popdown_data *unwind_data = XSAVE_POINTER (arg, 0);
+ struct Popdown_data *unwind_data = arg;
block_input ();
if (popup_activated_flag)
xfree (unwind_data);
unblock_input ();
-
- return Qnil;
}
Lisp_Object
-ns_popup_dialog (Lisp_Object position, Lisp_Object contents, Lisp_Object header)
+ns_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents)
{
id dialog;
- Lisp_Object window, tem, title;
- struct frame *f;
+ Lisp_Object tem, title;
NSPoint p;
BOOL isQ;
NSAutoreleasePool *pool;
isQ = NILP (header);
- if (EQ (position, Qt)
- || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar)
- || EQ (XCAR (position), Qtool_bar))))
- {
- window = selected_window;
- }
- else if (CONSP (position))
- {
- Lisp_Object tem;
- tem = Fcar (position);
- if (XTYPE (tem) == Lisp_Cons)
- window = Fcar (Fcdr (position));
- else
- {
- tem = Fcar (Fcdr (position)); /* EVENT_START (position) */
- window = Fcar (tem); /* POSN_WINDOW (tem) */
- }
- }
- else if (WINDOWP (position) || FRAMEP (position))
- {
- window = position;
- }
- else
- window = Qnil;
-
- if (FRAMEP (window))
- f = XFRAME (window);
- else if (WINDOWP (window))
- {
- CHECK_LIVE_WINDOW (window);
- f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
- }
- else
- CHECK_WINDOW (window);
-
check_window_system (f);
p.x = (int)f->left_pos + ((int)FRAME_COLUMN_WIDTH (f) * f->text_cols)/2;
if (NILP (Fcar (Fcdr (contents))))
/* No buttons specified, add an "Ok" button so users can pop down
the dialog. */
- contents = Fcons (title, Fcons (Fcons (build_string ("Ok"), Qt), Qnil));
+ contents = list2 (title, Fcons (build_string ("Ok"), Qt));
block_input ();
pool = [[NSAutoreleasePool alloc] init];
unwind_data->pool = pool;
unwind_data->dialog = dialog;
- record_unwind_protect (pop_down_menu, make_save_pointer (unwind_data));
+ record_unwind_protect_ptr (pop_down_menu, unwind_data);
popup_activated_flag = 1;
tem = [dialog runDialogAt: p];
unbind_to (specpdl_count, Qnil); /* calls pop_down_menu */
area.size.width = ICONSIZE;
area.size.height= ICONSIZE;
img = [[NSImage imageNamed: @"NSApplicationIcon"] copy];
+#ifdef NS_IMPL_COCOA
+#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6
[img setScalesWhenResized: YES];
+#endif
+#endif
[img setSize: NSMakeSize (ICONSIZE, ICONSIZE)];
imgView = [[NSImageView alloc] initWithFrame: area];
[imgView setImage: img];
}
if (buttons > 0)
- button_values = (Lisp_Object *) xmalloc (buttons * sizeof (*button_values));
+ button_values = xmalloc (buttons * sizeof *button_values);
for (; XTYPE (list) == Lisp_Cons; list = XCDR (list))
{
while (popup_activated_flag)
{
NSTimer *tmo = nil;
- EMACS_TIME next_time = timer_check ();
+ struct timespec next_time = timer_check ();
- if (EMACS_TIME_VALID_P (next_time))
+ if (timespec_valid_p (next_time))
{
- double time = EMACS_TIME_TO_DOUBLE (next_time);
+ double time = timespectod (next_time);
tmo = [NSTimer timerWithTimeInterval: time
target: self
selector: @selector (timeout_handler:)
}
-DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 3, 0,
- doc: /* Pop up a dialog box and return user's selection.
-POSITION specifies which frame to use.
-This is normally a mouse button event or a window or frame.
-If POSITION is t, it means to use the frame the mouse is on.
-The dialog box appears in the middle of the specified frame.
-
-CONTENTS specifies the alternatives to display in the dialog box.
-It is a list of the form (DIALOG ITEM1 ITEM2...).
-Each ITEM is a cons cell (STRING . VALUE).
-The return value is VALUE from the chosen item.
-
-An ITEM may also be just a string--that makes a nonselectable item.
-An ITEM may also be nil--that means to put all preceding items
-on the left of the dialog box and all following items on the right.
-\(By default, approximately half appear on each side.)
-
-If HEADER is non-nil, the frame title for the box is "Information",
-otherwise it is "Question".
-
-If the user gets rid of the dialog box without making a valid choice,
-for instance using the window manager, then this produces a quit and
-`x-popup-dialog' does not return. */)
- (Lisp_Object position, Lisp_Object contents, Lisp_Object header)
-{
- 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. */)
(void)
syms_of_nsmenu (void)
{
#ifndef NS_IMPL_COCOA
- /* Don't know how to keep track of this in Next/Open/Gnustep. Always
+ /* Don't know how to keep track of this in Next/Open/GNUstep. Always
update menus there. */
trackingMenu = 1;
#endif
- defsubr (&Sx_popup_dialog);
defsubr (&Sns_reset_menu);
defsubr (&Smenu_or_popup_active_p);
- Qdebug_on_next_call = intern_c_string ("debug-on-next-call");
- staticpro (&Qdebug_on_next_call);
+ DEFSYM (Qdebug_on_next_call, "debug-on-next-call");
}