X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/86b192c1479d167c13edb9cdaa026c231c8a0442..95c216526e3700d46319d8fb47844a5e07662bbf:/src/nsterm.m diff --git a/src/nsterm.m b/src/nsterm.m index 14706f6b91..733c05ae53 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -1,7 +1,7 @@ /* NeXT/Open/GNUstep / MacOSX communication module. -Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2013 Free Software -Foundation, Inc. +Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2013 + Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -64,6 +64,12 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu) #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; @@ -167,29 +173,21 @@ Lisp_Object Qalt, Qcontrol, Qhyper, Qmeta, Qsuper; extern Lisp_Object Qcursor_color, Qcursor_type, Qns, Qleft; static Lisp_Object QUTF8_STRING; +static Lisp_Object Qcocoa, Qgnustep; /* 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; /* 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; @@ -198,8 +196,6 @@ static NSRect uRect; #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 @@ -214,7 +210,7 @@ static NSTimer *scroll_repeat_entry = nil; static fd_set select_readfds, select_writefds; enum { SELECT_HAVE_READ = 1, SELECT_HAVE_WRITE = 2, SELECT_HAVE_TMO = 4 }; static int select_nfds = 0, select_valid = 0; -static EMACS_TIME select_timeout = { 0, 0 }; +static struct timespec select_timeout = { 0, 0 }; static int selfds[2] = { -1, -1 }; static pthread_mutex_t select_mutex; static int apploopnr = 0; @@ -250,9 +246,6 @@ static int menu_will_open_state = MENU_NONE; /* Saved position for menu click. */ static CGPoint menu_mouse_point; - -/* Title for the menu to open. */ -static char *menu_pending_title = 0; #endif /* Convert modifiers in a NeXTstep event to emacs style modifiers. */ @@ -311,8 +304,13 @@ static char *menu_pending_title = 0; /* This is a piece of code which is common to all the event handling methods. Maybe it should even be a function. */ #define EV_TRAILER(e) \ - { \ - XSETFRAME (emacs_event->frame_or_window, emacsframe); \ + { \ + XSETFRAME (emacs_event->frame_or_window, emacsframe); \ + EV_TRAILER2 (e); \ + } + +#define EV_TRAILER2(e) \ + { \ if (e) emacs_event->timestamp = EV_TIMESTAMP (e); \ if (q_event_ptr) \ { \ @@ -344,8 +342,8 @@ hold_event (struct input_event *event) { if (hold_event_q.cap == 0) hold_event_q.cap = 10; else hold_event_q.cap *= 2; - hold_event_q.q = (struct input_event *) - xrealloc (hold_event_q.q, hold_event_q.cap * sizeof (*hold_event_q.q)); + hold_event_q.q = + xrealloc (hold_event_q.q, hold_event_q.cap * sizeof *hold_event_q.q); } hold_event_q.q[hold_event_q.nr++] = *event; @@ -447,8 +445,8 @@ ns_exec_path (void) 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]; @@ -458,7 +456,7 @@ ns_load_path (void) BOOL isDir; NSArray *paths = [resourceDir stringsByAppendingPaths: [NSArray arrayWithObjects: - @"site-lisp", @"lisp", @"leim", nil]]; + @"site-lisp", @"lisp", nil]]; NSEnumerator *pathEnum = [paths objectEnumerator]; resourcePaths = @""; @@ -488,16 +486,16 @@ ns_timeout (int usecs) Blocking timer utility used by ns_ring_bell -------------------------------------------------------------------------- */ { - EMACS_TIME wakeup = add_emacs_time (current_emacs_time (), - make_emacs_time (0, usecs * 1000)); + struct timespec wakeup = timespec_add (current_timespec (), + make_timespec (0, usecs * 1000)); /* Keep waiting until past the time wakeup. */ while (1) { - EMACS_TIME timeout, now = current_emacs_time (); - if (EMACS_TIME_LE (wakeup, now)) + struct timespec timeout, now = current_timespec (); + if (timespec_cmp (wakeup, now) <= 0) break; - timeout = sub_emacs_time (wakeup, now); + timeout = timespec_sub (wakeup, now); /* Try to wait that long--but we might wake up sooner. */ pselect (0, NULL, NULL, NULL, &timeout, NULL); @@ -635,9 +633,7 @@ ns_update_auto_hide_menu_bar (void) 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. @@ -646,10 +642,11 @@ ns_update_auto_hide_menu_bar (void) 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]; @@ -675,11 +672,22 @@ ns_update_begin (struct frame *f) 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]; @@ -691,9 +699,18 @@ ns_update_begin (struct frame *f) { NSBezierPath *bp; NSRect r = [view frame]; - bp = [[NSBezierPath bezierPathWithRect: r] retain]; - [bp setClip]; - [bp release]; + NSRect cr = [[view window] frame]; + /* If a large frame size is set, r may be larger than the window frame + before constrained. In that case don't change the clip path, as we + will clear in to the tool bar and title bar. */ + if (r.size.height + + FRAME_NS_TITLEBAR_HEIGHT (f) + + FRAME_TOOLBAR_HEIGHT (f) <= cr.size.height) + { + bp = [[NSBezierPath bezierPathWithRect: r] retain]; + [bp setClip]; + [bp release]; + } } #endif @@ -711,10 +728,10 @@ ns_update_window_begin (struct window *w) -------------------------------------------------------------------------- */ { struct frame *f = XFRAME (WINDOW_FRAME (w)); - Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); + Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); + NSTRACE (ns_update_window_begin); - updated_window = w; - set_output_cursor (&w->cursor); + w->output_cursor = w->cursor; block_input (); @@ -736,15 +753,13 @@ ns_update_window_begin (struct window *w) static void -ns_update_window_end (struct window *w, int cursor_on_p, - int mouse_face_overwritten_p) +ns_update_window_end (struct window *w, bool cursor_on_p, + bool mouse_face_overwritten_p) /* -------------------------------------------------------------------------- Finished a grouped sequence of drawing calls external (RIF) call; for one window called before update_end -------------------------------------------------------------------------- */ { - Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame)); - /* note: this fn is nearly identical in all terms */ if (!w->pseudo_window_p) { @@ -752,11 +767,16 @@ ns_update_window_end (struct window *w, int cursor_on_p, if (cursor_on_p) display_and_set_cursor (w, 1, - output_cursor.hpos, output_cursor.vpos, - output_cursor.x, output_cursor.y); + w->output_cursor.hpos, w->output_cursor.vpos, + 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 (); } @@ -764,13 +784,8 @@ ns_update_window_end (struct window *w, int cursor_on_p, /* If a row with mouse-face was overwritten, arrange for frame_up_to_date to redisplay the mouse highlight. */ if (mouse_face_overwritten_p) - { - hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1; - hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1; - hlinfo->mouse_face_window = Qnil; - } + reset_mouse_highlight (MOUSE_HL_INFO (XFRAME (w->frame))); - updated_window = NULL; NSTRACE (update_window_end); } @@ -785,9 +800,9 @@ ns_update_end (struct frame *f) EmacsView *view = FRAME_NS_VIEW (f); /* if (f == MOUSE_HL_INFO (f)->mouse_face_mouse_frame) */ - MOUSE_HL_INFO (f)->mouse_face_defer = 0; + MOUSE_HL_INFO (f)->mouse_face_defer = 0; - block_input (); + block_input (); [view unlockFocus]; [[view window] flushWindow]; @@ -797,18 +812,6 @@ ns_update_end (struct frame *f) 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) /* -------------------------------------------------------------------------- @@ -886,7 +889,8 @@ ns_unfocus (struct frame *f) static void -ns_clip_to_row (struct window *w, struct glyph_row *row, int area, BOOL gc) +ns_clip_to_row (struct window *w, struct glyph_row *row, + enum glyph_row_area area, BOOL gc) /* -------------------------------------------------------------------------- Internal (but parallels other terms): Focus drawing on given row -------------------------------------------------------------------------- */ @@ -955,24 +959,6 @@ ns_ring_bell (struct frame *f) } } - -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 @@ -1032,7 +1018,7 @@ ns_frame_rehighlight (struct frame *frame) 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); @@ -1129,7 +1115,7 @@ x_iconify_frame (struct frame *f) 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; @@ -1161,7 +1147,7 @@ x_free_frame_resources (struct frame *f) 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 */ @@ -1169,21 +1155,14 @@ x_free_frame_resources (struct frame *f) 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; if (f == dpyinfo->x_highlight_frame) dpyinfo->x_highlight_frame = 0; if (f == hlinfo->mouse_face_mouse_frame) - { - hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1; - hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1; - hlinfo->mouse_face_window = Qnil; - hlinfo->mouse_face_mouse_frame = 0; - } + reset_mouse_highlight (hlinfo); if (f->output_data.ns->miniimage != nil) [f->output_data.ns->miniimage release]; @@ -1259,7 +1238,11 @@ x_set_offset (struct frame *f, int xoff, int yoff, int change_grav) 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 @@ -1271,23 +1254,36 @@ x_set_window_size (struct frame *f, int change_grav, int cols, int rows) 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]) @@ -1322,8 +1318,6 @@ x_set_window_size (struct frame *f, int change_grav, int cols, int rows) [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 @@ -1340,9 +1334,7 @@ x_set_window_size (struct frame *f, int change_grav, int cols, int rows) [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)); @@ -1353,7 +1345,7 @@ x_set_window_size (struct frame *f, int change_grav, int cols, int rows) static void -ns_fullscreen_hook (FRAME_PTR f) +ns_fullscreen_hook (struct frame *f) { EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f); @@ -1386,7 +1378,7 @@ ns_fullscreen_hook (FRAME_PTR f) 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]; @@ -1396,7 +1388,7 @@ ns_lookup_indexed_color (unsigned long idx, struct frame *f) 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; @@ -1409,7 +1401,7 @@ ns_index_color (NSColor *color, struct frame *f) 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; @@ -1446,7 +1438,7 @@ ns_free_indexed_color (unsigned long idx, struct frame *f) 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"); @@ -1485,10 +1477,40 @@ ns_get_color (const char *name, NSColor **col) /*fprintf (stderr, "ns_get_color: '%s'\n", name); */ block_input (); - if ([nsname isEqualToString: @"ns_selection_color"]) + if ([nsname isEqualToString: @"ns_selection_bg_color"]) + { +#ifdef NS_IMPL_COCOA + NSString *defname = [[NSUserDefaults standardUserDefaults] + stringForKey: @"AppleHighlightColor"]; + if (defname != nil) + nsname = defname; + else +#endif + if ((new = [NSColor selectedTextBackgroundColor]) != nil) + { + *col = [new colorUsingColorSpaceName: NSCalibratedRGBColorSpace]; + unblock_input (); + return 0; + } + else + nsname = NS_SELECTION_BG_COLOR_DEFAULT; + + name = [nsname UTF8String]; + } + else if ([nsname isEqualToString: @"ns_selection_fg_color"]) { - nsname = ns_selection_color; - name = [ns_selection_color UTF8String]; + /* 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 colorUsingColorSpaceName: NSCalibratedRGBColorSpace]; + unblock_input (); + return 0; + } + + nsname = NS_SELECTION_FG_COLOR_DEFAULT; + name = [nsname UTF8String]; } /* First, check for some sort of numeric specification. */ @@ -1681,7 +1703,7 @@ x_set_frame_alpha (struct frame *f) 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; @@ -1766,24 +1788,26 @@ note_mouse_movement (struct frame *frame, CGFloat x, CGFloat y) 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; } @@ -1816,18 +1840,19 @@ ns_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, 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 { @@ -1837,9 +1862,10 @@ ns_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, && 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 (); @@ -1850,7 +1876,8 @@ ns_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, 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; @@ -1858,7 +1885,8 @@ ns_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, 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; } } @@ -1883,10 +1911,9 @@ ns_frame_up_to_date (struct frame *f) { block_input (); ns_update_begin(f); - if (hlinfo->mouse_face_mouse_frame) - note_mouse_highlight (hlinfo->mouse_face_mouse_frame, - hlinfo->mouse_face_mouse_x, - hlinfo->mouse_face_mouse_y); + note_mouse_highlight (hlinfo->mouse_face_mouse_frame, + hlinfo->mouse_face_mouse_x, + hlinfo->mouse_face_mouse_y); ns_update_end(f); unblock_input (); } @@ -1996,9 +2023,6 @@ ns_clear_frame (struct frame *f) mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f))); - output_cursor.hpos = output_cursor.vpos = 0; - output_cursor.x = -1; - r = [view bounds]; block_input (); @@ -2054,7 +2078,7 @@ ns_scroll_run (struct window *w, struct run *run) /* Get frame-relative bounding box of the text display area of W, without mode lines. Include in this box the left and right fringe of W. */ - window_box (w, -1, &x, &y, &width, &height); + window_box (w, ANY_AREA, &x, &y, &width, &height); from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y); to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y); @@ -2085,7 +2109,6 @@ ns_scroll_run (struct window *w, struct run *run) block_input (); - updated_window = w; x_clear_cursor (w); { @@ -2103,12 +2126,11 @@ ns_scroll_run (struct window *w, struct run *run) static void -ns_after_update_window_line (struct glyph_row *desired_row) +ns_after_update_window_line (struct window *w, struct glyph_row *desired_row) /* -------------------------------------------------------------------------- External (RIF): preparatory to fringe update after text was updated -------------------------------------------------------------------------- */ { - struct window *w = updated_window; struct frame *f; int width, height; @@ -2194,8 +2216,11 @@ ns_compute_glyph_string_overhangs (struct glyph_string *s) 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; } } @@ -2231,7 +2256,7 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row, } /* Must clip because of partially visible lines. */ - ns_clip_to_row (w, row, -1, YES); + ns_clip_to_row (w, row, ANY_AREA, YES); if (!p->overlay_p) { @@ -2339,8 +2364,8 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row, static void ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, - int x, int y, int cursor_type, int cursor_width, - int on_p, int active_p) + int x, int y, enum text_cursor_kinds cursor_type, + int cursor_width, bool on_p, bool active_p) /* -------------------------------------------------------------------------- External call (RIF): draw cursor. Note that CURSOR_WIDTH is meaningful only for (h)bar cursors. @@ -2411,7 +2436,7 @@ ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, /* TODO: only needed in rare cases with last-resort font in HELLO.. should we do this more efficiently? */ - ns_clip_to_row (w, glyph_row, -1, NO); /* do ns_focus(f, &r, 1); if remove */ + ns_clip_to_row (w, glyph_row, ANY_AREA, NO); /* do ns_focus(f, &r, 1); if remove */ face = FACE_FROM_ID (f, phys_cursor_glyph->face_id); @@ -2495,6 +2520,28 @@ ns_draw_vertical_window_border (struct window *w, int x, int y0, int y1) } +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) { @@ -2913,7 +2960,7 @@ ns_maybe_dumpglyphs_background (struct glyph_string *s, char force_p) : 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]; } @@ -3169,8 +3216,10 @@ ns_draw_glyph_string (struct glyph_string *s) { /* 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); @@ -3237,13 +3286,10 @@ ns_draw_glyph_string (struct glyph_string *s) 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) { @@ -3252,10 +3298,21 @@ ns_draw_glyph_string (struct glyph_string *s) 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) { @@ -3376,7 +3433,6 @@ check_native_fs () 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); @@ -3392,12 +3448,6 @@ check_native_fs () /* 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 -const char * -ns_get_pending_menu_title () -{ - return menu_pending_title; -} - /* Check if menu open should be cancelled or continued as normal. */ void ns_check_menu_open (NSMenu *menu) @@ -3406,6 +3456,14 @@ ns_check_menu_open (NSMenu *menu) NSArray *a = [[NSApp mainMenu] itemArray]; int i; BOOL found = NO; + + if (menu == nil) // Menu tracking ended. + { + if (menu_will_open_state == MENU_OPENING) + menu_will_open_state = MENU_NONE; + return; + } + for (i = 0; ! found && i < [a count]; i++) found = menu == [[a objectAtIndex:i] submenu]; if (found) @@ -3423,8 +3481,6 @@ ns_check_menu_open (NSMenu *menu) CGEventRef ourEvent = CGEventCreate (NULL); menu_mouse_point = CGEventGetLocation (ourEvent); CFRelease (ourEvent); - xfree (menu_pending_title); - menu_pending_title = xstrdup ([[menu title] UTF8String]); } else if (menu_will_open_state == MENU_OPENING) { @@ -3538,7 +3594,8 @@ ns_read_socket (struct terminal *terminal, struct input_event *hold_quit) int ns_select (int nfds, fd_set *readfds, fd_set *writefds, - fd_set *exceptfds, EMACS_TIME *timeout, sigset_t *sigmask) + fd_set *exceptfds, struct timespec const *timeout, + sigset_t const *sigmask) /* -------------------------------------------------------------------------- Replacement for select, checking for events -------------------------------------------------------------------------- */ @@ -3608,7 +3665,7 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds, else if (nr == 0 && timeout) { /* No file descriptor, just a timeout, no need to wake fd_handler */ - double time = EMACS_TIME_TO_DOUBLE (*timeout); + double time = timespectod (*timeout); timed_entry = [[NSTimer scheduledTimerWithTimeInterval: time target: NSApp selector: @@ -3664,7 +3721,6 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds, pthread_mutex_lock (&select_mutex); if (readfds) *readfds = select_readfds; if (writefds) *writefds = select_writefds; - if (timeout) *timeout = select_timeout; pthread_mutex_unlock (&select_mutex); result = t; } @@ -3722,7 +3778,7 @@ ns_set_vertical_scroll_bar (struct window *window, NSTRACE (ns_set_vertical_scroll_bar); /* Get dimensions. */ - window_box (window, -1, 0, &window_y, 0, &window_height); + window_box (window, ANY_AREA, 0, &window_y, 0, &window_height); top = window_y; height = window_height; width = WINDOW_CONFIG_SCROLL_BAR_COLS (window) * FRAME_COLUMN_WIDTH (f); @@ -3738,16 +3794,7 @@ ns_set_vertical_scroll_bar (struct window *window, v = [view frame]; r.origin.y = (v.size.height - r.size.height - r.origin.y); - if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (window)) - fringe_extended_p = (WINDOW_LEFTMOST_P (window) - && WINDOW_LEFT_FRINGE_WIDTH (window) - && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (window) - || WINDOW_LEFT_MARGIN_COLS (window) == 0)); - else - fringe_extended_p = (WINDOW_RIGHTMOST_P (window) - && WINDOW_RIGHT_FRINGE_WIDTH (window) - && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (window) - || WINDOW_RIGHT_MARGIN_COLS (window) == 0)); + fringe_extended_p = WINDOW_FRINGE_EXTENDED_P (window); XSETWINDOW (win, window); block_input (); @@ -3863,15 +3910,6 @@ ns_judge_scroll_bars (struct frame *f) [eview updateFrameSize: NO]; } - -void -x_wm_set_icon_position (struct frame *f, int icon_x, int icon_y) -{ - /* XXX irrelevant under NS */ -} - - - /* ========================================================================== Initialization @@ -3967,7 +4005,6 @@ ns_initialize_display_info (struct ns_display_info *dpyinfo) { NSScreen *screen = [NSScreen mainScreen]; NSWindowDepth depth = [screen depth]; - Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight; dpyinfo->resx = 72.27; /* used 75.0, but this makes pt == pixel, expected */ dpyinfo->resy = 72.27; @@ -3976,26 +4013,15 @@ ns_initialize_display_info (struct ns_display_info *dpyinfo) && ![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.. */ - - hlinfo->mouse_face_mouse_frame = NULL; - hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1; - hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1; - hlinfo->mouse_face_face_id = DEFAULT_FACE_ID; - hlinfo->mouse_face_window = hlinfo->mouse_face_overlay = Qnil; - hlinfo->mouse_face_hidden = 0; - - hlinfo->mouse_face_mouse_x = hlinfo->mouse_face_mouse_y = 0; - hlinfo->mouse_face_defer = 0; - dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame = NULL; - dpyinfo->n_fonts = 0; dpyinfo->smallest_font_height = 1; dpyinfo->smallest_char_width = 1; + + reset_mouse_highlight (&dpyinfo->mouse_highlight); } @@ -4016,9 +4042,7 @@ static struct redisplay_interface ns_redisplay_interface = ns_after_update_window_line, ns_update_window_begin, ns_update_window_end, - x_cursor_to, - ns_flush, - 0, /* flush_display_optional */ + 0, /* flush_display */ x_clear_window_mouse_face, x_get_glyph_overhangs, x_fix_overlapping_area, @@ -4026,11 +4050,12 @@ static struct redisplay_interface ns_redisplay_interface = 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 }; @@ -4083,8 +4108,8 @@ ns_create_terminal (struct ns_display_info *dpyinfo) 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? */ @@ -4104,12 +4129,6 @@ ns_create_terminal (struct ns_display_info *dpyinfo) 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; } @@ -4182,11 +4201,7 @@ ns_term_init (Lisp_Object display_name) 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. */ @@ -4197,10 +4212,7 @@ ns_term_init (Lisp_Object display_name) 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)); @@ -4217,11 +4229,6 @@ ns_term_init (Lisp_Object 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"]; @@ -4399,6 +4406,56 @@ ns_term_shutdown (int sig) @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]; @@ -4551,6 +4608,9 @@ ns_term_shutdown (int sig) -------------------------------------------------------------------------- */ { NSTRACE (applicationDidFinishLaunching); +#ifdef NS_IMPL_GNUSTEP + ((EmacsApp *)self)->applicationDidFinishLaunchingCalled = YES; +#endif [NSApp setServicesProvider: NSApp]; ns_send_appdefined (-2); } @@ -4678,6 +4738,10 @@ not_in_argv (NSString *arg) { NSTRACE (applicationDidBecomeActive); +#ifdef NS_IMPL_GNUSTEP + if (! applicationDidFinishLaunchingCalled) + [self applicationDidFinishLaunching:notification]; +#endif //ns_app_active=YES; ns_update_auto_hide_menu_bar (); @@ -4724,8 +4788,8 @@ not_in_argv (NSString *arg) int waiting = 1, nfds; char c; - SELECT_TYPE readfds, writefds, *wfds; - EMACS_TIME timeout, *tmo; + fd_set readfds, writefds, *wfds; + struct timespec timeout, *tmo; NSAutoreleasePool *pool = nil; /* NSTRACE (fd_handler); */ @@ -4737,7 +4801,7 @@ not_in_argv (NSString *arg) if (waiting) { - SELECT_TYPE fds; + fd_set fds; FD_ZERO (&fds); FD_SET (selfds[0], &fds); result = select (selfds[0]+1, &fds, NULL, NULL, NULL); @@ -4876,17 +4940,26 @@ not_in_argv (NSString *arg) /* 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 */ @@ -5248,8 +5321,10 @@ not_in_argv (NSString *arg) 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]; @@ -5275,7 +5350,7 @@ not_in_argv (NSString *arg) 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; @@ -5403,6 +5478,7 @@ not_in_argv (NSString *arg) /* 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); @@ -5412,10 +5488,10 @@ not_in_argv (NSString *arg) 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) { @@ -5487,13 +5563,16 @@ not_in_argv (NSString *arg) - (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) @@ -5506,8 +5585,30 @@ not_in_argv (NSString *arg) previous_help_echo_string = help_echo_string; help_echo_string = Qnil; - if (!note_mouse_movement (emacsframe, last_mouse_motion_position.x, - last_mouse_motion_position.y)) + if (!NILP (Vmouse_autoselect_window)) + { + NSTRACE (mouse_autoselect_window); + 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_mouse_window) + && !EQ (window, selected_window) + && (focus_follows_mouse + || (EQ (XWINDOW (window)->frame, + XWINDOW (selected_window)->frame)))) + { + NSTRACE (in_window); + emacs_event->kind = SELECT_WINDOW_EVENT; + emacs_event->frame_or_window = window; + EV_TRAILER2 (e); + } + /* Remember the last window where we saw the mouse. */ + last_mouse_window = window; + } + + if (!note_mouse_movement (emacsframe, pt.x, pt.y)) help_echo_string = previous_help_echo_string; XSETFRAME (frame, emacsframe); @@ -5572,44 +5673,44 @@ not_in_argv (NSString *arg) 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 neww, newh; - cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (emacsframe, wr.size.width + gsextra); - - if (cols < MINWIDTH) - cols = MINWIDTH; - 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); + 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; - neww = (int)wr.size.width - emacsframe->border_width; - newh = (int)wr.size.height - extra; - 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); @@ -5631,10 +5732,6 @@ not_in_argv (NSString *arg) /* normalize frame to gridded text size */ { int extra = 0; - int gsextra = 0; -#ifdef NS_IMPL_GNUSTEP - gsextra = 3; -#endif NSTRACE (windowWillResize); /*fprintf (stderr,"Window will resize: %.0f x %.0f\n",frameSize.width,frameSize.height); */ @@ -5652,8 +5749,13 @@ not_in_argv (NSString *arg) 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; @@ -5673,17 +5775,17 @@ not_in_argv (NSString *arg) old_title = 0; } } - else + else if (fs_state == FULLSCREEN_NONE && ! maximizing_resize) { char *size_title; NSWindow *window = [self window]; if (old_title == 0) { - const char *t = [[[self window] title] UTF8String]; + char *t = strdup ([[[self window] title] UTF8String]); char *pos = strstr (t, " — "); if (pos) *pos = '\0'; - old_title = xstrdup (t); + old_title = t; } size_title = xmalloc (strlen (old_title) + 40); esprintf (size_title, "%s — (%d x %d)", old_title, cols, rows); @@ -5722,27 +5824,33 @@ not_in_argv (NSString *arg) NSTRACE (windowDidResize); /*fprintf (stderr,"windowDidResize: %.0f\n",[theWindow frame].size.height); */ +if (cols > 0 && rows > 0) + { + [self updateFrameSize: YES]; + } + + ns_send_appdefined (-1); +} + #ifdef NS_IMPL_COCOA +- (void)viewDidEndLiveResize +{ + [super viewDidEndLiveResize]; if (old_title != 0) { + [[self window] setTitle: [NSString stringWithUTF8String: old_title]]; xfree (old_title); old_title = 0; } -#endif /* NS_IMPL_COCOA */ - - if (cols > 0 && rows > 0) - { - [self updateFrameSize: YES]; - } - - ns_send_appdefined (-1); + maximizing_resize = NO; } +#endif /* NS_IMPL_COCOA */ - (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); @@ -5763,7 +5871,7 @@ not_in_argv (NSString *arg) - (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); @@ -5841,7 +5949,10 @@ not_in_argv (NSString *arg) FRAME_NS_VIEW (f) = self; emacsframe = f; +#ifdef NS_IMPL_COCOA old_title = 0; + maximizing_resize = NO; +#endif win = [[EmacsWindow alloc] initWithContentRect: r @@ -5984,6 +6095,9 @@ not_in_argv (NSString *arg) 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) { @@ -6002,12 +6116,18 @@ not_in_argv (NSString *arg) maximized_width = result.size.width; maximized_height = result.size.height; [self setFSValue: FULLSCREEN_MAXIMIZED]; +#ifdef NS_IMPL_COCOA + maximizing_resize = YES; +#endif } else { /* restore */ result = ns_userRect.size.height ? ns_userRect : result; ns_userRect = NSMakeRect (0, 0, 0, 0); +#ifdef NS_IMPL_COCOA + maximizing_resize = fs_state != FULLSCREEN_NONE; +#endif [self setFSValue: FULLSCREEN_NONE]; maximized_width = maximized_height = -1; } @@ -6026,7 +6146,7 @@ not_in_argv (NSString *arg) SET_FRAME_ICONIFIED (emacsframe, 0); SET_FRAME_VISIBLE (emacsframe, 1); - windows_or_buffers_changed++; + windows_or_buffers_changed = 63; if (emacs_event) { @@ -6088,8 +6208,29 @@ not_in_argv (NSString *arg) [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 @@ -6102,7 +6243,7 @@ not_in_argv (NSString *arg) { [self setFSValue: fs_before_fs]; fs_before_fs = -1; -#ifdef NS_IMPL_COCOA +#ifdef HAVE_NATIVE_FS [self updateCollectionBehaviour]; #endif if (FRAME_EXTERNAL_TOOL_BAR (emacsframe)) @@ -6163,7 +6304,7 @@ not_in_argv (NSString *arg) if (fs_is_native) { -#ifdef NS_IMPL_COCOA +#ifdef HAVE_NATIVE_FS [[self window] toggleFullScreen:sender]; #endif return; @@ -6334,7 +6475,9 @@ not_in_argv (NSString *arg) - (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); } @@ -6347,7 +6490,8 @@ not_in_argv (NSString *arg) 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) { @@ -7207,6 +7351,7 @@ Lisp_Object 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); @@ -7239,8 +7384,9 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset) } /* 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; } @@ -7410,12 +7556,6 @@ allowing it to be used at a lower level for accented character entry."); "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. */); @@ -7458,6 +7598,20 @@ variable `x-use-underline-position-properties', which is usually at the 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 + }