X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/37b3d30244ad822e049b6b20c2eadf5946cb02cc..a97f8f3f16c6370acb0076011588822e572fa589:/src/nsterm.m diff --git a/src/nsterm.m b/src/nsterm.m index a09c95c7d0..3d3723fc28 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -134,11 +134,12 @@ static unsigned convert_ns_to_X_keysym[] = 0x1B, 0x1B /* escape */ }; - static Lisp_Object Qmodifier_value; Lisp_Object Qalt, Qcontrol, Qhyper, Qmeta, Qsuper, Qnone; extern Lisp_Object Qcursor_color, Qcursor_type, Qns, Qleft; +static Lisp_Object QUTF8_STRING; + /* 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. */ @@ -158,18 +159,19 @@ long context_menu_value = 0; /* display update */ NSPoint last_mouse_motion_position; static NSRect last_mouse_glyph; -static unsigned long last_mouse_movement_time = 0; +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; +static int ns_window_num = 0; static NSRect uRect; static BOOL gsaved = NO; BOOL ns_in_resize = NO; static BOOL ns_fake_keydown = NO; int ns_tmp_flags; /* FIXME */ struct nsfont_info *ns_tmp_font; /* FIXME */ +static BOOL ns_menu_bar_is_hidden = NO; /*static int debug_lock = 0; */ /* event loop */ @@ -189,7 +191,7 @@ static NSMutableArray *ns_pending_files, *ns_pending_service_names, *ns_pending_service_args; static BOOL inNsSelect = 0; -/* Convert modifiers in a NeXTSTEP event to emacs style modifiers. */ +/* Convert modifiers in a NeXTstep event to emacs style modifiers. */ #define NS_FUNCTION_KEY_MASK 0x800000 #define NSLeftControlKeyMask (0x000001 | NSControlKeyMask) #define NSRightControlKeyMask (0x002000 | NSControlKeyMask) @@ -261,8 +263,6 @@ static void ns_condemn_scroll_bars (struct frame *f); static void ns_judge_scroll_bars (struct frame *f); void x_set_frame_alpha (struct frame *f); -/* FIXME: figure out what to do with underline_minimum_offset. */ - /* ========================================================================== @@ -505,6 +505,125 @@ ns_resize_handle_rect (NSWindow *window) } +// +// Window constraining +// ------------------- +// +// To ensure that the windows are not placed under the menu bar, they +// are typically moved by the call-back constrainFrameRect. However, +// by overriding it, it's possible to inhibit this, leaving the window +// in it's original position. +// +// It's possible to hide the menu bar. However, technically, it's only +// possible to hide it when the application is active. To ensure that +// this work properly, the menu bar and window constraining are +// deferred until the application becomes active. +// +// Even though it's not possible to manually move a window above the +// top of the screen, it is allowed if it's done programmatically, +// when the menu is hidden. This allows the editable area to cover the +// full screen height. +// +// Test cases +// ---------- +// +// Use the following extra files: +// +// init.el: +// ;; Hide menu and place frame slightly above the top of the screen. +// (setq ns-auto-hide-menu-bar t) +// (set-frame-position (selected-frame) 0 -20) +// +// Test 1: +// +// emacs -Q -l init.el +// +// Result: No menu bar, and the title bar should be above the screen. +// +// Test 2: +// +// emacs -Q +// +// Result: Menu bar visible, frame placed immediately below the menu. +// + +static void +ns_constrain_all_frames (void) +{ + Lisp_Object tail, frame; + + FOR_EACH_FRAME (tail, frame) + { + struct frame *f = XFRAME (frame); + if (FRAME_NS_P (f)) + { + NSView *view = FRAME_NS_VIEW (f); + /* This no-op will trigger the default window placing + * constriant system. */ + f->output_data.ns->dont_constrain = 0; + [[view window] setFrameOrigin:[[view window] frame].origin]; + } + } +} + + +/* True, if the menu bar should be hidden. */ + +static BOOL +ns_menu_bar_should_be_hidden (void) +{ + return !NILP (ns_auto_hide_menu_bar) + && [NSApp respondsToSelector:@selector(setPresentationOptions:)]; +} + + +/* Show or hide the menu bar, based on user setting. */ + +static void +ns_update_auto_hide_menu_bar (void) +{ +#ifndef MAC_OS_X_VERSION_10_6 +#define MAC_OS_X_VERSION_10_6 1060 +#endif +#ifdef NS_IMPL_COCOA +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 + BLOCK_INPUT; + + NSTRACE (ns_update_auto_hide_menu_bar); + + if (NSApp != nil + && [NSApp isActive] + && [NSApp respondsToSelector:@selector(setPresentationOptions:)]) + { + // Note, "setPresentationOptions" triggers an error unless the + // application is active. + BOOL menu_bar_should_be_hidden = ns_menu_bar_should_be_hidden (); + + if (menu_bar_should_be_hidden != ns_menu_bar_is_hidden) + { + NSApplicationPresentationOptions options + = NSApplicationPresentationAutoHideDock; + + if (menu_bar_should_be_hidden) + options |= NSApplicationPresentationAutoHideMenuBar; + + [NSApp setPresentationOptions: options]; + + ns_menu_bar_is_hidden = menu_bar_should_be_hidden; + + if (!ns_menu_bar_is_hidden) + { + ns_constrain_all_frames (); + } + } + } + + UNBLOCK_INPUT; +#endif +#endif +} + + static void ns_update_begin (struct frame *f) /* -------------------------------------------------------------------------- @@ -515,6 +634,8 @@ ns_update_begin (struct frame *f) NSView *view = FRAME_NS_VIEW (f); NSTRACE (ns_update_begin); + ns_update_auto_hide_menu_bar (); + ns_updating_frame = f; [view lockFocus]; @@ -1002,12 +1123,10 @@ x_iconify_frame (struct frame *f) [[view window] miniaturize: NSApp]; } +/* Free X resources of frame F. */ void -x_destroy_window (struct frame *f) -/* -------------------------------------------------------------------------- - External: Delete the window - -------------------------------------------------------------------------- */ +x_free_frame_resources (struct frame *f) { NSView *view = FRAME_NS_VIEW (f); struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (f); @@ -1042,10 +1161,21 @@ x_destroy_window (struct frame *f) [[view window] close]; [view release]; - ns_window_num--; UNBLOCK_INPUT; } +void +x_destroy_window (struct frame *f) +/* -------------------------------------------------------------------------- + External: Delete the window + -------------------------------------------------------------------------- */ +{ + NSTRACE (x_destroy_window); + check_ns (); + x_free_frame_resources (f); + ns_window_num--; +} + void x_set_offset (struct frame *f, int xoff, int yoff, int change_grav) @@ -1072,7 +1202,7 @@ x_set_offset (struct frame *f, int xoff, int yoff, int change_grav) : f->left_pos; /* We use visibleFrame here to take menu bar into account. Ideally we should also adjust left/top with visibleFrame.origin. */ - + f->top_pos = f->size_hint_flags & YNegative ? ([screen visibleFrame].size.height + f->top_pos - FRAME_PIXEL_HEIGHT (f) - FRAME_NS_TITLEBAR_HEIGHT (f) @@ -1154,7 +1284,7 @@ x_set_window_size (struct frame *f, int change_grav, int cols, int rows) FRAME_TOOLBAR_HEIGHT (f) = 0; wr.size.width = pixelwidth + f->border_width; - wr.size.height = pixelheight + FRAME_NS_TITLEBAR_HEIGHT (f) + wr.size.height = pixelheight + FRAME_NS_TITLEBAR_HEIGHT (f) + FRAME_TOOLBAR_HEIGHT (f); /* Do not try to constrain to this screen. We may have multiple @@ -1220,7 +1350,7 @@ unsigned long ns_index_color (NSColor *color, struct frame *f) { struct ns_color_table *color_table = FRAME_NS_DISPLAY_INFO (f)->color_table; - int idx; + ptrdiff_t idx; NSNumber *index; if (!color_table->colors) @@ -1235,7 +1365,7 @@ ns_index_color (NSColor *color, struct frame *f) /* do we already have this color ? */ { - int i; + ptrdiff_t i; for (i = 1; i < color_table->avail; i++) { if (color_table->colors[i] && [color_table->colors[i] isEqual: color]) @@ -1250,17 +1380,14 @@ ns_index_color (NSColor *color, struct frame *f) { index = [color_table->empty_indices anyObject]; [color_table->empty_indices removeObject: index]; - idx = [index unsignedIntValue]; + idx = [index unsignedLongValue]; } else { if (color_table->avail == color_table->size) - { - color_table->size += NS_COLOR_CAPACITY; - color_table->colors - = (NSColor **)xrealloc (color_table->colors, - color_table->size * sizeof (NSColor *)); - } + color_table->colors = + xpalloc (color_table->colors, &color_table->size, 1, + min (ULONG_MAX, PTRDIFF_MAX), sizeof *color_table->colors); idx = color_table->avail++; } @@ -1667,7 +1794,7 @@ note_mouse_movement (struct frame *frame, float x, float y) static void ns_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y, - unsigned long *time) + Time *time) /* -------------------------------------------------------------------------- External (hook): inform emacs about mouse position and hit parts. If a scrollbar is being dragged, set bar_window, part, x, y, time. @@ -2200,7 +2327,7 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row, if (!img) { unsigned short *bits = p->bits + p->dh; - int len = 8 * p->h/8; + int len = p->h; int i; unsigned char *cbits = xmalloc (len); @@ -2230,15 +2357,12 @@ 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) /* -------------------------------------------------------------------------- - External call (RIF): draw cursor - (modeled after x_draw_window_cursor - FIXME: cursor_width is effectively bogus -- it sometimes gets set - in xdisp.c set_frame_cursor_types, sometimes left uninitialized; - DON'T USE IT (no other terms do) + External call (RIF): draw cursor. + Note that CURSOR_WIDTH is meaningful only for (h)bar cursors. -------------------------------------------------------------------------- */ { NSRect r, s; - int fx, fy, h; + int fx, fy, h, cursor_height; struct frame *f = WINDOW_XFRAME (w); struct glyph *phys_cursor_glyph; int overspill; @@ -2251,7 +2375,6 @@ ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, and mini-buffer. */ NSTRACE (dumpcursor); -//fprintf(stderr, "drawcursor (%d,%d) activep = %d\tonp = %d\tc_type = %d\twidth = %d\n",x,y, active_p,on_p,cursor_type,cursor_width); if (!on_p) return; @@ -2276,8 +2399,28 @@ ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, return; } + /* We draw the cursor (with NSRectFill), then draw the glyph on top + (other terminals do it the other way round). We must set + w->phys_cursor_width to the cursor width. For bar cursors, that + is CURSOR_WIDTH; for box cursors, it is the glyph width. */ get_phys_cursor_geometry (w, glyph_row, phys_cursor_glyph, &fx, &fy, &h); + /* The above get_phys_cursor_geometry call set w->phys_cursor_width + to the glyph width; replace with CURSOR_WIDTH for (V)BAR cursors. */ + if (cursor_type == BAR_CURSOR) + { + if (cursor_width < 1) + cursor_width = max (FRAME_CURSOR_WIDTH (f), 1); + w->phys_cursor_width = cursor_width; + } + /* If we have an HBAR, "cursor_width" MAY specify height. */ + else if (cursor_type == HBAR_CURSOR) + { + cursor_height = (cursor_width < 1) ? lrint (0.25 * h) : cursor_width; + fy += h - cursor_height; + h = cursor_height; + } + r.origin.x = fx, r.origin.y = fy; r.size.height = h; r.size.width = w->phys_cursor_width; @@ -2285,7 +2428,7 @@ ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, /* FIXME: if we overwrite the internal border area, it does not get erased; fix by truncating cursor, but better would be to erase properly */ overspill = r.origin.x + r.size.width - - WINDOW_TEXT_TO_FRAME_PIXEL_X (w, WINDOW_BOX_RIGHT_EDGE_X (w) + WINDOW_TEXT_TO_FRAME_PIXEL_X (w, WINDOW_BOX_RIGHT_EDGE_X (w) - WINDOW_TOTAL_FRINGE_WIDTH (w) - FRAME_INTERNAL_BORDER_WIDTH (f)); if (overspill > 0) r.size.width -= overspill; @@ -2328,15 +2471,10 @@ ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, [FRAME_CURSOR_COLOR (f) set]; break; case HBAR_CURSOR: - s = r; - s.origin.y += lrint (0.75 * s.size.height); - s.size.height = lrint (s.size.height * 0.25); - NSRectFill (s); + NSRectFill (r); break; case BAR_CURSOR: s = r; - s.size.width = min (cursor_width, 2); //FIXME(see above) - /* If the character under cursor is R2L, draw the bar cursor on the right of its glyph, rather than on the left. */ cursor_glyph = get_phys_cursor_glyph (w); @@ -2463,6 +2601,107 @@ ns_get_glyph_string_clip_rect (struct glyph_string *s, NativeRectangle *nr) return n; } +void +ns_draw_text_decoration (struct glyph_string *s, struct face *face, + NSColor *defaultCol, CGFloat width, CGFloat x) +/* -------------------------------------------------------------------------- + Draw underline, overline, and strike-through on glyph string s. + -------------------------------------------------------------------------- */ +{ + if (s->for_overlaps) + return; + + /* Do underline. */ + if (face->underline_p) + { + NSRect r; + unsigned long thickness, position; + + /* If the prev was underlined, match its appearance. */ + if (s->prev && s->prev->face->underline_p + && s->prev->underline_thickness > 0) + { + thickness = s->prev->underline_thickness; + position = s->prev->underline_position; + } + else + { + struct font *font; + unsigned long descent; + + font=s->font; + descent = s->y + s->height - s->ybase; + + /* Use underline thickness of font, defaulting to 1. */ + thickness = (font && font->underline_thickness > 0) + ? font->underline_thickness : 1; + + /* Determine the offset of underlining from the baseline. */ + if (x_underline_at_descent_line) + position = descent - thickness; + else if (x_use_underline_position_properties + && font && font->underline_position >= 0) + position = font->underline_position; + else if (font) + position = lround (font->descent / 2); + else + position = underline_minimum_offset; + + position = max (position, underline_minimum_offset); + + /* Ensure underlining is not cropped. */ + if (descent <= position) + { + position = descent - 1; + thickness = 1; + } + else if (descent < position + thickness) + thickness = 1; + } + + s->underline_thickness = thickness; + s->underline_position = position; + + r = NSMakeRect (x, s->ybase + position, width, thickness); + + if (face->underline_defaulted_p) + [defaultCol set]; + else + [ns_lookup_indexed_color (face->underline_color, s->f) set]; + NSRectFill (r); + } + + /* Do overline. We follow other terms in using a thickness of 1 + and ignoring overline_margin. */ + if (face->overline_p) + { + NSRect r; + r = NSMakeRect (x, s->y, width, 1); + + if (face->overline_color_defaulted_p) + [defaultCol set]; + else + [ns_lookup_indexed_color (face->overline_color, s->f) set]; + NSRectFill (r); + } + + /* Do strike-through. We follow other terms for thickness and + vertical position.*/ + if (face->strike_through_p) + { + NSRect r; + unsigned long dy; + + dy = lrint ((s->height - 1) / 2); + r = NSMakeRect (x, s->y + dy, width, 1); + + if (face->strike_through_color_defaulted_p) + [defaultCol set]; + else + [ns_lookup_indexed_color (face->strike_through_color, s->f) set]; + NSRectFill (r); + } +} static void ns_draw_box (NSRect r, float thickness, NSColor *col, char left_p, char right_p) @@ -2720,6 +2959,7 @@ ns_dumpglyphs_image (struct glyph_string *s, NSRect r) char raised_p; NSRect br; struct face *face; + NSColor *tdCol; NSTRACE (ns_dumpglyphs_image); @@ -2748,10 +2988,7 @@ ns_dumpglyphs_image (struct glyph_string *s, NSRect r) else face = FACE_FROM_ID (s->f, s->first_glyph->face_id); - if (s->hl == DRAW_CURSOR) - [FRAME_CURSOR_COLOR (s->f) set]; - else - [ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f) set]; + [ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f) set]; if (bg_height > s->slice.height || s->img->hmargin || s->img->vmargin || s->img->mask || s->img->pixmap == 0 || s->width != s->background_width) @@ -2789,6 +3026,27 @@ ns_dumpglyphs_image (struct glyph_string *s, NSRect r) [img compositeToPoint: NSMakePoint (x, y + s->slice.height) operation: NSCompositeSourceOver]; + if (s->hl == DRAW_CURSOR) + { + [FRAME_CURSOR_COLOR (s->f) set]; + if (s->w->phys_cursor_type == FILLED_BOX_CURSOR) + tdCol = ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f); + else + /* Currently on NS img->mask is always 0. Since + get_window_cursor_type specifies a hollow box cursor when on + a non-masked image we never reach this clause. But we put it + in in antipication of better support for image masks on + NS. */ + tdCol = ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), s->f); + } + else + { + tdCol = ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), s->f); + } + + /* Draw underline, overline, strike-through. */ + ns_draw_text_decoration (s, face, tdCol, br.size.width, br.origin.x); + /* Draw relief, if requested */ if (s->img->relief || s->hl ==DRAW_IMAGE_RAISED || s->hl ==DRAW_IMAGE_SUNKEN) { @@ -2833,22 +3091,49 @@ ns_dumpglyphs_stretch (struct glyph_string *s) NSRect r[2]; int n, i; struct face *face; + NSColor *fgCol, *bgCol; if (!s->background_filled_p) { n = ns_get_glyph_string_clip_rect (s, r); *r = NSMakeRect (s->x, s->y, s->background_width, s->height); + ns_focus (s->f, r, n); + + if (s->hl == DRAW_MOUSE_FACE) + { + face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id); + if (!face) + face = FACE_FROM_ID (s->f, MOUSE_FACE_ID); + } + else + face = FACE_FROM_ID (s->f, s->first_glyph->face_id); + + bgCol = ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f); + fgCol = ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), s->f); + for (i=0; irow->full_width_p) { + int overrun, leftoverrun; + /* truncate to avoid overwriting fringe and/or scrollbar */ - int overrun = max (0, (s->x + s->background_width) - - (WINDOW_BOX_RIGHT_EDGE_X (s->w) - - WINDOW_RIGHT_FRINGE_WIDTH (s->w))); + overrun = max (0, (s->x + s->background_width) + - (WINDOW_BOX_RIGHT_EDGE_X (s->w) + - WINDOW_RIGHT_FRINGE_WIDTH (s->w))); r[i].size.width -= overrun; + /* truncate to avoid overwriting to left of the window box */ + leftoverrun = (WINDOW_BOX_LEFT_EDGE_X (s->w) + + WINDOW_LEFT_FRINGE_WIDTH (s->w)) - s->x; + + if (leftoverrun > 0) + { + r[i].origin.x += leftoverrun; + r[i].size.width -= leftoverrun; + } + /* XXX: Try to work between problem where a stretch glyph on a partially-visible bottom row will clear part of the modeline, and another where list-buffers headers and similar @@ -2864,30 +3149,37 @@ ns_dumpglyphs_stretch (struct glyph_string *s) FRAME_PIXEL_WIDTH (s->f)); } + [bgCol set]; + /* NOTE: under NS this is NOT used to draw cursors, but we must avoid overwriting cursor (usually when cursor on a tab) */ if (s->hl == DRAW_CURSOR) { - r[i].origin.x += s->width; - r[i].size.width -= s->width; - } - } + CGFloat x, width; - ns_focus (s->f, r, n); + x = r[i].origin.x; + width = s->w->phys_cursor_width; + r[i].size.width -= width; + r[i].origin.x += width; - if (s->hl == DRAW_MOUSE_FACE) - { - face = FACE_FROM_ID (s->f, MOUSE_HL_INFO (s->f)->mouse_face_face_id); - if (!face) - face = FACE_FROM_ID (s->f, MOUSE_FACE_ID); - } - else - face = FACE_FROM_ID (s->f, s->first_glyph->face_id); + NSRectFill (r[i]); - [ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f) set]; + /* Draw overlining, etc. on the cursor. */ + if (s->w->phys_cursor_type == FILLED_BOX_CURSOR) + ns_draw_text_decoration (s, face, bgCol, width, x); + else + ns_draw_text_decoration (s, face, fgCol, width, x); + } + else + { + NSRectFill (r[i]); + } - NSRectFill (r[0]); - NSRectFill (r[1]); + /* Draw overlining, etc. on the stretch glyph (or the part + of the stretch glyph after the cursor). */ + ns_draw_text_decoration (s, face, fgCol, r[i].size.width, + r[i].origin.x); + } ns_unfocus (s->f); s->background_filled_p = 1; } @@ -2984,7 +3276,7 @@ ns_draw_glyph_string (struct glyph_string *s) NS_FACE_BACKGROUND (s->face) = NS_FACE_FOREGROUND (s->face); NS_FACE_FOREGROUND (s->face) = tmp; } - + ns_tmp_font->font.driver->draw (s, 0, s->nchars, s->x, s->y, (ns_tmp_flags == NS_DUMPGLYPH_NORMAL && !s->background_filled_p) @@ -3010,9 +3302,9 @@ ns_draw_glyph_string (struct glyph_string *s) else ns_maybe_dumpglyphs_background (s, s->first_glyph->type == COMPOSITE_GLYPH); - /* ... */ + /* ... */ /* Not yet implemented. */ - /* ... */ + /* ... */ ns_unfocus (s->f); break; @@ -3785,7 +4077,7 @@ ns_term_init (Lisp_Object display_name) strncpy (terminal->name, SDATA (display_name), SBYTES (display_name)); terminal->name[SBYTES (display_name)] = 0; - UNBLOCK_INPUT; + UNBLOCK_INPUT; if (!inhibit_x_resources) { @@ -3802,7 +4094,7 @@ ns_term_init (Lisp_Object display_name) stringForKey: @"AppleHighlightColor"]; if (ns_selection_color == nil) ns_selection_color = NS_SELECTION_COLOR_DEFAULT; - + { NSColorList *cl = [NSColorList colorListNamed: @"Emacs"]; @@ -3898,7 +4190,7 @@ ns_term_init (Lisp_Object display_name) keyEquivalent: @"q" atIndex: 9]; - item = [mainMenu insertItemWithTitle: ns_app_name + item = [mainMenu insertItemWithTitle: ns_app_name action: @selector (menuDown:) keyEquivalent: @"" atIndex: 0]; @@ -3925,6 +4217,8 @@ ns_term_init (Lisp_Object display_name) void ns_term_shutdown (int sig) { + [[NSUserDefaults standardUserDefaults] synchronize]; + /* code not reached in emacs.c after this is called by shut_down_emacs: */ if (STRINGP (Vauto_save_list_file_name)) unlink (SDATA (Vauto_save_list_file_name)); @@ -3969,6 +4263,16 @@ ns_term_shutdown (int sig) /* NSTRACE (sendEvent); */ /*fprintf (stderr, "received event of type %d\t%d\n", type);*/ +#ifdef NS_IMPL_COCOA + if (type == NSApplicationDefined + && [theEvent data2] == NSAPP_DATA2_RUNASSCRIPT) + { + ns_run_ascript (); + [self stop: self]; + return; + } +#endif + if (type == NSCursorUpdate && window == nil) { fprintf (stderr, "Dropping external cursor update event.\n"); @@ -4103,7 +4407,7 @@ ns_term_shutdown (int sig) -appShouldTerminate Cancel -> Nothing else Accept -> - + -terminate KEY_NS_POWER_OFF, (save-buffers-kill-emacs) ns_term_shutdown() @@ -4113,10 +4417,10 @@ ns_term_shutdown (int sig) - (void) terminate: (id)sender { struct frame *emacsframe = SELECTED_FRAME (); - + if (!emacs_event) return; - + emacs_event->kind = NS_NONKEY_EVENT; emacs_event->code = KEY_NS_POWER_OFF; emacs_event->arg = Qt; /* mark as non-key event */ @@ -4194,7 +4498,13 @@ ns_term_shutdown (int sig) } - (void)applicationDidBecomeActive: (NSNotification *)notification { + NSTRACE (applicationDidBecomeActive); + //ns_app_active=YES; + + ns_update_auto_hide_menu_bar (); + // No constrining takes place when the application is not active. + ns_constrain_all_frames (); } - (void)applicationDidResignActive: (NSNotification *)notification { @@ -4373,7 +4683,9 @@ ns_term_shutdown (int sig) unsigned fnKeysym = 0; int flags; static NSMutableArray *nsEvArray; +#if !defined (NS_IMPL_COCOA) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 static BOOL firstTime = YES; +#endif int left_is_none; NSTRACE (keyDown); @@ -4418,7 +4730,7 @@ ns_term_shutdown (int sig) code = ([[theEvent charactersIgnoringModifiers] length] == 0) ? 0 : [[theEvent charactersIgnoringModifiers] characterAtIndex: 0]; /* (Carbon way: [theEvent keyCode]) */ - + /* is it a "function key"? */ fnKeysym = ns_convert_key (code); if (fnKeysym) @@ -4542,6 +4854,7 @@ ns_term_shutdown (int sig) /* if it was a function key or had modifiers, pass it directly to emacs */ if (fnKeysym || (emacs_event->modifiers + && (emacs_event->modifiers != shift_modifier) && [[theEvent charactersIgnoringModifiers] length] > 0)) /*[[theEvent characters] length] */ { @@ -4560,13 +4873,15 @@ ns_term_shutdown (int sig) } } + +#if !defined (NS_IMPL_COCOA) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 /* if we get here we should send the key for input manager processing */ if (firstTime && [[NSInputManager currentInputManager] wantsToDelayTextChangeNotifications] == NO) fprintf (stderr, "Emacs: WARNING: TextInput mgr wants marked text to be permanent!\n"); firstTime = NO; - +#endif if (NS_KEYLOG && !processingCompose) fprintf (stderr, "keyDown: Begin compose sequence.\n"); @@ -5010,7 +5325,7 @@ ns_term_shutdown (int sig) strcpy (old_title, t); } size_title = xmalloc (strlen (old_title) + 40); - sprintf (size_title, "%s — (%d x %d)", old_title, cols, rows); + esprintf (size_title, "%s — (%d x %d)", old_title, cols, rows); [window setTitle: [NSString stringWithUTF8String: size_title]]; [window display]; xfree (size_title); @@ -5051,7 +5366,23 @@ ns_term_shutdown (int sig) a "windowDidResize" which calls x_set_window_size). */ #ifndef NS_IMPL_GNUSTEP if (cols > 0 && rows > 0) - x_set_window_size (emacsframe, 0, cols, rows); + { + if (ns_in_resize) + x_set_window_size (emacsframe, 0, cols, rows); + else + { + NSWindow *window = [self window]; + NSRect wr = [window frame]; + FRAME_PIXEL_WIDTH (emacsframe) = (int)wr.size.width + - emacsframe->border_width; + FRAME_PIXEL_HEIGHT (emacsframe) = (int)wr.size.height + - FRAME_NS_TITLEBAR_HEIGHT (emacsframe) + - FRAME_TOOLBAR_HEIGHT (emacsframe); + change_frame_size (emacsframe, rows, cols, 0, 0, 1); + SET_FRAME_GARBAGED (emacsframe); + cancel_mouse_face (emacsframe); + } + } #endif ns_send_appdefined (-1); @@ -5157,6 +5488,9 @@ ns_term_shutdown (int sig) win = [[EmacsWindow alloc] initWithContentRect: r styleMask: (NSResizableWindowMask | +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 + NSTitledWindowMask | +#endif NSMiniaturizableWindowMask | NSClosableWindowMask) backing: NSBackingStoreBuffered @@ -5222,6 +5556,9 @@ ns_term_shutdown (int sig) [self allocateGState]; + [NSApp registerServicesMenuSendTypes: ns_send_types + returnTypes: nil]; + ns_window_num++; return self; } @@ -5445,7 +5782,7 @@ ns_term_shutdown (int sig) /* drawRect: may be called (at least in OS X 10.5) for invisible - views as well for some reason. Thus, do not infer visibility + views as well for some reason. Thus, do not infer visibility here. emacsframe->async_visible = 1; @@ -5593,13 +5930,16 @@ ns_term_shutdown (int sig) } -- validRequestorForSendType: (NSString *)typeSent - returnType: (NSString *)typeReturned +- (id) validRequestorForSendType: (NSString *)typeSent + returnType: (NSString *)typeReturned { NSTRACE (validRequestorForSendType); - if ([ns_send_types indexOfObjectIdenticalTo: typeSent] != NSNotFound && - [ns_return_types indexOfObjectIdenticalTo: typeSent] != NSNotFound) - return self; + if (typeSent != nil && [ns_send_types indexOfObject: typeSent] != NSNotFound + && typeReturned == nil) + { + if (! NILP (ns_get_local_selection (QPRIMARY, QUTF8_STRING))) + return self; + } return [super validRequestorForSendType: typeSent returnType: typeReturned]; @@ -5623,8 +5963,28 @@ ns_term_shutdown (int sig) - (BOOL) writeSelectionToPasteboard: (NSPasteboard *)pb types: (NSArray *)types { - /* supposed to write for as many of types as we are able */ - return NO; + NSArray *typesDeclared; + Lisp_Object val; + + /* We only support NSStringPboardType */ + if ([types containsObject:NSStringPboardType] == NO) { + return NO; + } + + val = ns_get_local_selection (QPRIMARY, QUTF8_STRING); + if (CONSP (val) && SYMBOLP (XCAR (val))) + { + val = XCDR (val); + if (CONSP (val) && NILP (XCDR (val))) + val = XCAR (val); + } + if (! STRINGP (val)) + return NO; + + typesDeclared = [NSArray arrayWithObject:NSStringPboardType]; + [pb declareTypes:typesDeclared owner:nil]; + ns_string_to_pasteboard (pb, val); + return YES; } @@ -5677,7 +6037,10 @@ ns_term_shutdown (int sig) /* When making the frame visible for the first time, we want to constrain. Other times not. */ struct frame *f = ((EmacsView *)[self delegate])->emacsframe; - if (f->output_data.ns->dont_constrain) + NSTRACE (constrainFrameRect); + + if (f->output_data.ns->dont_constrain + || ns_menu_bar_should_be_hidden ()) return frameRect; f->output_data.ns->dont_constrain = 1; @@ -5893,14 +6256,26 @@ ns_term_shutdown (int sig) em_whole = whole; if (portion >= whole) - [self setFloatValue: 0.0 knobProportion: 1.0]; + { +#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5 + [self setKnobProportion: 1.0]; + [self setDoubleValue: 1.0]; +#else + [self setFloatValue: 0.0 knobProportion: 1.0]; +#endif + } else { float pos, por; portion = max ((float)whole*min_portion/pixel_height, portion); pos = (float)position / (whole - portion); por = (float)portion/whole; +#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_5 + [self setKnobProportion: por]; + [self setDoubleValue: pos]; +#else [self setFloatValue: pos knobProportion: por]; +#endif } return self; } @@ -6245,6 +6620,8 @@ syms_of_nsterm (void) DEFSYM (Qsuper, "super"); DEFSYM (Qcontrol, "control"); DEFSYM (Qnone, "none"); + DEFSYM (QUTF8_STRING, "UTF8_STRING"); + Fput (Qalt, Qmodifier_value, make_number (alt_modifier)); Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier)); Fput (Qmeta, Qmodifier_value, make_number (meta_modifier)); @@ -6349,6 +6726,11 @@ allowing it to be used at a lower level for accented character entry."); 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. */); + ns_auto_hide_menu_bar = Qnil; + /* TODO: move to common code */ DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars, doc: /* If not nil, Emacs uses toolkit scroll bars. */); @@ -6358,23 +6740,17 @@ allowing it to be used at a lower level for accented character entry."); Vx_toolkit_scroll_bars = Qnil; #endif - /* these are unsupported but we need the declarations to avoid whining - messages from cus-start.el */ DEFVAR_BOOL ("x-use-underline-position-properties", x_use_underline_position_properties, - doc: /* NOT SUPPORTED UNDER NS. -*Non-nil means make use of UNDERLINE_POSITION font properties. + doc: /*Non-nil means make use of UNDERLINE_POSITION font properties. A value of nil means ignore them. If you encounter fonts with bogus UNDERLINE_POSITION font properties, for example 7x13 on XFree prior -to 4.1, set this to nil. - -NOTE: Not supported on Mac yet. */); +to 4.1, set this to nil. */); x_use_underline_position_properties = 0; DEFVAR_BOOL ("x-underline-at-descent-line", x_underline_at_descent_line, - doc: /* NOT SUPPORTED UNDER NS. -*Non-nil means to draw the underline at the same place as the descent line. + doc: /* Non-nil means to draw the underline at the same place as the descent line. A value of nil means to draw the underline according to the value of the variable `x-use-underline-position-properties', which is usually at the baseline level. The default value is nil. */); @@ -6383,5 +6759,3 @@ baseline level. The default value is nil. */); /* Tell emacs about this window system. */ Fprovide (intern ("ns"), Qnil); } - -