/* NeXT/Open/GNUstep / MacOSX communication module. -*- coding: utf-8 -*-
-Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2015 Free Software
+Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2016 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
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
#include "macfont.h"
#endif
-/* call tracing */
-#if 0
-int term_trace_num = 0;
-#define NSTRACE(x) fprintf (stderr, "%s:%d: [%d] " #x "\n", \
- __FILE__, __LINE__, ++term_trace_num)
-#else
-#define NSTRACE(x)
-#endif
-/* Detailed tracing. "S" means "size" and "LL" stands for "lower left". */
-#if 0
-int term_trace_num = 0;
-#define NSTRACE_SIZE(str,size) fprintf (stderr, \
- "%s:%d: [%d] " str \
- " (S:%.0f x %.0f)\n", \
- __FILE__, __LINE__, ++term_trace_num,\
- size.height, \
- size.width)
-#define NSTRACE_RECT(s,r) fprintf (stderr, \
- "%s:%d: [%d] " s \
- " (LL:%.0f x %.0f -> S:%.0f x %.0f)\n", \
- __FILE__, __LINE__, ++term_trace_num,\
- r.origin.x, \
- r.origin.y, \
- r.size.height, \
- r.size.width)
-#else
-#define NSTRACE_SIZE(str,size)
-#define NSTRACE_RECT(s,r)
+extern NSString *NSMenuDidBeginTrackingNotification;
+
+
+/* ==========================================================================
+
+ NSTRACE, Trace support.
+
+ ========================================================================== */
+
+#if NSTRACE_ENABLED
+
+/* The following use "volatile" since they can be accessed from
+ parallel threads. */
+volatile int nstrace_num = 0;
+volatile int nstrace_depth = 0;
+
+/* When 0, no trace is emitted. This is used by NSTRACE_WHEN and
+ NSTRACE_UNLESS to silence functions called.
+
+ TODO: This should really be a thread-local variable, to avoid that
+ a function with disabled trace thread silence trace output in
+ another. However, in practice this seldom is a problem. */
+volatile int nstrace_enabled_global = 1;
+
+/* Called when nstrace_enabled goes out of scope. */
+void nstrace_leave(int * pointer_to_nstrace_enabled)
+{
+ if (*pointer_to_nstrace_enabled)
+ {
+ --nstrace_depth;
+ }
+}
+
+
+/* Called when nstrace_saved_enabled_global goes out of scope. */
+void nstrace_restore_global_trace_state(int * pointer_to_saved_enabled_global)
+{
+ nstrace_enabled_global = *pointer_to_saved_enabled_global;
+}
+
+
+char const * nstrace_fullscreen_type_name (int fs_type)
+{
+ switch (fs_type)
+ {
+ case -1: return "-1";
+ case FULLSCREEN_NONE: return "FULLSCREEN_NONE";
+ case FULLSCREEN_WIDTH: return "FULLSCREEN_WIDTH";
+ case FULLSCREEN_HEIGHT: return "FULLSCREEN_HEIGHT";
+ case FULLSCREEN_BOTH: return "FULLSCREEN_BOTH";
+ case FULLSCREEN_MAXIMIZED: return "FULLSCREEN_MAXIMIZED";
+ default: return "FULLSCREEN_?????";
+ }
+}
#endif
-extern NSString *NSMenuDidBeginTrackingNotification;
/* ==========================================================================
static NSView *focus_view = NULL;
static int ns_window_num = 0;
#ifdef NS_IMPL_GNUSTEP
-static NSRect uRect;
+static NSRect uRect; // TODO: This is dead, remove it?
#endif
static BOOL gsaved = NO;
static BOOL ns_fake_keydown = NO;
return NULL;
}
-static void
-ns_timeout (int usecs)
-/* --------------------------------------------------------------------------
- Blocking timer utility used by ns_ring_bell
- -------------------------------------------------------------------------- */
+
+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. */
{
- struct timespec wakeup = timespec_add (current_timespec (),
- make_timespec (0, usecs * 1000));
+ NSLocale *locale = [NSLocale currentLocale];
+
+ NSTRACE ("ns_init_locale");
- /* Keep waiting until past the time wakeup. */
- while (1)
+ @try
{
- struct timespec timeout, now = current_timespec ();
- if (timespec_cmp (wakeup, now) <= 0)
- break;
- timeout = timespec_sub (wakeup, now);
+ /* 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]];
- /* Try to wait that long--but we might wake up sooner. */
- pselect (0, NULL, NULL, NULL, &timeout, NULL);
+ /* 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]);
}
}
}
+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:)];
+}
+
+
+struct EmacsMargins
+{
+ CGFloat top;
+ CGFloat bottom;
+ CGFloat left;
+ CGFloat right;
+};
+
+
+static struct EmacsMargins
+ns_screen_margins (NSScreen *screen)
+/* The parts of SCREEN used by the operating system. */
+{
+ 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())
+ {
+ margins.top = 0;
+ }
+ else
+ {
+ CGFloat frameTop = screenFrame.origin.y + screenFrame.size.height;
+ CGFloat visibleFrameTop = (screenVisibleFrame.origin.y
+ + screenVisibleFrame.size.height);
+
+ 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);
+
+ return res;
+}
+
/* ==========================================================================
// Result: Menu bar visible, frame placed immediately below the menu.
//
+static NSRect constrain_frame_rect(NSRect frameRect, bool isFullscreen)
+{
+ NSTRACE ("constrain_frame_rect(" NSTRACE_FMT_RECT ")",
+ NSTRACE_ARG_RECT (frameRect));
+
+ // --------------------
+ // Collect information about the screen the frame is covering.
+ //
+
+ NSArray *screens = [NSScreen screens];
+ NSUInteger nr_screens = [screens count];
+
+ int i;
+
+ // The height of the menu bar, if present in any screen the frame is
+ // displayed in.
+ int menu_bar_height = 0;
+
+ // A rectangle covering all the screen the frame is displayed in.
+ NSRect multiscreenRect = NSMakeRect(0, 0, 0, 0);
+ for (i = 0; i < nr_screens; ++i )
+ {
+ NSScreen *s = [screens objectAtIndex: i];
+ NSRect scrRect = [s frame];
+
+ NSTRACE_MSG ("Screen %d: " NSTRACE_FMT_RECT,
+ i, NSTRACE_ARG_RECT (scrRect));
+
+ if (NSIntersectionRect (frameRect, scrRect).size.height != 0)
+ {
+ multiscreenRect = NSUnionRect (multiscreenRect, scrRect);
+
+ if (!isFullscreen)
+ {
+ CGFloat screen_menu_bar_height = ns_menu_bar_height (s);
+ menu_bar_height = max(menu_bar_height, screen_menu_bar_height);
+ }
+ }
+ }
+
+ NSTRACE_RECT ("multiscreenRect", multiscreenRect);
+
+ NSTRACE_MSG ("menu_bar_height: %d", menu_bar_height);
+
+ if (multiscreenRect.size.width == 0
+ || multiscreenRect.size.height == 0)
+ {
+ // Failed to find any monitor, give up.
+ NSTRACE_MSG ("multiscreenRect empty");
+ NSTRACE_RETURN_RECT (frameRect);
+ return frameRect;
+ }
+
+
+ // --------------------
+ // Find a suitable placement.
+ //
+
+ if (ns_menu_bar_should_be_hidden())
+ {
+ // When the menu bar is hidden, the user may place part of the
+ // frame above the top of the screen, for example to hide the
+ // title bar.
+ //
+ // Hence, keep the original position.
+ }
+ else
+ {
+ // Ensure that the frame is below the menu bar, or below the top
+ // of the screen.
+ //
+ // This assume that the menu bar is placed at the top in the
+ // rectangle that covers the monitors. (It doesn't have to be,
+ // but if it's not it's hard to do anything useful.)
+ CGFloat topOfWorkArea = (multiscreenRect.origin.y
+ + multiscreenRect.size.height
+ - menu_bar_height);
+
+ CGFloat topOfFrame = frameRect.origin.y + frameRect.size.height;
+ if (topOfFrame > topOfWorkArea)
+ {
+ frameRect.origin.y -= topOfFrame - topOfWorkArea;
+ NSTRACE_RECT ("After placement adjust", frameRect);
+ }
+ }
+
+ // Include the following section to restrict frame to the screens.
+ // (If so, update it to allow the frame to stretch down below the
+ // screen.)
+#if 0
+ // --------------------
+ // Ensure frame doesn't stretch below the screens.
+ //
+
+ CGFloat diff = multiscreenRect.origin.y - frameRect.origin.y;
+
+ if (diff > 0)
+ {
+ frameRect.origin.y = multiscreenRect.origin.y;
+ frameRect.size.height -= diff;
+ }
+#endif
+
+ NSTRACE_RETURN_RECT (frameRect);
+ return frameRect;
+}
+
+
static void
ns_constrain_all_frames (void)
+/* --------------------------------------------------------------------------
+ Ensure that the menu bar doesn't cover any frames.
+ -------------------------------------------------------------------------- */
{
Lisp_Object tail, frame;
+ NSTRACE ("ns_constrain_all_frames");
+
+ block_input ();
+
FOR_EACH_FRAME (tail, frame)
{
struct frame *f = XFRAME (frame);
if (FRAME_NS_P (f))
{
- NSView *view = FRAME_NS_VIEW (f);
- /* This no-op will trigger the default window placing
- * constraint system. */
- [[view window] setFrameOrigin:[[view window] frame].origin];
+ EmacsView *view = FRAME_NS_VIEW (f);
+
+ if (![view isFullscreen])
+ {
+ [[view window]
+ setFrame:constrain_frame_rect([[view window] frame], false)
+ display:NO];
+ }
}
}
-}
-
-
-/* True, if the menu bar should be hidden. */
-static BOOL
-ns_menu_bar_should_be_hidden (void)
-{
- return !NILP (ns_auto_hide_menu_bar)
- && [NSApp respondsToSelector:@selector(setPresentationOptions:)];
+ unblock_input ();
}
-/* Show or hide the menu bar, based on user setting. */
-
static void
ns_update_auto_hide_menu_bar (void)
+/* --------------------------------------------------------------------------
+ Show or hide the menu bar, based on user setting.
+ -------------------------------------------------------------------------- */
{
#ifdef NS_IMPL_COCOA
- block_input ();
+ NSTRACE ("ns_update_auto_hide_menu_bar");
- NSTRACE (ns_update_auto_hide_menu_bar);
+ block_input ();
if (NSApp != nil && [NSApp isActive])
{
-------------------------------------------------------------------------- */
{
EmacsView *view = FRAME_NS_VIEW (f);
- NSTRACE (ns_update_begin);
+ NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_update_begin");
ns_update_auto_hide_menu_bar ();
struct frame *f = XFRAME (WINDOW_FRAME (w));
Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
- NSTRACE (ns_update_window_begin);
+ NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_update_window_begin");
w->output_cursor = w->cursor;
block_input ();
external (RIF) call; for one window called before update_end
-------------------------------------------------------------------------- */
{
+ NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_update_window_end");
+
/* note: this fn is nearly identical in all terms */
if (!w->pseudo_window_p)
{
frame_up_to_date to redisplay the mouse highlight. */
if (mouse_face_overwritten_p)
reset_mouse_highlight (MOUSE_HL_INFO (XFRAME (w->frame)));
-
- NSTRACE (update_window_end);
}
{
EmacsView *view = FRAME_NS_VIEW (f);
+ NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_update_end");
+
/* if (f == MOUSE_HL_INFO (f)->mouse_face_mouse_frame) */
MOUSE_HL_INFO (f)->mouse_face_defer = 0;
unblock_input ();
ns_updating_frame = NULL;
- NSTRACE (ns_update_end);
}
static void
the entire window.
-------------------------------------------------------------------------- */
{
-// NSTRACE (ns_focus);
-/* static int c =0;
- fprintf (stderr, "focus: %d", c++);
- if (r) fprintf (stderr, " (%.0f, %.0f : %.0f x %.0f)", r->origin.x, r->origin.y, r->size.width, r->size.height);
- fprintf (stderr, "\n"); */
+ NSTRACE_WHEN (NSTRACE_GROUP_FOCUS, "ns_focus");
+ if (r != NULL)
+ {
+ NSTRACE_RECT ("r", *r);
+ }
if (f != ns_updating_frame)
{
Internal: Remove focus on given frame
-------------------------------------------------------------------------- */
{
-// NSTRACE (ns_unfocus);
+ NSTRACE_WHEN (NSTRACE_GROUP_FOCUS, "ns_unfocus");
if (gsaved)
{
}
+/* ==========================================================================
+
+ Visible bell and beep.
+
+ ========================================================================== */
+
+
+// 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;
+- (void)hide;
+- (void)remove;
+@end
+
+@implementation EmacsBell
+
+- (id)init;
+{
+ NSTRACE ("[EmacsBell init]");
+ if ((self = [super init]))
+ {
+ nestCount = 0;
+ isAttached = false;
+#ifdef NS_IMPL_GNUSTEP
+ // GNUstep doesn't provide named images. This was reported in
+ // 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 * 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;
+}
+
+- (void)show:(NSView *)view
+{
+ NSTRACE ("[EmacsBell show:]");
+ NSTRACE_MSG ("nestCount: %u", nestCount);
+
+ // Show the image, unless it's already shown.
+ if (nestCount == 0)
+ {
+ NSRect rect = [view bounds];
+ NSPoint pos;
+ pos.x = rect.origin.x + (rect.size.width - self.image.size.width )/2;
+ pos.y = rect.origin.y + (rect.size.height - self.image.size.height)/2;
+
+ [self setFrameOrigin:pos];
+ [self setFrameSize:self.image.size];
+
+ isAttached = true;
+ mView = view;
+ [[[view window] contentView] addSubview:self
+ positioned:NSWindowAbove
+ relativeTo:nil];
+ }
+
+ ++nestCount;
+
+ [self performSelector:@selector(hide) withObject:self afterDelay:0.5];
+}
+
+
+- (void)hide
+{
+ // Note: Trace output from this method isn't shown, reason unknown.
+ // NSTRACE ("[EmacsBell hide]");
+
+ if (nestCount > 0)
+ --nestCount;
+
+ // Remove the image once the last bell became inactive.
+ if (nestCount == 0)
+ {
+ [self remove];
+ }
+}
+
+
+-(void)remove
+{
+ NSTRACE ("[EmacsBell remove]");
+ if (isAttached)
+ {
+ NSTRACE_MSG ("removeFromSuperview");
+ [self removeFromSuperview];
+ mView.needsDisplay = YES;
+ isAttached = false;
+ }
+}
+
+@end
+
+
+static EmacsBell * bell_view = nil;
+
static void
ns_ring_bell (struct frame *f)
/* --------------------------------------------------------------------------
"Beep" routine
-------------------------------------------------------------------------- */
{
- NSTRACE (ns_ring_bell);
+ NSTRACE ("ns_ring_bell");
if (visible_bell)
{
- NSAutoreleasePool *pool;
struct frame *frame = SELECTED_FRAME ();
NSView *view;
+ if (bell_view == nil)
+ {
+ bell_view = [[EmacsBell alloc] init];
+ [bell_view retain];
+ }
+
block_input ();
- pool = [[NSAutoreleasePool alloc] init];
view = FRAME_NS_VIEW (frame);
if (view != nil)
{
- NSRect r, surr;
- NSPoint dim = NSMakePoint (128, 128);
-
- r = [view bounds];
- r.origin.x += (r.size.width - dim.x) / 2;
- r.origin.y += (r.size.height - dim.y) / 2;
- r.size.width = dim.x;
- r.size.height = dim.y;
- surr = NSInsetRect (r, -2, -2);
- ns_focus (frame, &surr, 1);
- [[view window] cacheImageInRect: [view convertRect: surr toView:nil]];
- [ns_lookup_indexed_color (NS_FACE_FOREGROUND
- (FRAME_DEFAULT_FACE (frame)), frame) set];
- NSRectFill (r);
- [[view window] flushWindow];
- ns_timeout (150000);
- [[view window] restoreCachedImage];
- [[view window] flushWindow];
- ns_unfocus (frame);
+ [bell_view show:view];
}
- [pool release];
+
unblock_input ();
}
else
}
}
+
+static void hide_bell ()
+/* --------------------------------------------------------------------------
+ Ensure the bell is hidden.
+ -------------------------------------------------------------------------- */
+{
+ NSTRACE ("hide_bell");
+
+ if (bell_view != nil)
+ {
+ [bell_view remove];
+ }
+}
+
+
/* ==========================================================================
Frame / window manager related functions
-------------------------------------------------------------------------- */
{
NSView *view;
+
check_window_system (f);
view = FRAME_NS_VIEW (f);
block_input ();
-------------------------------------------------------------------------- */
{
NSView *view;
+
check_window_system (f);
view = FRAME_NS_VIEW (f);
block_input ();
External (hook)
-------------------------------------------------------------------------- */
{
- NSTRACE (ns_frame_raise_lower);
+ NSTRACE ("ns_frame_raise_lower");
if (raise)
ns_raise_frame (f);
struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame);
struct frame *old_highlight = dpyinfo->x_highlight_frame;
- NSTRACE (ns_frame_rehighlight);
+ NSTRACE ("ns_frame_rehighlight");
if (dpyinfo->x_focus_frame)
{
dpyinfo->x_highlight_frame
External: Show the window (X11 semantics)
-------------------------------------------------------------------------- */
{
- NSTRACE (x_make_frame_visible);
+ NSTRACE ("x_make_frame_visible");
/* XXX: at some points in past this was not needed, as the only place that
called this (frame.c:Fraise_frame ()) also called raise_lower;
if this ends up the case again, comment this out again. */
-------------------------------------------------------------------------- */
{
NSView *view;
- NSTRACE (x_make_frame_invisible);
+ NSTRACE ("x_make_frame_invisible");
check_window_system (f);
view = FRAME_NS_VIEW (f);
[[view window] orderOut: NSApp];
NSView *view;
struct ns_display_info *dpyinfo;
- NSTRACE (x_iconify_frame);
+ NSTRACE ("x_iconify_frame");
check_window_system (f);
view = FRAME_NS_VIEW (f);
dpyinfo = FRAME_DISPLAY_INFO (f);
struct ns_display_info *dpyinfo;
Mouse_HLInfo *hlinfo;
- NSTRACE (x_free_frame_resources);
+ NSTRACE ("x_free_frame_resources");
check_window_system (f);
view = FRAME_NS_VIEW (f);
dpyinfo = FRAME_DISPLAY_INFO (f);
External: Delete the window
-------------------------------------------------------------------------- */
{
- NSTRACE (x_destroy_window);
+ NSTRACE ("x_destroy_window");
check_window_system (f);
x_free_frame_resources (f);
ns_window_num--;
NSScreen *fscreen = [screens objectAtIndex: 0];
NSScreen *screen = [[view window] screen];
- NSTRACE (x_set_offset);
+ NSTRACE ("x_set_offset");
block_input ();
#endif
/* Constrain the setFrameTopLeftPoint so we don't move behind the
menu bar. */
- [[view window] setFrameTopLeftPoint:
- NSMakePoint (SCREENMAXBOUND (f->left_pos),
- SCREENMAXBOUND ([fscreen frame].size.height
- - NS_TOP_POS (f)))];
+ NSPoint pt = NSMakePoint (SCREENMAXBOUND (f->left_pos),
+ SCREENMAXBOUND ([fscreen frame].size.height
+ - NS_TOP_POS (f)));
+ NSTRACE_POINT ("setFrameTopLeftPoint", pt);
+ [[view window] setFrameTopLeftPoint: pt];
f->size_hint_flags &= ~(XNegative|YNegative);
}
NSRect wr = [window frame];
int tb = FRAME_EXTERNAL_TOOL_BAR (f);
int pixelwidth, pixelheight;
- int rows, cols;
int orig_height = wr.size.height;
- NSTRACE (x_set_window_size);
+ NSTRACE ("x_set_window_size");
if (view == nil)
return;
-/*fprintf (stderr, "\tsetWindowSize: %d x %d, pixelwise %d, font size %d x %d\n", width, height, pixelwise, FRAME_COLUMN_WIDTH (f), FRAME_LINE_HEIGHT (f));*/
+ NSTRACE_RECT ("current", wr);
+ NSTRACE_MSG ("Width:%d Height:%d Pixelwise:%d", width, height, pixelwise);
+ NSTRACE_MSG ("Font %d x %d", FRAME_COLUMN_WIDTH (f), FRAME_LINE_HEIGHT (f));
block_input ();
{
pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width);
pixelheight = FRAME_TEXT_TO_PIXEL_HEIGHT (f, height);
- cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pixelwidth);
- rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixelheight);
}
else
{
pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, width);
pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, height);
- cols = width;
- rows = height;
}
/* If we have a toolbar, take its height into account. */
make_number (FRAME_NS_TITLEBAR_HEIGHT (f)),
make_number (FRAME_TOOLBAR_HEIGHT (f))));
- [view setRows: rows andColumns: cols];
[window setFrame: wr display: YES];
/* This is a trick to compensate for Emacs' managing the scrollbar area
? NSMakePoint (FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f)
- NS_SCROLL_BAR_WIDTH (f), 0)
: NSMakePoint (0, 0);
+
[view setFrame: NSMakeRect (0, 0, pixelwidth, pixelheight)];
[view setBoundsOrigin: origin];
}
{
EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f);
+ NSTRACE ("ns_fullscreen_hook");
+
if (!FRAME_VISIBLE_P (f))
return;
float r = -1.0, g, b;
NSString *nsname = [NSString stringWithUTF8String: name];
-/*fprintf (stderr, "ns_get_color: '%s'\n", name); */
+ NSTRACE ("ns_get_color(%s, **)", name);
+
block_input ();
if ([nsname isEqualToString: @"ns_selection_bg_color"])
Convert a Lisp string object to a NS color
-------------------------------------------------------------------------- */
{
- NSTRACE (ns_lisp_to_color);
+ NSTRACE ("ns_lisp_to_color");
if (STRINGP (color))
return ns_get_color (SSDATA (color), col);
else if (SYMBOLP (color))
EmacsCGFloat red, green, blue, alpha, gray;
char buf[1024];
const char *str;
- NSTRACE (ns_color_to_lisp);
+ NSTRACE ("ns_color_to_lisp");
block_input ();
if ([[col colorSpaceName] isEqualToString: NSNamedColorSpace])
-------------------------------------------------------------------------- */
{
NSColor *col;
- NSTRACE (ns_defined_color);
+ NSTRACE_WHEN (NSTRACE_GROUP_COLOR, "ns_defined_color");
block_input ();
if (ns_get_color (name, &col) != 0) /* Color not found */
double alpha = 1.0;
double alpha_min = 1.0;
+ NSTRACE ("x_set_frame_alpha");
+
if (dpyinfo->x_highlight_frame == f)
alpha = f->alpha[0];
else
Programmatically reposition mouse pointer in pixel coordinates
-------------------------------------------------------------------------- */
{
- NSTRACE (frame_set_mouse_pixel_position);
+ NSTRACE ("frame_set_mouse_pixel_position");
ns_raise_frame (f);
#if 0
/* FIXME: this does not work, and what about GNUstep? */
struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame);
NSRect *r;
-// NSTRACE (note_mouse_movement);
+// NSTRACE ("note_mouse_movement");
dpyinfo->last_mouse_motion_frame = frame;
r = &dpyinfo->last_mouse_glyph;
struct frame *f;
struct ns_display_info *dpyinfo;
- NSTRACE (ns_mouse_position);
+ NSTRACE ("ns_mouse_position");
if (*fp == NULL)
{
position = [view convertPoint: position fromView: nil];
remember_mouse_glyph (f, position.x, position.y,
&dpyinfo->last_mouse_glyph);
-/*fprintf (stderr, "ns_mouse_position: %.0f, %.0f\n", position.x, position.y); */
+ NSTRACE_POINT ("position", position);
if (bar_window) *bar_window = Qnil;
if (part) *part = scroll_bar_above_handle;
Can't use FRAME_MOUSE_UPDATE due to ns_frame_begin and ns_frame_end calls.
-------------------------------------------------------------------------- */
{
- NSTRACE (ns_frame_up_to_date);
+ NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_frame_up_to_date");
if (FRAME_NS_P (f))
{
External (RIF): set frame mouse pointer type.
-------------------------------------------------------------------------- */
{
- NSTRACE (ns_define_frame_cursor);
+ NSTRACE ("ns_define_frame_cursor");
if (FRAME_POINTER_TYPE (f) != cursor)
{
EmacsView *view = FRAME_NS_VIEW (f);
-------------------------------------------------------------------------- */
{
static char value[16];
- NSTRACE (x_get_keysym_name);
+ NSTRACE ("x_get_keysym_name");
sprintf (value, "%d", keysym);
return value;
}
int i;
id view;
NSArray *subviews = [[FRAME_NS_VIEW (f) superview] subviews];
- NSTRACE (ns_redraw_scroll_bars);
+ NSTRACE ("ns_redraw_scroll_bars");
for (i =[subviews count]-1; i >= 0; i--)
{
view = [subviews objectAtIndex: i];
NSView *view = FRAME_NS_VIEW (f);
NSRect r;
- NSTRACE (ns_clear_frame);
+ NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_clear_frame");
/* comes on initial frame because we have
after-make-frame-functions = select-frame */
if (!view || !face)
return;
- NSTRACE (ns_clear_frame_area);
+ NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_clear_frame_area");
r = NSIntersectionRect (r, [view frame]);
ns_focus (f, &r, 1);
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.
+
ns_focus (f, &dest, 1);
[FRAME_NS_VIEW (f) scrollRect: src
by: NSMakeSize (dest.origin.x - src.origin.x,
struct frame *f = XFRAME (w->frame);
int x, y, width, height, from_y, to_y, bottom_y;
- NSTRACE (ns_scroll_run);
+ NSTRACE ("ns_scroll_run");
/* begin copy from other terms */
/* Get frame-relative bounding box of the text display area of W,
struct frame *f;
int width, height;
- NSTRACE (ns_after_update_window_line);
+ NSTRACE_WHEN (NSTRACE_GROUP_UPDATES, "ns_after_update_window_line");
/* begin copy from other terms */
eassert (w);
NSRect srcRect = NSMakeRect (x, y, width, height);
NSRect dstRect = NSMakeRect (x+shift_by, y, width, height);
- NSTRACE (ns_shift_glyphs_for_insert);
+ NSTRACE ("ns_shift_glyphs_for_insert");
ns_copy_bits (f, srcRect, dstRect);
}
External (RIF); fringe-related
-------------------------------------------------------------------------- */
{
+ /* Fringe bitmaps comes in two variants, normal and periodic. A
+ periodic bitmap is used to create a continuous pattern. Since a
+ bitmap is rendered one text line at a time, the start offset (dh)
+ of the bitmap varies. Concretely, this is used for the empty
+ line indicator.
+
+ For a bitmap, "h + dh" is the full height and is always
+ invariant. For a normal bitmap "dh" is zero.
+
+ For example, when the period is three and the full height is 72
+ the following combinations exists:
+
+ h=72 dh=0
+ h=71 dh=1
+ h=70 dh=2 */
+
struct frame *f = XFRAME (WINDOW_FRAME (w));
struct face *face = p->face;
static EmacsImage **bimgs = NULL;
static int nBimgs = 0;
+ NSTRACE_WHEN (NSTRACE_GROUP_FRINGE, "ns_draw_fringe_bitmap");
+ NSTRACE_MSG ("which:%d cursor:%d overlay:%d width:%d height:%d period:%d",
+ p->which, p->cursor_p, p->overlay_p, p->wd, p->h, p->dh);
+
/* grow bimgs if needed */
if (nBimgs < max_used_fringe_bitmap)
{
if (!img)
{
- unsigned short *bits = p->bits + p->dh;
- int len = p->h;
+ // Note: For "periodic" images, allocate one EmacsImage for
+ // the base image, and use it for all dh:s.
+ unsigned short *bits = p->bits;
+ int full_height = p->h + p->dh;
int i;
- unsigned char *cbits = xmalloc (len);
+ unsigned char *cbits = xmalloc (full_height);
- for (i = 0; i < len; i++)
- cbits[i] = ~(bits[i] & 0xff);
- img = [[EmacsImage alloc] initFromXBM: cbits width: 8 height: p->h
+ for (i = 0; i < full_height; i++)
+ cbits[i] = bits[i];
+ img = [[EmacsImage alloc] initFromXBM: cbits width: 8
+ height: full_height
fg: 0 bg: 0];
bimgs[p->which - 1] = img;
xfree (cbits);
}
+ NSTRACE_RECT ("r", r);
+
NSRectClip (r);
/* Since we composite the bitmap instead of just blitting it, we need
to erase the whole background. */
}
#ifdef NS_IMPL_COCOA
+ // Note: For periodic images, the full image height is "h + hd".
+ // By using the height h, a suitable part of the image is used.
+ NSRect fromRect = NSMakeRect(0, 0, p->wd, p->h);
+
+ NSTRACE_RECT ("fromRect", fromRect);
+
[img drawInRect: r
- fromRect: NSZeroRect
+ fromRect: fromRect
operation: NSCompositeSourceOver
fraction: 1.0
respectFlipped: YES
in mini-buffer windows when switching between echo area glyphs
and mini-buffer. */
- NSTRACE (dumpcursor);
+ NSTRACE ("ns_draw_window_cursor");
if (!on_p)
return;
struct face *face;
NSRect r = NSMakeRect (x, y0, 1, y1-y0);
- NSTRACE (ns_draw_vertical_window_border);
+ NSTRACE ("ns_draw_vertical_window_border");
face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
if (face)
struct face *face;
NSRect r = NSMakeRect (x0, y0, x1-x0, y1-y0);
- NSTRACE (ns_draw_window_divider);
+ NSTRACE ("ns_draw_window_divider");
face = FACE_FROM_ID (f, WINDOW_DIVIDER_FACE_ID);
if (face)
NSColor *newBaseCol = nil;
NSRect sr = r;
- NSTRACE (ns_draw_relief);
+ NSTRACE ("ns_draw_relief");
/* set up colors */
thickness = face->box_line_width;
- NSTRACE (ns_dumpglyphs_box_or_relief);
+ NSTRACE ("ns_dumpglyphs_box_or_relief");
last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
? WINDOW_RIGHT_EDGE_X (s->w)
certain cases. Others are left to the text rendering routine.
-------------------------------------------------------------------------- */
{
- NSTRACE (ns_maybe_dumpglyphs_background);
+ NSTRACE ("ns_maybe_dumpglyphs_background");
if (!s->background_filled_p/* || s->hl == DRAW_MOUSE_FACE*/)
{
struct face *face;
NSColor *tdCol;
- NSTRACE (ns_dumpglyphs_image);
+ NSTRACE ("ns_dumpglyphs_image");
if (s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p && s->slice.x == 0)
struct font *font = s->face->font;
if (! font) font = FRAME_FONT (s->f);
- NSTRACE (ns_draw_glyph_string);
+ NSTRACE_WHEN (NSTRACE_GROUP_GLYPHS, "ns_draw_glyph_string");
if (s->next && s->right_overhang && !s->for_overlaps/*&&s->hl!=DRAW_CURSOR*/)
{
recognize and take as a command to halt the event loop.
-------------------------------------------------------------------------- */
{
- /*NSTRACE (ns_send_appdefined); */
+ NSTRACE_WHEN (NSTRACE_GROUP_EVENTS, "ns_send_appdefined(%d)", value);
#ifdef NS_IMPL_GNUSTEP
// GNUstep needs postEvent to happen on the main thread.
struct input_event ev;
int nevents;
-/* NSTRACE (ns_read_socket); */
+ NSTRACE_WHEN (NSTRACE_GROUP_EVENTS, "ns_read_socket");
#ifdef HAVE_NATIVE_FS
check_native_fs ();
struct input_event event;
char c;
-/* NSTRACE (ns_select); */
+ NSTRACE_WHEN (NSTRACE_GROUP_EVENTS, "ns_select");
#ifdef HAVE_NATIVE_FS
check_native_fs ();
}
}
- NSTRACE (ns_set_vertical_scroll_bar);
+ NSTRACE ("ns_set_vertical_scroll_bar");
/* Get dimensions. */
window_box (window, ANY_AREA, 0, &window_y, 0, &window_height);
}
}
- NSTRACE (ns_set_horizontal_scroll_bar);
+ NSTRACE ("ns_set_horizontal_scroll_bar");
/* Get dimensions. */
window_box (window, ANY_AREA, 0, &window_x, &window_width, 0);
id view;
NSArray *subviews = [[FRAME_NS_VIEW (f) superview] subviews];
- NSTRACE (ns_condemn_scroll_bars);
+ NSTRACE ("ns_condemn_scroll_bars");
for (i =[subviews count]-1; i >= 0; i--)
{
-------------------------------------------------------------------------- */
{
id bar;
- NSTRACE (ns_redeem_scroll_bar);
+ NSTRACE ("ns_redeem_scroll_bar");
if (!NILP (window->vertical_scroll_bar))
{
bar = XNS_SCROLL_BAR (window->vertical_scroll_bar);
NSArray *subviews = [[eview superview] subviews];
BOOL removed = NO;
- NSTRACE (ns_judge_scroll_bars);
+ NSTRACE ("ns_judge_scroll_bars");
for (i = [subviews count]-1; i >= 0; --i)
{
view = [subviews objectAtIndex: i];
{
struct ns_display_info *dpyinfo = terminal->display_info.ns;
+ NSTRACE ("ns_delete_terminal");
+
/* Protect against recursive calls. delete_frame in
delete_terminal calls us back when it deletes our last frame. */
if (!terminal->name)
{
struct terminal *terminal;
- NSTRACE (ns_create_terminal);
+ NSTRACE ("ns_create_terminal");
terminal = create_terminal (output_ns, &ns_redisplay_interface);
if (ns_initialized) return x_display_list;
ns_initialized = 1;
- NSTRACE (ns_term_init);
+ block_input ();
+
+ NSTRACE ("ns_term_init");
[outerpool release];
outerpool = [[NSAutoreleasePool alloc] init];
ns_antialias_threshold = NILP (tmp) ? 10.0 : XFLOATINT (tmp);
}
+ NSTRACE_MSG ("Colors");
+
{
NSColorList *cl = [NSColorList colorListNamed: @"Emacs"];
}
}
+ NSTRACE_MSG ("Versions");
+
{
#ifdef NS_IMPL_GNUSTEP
Vwindow_system_version = build_string (gnustep_base_version);
ns_app_name = [[NSProcessInfo processInfo] processName];
-/* Set up OS X app menu */
+ /* Set up OS X app menu */
+
+ NSTRACE_MSG ("Menu init");
+
#ifdef NS_IMPL_COCOA
{
NSMenu *appMenu;
/* Register our external input/output types, used for determining
applicable services and also drag/drop eligibility. */
+
+ NSTRACE_MSG ("Input/output types");
+
ns_send_types = [[NSArray arrayWithObjects: NSStringPboardType, nil] retain];
ns_return_types = [[NSArray arrayWithObjects: NSStringPboardType, nil]
retain];
right for fullscreen windows, so set this. */
[NSApp activateIgnoringOtherApps:YES];
+ NSTRACE_MSG ("Call NSApp run");
+
[NSApp run];
ns_do_open_file = YES;
We must re-catch it so subprocess works. */
catch_child_signal ();
#endif
+
+ NSTRACE_MSG ("ns_term_init done");
+
+ unblock_input ();
+
return dpyinfo;
}
- (id)init
{
+ NSTRACE ("[EmacsApp init]");
+
if ((self = [super init]))
{
#ifdef NS_IMPL_COCOA
#ifdef NS_IMPL_COCOA
- (void)run
{
+ NSTRACE ("[EmacsApp run]");
+
#ifndef NSAppKitVersionNumber10_9
#define NSAppKitVersionNumber10_9 1265
#endif
- (void)stop: (id)sender
{
+ NSTRACE ("[EmacsApp stop:]");
+
shouldKeepRunning = NO;
// Stop possible dialog also. Noop if no dialog present.
// The file dialog still leaks 7k - 10k on 10.9 though.
- (void)logNotification: (NSNotification *)notification
{
+ NSTRACE ("[EmacsApp logNotification:]");
+
const char *name = [[notification name] UTF8String];
if (!strstr (name, "Update") && !strstr (name, "NSMenu")
&& !strstr (name, "WindowNumber"))
int type = [theEvent type];
NSWindow *window = [theEvent window];
-/* NSTRACE (sendEvent); */
-/*fprintf (stderr, "received event of type %d\t%d\n", type);*/
+ NSTRACE_WHEN (NSTRACE_GROUP_EVENTS, "[EmacsApp sendEvent:]");
+ NSTRACE_MSG ("Type: %d", type);
#ifdef NS_IMPL_GNUSTEP
// Keyboard events aren't propagated to file dialogs for some reason.
}
#endif
+ NSTRACE_UNSILENCE();
+
[super sendEvent: theEvent];
}
- (void)newFrame: (id)sender
{
+ NSTRACE ("[EmacsApp newFrame:]");
+
struct frame *emacsframe = SELECTED_FRAME ();
NSEvent *theEvent = [NSApp currentEvent];
/* Open a file (used by below, after going into queue read by ns_read_socket) */
- (BOOL) openFile: (NSString *)fileName
{
+ NSTRACE ("[EmacsApp openFile:]");
+
struct frame *emacsframe = SELECTED_FRAME ();
NSEvent *theEvent = [NSApp currentEvent];
When application is loaded, terminate event loop in ns_term_init
-------------------------------------------------------------------------- */
{
- NSTRACE (applicationDidFinishLaunching);
+ NSTRACE ("[EmacsApp applicationDidFinishLaunching:]");
+
#ifdef NS_IMPL_GNUSTEP
((EmacsApp *)self)->applicationDidFinishLaunchingCalled = YES;
#endif
- (void) terminate: (id)sender
{
+ NSTRACE ("[EmacsApp terminate:]");
+
struct frame *emacsframe = SELECTED_FRAME ();
if (!emacs_event)
- (NSApplicationTerminateReply)applicationShouldTerminate: (id)sender
{
+ NSTRACE ("[EmacsApp applicationShouldTerminate:]");
+
bool ret;
if (NILP (ns_confirm_quit)) // || ns_shutdown_properly --> TO DO
/* TODO: these may help w/IO switching btwn terminal and NSApp */
- (void)applicationWillBecomeActive: (NSNotification *)notification
{
+ NSTRACE ("[EmacsApp applicationWillBecomeActive:]");
//ns_app_active=YES;
}
+
- (void)applicationDidBecomeActive: (NSNotification *)notification
{
- NSTRACE (applicationDidBecomeActive);
+ NSTRACE ("[EmacsApp applicationDidBecomeActive:]");
#ifdef NS_IMPL_GNUSTEP
if (! applicationDidFinishLaunchingCalled)
}
- (void)applicationDidResignActive: (NSNotification *)notification
{
+ NSTRACE ("[EmacsApp applicationDidResignActive:]");
+
//ns_app_active=NO;
ns_send_appdefined (-1);
}
The timeout specified to ns_select has passed.
-------------------------------------------------------------------------- */
{
- /*NSTRACE (timeout_handler); */
+ /*NSTRACE ("timeout_handler"); */
ns_send_appdefined (-2);
}
struct timespec timeout, *tmo;
NSAutoreleasePool *pool = nil;
- /* NSTRACE (fd_handler); */
+ /* NSTRACE ("fd_handler"); */
for (;;)
{
struct frame *emacsframe = SELECTED_FRAME ();
NSEvent *theEvent = [NSApp currentEvent];
+ NSTRACE ("[EmacsApp fulfillService:withArg:]");
+
if (!emacs_event)
return NO;
/* needed to inform when window closed from LISP */
- (void) setWindowClosing: (BOOL)closing
{
+ NSTRACE ("[EmacsView setWindowClosing:%d]", closing);
+
windowClosing = closing;
}
- (void)dealloc
{
- NSTRACE (EmacsView_dealloc);
+ NSTRACE ("[EmacsView dealloc]");
[toolbar release];
if (fs_state == FULLSCREEN_BOTH)
[nonfs_window release];
CGFloat size;
NSFont *nsfont;
- NSTRACE (changeFont);
+ NSTRACE ("[EmacsView changeFont:]");
if (!emacs_event)
return;
- (BOOL)acceptsFirstResponder
{
- NSTRACE (acceptsFirstResponder);
+ NSTRACE ("[EmacsView acceptsFirstResponder]");
return YES;
}
{
NSRect visible = [self visibleRect];
NSCursor *currentCursor = FRAME_POINTER_TYPE (emacsframe);
- NSTRACE (resetCursorRects);
+ NSTRACE ("[EmacsView resetCursorRects]");
if (currentCursor == nil)
currentCursor = [NSCursor arrowCursor];
int left_is_none;
unsigned int flags = [theEvent modifierFlags];
- NSTRACE (keyDown);
+ NSTRACE ("[EmacsView keyDown:]");
/* Rhapsody and OS X give up and down events for the arrow keys */
if (ns_fake_keydown == YES)
{
int flags = [theEvent modifierFlags];
int code = [theEvent keyCode];
+
+ NSTRACE ("[EmacsView keyUp:]");
+
if (floor (NSAppKitVersionNumber) <= 824 /*NSAppKitVersionNumber10_4*/ &&
code == 0x30 && (flags & NSControlKeyMask) && !(flags & NSCommandKeyMask))
{
int len = [(NSString *)aString length];
int i;
+ NSTRACE ("[EmacsView insertText:]");
+
if (NS_KEYLOG)
NSLog (@"insertText '%@'\tlen = %d", aString, len);
processingCompose = NO;
{
NSString *str = [aString respondsToSelector: @selector (string)] ?
[aString string] : aString;
+
+ NSTRACE ("[EmacsView setMarkedText:selectedRange:]");
+
if (NS_KEYLOG)
NSLog (@"setMarkedText '%@' len =%lu range %lu from %lu",
str, (unsigned long)[str length],
/* delete display of composing characters [not in <NSTextInput>] */
- (void)deleteWorkingText
{
+ NSTRACE ("[EmacsView deleteWorkingText]");
+
if (workingText == nil)
return;
if (NS_KEYLOG)
- (BOOL)hasMarkedText
{
+ NSTRACE ("[EmacsView hasMarkedText]");
+
return workingText != nil;
}
- (NSRange)markedRange
{
+ NSTRACE ("[EmacsView markedRange]");
+
NSRange rng = workingText != nil
? NSMakeRange (0, [workingText length]) : NSMakeRange (NSNotFound, 0);
if (NS_KEYLOG)
- (void)unmarkText
{
+ NSTRACE ("[EmacsView unmarkText]");
+
if (NS_KEYLOG)
NSLog (@"unmark (accept) text");
[self deleteWorkingText];
NSRect rect;
NSPoint pt;
struct window *win = XWINDOW (FRAME_SELECTED_WINDOW (emacsframe));
+
+ NSTRACE ("[EmacsView firstRectForCharacterRange:]");
+
if (NS_KEYLOG)
NSLog (@"firstRectForCharRange request");
- (void)doCommandBySelector: (SEL)aSelector
{
+ NSTRACE ("[EmacsView doCommandBySelector:]");
+
if (NS_KEYLOG)
NSLog (@"doCommandBySelector: %@", NSStringFromSelector (aSelector));
struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (emacsframe);
NSPoint p = [self convertPoint: [theEvent locationInWindow] fromView: nil];
- NSTRACE (mouseDown);
+ NSTRACE ("[EmacsView mouseDown:]");
[self deleteWorkingText];
delta = [theEvent deltaX];
if (delta == 0)
{
- NSTRACE (deltaIsZero);
+ NSTRACE_MSG ("deltaIsZero");
return;
}
emacs_event->kind = HORIZ_WHEEL_EVENT;
- (void)rightMouseDown: (NSEvent *)theEvent
{
- NSTRACE (rightMouseDown);
+ NSTRACE ("[EmacsView rightMouseDown:]");
[self mouseDown: theEvent];
}
- (void)otherMouseDown: (NSEvent *)theEvent
{
- NSTRACE (otherMouseDown);
+ NSTRACE ("[EmacsView otherMouseDown:]");
[self mouseDown: theEvent];
}
- (void)mouseUp: (NSEvent *)theEvent
{
- NSTRACE (mouseUp);
+ NSTRACE ("[EmacsView mouseUp:]");
[self mouseDown: theEvent];
}
- (void)rightMouseUp: (NSEvent *)theEvent
{
- NSTRACE (rightMouseUp);
+ NSTRACE ("[EmacsView rightMouseUp:]");
[self mouseDown: theEvent];
}
- (void)otherMouseUp: (NSEvent *)theEvent
{
- NSTRACE (otherMouseUp);
+ NSTRACE ("[EmacsView otherMouseUp:]");
[self mouseDown: theEvent];
}
- (void) scrollWheel: (NSEvent *)theEvent
{
- NSTRACE (scrollWheel);
+ NSTRACE ("[EmacsView scrollWheel:]");
[self mouseDown: theEvent];
}
Lisp_Object frame;
NSPoint pt;
-// NSTRACE (mouseMoved);
+ NSTRACE_WHEN (NSTRACE_GROUP_EVENTS, "[EmacsView mouseMoved:]");
dpyinfo->last_mouse_movement_time = EV_TIMESTAMP (e);
pt = [self convertPoint: [e locationInWindow] fromView: nil];
if (!NILP (Vmouse_autoselect_window))
{
- NSTRACE (mouse_autoselect_window);
+ NSTRACE_MSG ("mouse_autoselect_window");
static Lisp_Object last_mouse_window;
Lisp_Object window
= window_from_coordinates (emacsframe, pt.x, pt.y, 0, 0);
|| (EQ (XWINDOW (window)->frame,
XWINDOW (selected_window)->frame))))
{
- NSTRACE (in_window);
+ NSTRACE_MSG ("in_window");
emacs_event->kind = SELECT_WINDOW_EVENT;
emacs_event->frame_or_window = window;
EV_TRAILER2 (e);
- (void)mouseDragged: (NSEvent *)e
{
- NSTRACE (mouseDragged);
+ NSTRACE ("[EmacsView mouseDragged:]");
[self mouseMoved: e];
}
- (void)rightMouseDragged: (NSEvent *)e
{
- NSTRACE (rightMouseDragged);
+ NSTRACE ("[EmacsView rightMouseDragged:]");
[self mouseMoved: e];
}
- (void)otherMouseDragged: (NSEvent *)e
{
- NSTRACE (otherMouseDragged);
+ NSTRACE ("[EmacsView otherMouseDragged:]");
[self mouseMoved: e];
}
{
NSEvent *e =[[self window] currentEvent];
- NSTRACE (windowShouldClose);
+ NSTRACE ("[EmacsView windowShouldClose:]");
windowClosing = YES;
if (!emacs_event)
return NO;
int oldh = FRAME_PIXEL_HEIGHT (emacsframe);
int neww, newh;
- NSTRACE (updateFrameSize);
+ NSTRACE ("[EmacsView updateFrameSize:]");
NSTRACE_SIZE ("Original size", NSMakeSize (oldw, oldh));
+ NSTRACE_RECT ("Original frame", wr);
+ NSTRACE_MSG ("Original columns: %d", cols);
+ NSTRACE_MSG ("Original rows: %d", rows);
if (! [self isFullscreen])
{
if (wait_for_tool_bar)
{
if (FRAME_TOOLBAR_HEIGHT (emacsframe) == 0)
- return;
+ {
+ NSTRACE_MSG ("Waiting for toolbar");
+ return;
+ }
wait_for_tool_bar = NO;
}
neww = (int)wr.size.width - emacsframe->border_width;
newh = (int)wr.size.height - extra;
+ NSTRACE_SIZE ("New size", NSMakeSize (neww, newh));
+ NSTRACE_MSG ("tool_bar_height: %d", emacsframe->tool_bar_height);
+
cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (emacsframe, neww);
rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (emacsframe, newh);
if (rows < MINHEIGHT)
rows = MINHEIGHT;
+ NSTRACE_MSG ("New columns: %d", cols);
+ NSTRACE_MSG ("New rows: %d", rows);
+
if (oldr != rows || oldc != cols || neww != oldw || newh != oldh)
{
NSView *view = FRAME_NS_VIEW (emacsframe);
- NSWindow *win = [view window];
- NSSize sz = [win resizeIncrements];
change_frame_size (emacsframe,
FRAME_PIXEL_TO_TEXT_WIDTH (emacsframe, neww),
SET_FRAME_GARBAGED (emacsframe);
cancel_mouse_face (emacsframe);
- // Did resize increments change because of a font change?
- if (sz.width != FRAME_COLUMN_WIDTH (emacsframe) ||
- sz.height != FRAME_LINE_HEIGHT (emacsframe) ||
- (frame_resize_pixelwise && sz.width != 1))
- {
- sz.width = frame_resize_pixelwise
- ? 1 : FRAME_COLUMN_WIDTH (emacsframe);
- sz.height = frame_resize_pixelwise
- ? 1 : FRAME_LINE_HEIGHT (emacsframe);
- [win setResizeIncrements: sz];
+ wr = NSMakeRect (0, 0, neww, newh);
- NSTRACE_SIZE ("New size", NSMakeSize (neww, newh));
- }
+ [view setFrame: wr];
- [view setFrame: NSMakeRect (0, 0, neww, newh)];
- [self windowDidMove:nil]; // Update top/left.
+ // to do: consider using [NSNotificationCenter postNotificationName:].
+ [self windowDidMove: // Update top/left.
+ [NSNotification notificationWithName:NSWindowDidMoveNotification
+ object:[view window]]];
+ }
+ else
+ {
+ NSTRACE_MSG ("No change");
}
}
{
int extra = 0;
- NSTRACE (windowWillResize);
- NSTRACE_SIZE ("Original size", frameSize);
-/*fprintf (stderr,"Window will resize: %.0f x %.0f\n",frameSize.width,frameSize.height); */
+ NSTRACE ("[EmacsView windowWillResize:toSize: " NSTRACE_FMT_SIZE "]",
+ NSTRACE_ARG_SIZE (frameSize));
+ NSTRACE_RECT ("[sender frame]", [sender frame]);
+ NSTRACE_FSTYPE ("fs_state", fs_state);
if (fs_state == FULLSCREEN_MAXIMIZED
&& (maximized_width != (int)frameSize.width
else if (fs_state == FULLSCREEN_HEIGHT
&& maximized_height != (int)frameSize.height)
[self setFSValue: FULLSCREEN_NONE];
+
if (fs_state == FULLSCREEN_NONE)
maximized_width = maximized_height = -1;
}
}
#endif /* NS_IMPL_COCOA */
-/*fprintf (stderr," ...size became %.0f x %.0f (%d x %d)\n",frameSize.width,frameSize.height,cols,rows); */
+
+ NSTRACE_MSG ("cols: %d rows: %d", cols, rows);
+
+ /* Restrict the new size to the text gird.
+
+ Don't restrict the width if the user only adjusted the height, and
+ vice versa. (Without this, the frame would shrink, and move
+ slightly, if the window was resized by dragging one of its
+ borders.) */
+ if (!frame_resize_pixelwise)
+ {
+ NSRect r = [[self window] frame];
+
+ if (r.size.width != frameSize.width)
+ {
+ frameSize.width =
+ FRAME_TEXT_COLS_TO_PIXEL_WIDTH (emacsframe, cols);
+ }
+
+ if (r.size.height != frameSize.height)
+ {
+ frameSize.height =
+ FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (emacsframe, rows) + extra;
+ }
+ }
+
+ NSTRACE_RETURN_SIZE (frameSize);
return frameSize;
}
- (void)windowDidResize: (NSNotification *)notification
{
+ NSTRACE ("[EmacsView windowDidResize:]");
+ if (!FRAME_LIVE_P (emacsframe))
+ {
+ NSTRACE_MSG ("Ignored (frame dead)");
+ return;
+ }
+ if (emacsframe->output_data.ns->in_animation)
+ {
+ NSTRACE_MSG ("Ignored (in animation)");
+ return;
+ }
+
if (! [self fsIsNative])
{
NSWindow *theWindow = [notification object];
if ([self window] != theWindow) return;
}
+ NSTRACE_RECT ("frame", [[notification object] frame]);
+
#ifdef NS_IMPL_GNUSTEP
NSWindow *theWindow = [notification object];
sz = [self windowWillResize: theWindow toSize: sz];
#endif /* NS_IMPL_GNUSTEP */
- NSTRACE (windowDidResize);
-/*fprintf (stderr,"windowDidResize: %.0f\n",[theWindow frame].size.height); */
-
-if (cols > 0 && rows > 0)
+ if (cols > 0 && rows > 0)
{
[self updateFrameSize: YES];
}
#ifdef NS_IMPL_COCOA
- (void)viewDidEndLiveResize
{
+ NSTRACE ("[EmacsView viewDidEndLiveResize]");
+
[super viewDidEndLiveResize];
if (old_title != 0)
{
- (void)windowDidBecomeKey: (NSNotification *)notification
/* cf. x_detect_focus_change(), x_focus_changed(), x_new_focus_frame() */
+{
+ [self windowDidBecomeKey];
+}
+
+
+- (void)windowDidBecomeKey /* for direct calls */
{
struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (emacsframe);
struct frame *old_focus = dpyinfo->x_focus_frame;
- NSTRACE (windowDidBecomeKey);
+ NSTRACE ("[EmacsView windowDidBecomeKey]");
if (emacsframe != old_focus)
dpyinfo->x_focus_frame = emacsframe;
{
struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (emacsframe);
BOOL is_focus_frame = dpyinfo->x_focus_frame == emacsframe;
- NSTRACE (windowDidResignKey);
+ NSTRACE ("[EmacsView windowDidResignKey:]");
if (is_focus_frame)
dpyinfo->x_focus_frame = 0;
- (void)windowWillMiniaturize: sender
{
- NSTRACE (windowWillMiniaturize);
+ NSTRACE ("[EmacsView windowWillMiniaturize:]");
+}
+
+
+- (void)setFrame:(NSRect)frameRect;
+{
+ NSTRACE ("[EmacsView setFrame:" NSTRACE_FMT_RECT "]",
+ NSTRACE_ARG_RECT (frameRect));
+
+ [super setFrame:(NSRect)frameRect];
}
NSRect r, wr;
Lisp_Object tem;
NSWindow *win;
- NSSize sz;
NSColor *col;
NSString *name;
- NSTRACE (initFrameFromEmacs);
+ NSTRACE ("[EmacsView initFrameFromEmacs:]");
+ NSTRACE_MSG ("cols:%d lines:%d", f->text_cols, f->text_lines);
windowClosing = NO;
processingCompose = NO;
maximized_width = maximized_height = -1;
nonfs_window = nil;
-/*fprintf (stderr,"init with %d, %d\n",f->text_cols, f->text_lines); */
-
ns_userRect = NSMakeRect (0, 0, 0, 0);
r = NSMakeRect (0, 0, FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, f->text_cols),
FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, f->text_lines));
MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_9
[win useOptimizedDrawing: YES];
#endif
- sz.width = frame_resize_pixelwise ? 1 : FRAME_COLUMN_WIDTH (f);
- sz.height = frame_resize_pixelwise ? 1 : FRAME_LINE_HEIGHT (f);
- [win setResizeIncrements: sz];
[[win contentView] addSubview: self];
NSScreen *screen = [win screen];
if (screen != 0)
- [win setFrameTopLeftPoint: NSMakePoint
- (IN_BOUND (-SCREENMAX, f->left_pos, SCREENMAX),
- IN_BOUND (-SCREENMAX,
- [screen frame].size.height - NS_TOP_POS (f), SCREENMAX))];
+ {
+ NSPoint pt = NSMakePoint
+ (IN_BOUND (-SCREENMAX, f->left_pos, SCREENMAX),
+ IN_BOUND (-SCREENMAX,
+ [screen frame].size.height - NS_TOP_POS (f), SCREENMAX));
+
+ [win setFrameTopLeftPoint: pt];
+
+ NSTRACE_RECT ("new frame", [win frame]);
+ }
}
[win makeFirstResponder: self];
NSArray *screens = [NSScreen screens];
NSScreen *screen = [screens objectAtIndex: 0];
- NSTRACE (windowDidMove);
+ NSTRACE ("[EmacsView windowDidMove:]");
if (!emacsframe->output_data.ns)
return;
location so set_window_size moves the frame. */
- (BOOL)windowShouldZoom: (NSWindow *)sender toFrame: (NSRect)newFrame
{
+ NSTRACE (("[EmacsView windowShouldZoom:toFrame:" NSTRACE_FMT_RECT "]"
+ NSTRACE_FMT_RETURN "YES"),
+ NSTRACE_ARG_RECT (newFrame));
+
emacsframe->output_data.ns->zooming = 1;
return YES;
}
- (NSRect)windowWillUseStandardFrame:(NSWindow *)sender
defaultFrame:(NSRect)defaultFrame
{
+ // TODO: Rename to "currentFrame" and assign "result" properly in
+ // all paths.
NSRect result = [sender frame];
- NSTRACE (windowWillUseStandardFrame);
+ NSTRACE (("[EmacsView windowWillUseStandardFrame:defaultFrame:"
+ NSTRACE_FMT_RECT "]"),
+ NSTRACE_ARG_RECT (defaultFrame));
+ NSTRACE_FSTYPE ("fs_state", fs_state);
+ NSTRACE_FSTYPE ("fs_before_fs", fs_before_fs);
+ NSTRACE_FSTYPE ("next_maximized", next_maximized);
+ NSTRACE_RECT ("ns_userRect", ns_userRect);
+ NSTRACE_RECT ("[sender frame]", [sender frame]);
if (fs_before_fs != -1) /* Entering fullscreen */
- {
- result = defaultFrame;
- }
- else if (next_maximized == FULLSCREEN_HEIGHT
- || (next_maximized == -1
- && abs ((int)(defaultFrame.size.height - result.size.height))
- > FRAME_LINE_HEIGHT (emacsframe)))
- {
- /* first click */
- ns_userRect = result;
- maximized_height = result.size.height = defaultFrame.size.height;
- maximized_width = -1;
- result.origin.y = defaultFrame.origin.y;
- [self setFSValue: FULLSCREEN_HEIGHT];
-#ifdef NS_IMPL_COCOA
- maximizing_resize = YES;
-#endif
- }
- else if (next_maximized == FULLSCREEN_WIDTH)
{
- ns_userRect = result;
- maximized_width = result.size.width = defaultFrame.size.width;
- maximized_height = -1;
- result.origin.x = defaultFrame.origin.x;
- [self setFSValue: FULLSCREEN_WIDTH];
+ NSTRACE_MSG ("Entering fullscreen");
+ result = defaultFrame;
}
- else if (next_maximized == FULLSCREEN_MAXIMIZED
- || (next_maximized == -1
- && abs ((int)(defaultFrame.size.width - result.size.width))
- > FRAME_COLUMN_WIDTH (emacsframe)))
+ else
{
- result = defaultFrame; /* second click */
- maximized_width = result.size.width;
- maximized_height = result.size.height;
- [self setFSValue: FULLSCREEN_MAXIMIZED];
+ // Save the window size and position (frame) before the resize.
+ if (fs_state != FULLSCREEN_MAXIMIZED
+ && fs_state != FULLSCREEN_WIDTH)
+ {
+ ns_userRect.size.width = result.size.width;
+ ns_userRect.origin.x = result.origin.x;
+ }
+
+ if (fs_state != FULLSCREEN_MAXIMIZED
+ && fs_state != FULLSCREEN_HEIGHT)
+ {
+ ns_userRect.size.height = result.size.height;
+ ns_userRect.origin.y = result.origin.y;
+ }
+
+ NSTRACE_RECT ("ns_userRect (2)", ns_userRect);
+
+ if (next_maximized == FULLSCREEN_HEIGHT
+ || (next_maximized == -1
+ && abs ((int)(defaultFrame.size.height - result.size.height))
+ > FRAME_LINE_HEIGHT (emacsframe)))
+ {
+ /* first click */
+ NSTRACE_MSG ("FULLSCREEN_HEIGHT");
+ maximized_height = result.size.height = defaultFrame.size.height;
+ maximized_width = -1;
+ result.origin.y = defaultFrame.origin.y;
+ if (ns_userRect.size.height != 0)
+ {
+ result.origin.x = ns_userRect.origin.x;
+ result.size.width = ns_userRect.size.width;
+ }
+ [self setFSValue: FULLSCREEN_HEIGHT];
#ifdef NS_IMPL_COCOA
- maximizing_resize = YES;
+ maximizing_resize = YES;
#endif
- }
- else
- {
- /* restore */
- result = ns_userRect.size.height ? ns_userRect : result;
- ns_userRect = NSMakeRect (0, 0, 0, 0);
+ }
+ else if (next_maximized == FULLSCREEN_WIDTH)
+ {
+ NSTRACE_MSG ("FULLSCREEN_WIDTH");
+ maximized_width = result.size.width = defaultFrame.size.width;
+ maximized_height = -1;
+ result.origin.x = defaultFrame.origin.x;
+ if (ns_userRect.size.width != 0)
+ {
+ result.origin.y = ns_userRect.origin.y;
+ result.size.height = ns_userRect.size.height;
+ }
+ [self setFSValue: FULLSCREEN_WIDTH];
+ }
+ else if (next_maximized == FULLSCREEN_MAXIMIZED
+ || (next_maximized == -1
+ && abs ((int)(defaultFrame.size.width - result.size.width))
+ > FRAME_COLUMN_WIDTH (emacsframe)))
+ {
+ NSTRACE_MSG ("FULLSCREEN_MAXIMIZED");
+
+ result = defaultFrame; /* second click */
+ maximized_width = result.size.width;
+ maximized_height = result.size.height;
+ [self setFSValue: FULLSCREEN_MAXIMIZED];
+#ifdef NS_IMPL_COCOA
+ maximizing_resize = YES;
+#endif
+ }
+ else
+ {
+ /* restore */
+ NSTRACE_MSG ("Restore");
+ result = ns_userRect.size.height ? ns_userRect : result;
+ NSTRACE_RECT ("restore (2)", result);
+ ns_userRect = NSMakeRect (0, 0, 0, 0);
#ifdef NS_IMPL_COCOA
- maximizing_resize = fs_state != FULLSCREEN_NONE;
+ maximizing_resize = fs_state != FULLSCREEN_NONE;
#endif
- [self setFSValue: FULLSCREEN_NONE];
- maximized_width = maximized_height = -1;
+ [self setFSValue: FULLSCREEN_NONE];
+ maximized_width = maximized_height = -1;
+ }
}
if (fs_before_fs == -1) next_maximized = -1;
+
+ NSTRACE_RECT ("Final ns_userRect", ns_userRect);
+ NSTRACE_MSG ("Final maximized_width: %d", maximized_width);
+ NSTRACE_MSG ("Final maximized_height: %d", maximized_height);
+ NSTRACE_FSTYPE ("Final next_maximized", next_maximized);
+
[self windowWillResize: sender toSize: result.size];
+
+ NSTRACE_RETURN_RECT (result);
+
return result;
}
- (void)windowDidDeminiaturize: sender
{
- NSTRACE (windowDidDeminiaturize);
+ NSTRACE ("[EmacsView windowDidDeminiaturize:]");
if (!emacsframe->output_data.ns)
return;
- (void)windowDidExpose: sender
{
- NSTRACE (windowDidExpose);
+ NSTRACE ("[EmacsView windowDidExpose:]");
if (!emacsframe->output_data.ns)
return;
- (void)windowDidMiniaturize: sender
{
- NSTRACE (windowDidMiniaturize);
+ NSTRACE ("[EmacsView windowDidMiniaturize:]");
if (!emacsframe->output_data.ns)
return;
- (void)windowWillEnterFullScreen:(NSNotification *)notification
{
+ NSTRACE ("[EmacsView windowWillEnterFullScreen:]");
+ [self windowWillEnterFullScreen];
+}
+- (void)windowWillEnterFullScreen /* provided for direct calls */
+{
+ NSTRACE ("[EmacsView windowWillEnterFullScreen]");
fs_before_fs = fs_state;
}
- (void)windowDidEnterFullScreen:(NSNotification *)notification
{
+ NSTRACE ("[EmacsView windowDidEnterFullScreen:]");
+ [self windowDidEnterFullScreen];
+}
+
+- (void)windowDidEnterFullScreen /* provided for direct calls */
+{
+ NSTRACE ("[EmacsView windowDidEnterFullScreen]");
[self setFSValue: FULLSCREEN_BOTH];
if (! [self fsIsNative])
{
- [self windowDidBecomeKey:notification];
+ [self windowDidBecomeKey];
[nonfs_window orderOut:self];
}
else
- (void)windowWillExitFullScreen:(NSNotification *)notification
{
+ NSTRACE ("[EmacsView windowWillExitFullScreen:]");
+ [self windowWillExitFullScreen];
+}
+
+- (void)windowWillExitFullScreen /* provided for direct calls */
+{
+ NSTRACE ("[EmacsView windowWillExitFullScreen]");
+ if (!FRAME_LIVE_P (emacsframe))
+ {
+ NSTRACE_MSG ("Ignored (frame dead)");
+ return;
+ }
if (next_maximized != -1)
fs_before_fs = next_maximized;
}
- (void)windowDidExitFullScreen:(NSNotification *)notification
{
+ NSTRACE ("[EmacsView windowDidExitFullScreen:]");
+ [self windowDidExitFullScreen];
+}
+
+- (void)windowDidExitFullScreen /* provided for direct calls */
+{
+ NSTRACE ("[EmacsView windowDidExitFullScreen]");
+ if (!FRAME_LIVE_P (emacsframe))
+ {
+ NSTRACE_MSG ("Ignored (frame dead)");
+ return;
+ }
[self setFSValue: fs_before_fs];
fs_before_fs = -1;
#ifdef HAVE_NATIVE_FS
- (BOOL)isFullscreen
{
- if (! fs_is_native) return nonfs_window != nil;
+ BOOL res;
+
+ if (! fs_is_native)
+ {
+ res = (nonfs_window != nil);
+ }
+ else
+ {
#ifdef HAVE_NATIVE_FS
- return ([[self window] styleMask] & NSFullScreenWindowMask) != 0;
+ res = (([[self window] styleMask] & NSFullScreenWindowMask) != 0);
#else
- return NO;
+ res = NO;
#endif
+ }
+
+ NSTRACE ("[EmacsView isFullscreen] " NSTRACE_FMT_RETURN " %d",
+ (int) res);
+
+ return res;
}
#ifdef HAVE_NATIVE_FS
- (void)updateCollectionBehavior
{
+ NSTRACE ("[EmacsView updateCollectionBehavior]");
+
if (! [self isFullscreen])
{
NSWindow *win = [self window];
NSWindow *w, *fw;
BOOL onFirstScreen;
struct frame *f;
- NSSize sz;
NSRect r, wr;
NSColor *col;
+ NSTRACE ("[EmacsView toggleFullScreen:]");
+
if (fs_is_native)
{
#ifdef HAVE_NATIVE_FS
(FRAME_DEFAULT_FACE (f)),
f);
- sz.width = frame_resize_pixelwise ? 1 : FRAME_COLUMN_WIDTH (f);
- sz.height = frame_resize_pixelwise ? 1 : FRAME_LINE_HEIGHT (f);
-
if (fs_state != FULLSCREEN_BOTH)
{
NSScreen *screen = [w screen];
MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_9
[fw useOptimizedDrawing: YES];
#endif
- [fw setResizeIncrements: sz];
[fw setBackgroundColor: col];
if ([col alphaComponent] != (EmacsCGFloat) 1.0)
[fw setOpaque: NO];
nonfs_window = w;
- [self windowWillEnterFullScreen:nil];
+ [self windowWillEnterFullScreen];
[fw makeKeyAndOrderFront:NSApp];
[fw makeFirstResponder:self];
[w orderOut:self];
r = [fw frameRectForContentRect:[screen frame]];
[fw setFrame: r display:YES animate:ns_use_fullscreen_animation];
- [self windowDidEnterFullScreen:nil];
+ [self windowDidEnterFullScreen];
[fw display];
}
else
}
[w setContentView:[fw contentView]];
- [w setResizeIncrements: sz];
[w setBackgroundColor: col];
if ([col alphaComponent] != (EmacsCGFloat) 1.0)
[w setOpaque: NO];
if (FRAME_EXTERNAL_TOOL_BAR (f))
FRAME_TOOLBAR_HEIGHT (f) = tobar_height;
- [self windowWillExitFullScreen:nil];
+ // to do: consider using [NSNotificationCenter postNotificationName:] to send notifications.
+
+ [self windowWillExitFullScreen];
[fw setFrame: [w frame] display:YES animate:ns_use_fullscreen_animation];
[fw close];
[w makeKeyAndOrderFront:NSApp];
- [self windowDidExitFullScreen:nil];
+ [self windowDidExitFullScreen];
[self updateFrameSize:YES];
}
}
- (void)handleFS
{
+ NSTRACE ("[EmacsView handleFS]");
+
if (fs_state != emacsframe->want_fullscreen)
{
- NSSize sz;
- sz.width = frame_resize_pixelwise ? 1 : FRAME_COLUMN_WIDTH (emacsframe);
- sz.height = frame_resize_pixelwise ? 1 : FRAME_LINE_HEIGHT (emacsframe);
- [[self window] setResizeIncrements:sz];
-
if (fs_state == FULLSCREEN_BOTH)
{
+ NSTRACE_MSG ("fs_state == FULLSCREEN_BOTH");
[self toggleFullScreen:self];
}
switch (emacsframe->want_fullscreen)
{
case FULLSCREEN_BOTH:
+ NSTRACE_MSG ("FULLSCREEN_BOTH");
[self toggleFullScreen:self];
break;
case FULLSCREEN_WIDTH:
+ NSTRACE_MSG ("FULLSCREEN_WIDTH");
next_maximized = FULLSCREEN_WIDTH;
if (fs_state != FULLSCREEN_BOTH)
[[self window] performZoom:self];
break;
case FULLSCREEN_HEIGHT:
+ NSTRACE_MSG ("FULLSCREEN_HEIGHT");
next_maximized = FULLSCREEN_HEIGHT;
if (fs_state != FULLSCREEN_BOTH)
[[self window] performZoom:self];
break;
case FULLSCREEN_MAXIMIZED:
+ NSTRACE_MSG ("FULLSCREEN_MAXIMIZED");
next_maximized = FULLSCREEN_MAXIMIZED;
if (fs_state != FULLSCREEN_BOTH)
[[self window] performZoom:self];
break;
case FULLSCREEN_NONE:
+ NSTRACE_MSG ("FULLSCREEN_NONE");
if (fs_state != FULLSCREEN_BOTH)
{
next_maximized = FULLSCREEN_NONE;
- (void) setFSValue: (int)value
{
+ NSTRACE ("[EmacsView setFSValue:" NSTRACE_FMT_FSTYPE "]",
+ NSTRACE_ARG_FSTYPE(value));
+
Lisp_Object lval = Qnil;
switch (value)
{
- (void)mouseEntered: (NSEvent *)theEvent
{
- NSTRACE (mouseEntered);
+ NSTRACE ("[EmacsView mouseEntered:]");
if (emacsframe)
FRAME_DISPLAY_INFO (emacsframe)->last_mouse_movement_time
= EV_TIMESTAMP (theEvent);
{
Mouse_HLInfo *hlinfo = emacsframe ? MOUSE_HL_INFO (emacsframe) : NULL;
- NSTRACE (mouseExited);
+ NSTRACE ("[EmacsView mouseExited:]");
if (!hlinfo)
return;
- menuDown: sender
{
- NSTRACE (menuDown);
+ NSTRACE ("[EmacsView menuDown:]");
if (context_menu_value == -1)
context_menu_value = [sender tag];
else
NSEvent *theEvent;
int idx = [item tag] * TOOL_BAR_ITEM_NSLOTS;
- NSTRACE (toolbarClicked);
+ NSTRACE ("[EmacsView toolbarClicked:]");
if (!emacs_event)
return self;
- toggleToolbar: (id)sender
{
+ NSTRACE ("[EmacsView toggleToolbar:]");
+
if (!emacs_event)
return self;
int x = NSMinX (rect), y = NSMinY (rect);
int width = NSWidth (rect), height = NSHeight (rect);
- NSTRACE (drawRect);
+ NSTRACE ("[EmacsView drawRect:" NSTRACE_FMT_RECT "]",
+ NSTRACE_ARG_RECT(rect));
if (!emacsframe || !emacsframe->output_data.ns)
return;
-(NSDragOperation) draggingEntered: (id <NSDraggingInfo>) sender
{
- NSTRACE (draggingEntered);
+ NSTRACE ("[EmacsView draggingEntered:]");
return NSDragOperationGeneric;
}
NSDragOperation op = [sender draggingSourceOperationMask];
int modifiers = 0;
- NSTRACE (performDragOperation);
+ NSTRACE ("[EmacsView performDragOperation:]");
if (!emacs_event)
return NO;
- (id) validRequestorForSendType: (NSString *)typeSent
returnType: (NSString *)typeReturned
{
- NSTRACE (validRequestorForSendType);
+ NSTRACE ("[EmacsView validRequestorForSendType:returnType:]");
if (typeSent != nil && [ns_send_types indexOfObject: typeSent] != NSNotFound
&& typeReturned == nil)
{
NSArray *typesDeclared;
Lisp_Object val;
+ NSTRACE ("[EmacsView writeSelectionToPasteboard:types:]");
+
/* We only support NSStringPboardType */
if ([types containsObject:NSStringPboardType] == NO) {
return NO;
- setMiniwindowImage: (BOOL) setMini
{
id image = [[self window] miniwindowImage];
- NSTRACE (setMiniwindowImage);
+ NSTRACE ("[EmacsView setMiniwindowImage:%d]", setMini);
/* NOTE: under Cocoa miniwindowImage always returns nil, documentation
about "AppleDockIconEnabled" notwithstanding, however the set message
- (void) setRows: (int) r andColumns: (int) c
{
+ NSTRACE ("[EmacsView setRows:%d andColumns:%d]", r, c);
rows = r;
cols = c;
}
+- (int) fullscreenState
+{
+ return fs_state;
+}
+
@end /* EmacsView */
struct frame *f = SELECTED_FRAME ();
struct buffer *curbuf = XBUFFER (XWINDOW (f->selected_window)->contents);
+ NSTRACE ("[EmacsWindow accessibilityAttributeValue:]");
+
if ([attribute isEqualToString:NSAccessibilityRoleAttribute])
return NSAccessibilityTextFieldRole;
}
#endif /* NS_IMPL_COCOA */
-/* If we have multiple monitors, one above the other, we don't want to
- restrict the height to just one monitor. So we override this. */
-- (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen
-{
- /* When making the frame visible for the first time or if there is just
- one screen, we want to constrain. Other times not. */
- NSArray *screens = [NSScreen screens];
- NSUInteger nr_screens = [screens count], nr_eff_screens = 0, i;
- NSTRACE (constrainFrameRect);
- NSTRACE_RECT ("input", frameRect);
+/* Constrain size and placement of a frame.
- if (ns_menu_bar_should_be_hidden ())
- return frameRect;
+ By returning the original "frameRect", the frame is not
+ constrained. This can lead to unwanted situations where, for
+ example, the menu bar covers the frame.
- if (nr_screens == 1)
- return [super constrainFrameRect:frameRect toScreen:screen];
+ The default implementation (accessed using "super") constrains the
+ frame to the visible area of SCREEN, minus the menu bar (if
+ present) and the Dock. Note that default implementation also calls
+ windowWillResize, with the frame it thinks should have. (This can
+ make the frame exit maximized mode.)
+
+ Note that this should work in situations where multiple monitors
+ are present. Common configurations are side-by-side monitors and a
+ monitor on top of another (e.g. when a laptop is placed under a
+ large screen). */
+- (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen
+{
+ NSTRACE ("[EmacsWindow constrainFrameRect:" NSTRACE_FMT_RECT " toScreen:]",
+ NSTRACE_ARG_RECT (frameRect));
#ifdef NS_IMPL_COCOA
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
// If separate spaces is on, it is like each screen is independent. There is
// no spanning of frames across screens.
if ([NSScreen screensHaveSeparateSpaces])
- return [super constrainFrameRect:frameRect toScreen:screen];
+ {
+ NSTRACE_MSG ("Screens have separate spaces");
+ frameRect = [super constrainFrameRect:frameRect toScreen:screen];
+ NSTRACE_RETURN_RECT (frameRect);
+ return frameRect;
+ }
#endif
#endif
- for (i = 0; i < nr_screens; ++i)
+ return constrain_frame_rect(frameRect,
+ [(EmacsView *)[self delegate] isFullscreen]);
+}
+
+
+- (void)performZoom:(id)sender
+{
+ NSTRACE ("[EmacsWindow performZoom:]");
+
+ return [super performZoom:sender];
+}
+
+- (void)zoom:(id)sender
+{
+ NSTRACE ("[EmacsWindow zoom:]");
+
+ ns_update_auto_hide_menu_bar();
+
+ // Below are three zoom implementations. In the final commit, the
+ // idea is that the last should be included.
+
+#if 0
+ // Native zoom done using the standard zoom animation. Size of the
+ // resulting frame reduced to accommodate the Dock and, if present,
+ // the menu-bar.
+ [super zoom:sender];
+
+#elif 0
+ // Native zoom done using the standard zoom animation, plus an
+ // 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
+ // entire screen, except the menu-bar.
+ //
+ // This works for all practical purposes. (The only minor oddity is
+ // when transiting from full-height frame to a maximized, the
+ // animation reduces the height of the frame slightly (to the 4
+ // pixels needed to accommodate the Doc) before it snaps back into
+ // full height. The user would need a very trained eye to spot
+ // this.)
+ NSScreen * screen = [self screen];
+ if (screen != nil)
{
- NSScreen *s = [screens objectAtIndex: i];
- NSRect scrrect = [s frame];
- NSRect intersect = NSIntersectionRect (frameRect, scrrect);
+ int fs_state = [(EmacsView *)[self delegate] fullscreenState];
- if (intersect.size.width > 0 || intersect.size.height > 0)
- ++nr_eff_screens;
- }
+ NSTRACE_FSTYPE ("fullscreenState", fs_state);
- if (nr_eff_screens == 1)
- return [super constrainFrameRect:frameRect toScreen:screen];
+ NSRect sr = [screen frame];
+ struct EmacsMargins margins
+ = ns_screen_margins_ignoring_hidden_dock(screen);
- /* The default implementation does two things 1) ensure that the top
- of the rectangle is below the menu bar (or below the top of the
- screen) and 2) resizes windows larger than the screen. As we
- don't want the latter, a smaller rectangle is used. */
-#define FAKE_HEIGHT 64
- float old_top = frameRect.origin.y + frameRect.size.height;
- NSRect r;
- r.size.height = FAKE_HEIGHT;
- r.size.width = frameRect.size.width;
- r.origin.x = frameRect.origin.x;
- r.origin.y = old_top - FAKE_HEIGHT;
+ NSRect wr = [self frame];
+ NSTRACE_RECT ("Rect after zoom", wr);
- NSTRACE_RECT ("input to super", r);
+ NSRect newWr = wr;
- r = [super constrainFrameRect:r toScreen:screen];
+ if (fs_state == FULLSCREEN_MAXIMIZED
+ || fs_state == FULLSCREEN_HEIGHT)
+ {
+ newWr.origin.y = sr.origin.y + margins.bottom;
+ newWr.size.height = sr.size.height - margins.top - margins.bottom;
+ }
- NSTRACE_RECT ("output from super", r);
+ if (fs_state == FULLSCREEN_MAXIMIZED
+ || fs_state == FULLSCREEN_WIDTH)
+ {
+ newWr.origin.x = sr.origin.x + margins.left;
+ newWr.size.width = sr.size.width - margins.right - margins.left;
+ }
- float new_top = r.origin.y + FAKE_HEIGHT;
- if (new_top < old_top)
- {
- frameRect.origin.y = new_top - frameRect.size.height;
- }
+ if (newWr.size.width != wr.size.width
+ || newWr.size.height != wr.size.height
+ || newWr.origin.x != wr.origin.x
+ || newWr.origin.y != wr.origin.y)
+ {
+ NSTRACE_MSG ("New frame different");
+ [self setFrame: newWr display: NO];
+ }
+ }
+#else
+ // 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];
+ struct EmacsMargins margins
+ = ns_screen_margins_ignoring_hidden_dock(screen);
- NSTRACE_RECT ("output", frameRect);
+ sr.size.height -= (margins.top + margins.bottom);
+ sr.size.width -= (margins.left + margins.right);
+ sr.origin.x += margins.left;
+ sr.origin.y += margins.bottom;
- return frameRect;
-#undef FAKE_HEIGHT
+ sr = [[self delegate] windowWillUseStandardFrame:self
+ defaultFrame:sr];
+ [self setFrame: sr display: NO];
+ }
+#endif
}
+- (void)setFrame:(NSRect)windowFrame
+ display:(BOOL)displayViews
+{
+ NSTRACE ("[EmacsWindow setFrame:" NSTRACE_FMT_RECT " display:%d]",
+ NSTRACE_ARG_RECT (windowFrame), displayViews);
+
+ [super setFrame:windowFrame display:displayViews];
+}
+
+- (void)setFrame:(NSRect)windowFrame
+ display:(BOOL)displayViews
+ animate:(BOOL)performAnimation
+{
+ NSTRACE ("[EmacsWindow setFrame:" NSTRACE_FMT_RECT
+ " display:%d performAnimation:%d]",
+ NSTRACE_ARG_RECT (windowFrame), displayViews, performAnimation);
+
+ [super setFrame:windowFrame display:displayViews animate:performAnimation];
+}
+
+- (void)setFrameTopLeftPoint:(NSPoint)point
+{
+ NSTRACE ("[EmacsWindow setFrameTopLeftPoint:" NSTRACE_FMT_POINT "]",
+ NSTRACE_ARG_POINT (point));
+
+ [super setFrameTopLeftPoint:point];
+}
@end /* EmacsWindow */
- initFrame: (NSRect )r window: (Lisp_Object)nwin
{
- NSTRACE (EmacsScroller_initFrame);
+ NSTRACE ("[EmacsScroller initFrame: window:]");
r.size.width = [EmacsScroller scrollerWidth];
[super initWithFrame: r/*NSMakeRect (0, 0, 0, 0)*/];
- (void)setFrame: (NSRect)newRect
{
- NSTRACE (EmacsScroller_setFrame);
+ NSTRACE ("[EmacsScroller setFrame:]");
+
/* block_input (); */
pixel_height = NSHeight (newRect);
if (pixel_height == 0) pixel_height = 1;
- (void)dealloc
{
- NSTRACE (EmacsScroller_dealloc);
+ NSTRACE ("[EmacsScroller dealloc]");
if (window)
wset_vertical_scroll_bar (window, Qnil);
window = 0;
- condemn
{
- NSTRACE (condemn);
+ NSTRACE ("[EmacsScroller condemn]");
condemned =YES;
return self;
}
- reprieve
{
- NSTRACE (reprieve);
+ NSTRACE ("[EmacsScroller reprieve]");
condemned =NO;
return self;
}
-(bool)judge
{
- NSTRACE (judge);
+ NSTRACE ("[EmacsScroller judge]");
bool ret = condemned;
if (condemned)
{
- (void)resetCursorRects
{
NSRect visible = [self visibleRect];
- NSTRACE (resetCursorRects);
+ NSTRACE ("[EmacsScroller resetCursorRects]");
if (!NSIsEmptyRect (visible))
[self addCursorRect: visible cursor: [NSCursor arrowCursor]];
- setPosition: (int)position portion: (int)portion whole: (int)whole
{
- NSTRACE (setPosition);
+ NSTRACE ("[EmacsScroller setPosition:portion:whole:]");
em_position = position;
em_portion = portion;
- (void) sendScrollEventAtLoc: (float)loc fromEvent: (NSEvent *)e
{
Lisp_Object win;
+
+ NSTRACE ("[EmacsScroller sendScrollEventAtLoc:fromEvent:]");
+
if (!emacs_event)
return;
NSPoint p = [[self window] mouseLocationOutsideOfEventStream];
BOOL inKnob = [self testPart: p] == NSScrollerKnob;
+ NSTRACE ("[EmacsScroller repeatScroll:]");
+
/* clear timer if need be */
if (inKnob || [scroll_repeat_entry timeInterval] == SCROLL_BAR_FIRST_DELAY)
{
CGFloat inc = 0.0, loc, kloc, pos;
int edge = 0;
- NSTRACE (EmacsScroller_mouseDown);
+ NSTRACE ("[EmacsScroller mouseDown:]");
switch (part)
{
NSRect sr;
double loc, pos;
- NSTRACE (EmacsScroller_mouseDragged);
+ NSTRACE ("[EmacsScroller mouseDragged:]");
sr = [self convertRect: [self rectForPart: NSScrollerKnobSlot]
toView: nil];
- (void)mouseUp: (NSEvent *)e
{
+ NSTRACE ("[EmacsScroller mouseUp:]");
+
if (scroll_repeat_entry)
{
[scroll_repeat_entry invalidate];
/* treat scrollwheel events in the bar as though they were in the main window */
- (void) scrollWheel: (NSEvent *)theEvent
{
+ NSTRACE ("[EmacsScroller scrollWheel:]");
+
EmacsView *view = (EmacsView *)FRAME_NS_VIEW (frame);
[view mouseDown: theEvent];
}
void
syms_of_nsterm (void)
{
- NSTRACE (syms_of_nsterm);
+ NSTRACE ("syms_of_nsterm");
ns_antialias_threshold = 10.0;