/* NeXT/Open/GNUstep / MacOSX communication module.
-Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2013 Free Software
+Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2014 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
#include "process.h"
#endif
+#ifdef NS_IMPL_COCOA
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+#include "macfont.h"
+#endif
+#endif
+
/* call tracing */
#if 0
int term_trace_num = 0;
#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)
+#endif
+
extern NSString *NSMenuDidBeginTrackingNotification;
+/* ==========================================================================
+
+ NSColor, EmacsColor category.
+
+ ========================================================================== */
+@implementation NSColor (EmacsColor)
++ (NSColor *)colorForEmacsRed:(CGFloat)red green:(CGFloat)green
+ blue:(CGFloat)blue alpha:(CGFloat)alpha
+{
+#ifdef NS_IMPL_COCOA
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
+ if (ns_use_srgb_colorspace)
+ return [NSColor colorWithSRGBRed: red
+ green: green
+ blue: blue
+ alpha: alpha];
+#endif
+#endif
+ return [NSColor colorWithCalibratedRed: red
+ green: green
+ blue: blue
+ alpha: alpha];
+}
+
+- (NSColor *)colorUsingDefaultColorSpace
+{
+#ifdef NS_IMPL_COCOA
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
+ if (ns_use_srgb_colorspace)
+ return [self colorUsingColorSpace: [NSColorSpace sRGBColorSpace]];
+#endif
+#endif
+ return [self colorUsingColorSpaceName: NSCalibratedRGBColorSpace];
+}
+
+@end
+
/* ==========================================================================
Local declarations
extern Lisp_Object Qcursor_color, Qcursor_type, Qns, Qleft;
static Lisp_Object QUTF8_STRING;
+static Lisp_Object Qcocoa, Qgnustep;
+static Lisp_Object Qfile, Qurl;
/* On OS X picks up the default NSGlobalDomain AppleAntiAliasingThreshold,
the maximum font size to NOT antialias. On GNUstep there is currently
no way to control this behavior. */
float ns_antialias_threshold;
-/* Used to pick up AppleHighlightColor on OS X */
-NSString *ns_selection_color;
-
NSArray *ns_send_types =0, *ns_return_types =0, *ns_drag_types =0;
NSString *ns_app_name = @"Emacs"; /* default changed later */
/* Display variables */
struct ns_display_info *x_display_list; /* Chain of existing displays */
-Lisp_Object ns_display_name_list;
long context_menu_value = 0;
-/* Last window where we saw the mouse. Used by mouse-autoselect-window. */
-static Lisp_Object last_window;
-
/* display update */
-NSPoint last_mouse_motion_position;
-static NSRect last_mouse_glyph;
-static Time last_mouse_movement_time = 0;
-static Lisp_Object last_mouse_motion_frame;
-static EmacsScroller *last_mouse_scroll_bar = nil;
static struct frame *ns_updating_frame;
static NSView *focus_view = NULL;
static int ns_window_num = 0;
#endif
static BOOL gsaved = NO;
static BOOL ns_fake_keydown = NO;
-int ns_tmp_flags; /* FIXME */
-struct nsfont_info *ns_tmp_font; /* FIXME */
#ifdef NS_IMPL_COCOA
static BOOL ns_menu_bar_is_hidden = NO;
#endif
#define NSRightCommandKeyMask (0x000010 | NSCommandKeyMask)
#define NSLeftAlternateKeyMask (0x000020 | NSAlternateKeyMask)
#define NSRightAlternateKeyMask (0x000040 | NSAlternateKeyMask)
-#define EV_MODIFIERS(e) \
- ((([e modifierFlags] & NSHelpKeyMask) ? \
+#define EV_MODIFIERS2(flags) \
+ (((flags & NSHelpKeyMask) ? \
hyper_modifier : 0) \
| (!EQ (ns_right_alternate_modifier, Qleft) && \
- (([e modifierFlags] & NSRightAlternateKeyMask) \
+ ((flags & NSRightAlternateKeyMask) \
== NSRightAlternateKeyMask) ? \
parse_solitary_modifier (ns_right_alternate_modifier) : 0) \
- | (([e modifierFlags] & NSAlternateKeyMask) ? \
+ | ((flags & NSAlternateKeyMask) ? \
parse_solitary_modifier (ns_alternate_modifier) : 0) \
- | (([e modifierFlags] & NSShiftKeyMask) ? \
+ | ((flags & NSShiftKeyMask) ? \
shift_modifier : 0) \
| (!EQ (ns_right_control_modifier, Qleft) && \
- (([e modifierFlags] & NSRightControlKeyMask) \
+ ((flags & NSRightControlKeyMask) \
== NSRightControlKeyMask) ? \
parse_solitary_modifier (ns_right_control_modifier) : 0) \
- | (([e modifierFlags] & NSControlKeyMask) ? \
+ | ((flags & NSControlKeyMask) ? \
parse_solitary_modifier (ns_control_modifier) : 0) \
- | (([e modifierFlags] & NS_FUNCTION_KEY_MASK) ? \
+ | ((flags & NS_FUNCTION_KEY_MASK) ? \
parse_solitary_modifier (ns_function_modifier) : 0) \
| (!EQ (ns_right_command_modifier, Qleft) && \
- (([e modifierFlags] & NSRightCommandKeyMask) \
+ ((flags & NSRightCommandKeyMask) \
== NSRightCommandKeyMask) ? \
parse_solitary_modifier (ns_right_command_modifier) : 0) \
- | (([e modifierFlags] & NSCommandKeyMask) ? \
+ | ((flags & NSCommandKeyMask) ? \
parse_solitary_modifier (ns_command_modifier):0))
+#define EV_MODIFIERS(e) EV_MODIFIERS2 ([e modifierFlags])
#define EV_UDMODIFIERS(e) \
((([e type] == NSLeftMouseDown) ? down_modifier : 0) \
const char *
ns_load_path (void)
/* If running as a self-contained app bundle, return as a path string
- the filenames of the site-lisp, lisp and leim directories.
- Ie, site-lisp:lisp:leim. Otherwise, return nil. */
+ the filenames of the site-lisp and lisp directories.
+ Ie, site-lisp:lisp. Otherwise, return nil. */
{
NSBundle *bundle = [NSBundle mainBundle];
NSString *resourceDir = [bundle resourcePath];
BOOL isDir;
NSArray *paths = [resourceDir stringsByAppendingPaths:
[NSArray arrayWithObjects:
- @"site-lisp", @"lisp", @"leim", nil]];
+ @"site-lisp", @"lisp", nil]];
NSEnumerator *pathEnum = [paths objectEnumerator];
resourcePaths = @"";
NSView *view = FRAME_NS_VIEW (f);
/* This no-op will trigger the default window placing
* constraint system. */
- f->output_data.ns->dont_constrain = 0;
[[view window] setFrameOrigin:[[view window] frame].origin];
}
}
NSTRACE (ns_update_auto_hide_menu_bar);
- if (NSApp != nil
- && [NSApp isActive]
- && [NSApp respondsToSelector:@selector(setPresentationOptions:)])
+ if (NSApp != nil && [NSApp isActive])
{
// Note, "setPresentationOptions" triggers an error unless the
// application is active.
if (menu_bar_should_be_hidden != ns_menu_bar_is_hidden)
{
NSApplicationPresentationOptions options
- = NSApplicationPresentationAutoHideDock;
+ = NSApplicationPresentationDefault;
if (menu_bar_should_be_hidden)
- options |= NSApplicationPresentationAutoHideMenuBar;
+ options |= NSApplicationPresentationAutoHideMenuBar
+ | NSApplicationPresentationAutoHideDock;
[NSApp setPresentationOptions: options];
external (RIF) call; whole frame, called before update_window_begin
-------------------------------------------------------------------------- */
{
- NSView *view = FRAME_NS_VIEW (f);
+ EmacsView *view = FRAME_NS_VIEW (f);
NSTRACE (ns_update_begin);
ns_update_auto_hide_menu_bar ();
+#ifdef NS_IMPL_COCOA
+ if ([view isFullscreen] && [view fsIsNative])
+ {
+ // Fix reappearing tool bar in fullscreen for OSX 10.7
+ BOOL tbar_visible = FRAME_EXTERNAL_TOOL_BAR (f) ? YES : NO;
+ NSToolbar *toolbar = [FRAME_NS_VIEW (f) toolbar];
+ if (! tbar_visible != ! [toolbar isVisible])
+ [toolbar setVisible: tbar_visible];
+ }
+#endif
+
ns_updating_frame = f;
[view lockFocus];
w->output_cursor.x, w->output_cursor.y);
if (draw_window_fringes (w, 1))
- x_draw_vertical_border (w);
+ {
+ if (WINDOW_RIGHT_DIVIDER_WIDTH (w))
+ x_draw_right_divider (w);
+ else
+ x_draw_vertical_border (w);
+ }
unblock_input ();
}
NSTRACE (ns_update_end);
}
-
-static void
-ns_flush (struct frame *f)
-/* --------------------------------------------------------------------------
- external (RIF) call
- NS impl is no-op since currently we flush in ns_update_end and elsewhere
- -------------------------------------------------------------------------- */
-{
- NSTRACE (ns_flush);
-}
-
-
static void
ns_focus (struct frame *f, NSRect *r, int n)
/* --------------------------------------------------------------------------
}
}
-
-static void
-ns_reset_terminal_modes (struct terminal *terminal)
-/* Externally called as hook */
-{
- NSTRACE (ns_reset_terminal_modes);
-}
-
-
-static void
-ns_set_terminal_modes (struct terminal *terminal)
-/* Externally called as hook */
-{
- NSTRACE (ns_set_terminal_modes);
-}
-
-
-
/* ==========================================================================
Frame / window manager related functions
External (hook): called on things like window switching within frame
-------------------------------------------------------------------------- */
{
- struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (frame);
+ struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame);
struct frame *old_highlight = dpyinfo->x_highlight_frame;
NSTRACE (ns_frame_rehighlight);
NSTRACE (x_iconify_frame);
check_window_system (f);
view = FRAME_NS_VIEW (f);
- dpyinfo = FRAME_NS_DISPLAY_INFO (f);
+ dpyinfo = FRAME_DISPLAY_INFO (f);
if (dpyinfo->x_highlight_frame == f)
dpyinfo->x_highlight_frame = 0;
NSTRACE (x_free_frame_resources);
check_window_system (f);
view = FRAME_NS_VIEW (f);
- dpyinfo = FRAME_NS_DISPLAY_INFO (f);
+ dpyinfo = FRAME_DISPLAY_INFO (f);
hlinfo = MOUSE_HL_INFO (f);
[(EmacsView *)view setWindowClosing: YES]; /* may not have been informed */
block_input ();
free_frame_menubar (f);
-
- if (FRAME_FACE_CACHE (f))
- free_frame_faces (f);
+ free_frame_faces (f);
if (f == dpyinfo->x_focus_frame)
dpyinfo->x_focus_frame = 0;
#endif
/* Constrain the setFrameTopLeftPoint so we don't move behind the
menu bar. */
- f->output_data.ns->dont_constrain = 0;
[[view window] setFrameTopLeftPoint:
NSMakePoint (SCREENMAXBOUND (f->left_pos),
SCREENMAXBOUND ([fscreen frame].size.height
void
-x_set_window_size (struct frame *f, int change_grav, int cols, int rows)
+x_set_window_size (struct frame *f,
+ int change_grav,
+ int width,
+ int height,
+ bool pixelwise)
/* --------------------------------------------------------------------------
Adjust window pixel size based on given character grid size
Impl is a bit more complex than other terms, need to do some
NSRect wr = [window frame];
int tb = FRAME_EXTERNAL_TOOL_BAR (f);
int pixelwidth, pixelheight;
+ int rows, cols;
NSTRACE (x_set_window_size);
if (view == nil)
return;
-/*fprintf (stderr, "\tsetWindowSize: %d x %d, font size %d x %d\n", cols, rows, FRAME_COLUMN_WIDTH (f), FRAME_LINE_HEIGHT (f)); */
+/*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));*/
block_input ();
- check_frame_size (f, &rows, &cols);
+ check_frame_size (f, &width, &height, pixelwise);
- f->scroll_bar_actual_width = NS_SCROLL_BAR_WIDTH (f);
compute_fringe_widths (f, 0);
- pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
- pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
+ if (pixelwise)
+ {
+ 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. */
if (tb && ! [view isFullscreen])
[view setRows: rows andColumns: cols];
[window setFrame: wr display: YES];
-/*fprintf (stderr, "\tx_set_window_size %d, %d\t%d, %d\n", cols, rows, pixelwidth, pixelheight); */
-
/* This is a trick to compensate for Emacs' managing the scrollbar area
as a fixed number of standard character columns. Instead of leaving
blank space for the extra, we chopped it off above. Now for
[view setBoundsOrigin: origin];
}
- change_frame_size (f, rows, cols, 0, 1, 0); /* pretend, delay, safe */
- FRAME_PIXEL_WIDTH (f) = pixelwidth;
- FRAME_PIXEL_HEIGHT (f) = pixelheight;
+ change_frame_size (f, width, height, 0, 1, 0, pixelwise);
/* SET_FRAME_GARBAGED (f); // this short-circuits expose call in drawRect */
mark_window_cursors_off (XWINDOW (f->root_window));
NSColor *
ns_lookup_indexed_color (unsigned long idx, struct frame *f)
{
- struct ns_color_table *color_table = FRAME_NS_DISPLAY_INFO (f)->color_table;
+ struct ns_color_table *color_table = FRAME_DISPLAY_INFO (f)->color_table;
if (idx < 1 || idx >= color_table->avail)
return nil;
return color_table->colors[idx];
unsigned long
ns_index_color (NSColor *color, struct frame *f)
{
- struct ns_color_table *color_table = FRAME_NS_DISPLAY_INFO (f)->color_table;
+ struct ns_color_table *color_table = FRAME_DISPLAY_INFO (f)->color_table;
ptrdiff_t idx;
ptrdiff_t i;
color_table->empty_indices = [[NSMutableSet alloc] init];
}
- /* do we already have this color ? */
+ /* Do we already have this color? */
for (i = 1; i < color_table->avail; i++)
if (color_table->colors[i] && [color_table->colors[i] isEqual: color])
return i;
if (!f)
return;
- color_table = FRAME_NS_DISPLAY_INFO (f)->color_table;
+ color_table = FRAME_DISPLAY_INFO (f)->color_table;
if (idx <= 0 || idx >= color_table->size) {
message1 ("ns_free_indexed_color: Color index out of range.\n");
/*fprintf (stderr, "ns_get_color: '%s'\n", name); */
block_input ();
- if ([nsname isEqualToString: @"ns_selection_color"])
+ if ([nsname isEqualToString: @"ns_selection_bg_color"])
{
- nsname = ns_selection_color;
- name = [ns_selection_color UTF8String];
+#ifdef NS_IMPL_COCOA
+ NSString *defname = [[NSUserDefaults standardUserDefaults]
+ stringForKey: @"AppleHighlightColor"];
+ if (defname != nil)
+ nsname = defname;
+ else
+#endif
+ if ((new = [NSColor selectedTextBackgroundColor]) != nil)
+ {
+ *col = [new colorUsingDefaultColorSpace];
+ unblock_input ();
+ return 0;
+ }
+ else
+ nsname = NS_SELECTION_BG_COLOR_DEFAULT;
+
+ name = [nsname UTF8String];
+ }
+ else if ([nsname isEqualToString: @"ns_selection_fg_color"])
+ {
+ /* NOTE: OSX applications normally don't set foreground selection, but
+ text may be unreadable if we don't.
+ */
+ if ((new = [NSColor selectedTextColor]) != nil)
+ {
+ *col = [new colorUsingDefaultColorSpace];
+ unblock_input ();
+ return 0;
+ }
+
+ nsname = NS_SELECTION_FG_COLOR_DEFAULT;
+ name = [nsname UTF8String];
}
/* First, check for some sort of numeric specification. */
if (r >= 0.0F)
{
- *col = [NSColor colorWithCalibratedRed: r green: g blue: b alpha: 1.0];
+ *col = [NSColor colorForEmacsRed: r green: g blue: b alpha: 1.0];
unblock_input ();
return 0;
}
}
if (new)
- *col = [new colorUsingColorSpaceName: NSCalibratedRGBColorSpace];
+ *col = [new colorUsingDefaultColorSpace];
unblock_input ();
return new ? 0 : 1;
}
return build_string ((char *)str);
}
- [[col colorUsingColorSpaceName: NSCalibratedRGBColorSpace]
+ [[col colorUsingDefaultColorSpace]
getRed: &red green: &green blue: &blue alpha: &alpha];
- if (red ==green && red ==blue)
+ if (red == green && red == blue)
{
[[col colorUsingColorSpaceName: NSCalibratedWhiteColorSpace]
getWhite: &gray alpha: &alpha];
change the entire-frame transparency
-------------------------------------------------------------------------- */
{
- struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (f);
+ struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
double alpha = 1.0;
double alpha_min = 1.0;
known as last_mouse_glyph.
------------------------------------------------------------------------ */
{
+ struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame);
+ NSRect *r;
+
// NSTRACE (note_mouse_movement);
- XSETFRAME (last_mouse_motion_frame, frame);
+ dpyinfo->last_mouse_motion_frame = frame;
+ r = &dpyinfo->last_mouse_glyph;
/* Note, this doesn't get called for enter/leave, since we don't have a
position. Those are taken care of in the corresponding NSView methods. */
/* has movement gone beyond last rect we were tracking? */
- if (x < last_mouse_glyph.origin.x ||
- x >= (last_mouse_glyph.origin.x + last_mouse_glyph.size.width) ||
- y < last_mouse_glyph.origin.y ||
- y >= (last_mouse_glyph.origin.y + last_mouse_glyph.size.height))
+ if (x < r->origin.x || x >= r->origin.x + r->size.width
+ || y < r->origin.y || y >= r->origin.y + r->size.height)
{
- ns_update_begin(frame);
+ ns_update_begin (frame);
frame->mouse_moved = 1;
note_mouse_highlight (frame, x, y);
- remember_mouse_glyph (frame, x, y, &last_mouse_glyph);
- ns_update_end(frame);
+ remember_mouse_glyph (frame, x, y, r);
+ ns_update_end (frame);
return 1;
}
return;
}
- dpyinfo = FRAME_NS_DISPLAY_INFO (*fp);
+ dpyinfo = FRAME_DISPLAY_INFO (*fp);
block_input ();
- if (last_mouse_scroll_bar != nil && insist == 0)
+ if (dpyinfo->last_mouse_scroll_bar != nil && insist == 0)
{
/* TODO: we do not use this path at the moment because drag events will
go directly to the EmacsScroller. Leaving code in for now. */
- [last_mouse_scroll_bar getMouseMotionPart: (int *)part window: bar_window
- x: x y: y];
- if (time) *time = last_mouse_movement_time;
- last_mouse_scroll_bar = nil;
+ [dpyinfo->last_mouse_scroll_bar
+ getMouseMotionPart: (int *)part window: bar_window x: x y: y];
+ if (time)
+ *time = dpyinfo->last_mouse_movement_time;
+ dpyinfo->last_mouse_scroll_bar = nil;
}
else
{
&& FRAME_NS_DISPLAY (XFRAME (frame)) == FRAME_NS_DISPLAY (*fp))
XFRAME (frame)->mouse_moved = 0;
- last_mouse_scroll_bar = nil;
- if (last_mouse_frame && FRAME_LIVE_P (last_mouse_frame))
- f = last_mouse_frame;
+ dpyinfo->last_mouse_scroll_bar = nil;
+ if (dpyinfo->last_mouse_frame
+ && FRAME_LIVE_P (dpyinfo->last_mouse_frame))
+ f = dpyinfo->last_mouse_frame;
else
f = dpyinfo->x_focus_frame ? dpyinfo->x_focus_frame
: SELECTED_FRAME ();
position = [[view window] mouseLocationOutsideOfEventStream];
position = [view convertPoint: position fromView: nil];
- remember_mouse_glyph (f, position.x, position.y, &last_mouse_glyph);
+ remember_mouse_glyph (f, position.x, position.y,
+ &dpyinfo->last_mouse_glyph);
/*fprintf (stderr, "ns_mouse_position: %.0f, %.0f\n", position.x, position.y); */
if (bar_window) *bar_window = Qnil;
if (x) XSETINT (*x, lrint (position.x));
if (y) XSETINT (*y, lrint (position.y));
- if (time) *time = last_mouse_movement_time;
+ if (time)
+ *time = dpyinfo->last_mouse_movement_time;
*fp = f;
}
}
else
{
s->left_overhang = 0;
- s->right_overhang = ((struct nsfont_info *)font)->ital ?
- FONT_HEIGHT (font) * 0.2 : 0;
+ if (EQ (font->driver->type, Qns))
+ s->right_overhang = ((struct nsfont_info *)font)->ital ?
+ FONT_HEIGHT (font) * 0.2 : 0;
+ else
+ s->right_overhang = 0;
}
}
}
+static void
+ns_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
+/* --------------------------------------------------------------------------
+ External (RIF): Draw a window divider.
+ -------------------------------------------------------------------------- */
+{
+ struct frame *f = XFRAME (WINDOW_FRAME (w));
+ struct face *face;
+ NSRect r = NSMakeRect (x0, y0, x1-x0, y1-y0);
+
+ NSTRACE (ns_draw_window_divider);
+
+ face = FACE_FROM_ID (f, WINDOW_DIVIDER_FACE_ID);
+ if (face)
+ [ns_lookup_indexed_color(face->foreground, f) set];
+
+ ns_focus (f, &r, 1);
+ NSRectFill(r);
+ ns_unfocus (f);
+}
+
+
void
show_hourglass (struct atimer *timer)
{
: FRAME_BACKGROUND_COLOR (s->f)) set];
else
{
- struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (s->f);
+ struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (s->f);
[[dpyinfo->bitmaps[face->stipple-1].img stippleMask] set];
}
{
/* TODO (optimize): focus for box and contents draw */
NSRect r[2];
- int n;
+ int n, flags;
char box_drawn_p = 0;
+ struct font *font = s->face->font;
+ if (! font) font = FRAME_FONT (s->f);
NSTRACE (ns_draw_glyph_string);
ns_maybe_dumpglyphs_background
(s, s->first_glyph->type == COMPOSITE_GLYPH);
- ns_tmp_flags = s->hl == DRAW_CURSOR ? NS_DUMPGLYPH_CURSOR :
- (s->hl == DRAW_MOUSE_FACE ? NS_DUMPGLYPH_MOUSEFACE :
- (s->for_overlaps ? NS_DUMPGLYPH_FOREGROUND :
- NS_DUMPGLYPH_NORMAL));
- ns_tmp_font = (struct nsfont_info *)s->face->font;
- if (ns_tmp_font == NULL)
- ns_tmp_font = (struct nsfont_info *)FRAME_FONT (s->f);
+ flags = s->hl == DRAW_CURSOR ? NS_DUMPGLYPH_CURSOR :
+ (s->hl == DRAW_MOUSE_FACE ? NS_DUMPGLYPH_MOUSEFACE :
+ (s->for_overlaps ? NS_DUMPGLYPH_FOREGROUND :
+ NS_DUMPGLYPH_NORMAL));
if (s->hl == DRAW_CURSOR && s->w->phys_cursor_type == FILLED_BOX_CURSOR)
{
NS_FACE_FOREGROUND (s->face) = tmp;
}
- ns_tmp_font->font.driver->draw
+ font->driver->draw
(s, 0, s->nchars, s->x, s->y,
- (ns_tmp_flags == NS_DUMPGLYPH_NORMAL && !s->background_filled_p)
- || ns_tmp_flags == NS_DUMPGLYPH_MOUSEFACE);
+ (flags == NS_DUMPGLYPH_NORMAL && !s->background_filled_p)
+ || flags == NS_DUMPGLYPH_MOUSEFACE);
+
+ {
+ NSColor *col = (NS_FACE_FOREGROUND (s->face) != 0
+ ? ns_lookup_indexed_color (NS_FACE_FOREGROUND (s->face),
+ s->f)
+ : FRAME_FOREGROUND_COLOR (s->f));
+ [col set];
+
+ /* Draw underline, overline, strike-through. */
+ ns_draw_text_decoration (s, s->face, col, s->width, s->x);
+ }
if (s->hl == DRAW_CURSOR && s->w->phys_cursor_type == FILLED_BOX_CURSOR)
{
/*NSTRACE (ns_send_appdefined); */
#ifdef NS_IMPL_GNUSTEP
- // GNUStep needs postEvent to happen on the main thread.
+ // GNUstep needs postEvent to happen on the main thread.
if (! [[NSThread currentThread] isMainThread])
{
EmacsApp *app = (EmacsApp *)NSApp;
ns_last_use_native_fullscreen = ns_use_native_fullscreen;
- /* Clear the mouse-moved flag for every frame on this display. */
FOR_EACH_FRAME (tail, frame)
{
struct frame *f = XFRAME (frame);
if (FRAME_NS_P (f))
{
EmacsView *view = FRAME_NS_VIEW (f);
- [view updateCollectionBehaviour];
+ [view updateCollectionBehavior];
}
}
}
#endif
-/* GNUStep and OSX <= 10.4 does not have cancelTracking. */
+/* GNUstep and OSX <= 10.4 does not have cancelTracking. */
#if defined (NS_IMPL_COCOA) && \
MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
-/* Check if menu open should be cancelled or continued as normal. */
+/* Check if menu open should be canceled or continued as normal. */
void
ns_check_menu_open (NSMenu *menu)
{
&& ![NSCalibratedWhiteColorSpace isEqualToString:
NSColorSpaceFromDepth (depth)];
dpyinfo->n_planes = NSBitsPerPixelFromDepth (depth);
- dpyinfo->image_cache = make_image_cache ();
dpyinfo->color_table = xmalloc (sizeof *dpyinfo->color_table);
dpyinfo->color_table->colors = NULL;
dpyinfo->root_window = 42; /* a placeholder.. */
ns_after_update_window_line,
ns_update_window_begin,
ns_update_window_end,
- ns_flush,
- 0, /* flush_display_optional */
+ 0, /* flush_display */
x_clear_window_mouse_face,
x_get_glyph_overhangs,
x_fix_overlapping_area,
0, /* define_fringe_bitmap */ /* FIXME: simplify ns_draw_fringe_bitmap */
0, /* destroy_fringe_bitmap */
ns_compute_glyph_string_overhangs,
- ns_draw_glyph_string, /* interface to nsfont.m */
+ ns_draw_glyph_string,
ns_define_frame_cursor,
ns_clear_frame_area,
ns_draw_window_cursor,
ns_draw_vertical_window_border,
+ ns_draw_window_divider,
ns_shift_glyphs_for_insert
};
terminal->ins_del_lines_hook = 0; /* XXX vestigial? */
terminal->delete_glyphs_hook = 0; /* XXX vestigial? */
terminal->ring_bell_hook = ns_ring_bell;
- terminal->reset_terminal_modes_hook = ns_reset_terminal_modes;
- terminal->set_terminal_modes_hook = ns_set_terminal_modes;
+ terminal->reset_terminal_modes_hook = NULL;
+ terminal->set_terminal_modes_hook = NULL;
terminal->update_begin_hook = ns_update_begin;
terminal->update_end_hook = ns_update_end;
terminal->set_terminal_window_hook = NULL; /* XXX vestigial? */
terminal->delete_frame_hook = x_destroy_window;
terminal->delete_terminal_hook = ns_delete_terminal;
- terminal->scroll_region_ok = 1;
- terminal->char_ins_del_ok = 1;
- terminal->line_ins_del_ok = 1;
- terminal->fast_clear_end_of_line = 1;
- terminal->memory_below_frame = 0;
-
return terminal;
}
ns_initialize_display_info (dpyinfo);
terminal = ns_create_terminal (dpyinfo);
- terminal->kboard = xmalloc (sizeof *terminal->kboard);
- init_kboard (terminal->kboard);
- kset_window_system (terminal->kboard, Qns);
- terminal->kboard->next_kboard = all_kboards;
- all_kboards = terminal->kboard;
+ terminal->kboard = allocate_kboard (Qns);
/* Don't let the initial kboard remain current longer than necessary.
That would cause problems if a file loaded on startup tries to
prompt in the mini-buffer. */
dpyinfo->next = x_display_list;
x_display_list = dpyinfo;
- /* Put it on ns_display_name_list */
- ns_display_name_list = Fcons (Fcons (display_name, Qnil),
- ns_display_name_list);
- dpyinfo->name_list_element = XCAR (ns_display_name_list);
+ dpyinfo->name_list_element = Fcons (display_name, Qnil);
terminal->name = xstrdup (SSDATA (display_name));
ns_antialias_threshold = NILP (tmp) ? 10.0 : XFLOATINT (tmp);
}
- ns_selection_color = [[NSUserDefaults standardUserDefaults]
- stringForKey: @"AppleHighlightColor"];
- if (ns_selection_color == nil)
- ns_selection_color = NS_SELECTION_COLOR_DEFAULT;
-
{
NSColorList *cl = [NSColorList colorListNamed: @"Emacs"];
name = SSDATA (XCAR (color));
c = XINT (XCDR (color));
[cl setColor:
- [NSColor colorWithCalibratedRed: RED_FROM_ULONG (c) / 255.0
- green: GREEN_FROM_ULONG (c) / 255.0
- blue: BLUE_FROM_ULONG (c) / 255.0
- alpha: 1.0]
+ [NSColor colorForEmacsRed: RED_FROM_ULONG (c) / 255.0
+ green: GREEN_FROM_ULONG (c) / 255.0
+ blue: BLUE_FROM_ULONG (c) / 255.0
+ alpha: 1.0]
forKey: [NSString stringWithUTF8String: name]];
}
[cl writeToFile: nil];
NSStringPboardType,
NSTabularTextPboardType,
NSFilenamesPboardType,
- NSURLPboardType,
- NSColorPboardType,
- NSFontPboardType, nil] retain];
+ NSURLPboardType, nil] retain];
/* If fullscreen is in init/default-frame-alist, focus isn't set
right for fullscreen windows, so set this. */
@implementation EmacsApp
+- (id)init
+{
+ if (self = [super init])
+ {
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
+ self->isFirst = YES;
+#endif
+#ifdef NS_IMPL_GNUSTEP
+ self->applicationDidFinishLaunchingCalled = NO;
+#endif
+ }
+
+ return self;
+}
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
+- (void)run
+{
+ NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+
+ if (isFirst) [self finishLaunching];
+ isFirst = NO;
+
+ shouldKeepRunning = YES;
+ do
+ {
+ [pool release];
+ pool = [[NSAutoreleasePool alloc] init];
+
+ NSEvent *event =
+ [self nextEventMatchingMask:NSAnyEventMask
+ untilDate:[NSDate distantFuture]
+ inMode:NSDefaultRunLoopMode
+ dequeue:YES];
+ [self sendEvent:event];
+ [self updateWindows];
+ } while (shouldKeepRunning);
+
+ [pool release];
+}
+
+- (void)stop: (id)sender
+{
+ shouldKeepRunning = NO;
+ // Stop possible dialog also. Noop if no dialog present.
+ // The file dialog still leaks 7k - 10k on 10.9 though.
+ [super stop:sender];
+}
+#endif
+
- (void)logNotification: (NSNotification *)notification
{
const char *name = [[notification name] UTF8String];
-------------------------------------------------------------------------- */
{
NSTRACE (applicationDidFinishLaunching);
+#ifdef NS_IMPL_GNUSTEP
+ ((EmacsApp *)self)->applicationDidFinishLaunchingCalled = YES;
+#endif
[NSApp setServicesProvider: NSApp];
ns_send_appdefined (-2);
}
{
NSTRACE (applicationDidBecomeActive);
+#ifdef NS_IMPL_GNUSTEP
+ if (! applicationDidFinishLaunchingCalled)
+ [self applicationDidFinishLaunching:notification];
+#endif
//ns_app_active=YES;
ns_update_auto_hide_menu_bar ();
/* called on font panel selection */
- (void)changeFont: (id)sender
{
- NSEvent *e =[[self window] currentEvent];
- struct face *face =FRAME_DEFAULT_FACE (emacsframe);
+ NSEvent *e = [[self window] currentEvent];
+ struct face *face = FRAME_DEFAULT_FACE (emacsframe);
+ struct font *font = face->font;
id newFont;
CGFloat size;
+ NSFont *nsfont;
NSTRACE (changeFont);
+
if (!emacs_event)
return;
- if ((newFont = [sender convertFont:
- ((struct nsfont_info *)face->font)->nsfont]))
+ if (EQ (font->driver->type, Qns))
+ nsfont = ((struct nsfont_info *)font)->nsfont;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+ else
+ nsfont = (NSFont *) macfont_get_nsctfont (font);
+#endif
+
+ if ((newFont = [sender convertFont: nsfont]))
{
SET_FRAME_GARBAGED (emacsframe); /* now needed as of 2008/10 */
/* (Carbon way: [theEvent keyCode]) */
/* is it a "function key"? */
- fnKeysym = (code < 0x00ff && (flags&NSNumericPadKeyMask))
- ? ns_convert_key ([theEvent keyCode] | NSNumericPadKeyMask)
- : ns_convert_key (code);
+ /* Note: Sometimes a plain key will have the NSNumericPadKeyMask
+ flag set (this is probably a bug in the OS).
+ */
+ if (code < 0x00ff && (flags&NSNumericPadKeyMask))
+ {
+ fnKeysym = ns_convert_key ([theEvent keyCode] | NSNumericPadKeyMask);
+ }
+ if (fnKeysym == 0)
+ {
+ fnKeysym = ns_convert_key (code);
+ }
if (fnKeysym)
{
NSString *str = [aString respondsToSelector: @selector (string)] ?
[aString string] : aString;
if (NS_KEYLOG)
- NSLog (@"setMarkedText '%@' len =%d range %d from %d", str, [str length],
- selRange.length, selRange.location);
+ NSLog (@"setMarkedText '%@' len =%lu range %lu from %lu",
+ str, (unsigned long)[str length],
+ (unsigned long)selRange.length,
+ (unsigned long)selRange.location);
if (workingText != nil)
[self deleteWorkingText];
if (workingText == nil)
return;
if (NS_KEYLOG)
- NSLog(@"deleteWorkingText len =%d\n", [workingText length]);
+ NSLog(@"deleteWorkingText len =%lu\n", (unsigned long)[workingText length]);
[workingText release];
workingText = nil;
processingCompose = NO;
/* This is what happens when the user presses a mouse button. */
- (void)mouseDown: (NSEvent *)theEvent
{
+ struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (emacsframe);
NSPoint p = [self convertPoint: [theEvent locationInWindow] fromView: nil];
NSTRACE (mouseDown);
if (!emacs_event)
return;
- last_mouse_frame = emacsframe;
+ dpyinfo->last_mouse_frame = emacsframe;
/* appears to be needed to prevent spurious movement events generated on
button clicks */
- last_mouse_frame->mouse_moved = 0;
+ emacsframe->mouse_moved = 0;
if ([theEvent type] == NSScrollWheel)
{
CGFloat delta = [theEvent deltaY];
/* Mac notebooks send wheel events w/delta =0 when trackpad scrolling */
if (delta == 0)
- return;
- emacs_event->kind = WHEEL_EVENT;
+ {
+ delta = [theEvent deltaX];
+ if (delta == 0)
+ {
+ NSTRACE (deltaIsZero);
+ return;
+ }
+ emacs_event->kind = HORIZ_WHEEL_EVENT;
+ }
+ else
+ emacs_event->kind = WHEEL_EVENT;
+
emacs_event->code = 0;
emacs_event->modifiers = EV_MODIFIERS (theEvent) |
((delta > 0) ? up_modifier : down_modifier);
- (void)mouseMoved: (NSEvent *)e
{
Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (emacsframe);
+ struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (emacsframe);
Lisp_Object frame;
+ NSPoint pt;
// NSTRACE (mouseMoved);
- last_mouse_movement_time = EV_TIMESTAMP (e);
- last_mouse_motion_position
- = [self convertPoint: [e locationInWindow] fromView: nil];
+ dpyinfo->last_mouse_movement_time = EV_TIMESTAMP (e);
+ pt = [self convertPoint: [e locationInWindow] fromView: nil];
+ dpyinfo->last_mouse_motion_x = pt.x;
+ dpyinfo->last_mouse_motion_y = pt.y;
/* update any mouse face */
if (hlinfo->mouse_face_hidden)
if (!NILP (Vmouse_autoselect_window))
{
NSTRACE (mouse_autoselect_window);
- Lisp_Object window;
- window = window_from_coordinates(emacsframe, last_mouse_motion_position.x,
- last_mouse_motion_position.y, 0, 0);
+ static Lisp_Object last_mouse_window;
+ Lisp_Object window
+ = window_from_coordinates (emacsframe, pt.x, pt.y, 0, 0);
+
if (WINDOWP (window)
- && !EQ (window, last_window)
+ && !EQ (window, last_mouse_window)
&& !EQ (window, selected_window)
&& (focus_follows_mouse
|| (EQ (XWINDOW (window)->frame,
emacs_event->frame_or_window = window;
EV_TRAILER2 (e);
}
- last_window = window;
+ /* Remember the last window where we saw the mouse. */
+ last_mouse_window = window;
}
- if (!note_mouse_movement (emacsframe, last_mouse_motion_position.x,
- last_mouse_motion_position.y))
+ if (!note_mouse_movement (emacsframe, pt.x, pt.y))
help_echo_string = previous_help_echo_string;
XSETFRAME (frame, emacsframe);
NSWindow *window = [self window];
NSRect wr = [window frame];
int extra = 0;
- int gsextra = 0;
-#ifdef NS_IMPL_GNUSTEP
- gsextra = 3;
-#endif
-
int oldc = cols, oldr = rows;
- int oldw = FRAME_PIXEL_WIDTH (emacsframe),
- oldh = FRAME_PIXEL_HEIGHT (emacsframe);
+ int oldw = FRAME_PIXEL_WIDTH (emacsframe);
+ int oldh = FRAME_PIXEL_HEIGHT (emacsframe);
int neww, newh;
- cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (emacsframe, wr.size.width + gsextra);
-
- if (cols < MINWIDTH)
- cols = MINWIDTH;
+ NSTRACE (updateFrameSize);
+ NSTRACE_SIZE ("Original size", NSMakeSize (oldw, oldh));
if (! [self isFullscreen])
{
+#ifdef NS_IMPL_GNUSTEP
+ // GNUstep does not always update the tool bar height. Force it.
+ if (toolbar) update_frame_tool_bar (emacsframe);
+#endif
+
extra = FRAME_NS_TITLEBAR_HEIGHT (emacsframe)
- + FRAME_TOOLBAR_HEIGHT (emacsframe) - gsextra;
+ + FRAME_TOOLBAR_HEIGHT (emacsframe);
}
- rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (emacsframe, wr.size.height - extra);
-
- if (rows < MINHEIGHT)
- rows = MINHEIGHT;
+ if (wait_for_tool_bar)
+ {
+ if (FRAME_TOOLBAR_HEIGHT (emacsframe) == 0)
+ return;
+ wait_for_tool_bar = NO;
+ }
neww = (int)wr.size.width - emacsframe->border_width;
newh = (int)wr.size.height - extra;
+ cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (emacsframe, neww);
+ rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (emacsframe, newh);
+
+ if (cols < MINWIDTH)
+ cols = MINWIDTH;
+
+ if (rows < MINHEIGHT)
+ rows = MINHEIGHT;
+
if (oldr != rows || oldc != cols || neww != oldw || newh != oldh)
{
NSView *view = FRAME_NS_VIEW (emacsframe);
NSWindow *win = [view window];
NSSize sz = [win resizeIncrements];
- FRAME_PIXEL_WIDTH (emacsframe) = neww;
- FRAME_PIXEL_HEIGHT (emacsframe) = newh;
- change_frame_size (emacsframe, rows, cols, 0, delay, 0);
+ change_frame_size (emacsframe,
+ FRAME_PIXEL_TO_TEXT_WIDTH (emacsframe, neww),
+ FRAME_PIXEL_TO_TEXT_HEIGHT (emacsframe, newh),
+ 0, delay, 0, 1);
SET_FRAME_GARBAGED (emacsframe);
cancel_mouse_face (emacsframe);
sz.width = FRAME_COLUMN_WIDTH (emacsframe);
sz.height = FRAME_LINE_HEIGHT (emacsframe);
[win setResizeIncrements: sz];
+
+ NSTRACE_SIZE ("New size", NSMakeSize (neww, newh));
}
[view setFrame: NSMakeRect (0, 0, neww, newh)];
/* normalize frame to gridded text size */
{
int extra = 0;
- int gsextra = 0;
-#ifdef NS_IMPL_GNUSTEP
- gsextra = 3;
-#endif
NSTRACE (windowWillResize);
+ NSTRACE_SIZE ("Original size", frameSize);
/*fprintf (stderr,"Window will resize: %.0f x %.0f\n",frameSize.width,frameSize.height); */
if (fs_state == FULLSCREEN_MAXIMIZED
if (fs_state == FULLSCREEN_NONE)
maximized_width = maximized_height = -1;
- cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (emacsframe,
- frameSize.width + gsextra);
+ if (! [self isFullscreen])
+ {
+ extra = FRAME_NS_TITLEBAR_HEIGHT (emacsframe)
+ + FRAME_TOOLBAR_HEIGHT (emacsframe);
+ }
+
+ cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (emacsframe, frameSize.width);
if (cols < MINWIDTH)
cols = MINWIDTH;
- (void)windowDidBecomeKey: (NSNotification *)notification
/* cf. x_detect_focus_change(), x_focus_changed(), x_new_focus_frame() */
{
- struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (emacsframe);
+ struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (emacsframe);
struct frame *old_focus = dpyinfo->x_focus_frame;
NSTRACE (windowDidBecomeKey);
- (void)windowDidResignKey: (NSNotification *)notification
/* cf. x_detect_focus_change(), x_focus_changed(), x_new_focus_frame() */
{
- struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (emacsframe);
+ struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (emacsframe);
BOOL is_focus_frame = dpyinfo->x_focus_frame == emacsframe;
NSTRACE (windowDidResignKey);
if (is_focus_frame)
dpyinfo->x_focus_frame = 0;
+ emacsframe->mouse_moved = 0;
ns_frame_rehighlight (emacsframe);
/* FIXME: for some reason needed on second and subsequent clicks away
ns_window_num]];
[win setToolbar: toolbar];
[toolbar setVisible: NO];
+
+ /* Don't set frame garbaged until tool bar is up to date?
+ This avoids an extra clear and redraw (flicker) at frame creation. */
+ if (FRAME_EXTERNAL_TOOL_BAR (f)) wait_for_tool_bar = YES;
+ else wait_for_tool_bar = NO;
+
+
#ifdef NS_IMPL_COCOA
{
NSButton *toggleButton;
SET_FRAME_ICONIFIED (emacsframe, 0);
SET_FRAME_VISIBLE (emacsframe, 1);
- windows_or_buffers_changed++;
+ windows_or_buffers_changed = 63;
if (emacs_event)
{
[self windowDidBecomeKey:notification];
[nonfs_window orderOut:self];
}
- else if (! FRAME_EXTERNAL_TOOL_BAR (emacsframe))
- [toolbar setVisible:NO];
+ else
+ {
+ BOOL tbar_visible = FRAME_EXTERNAL_TOOL_BAR (emacsframe) ? YES : NO;
+#ifdef NS_IMPL_COCOA
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
+ unsigned val = (unsigned)[NSApp presentationOptions];
+
+ // OSX 10.7 bug fix, the menu won't appear without this.
+ // val is non-zero on other OSX versions.
+ if (val == 0)
+ {
+ NSApplicationPresentationOptions options
+ = NSApplicationPresentationAutoHideDock
+ | NSApplicationPresentationAutoHideMenuBar
+ | NSApplicationPresentationFullScreen
+ | NSApplicationPresentationAutoHideToolbar;
+
+ [NSApp setPresentationOptions: options];
+ }
+#endif
+#endif
+ [toolbar setVisible:tbar_visible];
+ }
}
- (void)windowWillExitFullScreen:(NSNotification *)notification
{
[self setFSValue: fs_before_fs];
fs_before_fs = -1;
-#ifdef NS_IMPL_COCOA
- [self updateCollectionBehaviour];
+#ifdef HAVE_NATIVE_FS
+ [self updateCollectionBehavior];
#endif
if (FRAME_EXTERNAL_TOOL_BAR (emacsframe))
{
}
#ifdef HAVE_NATIVE_FS
-- (void)updateCollectionBehaviour
+- (void)updateCollectionBehavior
{
if (! [self isFullscreen])
{
if (fs_is_native)
{
-#ifdef NS_IMPL_COCOA
+#ifdef HAVE_NATIVE_FS
[[self window] toggleFullScreen:sender];
#endif
return;
if (fs_state != FULLSCREEN_BOTH)
{
+ NSScreen *screen = [w screen];
+
+#if defined (NS_IMPL_COCOA) && \
+ MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
+ /* Hide ghost menu bar on secondary monitor? */
+ if (! onFirstScreen)
+ onFirstScreen = [NSScreen screensHaveSeparateSpaces];
+#endif
/* Hide dock and menubar if we are on the primary screen. */
if (onFirstScreen)
{
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:YES
- screen:[w screen]];
+ screen:screen];
[fw setContentView:[w contentView]];
[fw setTitle:[w title]];
[fw makeKeyAndOrderFront:NSApp];
[fw makeFirstResponder:self];
[w orderOut:self];
- r = [fw frameRectForContentRect:[[fw screen] frame]];
+ r = [fw frameRectForContentRect:[screen frame]];
[fw setFrame: r display:YES animate:YES];
[self windowDidEnterFullScreen:nil];
[fw display];
- (void)mouseEntered: (NSEvent *)theEvent
{
NSTRACE (mouseEntered);
- last_mouse_movement_time = EV_TIMESTAMP (theEvent);
+ if (emacsframe)
+ FRAME_DISPLAY_INFO (emacsframe)->last_mouse_movement_time
+ = EV_TIMESTAMP (theEvent);
}
if (!hlinfo)
return;
- last_mouse_movement_time = EV_TIMESTAMP (theEvent);
+ FRAME_DISPLAY_INFO (emacsframe)->last_mouse_movement_time
+ = EV_TIMESTAMP (theEvent);
if (emacsframe == hlinfo->mouse_face_mouse_frame)
{
NSString *type;
NSEvent *theEvent = [[self window] currentEvent];
NSPoint position;
+ NSDragOperation op = [sender draggingSourceOperationMask];
+ int modifiers = 0;
NSTRACE (performDragOperation);
pb = [sender draggingPasteboard];
type = [pb availableTypeFromArray: ns_drag_types];
+
+ if (! (op & (NSDragOperationMove|NSDragOperationDelete)) &&
+ // URL drags contain all operations (0xf), don't allow all to be set.
+ (op & 0xf) != 0xf)
+ {
+ if (op & NSDragOperationLink)
+ modifiers |= NSControlKeyMask;
+ if (op & NSDragOperationCopy)
+ modifiers |= NSAlternateKeyMask;
+ if (op & NSDragOperationGeneric)
+ modifiers |= NSCommandKeyMask;
+ }
+
+ modifiers = EV_MODIFIERS2 (modifiers);
if (type == 0)
{
return NO;
fenum = [files objectEnumerator];
while ( (file = [fenum nextObject]) )
{
- emacs_event->kind = NS_NONKEY_EVENT;
- emacs_event->code = KEY_NS_DRAG_FILE;
+ emacs_event->kind = DRAG_N_DROP_EVENT;
XSETINT (emacs_event->x, x);
XSETINT (emacs_event->y, y);
ns_input_file = append2 (ns_input_file,
build_string ([file UTF8String]));
- emacs_event->modifiers = EV_MODIFIERS (theEvent);
+ emacs_event->modifiers = modifiers;
+ emacs_event->arg = list2 (Qfile, build_string ([file UTF8String]));
EV_TRAILER (theEvent);
}
return YES;
}
else if ([type isEqualToString: NSURLPboardType])
{
- NSString *file;
- NSURL *fileURL;
+ NSURL *url = [NSURL URLFromPasteboard: pb];
+ if (url == nil) return NO;
- if (!(fileURL = [NSURL URLFromPasteboard: pb]) ||
- [fileURL isFileURL] == NO)
- return NO;
-
- file = [fileURL path];
- emacs_event->kind = NS_NONKEY_EVENT;
- emacs_event->code = KEY_NS_DRAG_FILE;
+ emacs_event->kind = DRAG_N_DROP_EVENT;
XSETINT (emacs_event->x, x);
XSETINT (emacs_event->y, y);
- ns_input_file = append2 (ns_input_file, build_string ([file UTF8String]));
- emacs_event->modifiers = EV_MODIFIERS (theEvent);
+ emacs_event->modifiers = modifiers;
+ emacs_event->arg = list2 (Qurl,
+ build_string ([[url absoluteString]
+ UTF8String]));
EV_TRAILER (theEvent);
+
+ if ([url isFileURL] != NO)
+ {
+ NSString *file = [url path];
+ ns_input_file = append2 (ns_input_file,
+ build_string ([file UTF8String]));
+ }
return YES;
}
else if ([type isEqualToString: NSStringPboardType]
if (! (data = [pb stringForType: type]))
return NO;
- emacs_event->kind = NS_NONKEY_EVENT;
- emacs_event->code = KEY_NS_DRAG_TEXT;
- XSETINT (emacs_event->x, x);
- XSETINT (emacs_event->y, y);
- ns_input_text = build_string ([data UTF8String]);
- emacs_event->modifiers = EV_MODIFIERS (theEvent);
- EV_TRAILER (theEvent);
- return YES;
- }
- else if ([type isEqualToString: NSColorPboardType])
- {
- NSColor *c = [NSColor colorFromPasteboard: pb];
- emacs_event->kind = NS_NONKEY_EVENT;
- emacs_event->code = KEY_NS_DRAG_COLOR;
- XSETINT (emacs_event->x, x);
- XSETINT (emacs_event->y, y);
- ns_input_color = ns_color_to_lisp (c);
- emacs_event->modifiers = EV_MODIFIERS (theEvent);
- EV_TRAILER (theEvent);
- return YES;
- }
- else if ([type isEqualToString: NSFontPboardType])
- {
- /* impl based on GNUstep NSTextView.m */
- NSData *data = [pb dataForType: NSFontPboardType];
- NSDictionary *dict = [NSUnarchiver unarchiveObjectWithData: data];
- NSFont *font = [dict objectForKey: NSFontAttributeName];
- char fontSize[10];
-
- if (font == nil)
- return NO;
-
- emacs_event->kind = NS_NONKEY_EVENT;
- emacs_event->code = KEY_NS_CHANGE_FONT;
+ emacs_event->kind = DRAG_N_DROP_EVENT;
XSETINT (emacs_event->x, x);
XSETINT (emacs_event->y, y);
- ns_input_font = build_string ([[font fontName] UTF8String]);
- snprintf (fontSize, 10, "%f", [font pointSize]);
- ns_input_fontsize = build_string (fontSize);
- emacs_event->modifiers = EV_MODIFIERS (theEvent);
+ emacs_event->modifiers = modifiers;
+ emacs_event->arg = list2 (Qnil, build_string ([data UTF8String]));
EV_TRAILER (theEvent);
return YES;
}
else
{
- error ("Invalid data type in dragging pasteboard.");
+ error ("Invalid data type in dragging pasteboard");
return NO;
}
}
{
/* When making the frame visible for the first time or if there is just
one screen, we want to constrain. Other times not. */
- NSUInteger nr_screens = [[NSScreen screens] count];
+ NSArray *screens = [NSScreen screens];
+ NSUInteger nr_screens = [screens count], nr_eff_screens = 0, i;
struct frame *f = ((EmacsView *)[self delegate])->emacsframe;
NSTRACE (constrainFrameRect);
+ NSTRACE_RECT ("input", frameRect);
+
+ if (ns_menu_bar_should_be_hidden ())
+ return frameRect;
if (nr_screens == 1)
+ return [super constrainFrameRect:frameRect toScreen:screen];
+
+#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];
+#endif
+#endif
+
+ for (i = 0; i < nr_screens; ++i)
{
- NSRect r = [super constrainFrameRect:frameRect toScreen:screen];
- return r;
+ NSScreen *s = [screens objectAtIndex: i];
+ NSRect scrrect = [s frame];
+ NSRect intersect = NSIntersectionRect (frameRect, scrrect);
+
+ if (intersect.size.width > 0 || intersect.size.height > 0)
+ ++nr_eff_screens;
}
- if (f->output_data.ns->dont_constrain
- || ns_menu_bar_should_be_hidden ())
- return frameRect;
+ if (nr_eff_screens == 1)
+ return [super constrainFrameRect:frameRect toScreen: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;
+
+ NSTRACE_RECT ("input to super", r);
+
+ r = [super constrainFrameRect:r toScreen:screen];
+
+ NSTRACE_RECT ("output from super", r);
+
+ float new_top = r.origin.y + FAKE_HEIGHT;
+ if (new_top < old_top)
+ {
+ frameRect.origin.y = new_top - frameRect.size.height;
+ }
+
+ NSTRACE_RECT ("output", frameRect);
- f->output_data.ns->dont_constrain = 1;
- return [super constrainFrameRect:frameRect toScreen:screen];
+ return frameRect;
+#undef FAKE_HEIGHT
}
@end /* EmacsWindow */
x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
{
struct font *font = XFONT_OBJECT (font_object);
+ EmacsView *view = FRAME_NS_VIEW (f);
if (fontset < 0)
fontset = fontset_from_font (font_object);
}
/* Now make the frame display the given font. */
- if (FRAME_NS_WINDOW (f) != 0)
- x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
+ if (FRAME_NS_WINDOW (f) != 0 && ! [view isFullscreen])
+ x_set_window_size (f, 0, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
+ FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 1);
return font_object;
}
DEFSYM (Qcontrol, "control");
DEFSYM (QUTF8_STRING, "UTF8_STRING");
+ DEFSYM (Qfile, "file");
+ DEFSYM (Qurl, "url");
+
Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
"The file specified in the last NS event.");
ns_input_file =Qnil;
- DEFVAR_LISP ("ns-input-text", ns_input_text,
- "The data received in the last NS text drag event.");
- ns_input_text =Qnil;
-
DEFVAR_LISP ("ns-working-text", ns_working_text,
"String for visualizing working composition sequence.");
ns_working_text =Qnil;
"The line specified in the last NS event.");
ns_input_line =Qnil;
- DEFVAR_LISP ("ns-input-color", ns_input_color,
- "The color specified in the last NS event.");
- ns_input_color =Qnil;
-
DEFVAR_LISP ("ns-input-spi-name", ns_input_spi_name,
"The service name specified in the last NS event.");
ns_input_spi_name =Qnil;
"Whether to confirm application quit using dialog.");
ns_confirm_quit = Qnil;
- staticpro (&ns_display_name_list);
- ns_display_name_list = Qnil;
-
- staticpro (&last_mouse_motion_frame);
- last_mouse_motion_frame = Qnil;
-
DEFVAR_LISP ("ns-auto-hide-menu-bar", ns_auto_hide_menu_bar,
doc: /* Non-nil means that the menu bar is hidden, but appears when the mouse is near.
Only works on OSX 10.6 or later. */);
doc: /*Non-nil means to use native fullscreen on OSX >= 10.7.
Nil means use fullscreen the old (< 10.7) way. The old way works better with
multiple monitors, but lacks tool bar. This variable is ignored on OSX < 10.7.
-Default is t for OSX >= 10.7, nil otherwise. */);
+Default is t for OSX >= 10.7, nil otherwise. */);
#ifdef HAVE_NATIVE_FS
ns_use_native_fullscreen = YES;
#else
#endif
ns_last_use_native_fullscreen = ns_use_native_fullscreen;
+ DEFVAR_BOOL ("ns-use-srgb-colorspace", ns_use_srgb_colorspace,
+ doc: /*Non-nil means to use sRGB colorspace on OSX >= 10.7.
+Note that this does not apply to images.
+This variable is ignored on OSX < 10.7 and GNUstep. */);
+ ns_use_srgb_colorspace = YES;
+
/* TODO: move to common code */
DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars,
doc: /* Which toolkit scroll bars Emacs uses, if any.
baseline level. The default value is nil. */);
x_underline_at_descent_line = 0;
- /* Tell emacs about this window system. */
- Fprovide (intern ("ns"), Qnil);
+ /* Tell Emacs about this window system. */
+ Fprovide (Qns, Qnil);
+
+ DEFSYM (Qcocoa, "cocoa");
+ DEFSYM (Qgnustep, "gnustep");
+
+ syms_of_nsfont ();
+#ifdef NS_IMPL_COCOA
+ Fprovide (Qcocoa, Qnil);
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
+ syms_of_macfont ();
+#endif
+#else
+ Fprovide (Qgnustep, Qnil);
+#endif
+
}