GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
+the Free Software Foundation, either version 3 of the License, or (at
+your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
}
+void
+ns_init_locale (void)
+/* OS X doesn't set any environment variables for the locale when run
+ from the GUI. Get the locale from the OS and set LANG. */
+{
+ NSLocale *locale = [NSLocale currentLocale];
+
+ NSTRACE ("ns_init_locale");
+
+ @try
+ {
+ /* It seems OS X should probably use UTF-8 everywhere.
+ 'localeIdentifier' does not specify the encoding, and I can't
+ find any way to get the OS to tell us which encoding to use,
+ so hard-code '.UTF-8'. */
+ NSString *localeID = [NSString stringWithFormat:@"%@.UTF-8",
+ [locale localeIdentifier]];
+
+ /* Set LANG to locale, but not if LANG is already set. */
+ setenv("LANG", [localeID UTF8String], 0);
+ }
+ @catch (NSException *e)
+ {
+ NSLog (@"Locale detection failed: %@: %@", [e name], [e reason]);
+ }
+}
+
+
void
ns_release_object (void *obj)
/* --------------------------------------------------------------------------
}
-/* True, if the menu bar should be hidden. */
-
static BOOL
ns_menu_bar_should_be_hidden (void)
+/* True, if the menu bar should be hidden. */
{
return !NILP (ns_auto_hide_menu_bar)
&& [NSApp respondsToSelector:@selector(setPresentationOptions:)];
}
-static CGFloat
-ns_menu_bar_height (NSScreen *screen)
-/* The height of the menu bar, if visible.
+struct EmacsMargins
+{
+ CGFloat top;
+ CGFloat bottom;
+ CGFloat left;
+ CGFloat right;
+};
- Note: Don't use this when fullscreen is enabled -- the screen
- sometimes includes, sometimes excludes the menu bar area. */
+
+static struct EmacsMargins
+ns_screen_margins (NSScreen *screen)
+/* The parts of SCREEN used by the operating system. */
{
- CGFloat res;
+ NSTRACE ("ns_screen_margins");
+ struct EmacsMargins margins;
+
+ NSRect screenFrame = [screen frame];
+ NSRect screenVisibleFrame = [screen visibleFrame];
+
+ /* Sometimes, visibleFrame isn't up-to-date with respect to a hidden
+ menu bar, check this explicitly. */
if (ns_menu_bar_should_be_hidden())
{
- res = 0;
+ margins.top = 0;
}
else
{
- NSRect screenFrame = [screen frame];
- NSRect screenVisibleFrame = [screen visibleFrame];
-
CGFloat frameTop = screenFrame.origin.y + screenFrame.size.height;
CGFloat visibleFrameTop = (screenVisibleFrame.origin.y
+ screenVisibleFrame.size.height);
- res = frameTop - visibleFrameTop;
+ margins.top = frameTop - visibleFrameTop;
+ }
+
+ {
+ CGFloat frameRight = screenFrame.origin.x + screenFrame.size.width;
+ CGFloat visibleFrameRight = (screenVisibleFrame.origin.x
+ + screenVisibleFrame.size.width);
+ margins.right = frameRight - visibleFrameRight;
+ }
+
+ margins.bottom = screenVisibleFrame.origin.y - screenFrame.origin.y;
+ margins.left = screenVisibleFrame.origin.x - screenFrame.origin.x;
+
+ NSTRACE_MSG ("left:%g right:%g top:%g bottom:%g",
+ margins.left,
+ margins.right,
+ margins.top,
+ margins.bottom);
+
+ return margins;
+}
+
+/* A screen margin between 1 and DOCK_IGNORE_LIMIT (inclusive) is
+ assumed to contain a hidden dock. OS X currently use 4 pixels for
+ this, however, to be future compatible, a larger value is used. */
+#define DOCK_IGNORE_LIMIT 6
+
+static struct EmacsMargins
+ns_screen_margins_ignoring_hidden_dock (NSScreen *screen)
+/* The parts of SCREEN used by the operating system, excluding the parts
+reserved for an hidden dock. */
+{
+ NSTRACE ("ns_screen_margins_ignoring_hidden_dock");
+
+ struct EmacsMargins margins = ns_screen_margins(screen);
+
+ /* OS X (currently) reserved 4 pixels along the edge where a hidden
+ dock is located. Unfortunately, it's not possible to find the
+ location and information about if the dock is hidden. Instead,
+ it is assumed that if the margin of an edge is less than
+ DOCK_IGNORE_LIMIT, it contains a hidden dock. */
+ if (margins.left <= DOCK_IGNORE_LIMIT)
+ {
+ margins.left = 0;
+ }
+ if (margins.right <= DOCK_IGNORE_LIMIT)
+ {
+ margins.right = 0;
+ }
+ if (margins.top <= DOCK_IGNORE_LIMIT)
+ {
+ margins.top = 0;
}
+ /* Note: This doesn't occur in current versions of OS X, but
+ included for completeness and future compatibility. */
+ if (margins.bottom <= DOCK_IGNORE_LIMIT)
+ {
+ margins.bottom = 0;
+ }
+
+ NSTRACE_MSG ("left:%g right:%g top:%g bottom:%g",
+ margins.left,
+ margins.right,
+ margins.top,
+ margins.bottom);
+
+ return margins;
+}
+
+
+static CGFloat
+ns_menu_bar_height (NSScreen *screen)
+/* The height of the menu bar, if visible.
+
+ Note: Don't use this when fullscreen is enabled -- the screen
+ sometimes includes, sometimes excludes the menu bar area. */
+{
+ struct EmacsMargins margins = ns_screen_margins(screen);
+
+ CGFloat res = margins.top;
NSTRACE ("ns_menu_bar_height " NSTRACE_FMT_RETURN " %.0f", res);
========================================================================== */
+// This bell implementation shows the visual bell image asynchronously
+// from the rest of Emacs. This is done by adding a NSView to the
+// superview of the Emacs window and removing it using a timer.
+//
+// Unfortunately, some Emacs operations, like scrolling, is done using
+// low-level primitives that copy the content of the window, including
+// the bell image. To some extent, this is handled by removing the
+// image prior to scrolling and marking that the window is in need for
+// redisplay.
+//
+// To test this code, make sure that there is no artifacts of the bell
+// image in the following situations. Use a non-empty buffer (like the
+// tutorial) to ensure that a scroll is performed:
+//
+// * Single-window: C-g C-v
+//
+// * Side-by-windows: C-x 3 C-g C-v
+//
+// * Windows above each other: C-x 2 C-g C-v
+
@interface EmacsBell : NSImageView
{
// Number of currently active bell:s.
unsigned int nestCount;
+ NSView * mView;
bool isAttached;
}
- (void)show:(NSView *)view;
// 2011, see https://savannah.gnu.org/bugs/?33396
//
// As a drop in replacement, a semitransparent gray square is used.
- self.image = [[NSImage alloc] initWithSize:NSMakeSize(32, 32)];
+ self.image = [[NSImage alloc] initWithSize:NSMakeSize(32 * 5, 32 * 5)];
[self.image lockFocus];
[[NSColor colorForEmacsRed:0.5 green:0.5 blue:0.5 alpha:0.5] set];
NSRectFill(NSMakeRect(0, 0, 32, 32));
[self.image unlockFocus];
#else
self.image = [NSImage imageNamed:NSImageNameCaution];
+ [self.image setSize:NSMakeSize(self.image.size.width * 5,
+ self.image.size.height * 5)];
#endif
}
return self;
[self setFrameSize:self.image.size];
isAttached = true;
+ mView = view;
[[[view window] contentView] addSubview:self
positioned:NSWindowAbove
relativeTo:nil];
-(void)remove
{
+ NSTRACE ("[EmacsBell remove]");
if (isAttached)
{
+ NSTRACE_MSG ("removeFromSuperview");
[self removeFromSuperview];
+ mView.needsDisplay = YES;
isAttached = false;
}
}
Ensure the bell is hidden.
-------------------------------------------------------------------------- */
{
+ NSTRACE ("hide_bell");
+
if (bell_view != nil)
{
[bell_view remove];
static void
ns_copy_bits (struct frame *f, NSRect src, NSRect dest)
{
+ NSTRACE ("ns_copy_bits");
+
if (FRAME_NS_VIEW (f))
{
hide_bell(); // Ensure the bell image isn't scrolled.
// the menu-bar.
[super zoom:sender];
-#elsif 0
+#elif 0
// Native zoom done using the standard zoom animation, plus an
- // explicit resize to cover the full screen.
+ // explicit resize to cover the full screen, except the menu-bar and
+ // dock, if present.
[super zoom:sender];
// After the native zoom, resize the resulting frame to fill the
NSTRACE_FSTYPE ("fullscreenState", fs_state);
NSRect sr = [screen frame];
+ struct EmacsMargins margins
+ = ns_screen_margins_ignoring_hidden_dock(screen);
+
NSRect wr = [self frame];
NSTRACE_RECT ("Rect after zoom", wr);
if (fs_state == FULLSCREEN_MAXIMIZED
|| fs_state == FULLSCREEN_HEIGHT)
{
- newWr.origin.x = 0;
- newWr.size.height = sr.size.height - ns_menu_bar_height(screen);
+ newWr.origin.y = sr.origin.y + margins.bottom;
+ newWr.size.height = sr.size.height - margins.top - margins.bottom;
}
if (fs_state == FULLSCREEN_MAXIMIZED
|| fs_state == FULLSCREEN_WIDTH)
{
- newWr.origin.y = 0;
- newWr.size.width = sr.size.width;
+ newWr.origin.x = sr.origin.x + margins.left;
+ newWr.size.width = sr.size.width - margins.right - margins.left;
}
if (newWr.size.width != wr.size.width
}
}
#else
- // Non-native zoom which is done instantaneously. The resulting frame
- // covers the entire screen, except the menu-bar, if present.
+ // Non-native zoom which is done instantaneously. The resulting
+ // frame covers the entire screen, except the menu-bar and dock, if
+ // present.
NSScreen * screen = [self screen];
if (screen != nil)
{
NSRect sr = [screen frame];
- sr.size.height -= ns_menu_bar_height (screen);
+ struct EmacsMargins margins
+ = ns_screen_margins_ignoring_hidden_dock(screen);
+
+ sr.size.height -= (margins.top + margins.bottom);
+ sr.size.width -= (margins.left + margins.right);
+ sr.origin.x += margins.left;
+ sr.origin.y += margins.bottom;
sr = [[self delegate] windowWillUseStandardFrame:self
defaultFrame:sr];