}
+/* tabbar support */
+static void
+ns_set_tab_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
+{
+ /* Currently, when the tab bar changes state, the frame is resized.
+
+ TODO: It would be better if this didn't occur when 1) the frame
+ is full height or maximized or 2) when specified by
+ `frame-inhibit-implied-resize'. */
+ int nlines;
+
+ NSTRACE ("ns_set_tab_bar_lines");
+
+ if (FRAME_MINIBUF_ONLY_P (f))
+ return;
+
+ if (RANGED_FIXNUMP (0, value, INT_MAX))
+ nlines = XFIXNAT (value);
+ else
+ nlines = 0;
+
+ if (nlines)
+ {
+ FRAME_EXTERNAL_TAB_BAR (f) = 1;
+ update_frame_tab_bar (f);
+ }
+ else
+ {
+ if (FRAME_EXTERNAL_TAB_BAR (f))
+ {
+ free_frame_tab_bar (f);
+ FRAME_EXTERNAL_TAB_BAR (f) = 0;
+
+ {
+ EmacsView *view = FRAME_NS_VIEW (f);
+ int fs_state = [view fullscreenState];
+
+ if (fs_state == FULLSCREEN_MAXIMIZED)
+ {
+ [view setFSValue:FULLSCREEN_WIDTH];
+ }
+ else if (fs_state == FULLSCREEN_HEIGHT)
+ {
+ [view setFSValue:FULLSCREEN_NONE];
+ }
+ }
+ }
+ }
+
+ {
+ int inhibit
+ = ((f->after_make_frame
+ && !f->tab_bar_resized
+ && (EQ (frame_inhibit_implied_resize, Qt)
+ || (CONSP (frame_inhibit_implied_resize)
+ && !NILP (Fmemq (Qtab_bar_lines,
+ frame_inhibit_implied_resize))))
+ && NILP (get_frame_param (f, Qfullscreen)))
+ ? 0
+ : 2);
+
+ NSTRACE_MSG ("inhibit:%d", inhibit);
+
+ frame_size_history_add (f, Qupdate_frame_tab_bar, 0, 0, Qnil);
+ adjust_frame_size (f, -1, -1, inhibit, 0, Qtab_bar_lines);
+ }
+}
+
+
/* toolbar support */
static void
ns_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
gui_set_vertical_scroll_bars, /* generic OK */
gui_set_horizontal_scroll_bars, /* generic OK */
gui_set_visibility, /* generic OK */
+ ns_set_tab_bar_lines,
ns_set_tool_bar_lines,
0, /* x_set_scroll_bar_foreground, will ignore (not possible on NS) */
0, /* x_set_scroll_bar_background, will ignore (not possible on NS) */
NILP (Vmenu_bar_mode)
? make_fixnum (0) : make_fixnum (1),
NULL, NULL, RES_TYPE_NUMBER);
+ gui_default_parameter (f, parms, Qtab_bar_lines,
+ NILP (Vtab_bar_mode)
+ ? make_fixnum (0) : make_fixnum (1),
+ NULL, NULL, RES_TYPE_NUMBER);
gui_default_parameter (f, parms, Qtool_bar_lines,
NILP (Vtool_bar_mode)
? make_fixnum (0) : make_fixnum (1),
int native_right = f->left_pos + outer_width - border;
int native_bottom = f->top_pos + outer_height - border;
int internal_border_width = FRAME_INTERNAL_BORDER_WIDTH (f);
+ int tab_bar_height = FRAME_TABBAR_HEIGHT (f);
+ int tab_bar_width = (tab_bar_height
+ ? outer_width - 2 * internal_border_width
+ : 0);
int tool_bar_height = FRAME_TOOLBAR_HEIGHT (f);
int tool_bar_width = (tool_bar_height
? outer_width - 2 * internal_border_width
native_right, native_bottom);
else if (EQ (attribute, Qinner_edges))
return list4i (native_left + internal_border_width,
- native_top + tool_bar_height + internal_border_width,
+ native_top + tab_bar_height + tool_bar_height + internal_border_width,
native_right - internal_border_width,
native_bottom - internal_border_width);
else
Fcons (make_fixnum (0), make_fixnum (title_height))),
Fcons (Qmenu_bar_external, Qnil),
Fcons (Qmenu_bar_size, Fcons (make_fixnum (0), make_fixnum (0))),
+ Fcons (Qtab_bar_size,
+ Fcons (make_fixnum (tab_bar_width),
+ make_fixnum (tab_bar_height))),
Fcons (Qtool_bar_external,
FRAME_EXTERNAL_TOOL_BAR (f) ? Qt : Qnil),
Fcons (Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f)),
`menu-bar-size' is a cons of the width and height of the menu bar of
FRAME.
+`tab-bar-size' is a cons of the width and height of the tab bar of
+ FRAME.
+
`tool-bar-external', if non-nil, means the tool bar is external (never
included in the inner edges of FRAME).
}
+/* ==========================================================================
+
+ Tabbar: externally-called functions
+
+ ========================================================================== */
+
+void
+free_frame_tab_bar (struct frame *f)
+/* --------------------------------------------------------------------------
+ Under NS we just hide the tabbar until it might be needed again.
+ -------------------------------------------------------------------------- */
+{
+ EmacsView *view = FRAME_NS_VIEW (f);
+
+ NSTRACE ("free_frame_tab_bar");
+
+ block_input ();
+ view->wait_for_tab_bar = NO;
+
+ /* Note: This triggers an animation, which calls windowDidResize
+ repeatedly. */
+ f->output_data.ns->in_animation = 1;
+ [[view tabbar] setVisible: NO];
+ f->output_data.ns->in_animation = 0;
+
+ unblock_input ();
+}
+
+void
+update_frame_tab_bar (struct frame *f)
+/* --------------------------------------------------------------------------
+ Update tabbar contents.
+ -------------------------------------------------------------------------- */
+{
+ int i, k = 0;
+ EmacsView *view = FRAME_NS_VIEW (f);
+ EmacsTabbar *tabbar = [view tabbar];
+ int oldh;
+
+ NSTRACE ("update_frame_tab_bar");
+
+ if (view == nil || tabbar == nil) return;
+ block_input ();
+
+ oldh = FRAME_TABBAR_HEIGHT (f);
+
+#ifdef NS_IMPL_COCOA
+ [tabbar clearActive];
+#else
+ [tabbar clearAll];
+#endif
+
+ /* Update EmacsTabbar as in GtkUtils, build items list. */
+ for (i = 0; i < f->n_tab_bar_items; ++i)
+ {
+#define TABPROP(IDX) AREF (f->tab_bar_items, \
+ i * TAB_BAR_ITEM_NSLOTS + (IDX))
+
+ BOOL enabled_p = !NILP (TABPROP (TAB_BAR_ITEM_ENABLED_P));
+ int idx;
+ ptrdiff_t img_id;
+ struct image *img;
+ Lisp_Object image;
+ Lisp_Object helpObj;
+ const char *helpText;
+
+ /* Check if this is a separator. */
+ if (EQ (TABPROP (TAB_BAR_ITEM_TYPE), Qt))
+ {
+ /* Skip separators. Newer macOS don't show them, and on
+ GNUstep they are wide as a button, thus overflowing the
+ tabbar most of the time. */
+ continue;
+ }
+
+ /* If image is a vector, choose the image according to the
+ button state. */
+ image = TABPROP (TAB_BAR_ITEM_IMAGES);
+ if (VECTORP (image))
+ {
+ /* NS tabbar auto-computes disabled and selected images. */
+ idx = TAB_BAR_IMAGE_ENABLED_SELECTED;
+ eassert (ASIZE (image) >= idx);
+ image = AREF (image, idx);
+ }
+ else
+ {
+ idx = -1;
+ }
+ helpObj = TABPROP (TAB_BAR_ITEM_HELP);
+ if (NILP (helpObj))
+ helpObj = TABPROP (TAB_BAR_ITEM_CAPTION);
+ helpText = NILP (helpObj) ? "" : SSDATA (helpObj);
+
+ /* Ignore invalid image specifications. */
+ if (!valid_image_p (image))
+ {
+ /* Don't log anything, GNUS makes invalid images all the time. */
+ continue;
+ }
+
+ img_id = lookup_image (f, image);
+ img = IMAGE_FROM_ID (f, img_id);
+ prepare_image_for_display (f, img);
+
+ if (img->load_failed_p || img->pixmap == nil)
+ {
+ NSLog (@"Could not prepare tabbar image for display.");
+ continue;
+ }
+
+ [tabbar addDisplayItemWithImage: img->pixmap
+ idx: k++
+ tag: i
+ helpText: helpText
+ enabled: enabled_p];
+#undef TABPROP
+ }
+
+ if (![tabbar isVisible])
+ {
+ f->output_data.ns->in_animation = 1;
+ [tabbar setVisible: YES];
+ f->output_data.ns->in_animation = 0;
+ }
+
+#ifdef NS_IMPL_COCOA
+ if ([tabbar changed])
+ {
+ /* Inform app that tabbar has changed. */
+ NSDictionary *dict = [tabbar configurationDictionary];
+ NSMutableDictionary *newDict = [dict mutableCopy];
+ NSEnumerator *keys = [[dict allKeys] objectEnumerator];
+ id key;
+ while ((key = [keys nextObject]) != nil)
+ {
+ NSObject *val = [dict objectForKey: key];
+ if ([val isKindOfClass: [NSArray class]])
+ {
+ [newDict setObject:
+ [tabbar tabbarDefaultItemIdentifiers: tabbar]
+ forKey: key];
+ break;
+ }
+ }
+ [tabbar setConfigurationFromDictionary: newDict];
+ [newDict release];
+ }
+#endif
+
+ if (oldh != FRAME_TABBAR_HEIGHT (f))
+ [view updateFrameSize:YES];
+ if (view->wait_for_tab_bar && FRAME_TABBAR_HEIGHT (f) > 0)
+ {
+ view->wait_for_tab_bar = NO;
+ [view setNeedsDisplay: YES];
+ }
+
+ unblock_input ();
+}
+
+
+/* ==========================================================================
+
+ Tabbar: class implementation
+
+ ========================================================================== */
+
+@implementation EmacsTabbar
+
+- (instancetype)initForView: (EmacsView *)view withIdentifier: (NSString *)identifier
+{
+ NSTRACE ("[EmacsTabbar initForView: withIdentifier:]");
+
+ self = [super initWithIdentifier: identifier];
+ emacsView = view;
+ [self setDisplayMode: NSTabbarDisplayModeIconOnly];
+ [self setSizeMode: NSTabbarSizeModeSmall];
+ [self setDelegate: self];
+ identifierToItem = [[NSMutableDictionary alloc] initWithCapacity: 10];
+ activeIdentifiers = [[NSMutableArray alloc] initWithCapacity: 8];
+ prevIdentifiers = nil;
+ prevEnablement = enablement = 0L;
+ return self;
+}
+
+- (void)dealloc
+{
+ NSTRACE ("[EmacsTabbar dealloc]");
+
+ [prevIdentifiers release];
+ [activeIdentifiers release];
+ [identifierToItem release];
+ [super dealloc];
+}
+
+- (void) clearActive
+{
+ NSTRACE ("[EmacsTabbar clearActive]");
+
+ [prevIdentifiers release];
+ prevIdentifiers = [activeIdentifiers copy];
+ [activeIdentifiers removeAllObjects];
+ prevEnablement = enablement;
+ enablement = 0L;
+}
+
+- (void) clearAll
+{
+ NSTRACE ("[EmacsTabbar clearAll]");
+
+ [self clearActive];
+ while ([[self items] count] > 0)
+ [self removeItemAtIndex: 0];
+}
+
+- (BOOL) changed
+{
+ NSTRACE ("[EmacsTabbar changed]");
+
+ return [activeIdentifiers isEqualToArray: prevIdentifiers] &&
+ enablement == prevEnablement ? NO : YES;
+}
+
+- (void) addDisplayItemWithImage: (EmacsImage *)img
+ idx: (int)idx
+ tag: (int)tag
+ helpText: (const char *)help
+ enabled: (BOOL)enabled
+{
+ NSTRACE ("[EmacsTabbar addDisplayItemWithImage: ...]");
+
+ /* 1) come up w/identifier */
+ NSString *identifier
+ = [NSString stringWithFormat: @"%lu", (unsigned long)[img hash]];
+ [activeIdentifiers addObject: identifier];
+
+ /* 2) create / reuse item */
+ NSTabbarItem *item = [identifierToItem objectForKey: identifier];
+ if (item == nil)
+ {
+ item = [[[NSTabbarItem alloc] initWithItemIdentifier: identifier]
+ autorelease];
+ [item setImage: img];
+ [item setTabTip: [NSString stringWithUTF8String: help]];
+ [item setTarget: emacsView];
+ [item setAction: @selector (tabbarClicked:)];
+ [identifierToItem setObject: item forKey: identifier];
+ }
+
+#ifdef NS_IMPL_GNUSTEP
+ [self insertItemWithItemIdentifier: identifier atIndex: idx];
+#endif
+
+ [item setTag: tag];
+ [item setEnabled: enabled];
+
+ /* 3) update state */
+ enablement = (enablement << 1) | (enabled == YES);
+}
+
+/* This overrides super's implementation, which automatically sets
+ all items to enabled state (for some reason). */
+- (void)validateVisibleItems
+{
+ NSTRACE ("[EmacsTabbar validateVisibleItems]");
+}
+
+
+/* delegate methods */
+
+- (NSTabbarItem *)tabbar: (NSTabbar *)tabbar
+ itemForItemIdentifier: (NSString *)itemIdentifier
+ willBeInsertedIntoTabbar: (BOOL)flag
+{
+ NSTRACE ("[EmacsTabbar tabbar: ...]");
+
+ /* Look up NSTabbarItem by identifier and return... */
+ return [identifierToItem objectForKey: itemIdentifier];
+}
+
+- (NSArray *)tabbarDefaultItemIdentifiers: (NSTabbar *)tabbar
+{
+ NSTRACE ("[EmacsTabbar tabbarDefaultItemIdentifiers:]");
+
+ /* Return entire set. */
+ return activeIdentifiers;
+}
+
+/* for configuration palette (not yet supported) */
+- (NSArray *)tabbarAllowedItemIdentifiers: (NSTabbar *)tabbar
+{
+ NSTRACE ("[EmacsTabbar tabbarAllowedItemIdentifiers:]");
+
+ /* return entire set... */
+ return activeIdentifiers;
+ //return [identifierToItem allKeys];
+}
+
+- (void)setVisible:(BOOL)shown
+{
+ NSTRACE ("[EmacsTabbar setVisible:%d]", shown);
+
+ [super setVisible:shown];
+}
+
+
+/* optional and unneeded */
+/* - tabbarWillAddItem: (NSNotification *)notification { } */
+/* - tabbarDidRemoveItem: (NSNotification *)notification { } */
+/* - (NSArray *)tabbarSelectableItemIdentifiers: (NSTabbar *)tabbar */
+
+@end /* EmacsTabbar */
+
+
+
/* ==========================================================================
Toolbar: externally-called functions
========================================================================== */
+@class EmacsTabbar;
@class EmacsToolbar;
#ifdef NS_IMPL_COCOA
struct frame *emacsframe;
int rows, cols;
int scrollbarsNeedingUpdate;
+ EmacsTabbar *tabbar;
EmacsToolbar *toolbar;
NSRect ns_userRect;
+ BOOL wait_for_tab_bar;
BOOL wait_for_tool_bar;
}
/* AppKit-side interface */
- (instancetype)menuDown: (id)sender;
+- (instancetype)tabbarClicked: (id)item;
- (instancetype)toolbarClicked: (id)item;
+- (instancetype)toggleTabbar: (id)sender;
- (instancetype)toggleToolbar: (id)sender;
- (void)keyDown: (NSEvent *)theEvent;
- (void)mouseDown: (NSEvent *)theEvent;
/* Emacs-side interface */
- (instancetype) initFrameFromEmacs: (struct frame *) f;
+- (void) createTabbar: (struct frame *)f;
- (void) createToolbar: (struct frame *)f;
- (void) setRows: (int) r andColumns: (int) c;
- (void) setWindowClosing: (BOOL)closing;
+- (EmacsTabbar *) tabbar;
- (EmacsToolbar *) toolbar;
- (void) deleteWorkingText;
- (void) updateFrameSize: (BOOL) delay;
@end
+/* ==========================================================================
+
+ Tabbar
+
+ ========================================================================== */
+
+@class EmacsImage;
+
+#ifdef NS_IMPL_COCOA
+@interface EmacsTabbar : NSTabbar <NSTabbarDelegate>
+#else
+@interface EmacsTabbar : NSTabbar
+#endif
+ {
+ EmacsView *emacsView;
+ NSMutableDictionary *identifierToItem;
+ NSMutableArray *activeIdentifiers;
+ NSArray *prevIdentifiers;
+ unsigned long enablement, prevEnablement;
+ }
+- (instancetype) initForView: (EmacsView *)view withIdentifier: (NSString *)identifier;
+- (void) clearActive;
+- (void) clearAll;
+- (BOOL) changed;
+- (void) addDisplayItemWithImage: (EmacsImage *)img
+ idx: (int)idx
+ tag: (int)tag
+ helpText: (const char *)help
+ enabled: (BOOL)enabled;
+
+/* delegate methods */
+- (NSTabbarItem *)tabbar: (NSTabbar *)tabbar
+ itemForItemIdentifier: (NSString *)itemIdentifier
+ willBeInsertedIntoTabbar: (BOOL)flag;
+- (NSArray *)tabbarDefaultItemIdentifiers: (NSTabbar *)tabbar;
+- (NSArray *)tabbarAllowedItemIdentifiers: (NSTabbar *)tabbar;
+@end
+
+
/* ==========================================================================
Toolbar
#define KEY_NS_NEW_FRAME ((1<<28)|(0<<16)|12)
#define KEY_NS_TOGGLE_TOOLBAR ((1<<28)|(0<<16)|13)
#define KEY_NS_SHOW_PREFS ((1<<28)|(0<<16)|14)
+#define KEY_NS_TOGGLE_TABBAR ((1<<28)|(0<<16)|15)
/* Could use list to store these, but rest of emacs has a big infrastructure
for managing a table of bitmap "records". */
NSColor *cursor_color;
NSColor *foreground_color;
NSColor *background_color;
+ EmacsTabbar *tabbar;
EmacsToolbar *toolbar;
#else
void *view;
void *cursor_color;
void *foreground_color;
void *background_color;
+ void *tabbar;
void *toolbar;
#endif
/* The height of the titlebar decoration (included in NSWindow's frame). */
int titlebar_height;
+ /* The height of the tabbar if displayed, else 0. */
+ int tabbar_height;
+
/* The height of the toolbar if displayed, else 0. */
int toolbar_height;
[[FRAME_NS_VIEW (f) window] frame] \
styleMask:[[FRAME_NS_VIEW (f) window] styleMask]])))
+/* Compute pixel height of the tabbar. */
+#define FRAME_TABBAR_HEIGHT(f) \
+ (([[FRAME_NS_VIEW (f) window] tabbar] == nil \
+ || ! [[FRAME_NS_VIEW (f) window] tabbar].isVisible) ? \
+ 0 \
+ : (int)(NSHeight([NSWindow contentRectForFrameRect: \
+ [[FRAME_NS_VIEW (f) window] frame] \
+ styleMask:[[FRAME_NS_VIEW (f) window] styleMask]]) \
+ - NSHeight([[[FRAME_NS_VIEW (f) window] contentView] frame])))
+
/* Compute pixel height of the toolbar. */
#define FRAME_TOOLBAR_HEIGHT(f) \
(([[FRAME_NS_VIEW (f) window] toolbar] == nil \
extern void ns_init_locale (void);
/* in nsmenu */
+extern void update_frame_tab_bar (struct frame *f);
+extern void free_frame_tab_bar (struct frame *f);
extern void update_frame_tool_bar (struct frame *f);
extern void free_frame_tool_bar (struct frame *f);
extern Lisp_Object find_and_return_menu_selection (struct frame *f,
#define NSWindowCollectionBehaviorFullScreenPrimary (1 << 7)
#define NSApplicationPresentationFullScreen (1 << 10)
#define NSApplicationPresentationAutoHideToolbar (1 << 11)
+#define NSApplicationPresentationAutoHideTabbar (1 << 12)
#define NSAppKitVersionNumber10_7 1138
#endif /* !defined (MAC_OS_X_VERSION_10_7) */
if ([view isFullscreen] && [view fsIsNative])
{
- // Fix reappearing tool bar in fullscreen for Mac OS X 10.7
- BOOL tbar_visible = FRAME_EXTERNAL_TOOL_BAR (f) ? YES : NO;
+ // Fix reappearing tool bar or tab bar in fullscreen for Mac OS X 10.7
+ BOOL tarbar_visible = FRAME_EXTERNAL_TAB_BAR (f) ? YES : NO;
+ NSTabbar *tabbar = [FRAME_NS_VIEW (f) tabbar];
+ if (! tarbar_visible != ! [tabbar isVisible])
+ [tabbar setVisible: tarbar_visible];
+ BOOL toolbar_visible = FRAME_EXTERNAL_TOOL_BAR (f) ? YES : NO;
NSToolbar *toolbar = [FRAME_NS_VIEW (f) toolbar];
- if (! tbar_visible != ! [toolbar isVisible])
- [toolbar setVisible: tbar_visible];
+ if (! toolbar_visible != ! [toolbar isVisible])
+ [toolbar setVisible: toolbar_visible];
}
#endif
}
f->top_pos = f->size_hint_flags & YNegative
? ([screen visibleFrame].size.height + f->top_pos
- FRAME_PIXEL_HEIGHT (f) - FRAME_NS_TITLEBAR_HEIGHT (f)
- - FRAME_TOOLBAR_HEIGHT (f))
+ - FRAME_TABBAR_HEIGHT (f) - FRAME_TOOLBAR_HEIGHT (f))
: f->top_pos;
#ifdef NS_IMPL_GNUSTEP
if (f->left_pos < 100)
f->left_pos = FRAME_PIXEL_WIDTH (parent) - FRAME_PIXEL_WIDTH (f) + f->left_pos;
if (f->top_pos < 0)
- f->top_pos = FRAME_PIXEL_HEIGHT (parent) + FRAME_TOOLBAR_HEIGHT (parent)
+ f->top_pos = FRAME_PIXEL_HEIGHT (parent) + FRAME_TABBAR_HEIGHT (parent) + FRAME_TOOLBAR_HEIGHT (parent)
- FRAME_PIXEL_HEIGHT (f) + f->top_pos;
}
wr.size.height = pixelheight;
if (! [view isFullscreen])
wr.size.height += FRAME_NS_TITLEBAR_HEIGHT (f)
+ + FRAME_TABBAR_HEIGHT (f)
+ FRAME_TOOLBAR_HEIGHT (f);
/* Do not try to constrain to this screen. We may have multiple
Fcons (make_fixnum (wr.size.width), make_fixnum (wr.size.height)),
make_fixnum (f->border_width),
make_fixnum (FRAME_NS_TITLEBAR_HEIGHT (f)),
- make_fixnum (FRAME_TOOLBAR_HEIGHT (f))));
+ make_fixnum (FRAME_TABBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f))));
[window setFrame: wr display: YES];
[window setStyleMask: ((window.styleMask | FRAME_DECORATED_FLAGS)
^ FRAME_UNDECORATED_FLAGS)];
+ [view createTabbar: f];
[view createToolbar: f];
}
else
{
+ [window setTabbar: nil];
[window setToolbar: nil];
/* Do I need to release the toolbar here? */
CGPoint mouse_pos =
CGPointMake(f->left_pos + pix_x,
f->top_pos + pix_y +
- FRAME_NS_TITLEBAR_HEIGHT(f) + FRAME_TOOLBAR_HEIGHT(f));
+ FRAME_NS_TITLEBAR_HEIGHT(f) + FRAME_TABBAR_HEIGHT(f) + FRAME_TOOLBAR_HEIGHT(f));
CGWarpMouseCursorPosition (mouse_pos);
#endif
}
- (void)dealloc
{
NSTRACE ("[EmacsView dealloc]");
+ [tabbar release];
[toolbar release];
if (fs_state == FULLSCREEN_BOTH)
[nonfs_window release];
if (! [self isFullscreen])
{
+ int tabbar_height;
int toolbar_height;
#ifdef NS_IMPL_GNUSTEP
// GNUstep does not always update the tool bar height. Force it.
if (toolbar && [toolbar isVisible])
update_frame_tool_bar (emacsframe);
+ if (tabbar && [tabbar isVisible])
+ update_frame_tab_bar (emacsframe);
#endif
+ tabbar_height = FRAME_TABBAR_HEIGHT (emacsframe);
+ if (tabbar_height < 0)
+ tabbar_height = 35;
+
toolbar_height = FRAME_TOOLBAR_HEIGHT (emacsframe);
if (toolbar_height < 0)
toolbar_height = 35;
extra = FRAME_NS_TITLEBAR_HEIGHT (emacsframe)
- + toolbar_height;
+ + tabbar_height + toolbar_height;
+ }
+
+ if (wait_for_tab_bar)
+ {
+ /* The tabbar height is always 0 in fullscreen and undecorated
+ frames, so don't wait for it to become available. */
+ if (FRAME_TABBAR_HEIGHT (emacsframe) == 0
+ && FRAME_UNDECORATED (emacsframe) == false
+ && ! [self isFullscreen])
+ {
+ NSTRACE_MSG ("Waiting for tabbar");
+ return;
+ }
+ wait_for_tab_bar = NO;
}
if (wait_for_tool_bar)
newh = (int)wr.size.height - extra;
NSTRACE_SIZE ("New size", NSMakeSize (neww, newh));
+ NSTRACE_MSG ("FRAME_TABBAR_HEIGHT: %d", FRAME_TABBAR_HEIGHT (emacsframe));
NSTRACE_MSG ("FRAME_TOOLBAR_HEIGHT: %d", FRAME_TOOLBAR_HEIGHT (emacsframe));
NSTRACE_MSG ("FRAME_NS_TITLEBAR_HEIGHT: %d", FRAME_NS_TITLEBAR_HEIGHT (emacsframe));
if (! [self isFullscreen])
{
extra = FRAME_NS_TITLEBAR_HEIGHT (emacsframe)
+ + FRAME_TABBAR_HEIGHT (emacsframe)
+ FRAME_TOOLBAR_HEIGHT (emacsframe);
}
}
+- (void)createTabbar: (struct frame *)f
+{
+ EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f);
+ NSWindow *window = [view window];
+
+ tabbar = [[EmacsTabbar alloc] initForView: self withIdentifier:
+ [NSString stringWithFormat: @"Emacs Frame %d",
+ ns_window_num]];
+ [tabbar setVisible: NO];
+ [window setTabbar: tabbar];
+
+ /* Don't set frame garbaged until tab bar is up to date?
+ This avoids an extra clear and redraw (flicker) at frame creation. */
+ if (FRAME_EXTERNAL_TAB_BAR (f)) wait_for_tab_bar = YES;
+ else wait_for_tab_bar = NO;
+
+
+#ifdef NS_IMPL_COCOA
+ {
+ NSButton *toggleButton;
+ toggleButton = [window standardWindowButton: NSWindowTabbarButton];
+ [toggleButton setTarget: self];
+ [toggleButton setAction: @selector (toggleTabbar: )];
+ }
+#endif
+}
+
+
- (void)createToolbar: (struct frame *)f
{
EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f);
NILP (tem) ? "Emacs" : SSDATA (tem)];
[win setTitle: name];
+ /* tabbar support */
+ if (! FRAME_UNDECORATED (f))
+ [self createTabbar: f];
+
/* toolbar support */
if (! FRAME_UNDECORATED (f))
[self createToolbar: f];
willUseFullScreenPresentationOptions:
(NSApplicationPresentationOptions)proposedOptions
{
- return proposedOptions|NSApplicationPresentationAutoHideToolbar;
+ return proposedOptions|NSApplicationPresentationAutoHideTabbar|NSApplicationPresentationAutoHideToolbar;
}
#endif
}
else
{
- BOOL tbar_visible = FRAME_EXTERNAL_TOOL_BAR (emacsframe) ? YES : NO;
+ BOOL tarbar_visible = FRAME_EXTERNAL_TAB_BAR (emacsframe) ? YES : NO;
+ BOOL toolbar_visible = FRAME_EXTERNAL_TOOL_BAR (emacsframe) ? YES : NO;
#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 \
&& MAC_OS_X_VERSION_MIN_REQUIRED <= 1070
unsigned val = (unsigned)[NSApp presentationOptions];
= NSApplicationPresentationAutoHideDock
| NSApplicationPresentationAutoHideMenuBar
| NSApplicationPresentationFullScreen
+ | NSApplicationPresentationAutoHideTabbar
| NSApplicationPresentationAutoHideToolbar;
[NSApp setPresentationOptions: options];
}
#endif
- [toolbar setVisible:tbar_visible];
+ [tabbar setVisible:tarbar_visible];
+ [toolbar setVisible:toolbar_visible];
}
}
#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
[self updateCollectionBehavior];
#endif
+ if (FRAME_EXTERNAL_TAB_BAR (emacsframe))
+ {
+ [tabbar setVisible:YES];
+ update_frame_tab_bar (emacsframe);
+ [self updateFrameSize:YES];
+ [[self window] display];
+ }
+ else
+ [tabbar setVisible:NO];
+
if (FRAME_EXTERNAL_TOOL_BAR (emacsframe))
{
[toolbar setVisible:YES];
}
+- (EmacsTabbar *)tabbar
+{
+ return tabbar;
+}
+
+
+/* This gets called on tabbar button click. */
+- (instancetype)tabbarClicked: (id)item
+{
+ NSEvent *theEvent;
+ int idx = [item tag] * TAB_BAR_ITEM_NSLOTS;
+
+ NSTRACE ("[EmacsView tabbarClicked:]");
+
+ if (!emacs_event)
+ return self;
+
+ /* Send first event (for some reason two needed). */
+ theEvent = [[self window] currentEvent];
+ emacs_event->kind = TAB_BAR_EVENT;
+ XSETFRAME (emacs_event->arg, emacsframe);
+ EV_TRAILER (theEvent);
+
+ emacs_event->kind = TAB_BAR_EVENT;
+ /* XSETINT (emacs_event->code, 0); */
+ emacs_event->arg = AREF (emacsframe->tab_bar_items,
+ idx + TAB_BAR_ITEM_KEY);
+ emacs_event->modifiers = EV_MODIFIERS (theEvent);
+ EV_TRAILER (theEvent);
+ return self;
+}
+
+
+- (instancetype)toggleTabbar: (id)sender
+{
+ NSTRACE ("[EmacsView toggleTabbar:]");
+
+ if (!emacs_event)
+ return self;
+
+ emacs_event->kind = NS_NONKEY_EVENT;
+ emacs_event->code = KEY_NS_TOGGLE_TABBAR;
+ EV_TRAILER ((id)nil);
+ return self;
+}
+
+
- (EmacsToolbar *)toolbar
{
return toolbar;