X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/4ce7a13803d72d6def8943033a94656f9b02cbd8..8ad5b73b601fba3328b7e75ecd64c8cd0eef9fac:/src/nsterm.m diff --git a/src/nsterm.m b/src/nsterm.m index c892a5486a..6b739befee 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -35,7 +35,6 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu) #include #include #include -#include #include #include @@ -73,6 +72,11 @@ int term_trace_num = 0; #define NSTRACE(x) #endif +#if defined (NS_IMPL_COCOA) && \ + MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 +#define NEW_STYLE_FS +#endif + extern NSString *NSMenuDidBeginTrackingNotification; /* ========================================================================== @@ -179,7 +183,6 @@ static int ns_window_num = 0; static NSRect uRect; #endif 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 */ @@ -489,17 +492,6 @@ ns_release_autorelease_pool (void *pool) ========================================================================== */ -static NSRect -ns_resize_handle_rect (NSWindow *window) -{ - NSRect r = [window frame]; - r.origin.x = r.size.width - RESIZE_HANDLE_SIZE; - r.origin.y = 0; - r.size.width = r.size.height = RESIZE_HANDLE_SIZE; - return r; -} - - // // Window constraining // ------------------- @@ -577,12 +569,9 @@ ns_menu_bar_should_be_hidden (void) 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; + block_input (); NSTRACE (ns_update_auto_hide_menu_bar); @@ -613,7 +602,7 @@ ns_update_auto_hide_menu_bar (void) } } - UNBLOCK_INPUT; + unblock_input (); #endif #endif } @@ -627,6 +616,8 @@ ns_update_begin (struct frame *f) -------------------------------------------------------------------------- */ { NSView *view = FRAME_NS_VIEW (f); + NSRect r = [view frame]; + NSBezierPath *bp; NSTRACE (ns_update_begin); ns_update_auto_hide_menu_bar (); @@ -634,6 +625,14 @@ ns_update_begin (struct frame *f) ns_updating_frame = f; [view lockFocus]; + /* drawRect may have been called for say the minibuffer, and then clip path + is for the minibuffer. But the display engine may draw more because + we have set the frame as garbaged. So reset clip path to the whole + view. */ + bp = [[NSBezierPath bezierPathWithRect: r] retain]; + [bp setClip]; + [bp release]; + #ifdef NS_IMPL_GNUSTEP uRect = NSMakeRect (0, 0, 0, 0); #endif @@ -650,11 +649,10 @@ ns_update_window_begin (struct window *w) struct frame *f = XFRAME (WINDOW_FRAME (w)); Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); NSTRACE (ns_update_window_begin); - updated_window = w; set_output_cursor (&w->cursor); - BLOCK_INPUT; + block_input (); if (f == hlinfo->mouse_face_mouse_frame) { @@ -669,7 +667,7 @@ ns_update_window_begin (struct window *w) /* (further code for mouse faces ifdef'd out in other terms elided) */ } - UNBLOCK_INPUT; + unblock_input (); } @@ -686,7 +684,7 @@ ns_update_window_end (struct window *w, int cursor_on_p, /* note: this fn is nearly identical in all terms */ if (!w->pseudo_window_p) { - BLOCK_INPUT; + block_input (); if (cursor_on_p) display_and_set_cursor (w, 1, @@ -696,7 +694,7 @@ ns_update_window_end (struct window *w, int cursor_on_p, if (draw_window_fringes (w, 1)) x_draw_vertical_border (w); - UNBLOCK_INPUT; + unblock_input (); } /* If a row with mouse-face was overwritten, arrange for @@ -725,7 +723,7 @@ ns_update_end (struct frame *f) /* if (f == MOUSE_HL_INFO (f)->mouse_face_mouse_frame) */ MOUSE_HL_INFO (f)->mouse_face_defer = 0; - BLOCK_INPUT; + block_input (); #ifdef NS_IMPL_GNUSTEP /* trigger flush only in the rectangle we tracked as being drawn */ @@ -737,7 +735,7 @@ ns_update_end (struct frame *f) [view unlockFocus]; [[view window] flushWindow]; - UNBLOCK_INPUT; + unblock_input (); ns_updating_frame = NULL; NSTRACE (ns_update_end); } @@ -871,25 +869,12 @@ ns_clip_to_row (struct window *w, struct glyph_row *row, int area, BOOL gc) window_box (w, area, &window_x, &window_y, &window_width, 0); - clip_rect.origin.x = window_x - FRAME_INTERNAL_BORDER_WIDTH (f); + clip_rect.origin.x = window_x; clip_rect.origin.y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y)); clip_rect.origin.y = max (clip_rect.origin.y, window_y); - clip_rect.size.width = window_width + 2 * FRAME_INTERNAL_BORDER_WIDTH (f); + clip_rect.size.width = window_width; clip_rect.size.height = row->visible_height; - /* allow a full-height row at the top when requested - (used to draw fringe all the way through internal border area) */ - if (gc && clip_rect.origin.y < 5) - { - clip_rect.origin.y -= FRAME_INTERNAL_BORDER_WIDTH (f); - clip_rect.size.height += FRAME_INTERNAL_BORDER_WIDTH (f); - } - - /* likewise at bottom */ - if (gc && - FRAME_PIXEL_HEIGHT (f) - (clip_rect.origin.y + clip_rect.size.height) < 5) - clip_rect.size.height += FRAME_INTERNAL_BORDER_WIDTH (f); - ns_focus (f, &clip_rect, 1); } @@ -907,7 +892,7 @@ ns_ring_bell (struct frame *f) struct frame *frame = SELECTED_FRAME (); NSView *view; - BLOCK_INPUT; + block_input (); pool = [[NSAutoreleasePool alloc] init]; view = FRAME_NS_VIEW (frame); @@ -934,7 +919,7 @@ ns_ring_bell (struct frame *f) ns_unfocus (frame); } [pool release]; - UNBLOCK_INPUT; + unblock_input (); } else { @@ -975,13 +960,13 @@ ns_raise_frame (struct frame *f) { NSView *view = FRAME_NS_VIEW (f); check_ns (); - BLOCK_INPUT; + block_input (); FRAME_SAMPLE_VISIBILITY (f); if (FRAME_VISIBLE_P (f)) { [[view window] makeKeyAndOrderFront: NSApp]; } - UNBLOCK_INPUT; + unblock_input (); } @@ -993,9 +978,9 @@ ns_lower_frame (struct frame *f) { NSView *view = FRAME_NS_VIEW (f); check_ns (); - BLOCK_INPUT; + block_input (); [[view window] orderBack: NSApp]; - UNBLOCK_INPUT; + unblock_input (); } @@ -1068,8 +1053,23 @@ x_make_frame_visible (struct frame *f) if this ends up the case again, comment this out again. */ if (!FRAME_VISIBLE_P (f)) { + EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f); f->async_visible = 1; ns_raise_frame (f); + +#ifdef NEW_STYLE_FS + /* Making a new frame from a fullscreen frame will make the new frame + fullscreen also. So skip handleFS as this will print an error. */ + if (f->want_fullscreen == FULLSCREEN_BOTH + && ([[view window] styleMask] & NSFullScreenWindowMask) != 0) + return; +#endif + if (f->want_fullscreen != FULLSCREEN_NONE) + { + block_input (); + [view handleFS]; + unblock_input (); + } } } @@ -1131,7 +1131,7 @@ x_free_frame_resources (struct frame *f) [(EmacsView *)view setWindowClosing: YES]; /* may not have been informed */ - BLOCK_INPUT; + block_input (); free_frame_menubar (f); @@ -1159,7 +1159,7 @@ x_free_frame_resources (struct frame *f) xfree (f->output_data.ns); - UNBLOCK_INPUT; + unblock_input (); } void @@ -1188,7 +1188,7 @@ x_set_offset (struct frame *f, int xoff, int yoff, int change_grav) NSTRACE (x_set_offset); - BLOCK_INPUT; + block_input (); f->left_pos = xoff; f->top_pos = yoff; @@ -1220,7 +1220,7 @@ x_set_offset (struct frame *f, int xoff, int yoff, int change_grav) f->size_hint_flags &= ~(XNegative|YNegative); } - UNBLOCK_INPUT; + unblock_input (); } @@ -1237,31 +1237,17 @@ 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; - static int oldRows, oldCols, oldFontWidth, oldFontHeight; - static int oldTB; - static struct frame *oldF; NSTRACE (x_set_window_size); - if (view == nil || - (f == oldF - && rows == oldRows && cols == oldCols - && oldFontWidth == FRAME_COLUMN_WIDTH (f) - && oldFontHeight == FRAME_LINE_HEIGHT (f) - && oldTB == tb)) + 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)); */ - BLOCK_INPUT; + block_input (); check_frame_size (f, &rows, &cols); - oldF = f; - oldRows = rows; - oldCols = cols; - oldFontWidth = FRAME_COLUMN_WIDTH (f); - oldFontHeight = FRAME_LINE_HEIGHT (f); - oldTB = tb; f->scroll_bar_actual_width = NS_SCROLL_BAR_WIDTH (f); compute_fringe_widths (f, 0); @@ -1321,10 +1307,33 @@ x_set_window_size (struct frame *f, int change_grav, int cols, int rows) mark_window_cursors_off (XWINDOW (f->root_window)); cancel_mouse_face (f); - UNBLOCK_INPUT; + unblock_input (); } +static void +ns_fullscreen_hook (FRAME_PTR f) +{ + EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f); + + if (! f->async_visible) return; +#ifndef NEW_STYLE_FS + if (f->want_fullscreen == FULLSCREEN_BOTH) + { + /* Old style fs don't initiate correctly if created from + init/default-frame alist, so use a timer (not nice...). + */ + [NSTimer scheduledTimerWithTimeInterval: 0.5 target: view + selector: @selector (handleFS) + userInfo: nil repeats: NO]; + return; + } +#endif + + block_input (); + [view handleFS]; + unblock_input (); +} /* ========================================================================== @@ -1433,7 +1442,7 @@ ns_get_color (const char *name, NSColor **col) NSString *nsname = [NSString stringWithUTF8String: name]; /*fprintf (stderr, "ns_get_color: '%s'\n", name); */ - BLOCK_INPUT; + block_input (); if ([nsname isEqualToString: @"ns_selection_color"]) { @@ -1480,7 +1489,7 @@ ns_get_color (const char *name, NSColor **col) if (r >= 0.0) { *col = [NSColor colorWithCalibratedRed: r green: g blue: b alpha: 1.0]; - UNBLOCK_INPUT; + unblock_input (); return 0; } @@ -1512,7 +1521,7 @@ ns_get_color (const char *name, NSColor **col) if (new) *col = [new colorUsingColorSpaceName: NSCalibratedRGBColorSpace]; - UNBLOCK_INPUT; + unblock_input (); return new ? 0 : 1; } @@ -1543,12 +1552,12 @@ ns_color_to_lisp (NSColor *col) const char *str; NSTRACE (ns_color_to_lisp); - BLOCK_INPUT; + block_input (); if ([[col colorSpaceName] isEqualToString: NSNamedColorSpace]) if ((str =[[col colorNameComponent] UTF8String])) { - UNBLOCK_INPUT; + unblock_input (); return build_string ((char *)str); } @@ -1560,14 +1569,14 @@ ns_color_to_lisp (NSColor *col) getWhite: &gray alpha: &alpha]; snprintf (buf, sizeof (buf), "#%2.2lx%2.2lx%2.2lx", lrint (gray * 0xff), lrint (gray * 0xff), lrint (gray * 0xff)); - UNBLOCK_INPUT; + unblock_input (); return build_string (buf); } snprintf (buf, sizeof (buf), "#%2.2lx%2.2lx%2.2lx", lrint (red*0xff), lrint (green*0xff), lrint (blue*0xff)); - UNBLOCK_INPUT; + unblock_input (); return build_string (buf); } @@ -1594,33 +1603,33 @@ ns_query_color(void *col, XColor *color_def, int setPixel) } -int +bool ns_defined_color (struct frame *f, const char *name, XColor *color_def, - int alloc, - char makeIndex) + bool alloc, + bool makeIndex) /* -------------------------------------------------------------------------- - Return 1 if named color found, and set color_def rgb accordingly. + Return true if named color found, and set color_def rgb accordingly. If makeIndex and alloc are nonzero put the color in the color_table, and set color_def pixel to the resulting index. If makeIndex is zero, set color_def pixel to ARGB. - Return 0 if not found + Return false if not found -------------------------------------------------------------------------- */ { NSColor *col; NSTRACE (ns_defined_color); - BLOCK_INPUT; + block_input (); if (ns_get_color (name, &col) != 0) /* Color not found */ { - UNBLOCK_INPUT; + unblock_input (); return 0; } if (makeIndex && alloc) color_def->pixel = ns_index_color (col, f); ns_query_color (col, color_def, !makeIndex); - UNBLOCK_INPUT; + unblock_input (); return 1; } @@ -1786,7 +1795,7 @@ ns_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, dpyinfo = FRAME_NS_DISPLAY_INFO (*fp); - BLOCK_INPUT; + block_input (); if (last_mouse_scroll_bar != nil && insist == 0) { @@ -1831,7 +1840,7 @@ ns_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, } } - UNBLOCK_INPUT; + unblock_input (); } @@ -1851,7 +1860,7 @@ ns_frame_up_to_date (struct frame *f) if ((hlinfo->mouse_face_deferred_gc || f ==hlinfo->mouse_face_mouse_frame) /*&& hlinfo->mouse_face_mouse_frame*/) { - BLOCK_INPUT; + block_input (); ns_update_begin(f); if (hlinfo->mouse_face_mouse_frame) note_mouse_highlight (hlinfo->mouse_face_mouse_frame, @@ -1859,7 +1868,7 @@ ns_frame_up_to_date (struct frame *f) hlinfo->mouse_face_mouse_y); hlinfo->mouse_face_deferred_gc = 0; ns_update_end(f); - UNBLOCK_INPUT; + unblock_input (); } } } @@ -1939,7 +1948,7 @@ ns_redraw_scroll_bars (struct frame *f) int i; id view; NSArray *subviews = [[FRAME_NS_VIEW (f) superview] subviews]; - NSTRACE (ns_judge_scroll_bars); + NSTRACE (ns_redraw_scroll_bars); for (i =[subviews count]-1; i >= 0; i--) { view = [subviews objectAtIndex: i]; @@ -1959,8 +1968,6 @@ ns_clear_frame (struct frame *f) NSRect r; NSTRACE (ns_clear_frame); - if (ns_in_resize) - return; /* comes on initial frame because we have after-make-frame-functions = select-frame */ @@ -1974,19 +1981,15 @@ ns_clear_frame (struct frame *f) r = [view bounds]; - BLOCK_INPUT; + block_input (); ns_focus (f, &r, 1); [ns_lookup_indexed_color (NS_FACE_BACKGROUND (FRAME_DEFAULT_FACE (f)), f) set]; NSRectFill (r); ns_unfocus (f); -#ifdef NS_IMPL_COCOA - [[view window] display]; /* redraw resize handle */ -#endif - /* as of 2006/11 or so this is now needed */ ns_redraw_scroll_bars (f); - UNBLOCK_INPUT; + unblock_input (); } @@ -2009,35 +2012,8 @@ ns_clear_frame_area (struct frame *f, int x, int y, int width, int height) ns_focus (f, &r, 1); [ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), f) set]; -#ifdef NS_IMPL_COCOA - { - /* clip out the resize handle */ - NSWindow *window = [FRAME_NS_VIEW (f) window]; - NSRect ir - = [view convertRect: ns_resize_handle_rect (window) fromView: nil]; - - ir = NSIntersectionRect (r, ir); - if (NSIsEmptyRect (ir)) - { -#endif - NSRectFill (r); -#ifdef NS_IMPL_COCOA - } - else - { - NSRect r1 = r, r2 = r; /* upper and lower non-intersecting */ - r1.size.height -= ir.size.height; - r2.origin.y += r1.size.height; - r2.size.width -= ir.size.width; - r2.size.height = ir.size.height; - NSRectFill (r1); - NSRectFill (r2); - } - } -#endif - ns_unfocus (f); return; } @@ -2087,7 +2063,7 @@ ns_scroll_run (struct window *w, struct run *run) if (height == 0) return; - BLOCK_INPUT; + block_input (); updated_window = w; x_clear_cursor (w); @@ -2102,7 +2078,7 @@ ns_scroll_run (struct window *w, struct run *run) ns_unfocus (f); } - UNBLOCK_INPUT; + unblock_input (); } @@ -2125,9 +2101,9 @@ ns_after_update_window_line (struct glyph_row *desired_row) desired_row->redraw_fringe_bitmaps_p = 1; /* When a window has disappeared, make sure that no rest of - full-width rows stays visible in the internal border. - Under NS this is drawn inside the fringes. */ + full-width rows stays visible in the internal border. */ if (windows_or_buffers_changed + && desired_row->full_width_p && (f = XFRAME (w->frame), width = FRAME_INTERNAL_BORDER_WIDTH (f), width != 0) @@ -2136,25 +2112,12 @@ ns_after_update_window_line (struct glyph_row *desired_row) { int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y)); - /* Internal border is drawn below the tool bar. */ - if (WINDOWP (f->tool_bar_window) - && w == XWINDOW (f->tool_bar_window)) - y -= width; - /* end copy from other terms */ - - BLOCK_INPUT; - if (!desired_row->full_width_p) - { - int x1 = WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w) - + WINDOW_LEFT_FRINGE_WIDTH (w); - int x2 = WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w) - + FRAME_PIXEL_WIDTH (f) - NS_SCROLL_BAR_WIDTH (f) - - WINDOW_RIGHT_FRINGE_WIDTH (w) - - FRAME_INTERNAL_BORDER_WIDTH (f); - ns_clear_frame_area (f, x1, y, width, height); - ns_clear_frame_area (f, x2, y, width, height); - } - UNBLOCK_INPUT; + block_input (); + ns_clear_frame_area (f, 0, y, width, height); + ns_clear_frame_area (f, + FRAME_PIXEL_WIDTH (f) - width, + y, width, height); + unblock_input (); } } @@ -2187,7 +2150,7 @@ ns_shift_glyphs_for_insert (struct frame *f, ========================================================================== */ -static inline void +static void ns_compute_glyph_string_overhangs (struct glyph_string *s) /* -------------------------------------------------------------------------- External (RIF); compute left/right overhang of whole string and set in s @@ -2238,17 +2201,6 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row, int rowY; static EmacsImage **bimgs = NULL; static int nBimgs = 0; - /* NS-specific: move internal border inside fringe */ - int x = p->bx < 0 ? p->x : p->bx; - int wd = p->bx < 0 ? p->wd : p->nx; - BOOL fringeOnVeryLeft - = x - WINDOW_LEFT_SCROLL_BAR_COLS (w) * WINDOW_FRAME_COLUMN_WIDTH (w) - - FRAME_INTERNAL_BORDER_WIDTH (f) < 10; - BOOL fringeOnVeryRight - = FRAME_PIXEL_WIDTH (f) - x - wd - FRAME_INTERNAL_BORDER_WIDTH (f) - - WINDOW_RIGHT_SCROLL_BAR_COLS (w) * WINDOW_FRAME_COLUMN_WIDTH (w) < 10; - int xAdjust = FRAME_INTERNAL_BORDER_WIDTH (f) * - (fringeOnVeryLeft ? -1 : (fringeOnVeryRight ? 1 : 0)); /* grow bimgs if needed */ if (nBimgs < max_used_fringe_bitmap) @@ -2263,22 +2215,68 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row, rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y); ns_clip_to_row (w, row, -1, YES); - if (p->bx >= 0 && !p->overlay_p) + if (!p->overlay_p) { - int yAdjust = rowY - FRAME_INTERNAL_BORDER_WIDTH (f) < 5 ? - -FRAME_INTERNAL_BORDER_WIDTH (f) : 0; - int yIncr = FRAME_PIXEL_HEIGHT (f) - (p->by+yAdjust + p->ny) < 5 ? - FRAME_INTERNAL_BORDER_WIDTH (f) : 0 - + (yAdjust ? FRAME_INTERNAL_BORDER_WIDTH (f) : 0); - NSRect r = NSMakeRect (p->bx+xAdjust, p->by+yAdjust, p->nx, p->ny+yIncr); - NSRectClip (r); - [ns_lookup_indexed_color(face->background, f) set]; - NSRectFill (r); + int bx = p->bx, by = p->by, nx = p->nx, ny = p->ny; + + /* If the fringe is adjacent to the left (right) scroll bar of a + leftmost (rightmost, respectively) window, then extend its + background to the gap between the fringe and the bar. */ + if ((WINDOW_LEFTMOST_P (w) + && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w)) + || (WINDOW_RIGHTMOST_P (w) + && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))) + { + int sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w); + + if (sb_width > 0) + { + int bar_area_x = WINDOW_SCROLL_BAR_AREA_X (w); + int bar_area_width = (WINDOW_CONFIG_SCROLL_BAR_COLS (w) + * FRAME_COLUMN_WIDTH (f)); + + if (bx < 0) + { + /* Bitmap fills the fringe. */ + if (bar_area_x + bar_area_width == p->x) + bx = bar_area_x + sb_width; + else if (p->x + p->wd == bar_area_x) + bx = bar_area_x; + if (bx >= 0) + { + int header_line_height = WINDOW_HEADER_LINE_HEIGHT (w); + + nx = bar_area_width - sb_width; + by = WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, + row->y)); + ny = row->visible_height; + } + } + else + { + if (bar_area_x + bar_area_width == bx) + { + bx = bar_area_x + sb_width; + nx += bar_area_width - sb_width; + } + else if (bx + nx == bar_area_x) + nx += bar_area_width - sb_width; + } + } + } + + if (bx >= 0 && nx > 0) + { + NSRect r = NSMakeRect (bx, by, nx, ny); + NSRectClip (r); + [ns_lookup_indexed_color (face->background, f) set]; + NSRectFill (r); + } } if (p->which) { - NSRect r = NSMakeRect (p->x+xAdjust, p->y, p->wd, p->h); + NSRect r = NSMakeRect (p->x, p->y, p->wd, p->h); EmacsImage *img = bimgs[p->which - 1]; if (!img) @@ -2288,7 +2286,7 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row, int i; unsigned char *cbits = xmalloc (len); - for (i =0; ih flip: NO]; @@ -2302,12 +2300,20 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row, [ns_lookup_indexed_color(face->background, f) set]; NSRectFill (r); [img setXBMColor: ns_lookup_indexed_color(face->foreground, f)]; +#if !defined (NS_IMPL_COCOA) || MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 [img drawInRect: r fromRect: NSZeroRect operation: NSCompositeSourceOver fraction: 1.0 respectFlipped: YES hints: nil]; +#else + { + NSPoint pt = r.origin; + pt.y += p->h; + [img compositeToPoint: pt operation: NSCompositeSourceOver]; + } +#endif } ns_unfocus (f); } @@ -2386,14 +2392,6 @@ ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, r.size.height = h; r.size.width = w->phys_cursor_width; - /* 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_TOTAL_FRINGE_WIDTH (w) - FRAME_INTERNAL_BORDER_WIDTH (f)); - if (overspill > 0) - r.size.width -= overspill; - /* 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 */ @@ -2486,12 +2484,12 @@ show_hourglass (struct atimer *timer) if (hourglass_shown_p) return; - BLOCK_INPUT; + block_input (); /* TODO: add NSProgressIndicator to selected frame (see macfns.c) */ hourglass_shown_p = 1; - UNBLOCK_INPUT; + unblock_input (); } @@ -2501,12 +2499,12 @@ hide_hourglass (void) if (!hourglass_shown_p) return; - BLOCK_INPUT; + block_input (); /* TODO: remove NSProgressIndicator from all frames */ hourglass_shown_p = 0; - UNBLOCK_INPUT; + unblock_input (); } @@ -2517,31 +2515,6 @@ hide_hourglass (void) ========================================================================== */ - -static inline NSRect -ns_fix_rect_ibw (NSRect r, int fibw, int frame_pixel_width) -/* -------------------------------------------------------------------------- - Under NS we draw internal borders inside fringes, and want full-width - rendering to go all the way to edge. This function makes that correction. - -------------------------------------------------------------------------- */ -{ - if (r.origin.y <= fibw+1) - { - r.size.height += r.origin.y; - r.origin.y = 0; - } - if (r.origin.x <= fibw+1) - { - r.size.width += r.origin.x; - r.origin.x = 0; - } - if (frame_pixel_width - (r.origin.x+r.size.width) <= fibw+1) - r.size.width += fibw; - - return r; -} - - static int ns_get_glyph_string_clip_rect (struct glyph_string *s, NativeRectangle *nr) /* -------------------------------------------------------------------------- @@ -2551,14 +2524,6 @@ ns_get_glyph_string_clip_rect (struct glyph_string *s, NativeRectangle *nr) -------------------------------------------------------------------------- */ { int n = get_glyph_string_clip_rects (s, nr, 2); - if (s->row->full_width_p) - { - *nr = ns_fix_rect_ibw (*nr, FRAME_INTERNAL_BORDER_WIDTH (s->f), - FRAME_PIXEL_WIDTH (s->f)); - if (n == 2) - *nr = ns_fix_rect_ibw (*(nr+1), FRAME_INTERNAL_BORDER_WIDTH (s->f), - FRAME_PIXEL_WIDTH (s->f)); - } return n; } @@ -2883,11 +2848,6 @@ ns_dumpglyphs_box_or_relief (struct glyph_string *s) r = NSMakeRect (s->x, s->y, right_x - s->x + 1, s->height); - /* expand full-width row over internal borders */ - if (s->row->full_width_p) - r = ns_fix_rect_ibw (r, FRAME_INTERNAL_BORDER_WIDTH (s->f), - FRAME_PIXEL_WIDTH (s->f)); - /* TODO: Sometimes box_color is 0 and this seems wrong; should investigate. */ if (s->face->box == FACE_SIMPLE_BOX && s->face->box_color) { @@ -2943,26 +2903,6 @@ ns_maybe_dumpglyphs_background (struct glyph_string *s, char force_p) NSRect r = NSMakeRect (s->x, s->y + box_line_width, s->background_width, s->height-2*box_line_width); - - /* expand full-width row over internal borders */ - if (s->row->full_width_p) - { - int fibw = FRAME_INTERNAL_BORDER_WIDTH (s->f); - if (r.origin.y <= fibw+1 + box_line_width) - { - r.size.height += r.origin.y; - r.origin.y = 0; - } - if (r.origin.x <= fibw+1) - { - r.size.width += 2*r.origin.x; - r.origin.x = 0; - } - if (FRAME_PIXEL_WIDTH (s->f) - (r.origin.x + r.size.width) - <= fibw+1) - r.size.width += fibw; - } - NSRectFill (r); } @@ -3028,34 +2968,26 @@ ns_dumpglyphs_image (struct glyph_string *s, NSRect r) br = NSMakeRect (x, y, s->slice.width, s->slice.height); } - /* expand full-width row over internal borders */ - if (s->row->full_width_p) - { - int fibw = FRAME_INTERNAL_BORDER_WIDTH (s->f); - if (br.origin.y <= fibw+1 + box_line_vwidth) - { - br.size.height += br.origin.y; - br.origin.y = 0; - } - if (br.origin.x <= fibw+1 + box_line_vwidth) - { - br.size.width += br.origin.x; - br.origin.x = 0; - } - if (FRAME_PIXEL_WIDTH (s->f) - (br.origin.x + br.size.width) <= fibw+1) - br.size.width += fibw; - } - NSRectFill (br); /* Draw the image.. do we need to draw placeholder if img ==nil? */ if (img != nil) - [img drawInRect: br - fromRect: NSZeroRect + { +#if !defined (NS_IMPL_COCOA) || MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 + NSRect dr = NSMakeRect (x, y, s->slice.width, s->slice.height); + NSRect ir = NSMakeRect (s->slice.x, s->slice.y, + s->slice.width, s->slice.height); + [img drawInRect: dr + fromRect: ir operation: NSCompositeSourceOver fraction: 1.0 respectFlipped: YES hints: nil]; +#else + [img compositeToPoint: NSMakePoint (x, y + s->slice.height) + operation: NSCompositeSourceOver]; +#endif + } if (s->hl == DRAW_CURSOR) { @@ -3143,7 +3075,7 @@ ns_dumpglyphs_stretch (struct glyph_string *s) 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) { @@ -3173,13 +3105,6 @@ ns_dumpglyphs_stretch (struct glyph_string *s) r[i].size.height = min (s->height, s->row->visible_height); } - /* expand full-width rows over internal borders */ - else - { - r[i] = ns_fix_rect_ibw (r[i], FRAME_INTERNAL_BORDER_WIDTH (s->f), - FRAME_PIXEL_WIDTH (s->f)); - } - [bgCol set]; /* NOTE: under NS this is NOT used to draw cursors, but we must avoid @@ -3340,7 +3265,7 @@ ns_draw_glyph_string (struct glyph_string *s) break; default: - abort (); + emacs_abort (); } /* Draw box if not done already. */ @@ -3409,8 +3334,7 @@ ns_send_appdefined (int value) } static int -ns_read_socket (struct terminal *terminal, int expected, - struct input_event *hold_quit) +ns_read_socket (struct terminal *terminal, struct input_event *hold_quit) /* -------------------------------------------------------------------------- External (hook): Post an event to ourself and keep reading events until we read it back again. In effect process all events which were waiting. @@ -3425,21 +3349,7 @@ ns_read_socket (struct terminal *terminal, int expected, if ([NSApp modalWindow] != nil) return -1; - if (interrupt_input_blocked) - { - interrupt_input_pending = 1; -#ifdef SYNC_INPUT - pending_signals = 1; -#endif - return -1; - } - - interrupt_input_pending = 0; -#ifdef SYNC_INPUT - pending_signals = pending_atimers; -#endif - - BLOCK_INPUT; + block_input (); n_emacs_events_pending = 0; EVENT_INIT (ev); emacs_event = &ev; @@ -3475,7 +3385,7 @@ ns_read_socket (struct terminal *terminal, int expected, if (++apploopnr != 1) { - abort (); + emacs_abort (); } [NSApp run]; --apploopnr; @@ -3484,7 +3394,7 @@ ns_read_socket (struct terminal *terminal, int expected, nevents = n_emacs_events_pending; n_emacs_events_pending = 0; emacs_event = q_event_ptr = NULL; - UNBLOCK_INPUT; + unblock_input (); return nevents; } @@ -3515,7 +3425,7 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds, [outerpool release]; outerpool = [[NSAutoreleasePool alloc] init]; - + send_appdefined = YES; if (nr > 0) { @@ -3564,11 +3474,11 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds, } EVENT_INIT (event); - BLOCK_INPUT; + block_input (); emacs_event = &event; if (++apploopnr != 1) { - abort(); + emacs_abort (); } [NSApp run]; --apploopnr; @@ -3578,7 +3488,7 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds, c = 's'; write (selfds[1], &c, 1); } - UNBLOCK_INPUT; + unblock_input (); ev = last_appdefined_event; @@ -3586,7 +3496,7 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds, { int t; if ([ev type] != NSApplicationDefined) - abort (); + emacs_abort (); t = [ev data1]; last_appdefined_event = 0; @@ -3639,9 +3549,9 @@ ns_set_vertical_scroll_bar (struct window *window, struct frame *f = XFRAME (WINDOW_FRAME (window)); EmacsView *view = FRAME_NS_VIEW (f); int window_y, window_height; - BOOL barOnVeryLeft, barOnVeryRight; int top, left, height, width, sb_width, sb_left; EmacsScroller *bar; + BOOL fringe_extended_p; /* optimization; display engine sends WAY too many of these.. */ if (!NILP (window->vertical_scroll_bar)) @@ -3668,28 +3578,29 @@ ns_set_vertical_scroll_bar (struct window *window, width = WINDOW_CONFIG_SCROLL_BAR_COLS (window) * FRAME_COLUMN_WIDTH (f); left = WINDOW_SCROLL_BAR_AREA_X (window); - if (top < 5) /* top scrollbar adjustment */ - { - top -= FRAME_INTERNAL_BORDER_WIDTH (f); - height += FRAME_INTERNAL_BORDER_WIDTH (f); - } - /* allow for displaying a skinnier scrollbar than char area allotted */ sb_width = (WINDOW_CONFIG_SCROLL_BAR_WIDTH (window) > 0) ? WINDOW_CONFIG_SCROLL_BAR_WIDTH (window) : width; - - barOnVeryLeft = left < 5; - barOnVeryRight = FRAME_PIXEL_WIDTH (f) - left - width < 5; - sb_left = left + FRAME_INTERNAL_BORDER_WIDTH (f) - * (barOnVeryLeft ? -1 : (barOnVeryRight ? 1 : 0)); + sb_left = left; r = NSMakeRect (sb_left, top, sb_width, height); /* the parent view is flipped, so we need to flip y value */ 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)); + XSETWINDOW (win, window); - BLOCK_INPUT; + block_input (); /* we want at least 5 lines to display a scrollbar */ if (WINDOW_TOTAL_LINES (window) < 5) @@ -3701,13 +3612,20 @@ ns_set_vertical_scroll_bar (struct window *window, wset_vertical_scroll_bar (window, Qnil); } ns_clear_frame_area (f, sb_left, top, width, height); - UNBLOCK_INPUT; + unblock_input (); return; } if (NILP (window->vertical_scroll_bar)) { - ns_clear_frame_area (f, sb_left, top, width, height); + if (width > 0 && height > 0) + { + if (fringe_extended_p) + ns_clear_frame_area (f, sb_left, top, sb_width, height); + else + ns_clear_frame_area (f, left, top, width, height); + } + bar = [[EmacsScroller alloc] initFrame: r window: win]; wset_vertical_scroll_bar (window, make_save_value (bar, 0)); } @@ -3726,7 +3644,7 @@ ns_set_vertical_scroll_bar (struct window *window, } [bar setPosition: position portion: portion whole: whole]; - UNBLOCK_INPUT; + unblock_input (); } @@ -3778,14 +3696,21 @@ ns_judge_scroll_bars (struct frame *f) { int i; id view; - NSArray *subviews = [[FRAME_NS_VIEW (f) superview] subviews]; + EmacsView *eview = FRAME_NS_VIEW (f); + NSArray *subviews = [[eview superview] subviews]; + BOOL removed = NO; + NSTRACE (ns_judge_scroll_bars); - for (i =[subviews count]-1; i >= 0; i--) + for (i = [subviews count]-1; i >= 0; --i) { view = [subviews objectAtIndex: i]; if (![view isKindOfClass: [EmacsScroller class]]) continue; [view judge]; + removed = YES; } + + if (removed) + [eview updateFrameSize: NO]; } @@ -3963,11 +3888,11 @@ ns_delete_terminal (struct terminal *terminal) if (!terminal->name) return; - BLOCK_INPUT; + block_input (); x_destroy_all_bitmaps (dpyinfo); ns_delete_display (dpyinfo); - UNBLOCK_INPUT; + unblock_input (); } @@ -4004,7 +3929,7 @@ ns_create_terminal (struct ns_display_info *dpyinfo) terminal->frame_rehighlight_hook = ns_frame_rehighlight; terminal->frame_raise_lower_hook = ns_frame_raise_lower; - terminal->fullscreen_hook = 0; /* see XTfullscreen_hook */ + terminal->fullscreen_hook = ns_fullscreen_hook; terminal->set_vertical_scroll_bar_hook = ns_set_vertical_scroll_bar; terminal->condemn_scroll_bars_hook = ns_condemn_scroll_bars; @@ -4035,33 +3960,34 @@ ns_term_init (Lisp_Object display_name) static int ns_initialized = 0; Lisp_Object tmp; + if (ns_initialized) return x_display_list; + ns_initialized = 1; + NSTRACE (ns_term_init); + [outerpool release]; + outerpool = [[NSAutoreleasePool alloc] init]; + /* count object allocs (About, click icon); on OS X use ObjectAlloc tool */ /*GSDebugAllocationActive (YES); */ - BLOCK_INPUT; - handling_signal = 0; + block_input (); - if (!ns_initialized) - { - baud_rate = 38400; - Fset_input_interrupt_mode (Qnil); + baud_rate = 38400; + Fset_input_interrupt_mode (Qnil); - if (selfds[0] == -1) + if (selfds[0] == -1) + { + if (pipe (selfds) == -1) { - if (pipe (selfds) == -1) - { - fprintf (stderr, "Failed to create pipe: %s\n", - emacs_strerror (errno)); - abort (); - } - - fcntl (selfds[0], F_SETFL, O_NONBLOCK|fcntl (selfds[0], F_GETFL)); - FD_ZERO (&select_readfds); - FD_ZERO (&select_writefds); - pthread_mutex_init (&select_mutex, NULL); + fprintf (stderr, "Failed to create pipe: %s\n", + emacs_strerror (errno)); + emacs_abort (); } - ns_initialized = 1; + + fcntl (selfds[0], F_SETFL, O_NONBLOCK|fcntl (selfds[0], F_GETFL)); + FD_ZERO (&select_readfds); + FD_ZERO (&select_writefds); + pthread_mutex_init (&select_mutex, NULL); } ns_pending_files = [[NSMutableArray alloc] init]; @@ -4113,7 +4039,7 @@ ns_term_init (Lisp_Object display_name) terminal->name = xstrdup (SSDATA (display_name)); - UNBLOCK_INPUT; + unblock_input (); if (!inhibit_x_resources) { @@ -4252,6 +4178,25 @@ ns_term_init (Lisp_Object display_name) } #endif /* MAC OS X menu setup */ + /* Register our external input/output types, used for determining + applicable services and also drag/drop eligibility. */ + ns_send_types = [[NSArray arrayWithObjects: NSStringPboardType, nil] retain]; + ns_return_types = [[NSArray arrayWithObjects: NSStringPboardType, nil] + retain]; + ns_drag_types = [[NSArray arrayWithObjects: + NSStringPboardType, + NSTabularTextPboardType, + NSFilenamesPboardType, + NSURLPboardType, + NSColorPboardType, + NSFontPboardType, nil] retain]; + +#ifndef NEW_STYLE_FS + /* If fullscreen is in init/default-frame-alist, focus isn't set + right for fullscreen windows, so set this. */ + [NSApp activateIgnoringOtherApps:YES]; +#endif + [NSApp run]; ns_do_open_file = YES; return dpyinfo; @@ -4273,7 +4218,7 @@ ns_term_shutdown (int sig) } else // force a stack trace to happen { - abort(); + emacs_abort (); } } @@ -4323,34 +4268,6 @@ ns_term_shutdown (int sig) return; } -#ifdef NS_IMPL_COCOA - /* pass mouse down in resize handle and subsequent drags directly to - EmacsWindow so we can generate continuous redisplays */ - if (ns_in_resize) - { - if (type == NSLeftMouseDragged) - { - [window mouseDragged: theEvent]; - return; - } - else if (type == NSLeftMouseUp) - { - [window mouseUp: theEvent]; - return; - } - } - else if (type == NSLeftMouseDown) - { - NSRect r = ns_resize_handle_rect (window); - if (NSPointInRect ([theEvent locationInWindow], r)) - { - ns_in_resize = YES; - [window mouseDown: theEvent]; - return; - } - } -#endif - if (type == NSApplicationDefined) { /* Events posted by ns_send_appdefined interrupt the run loop here. @@ -4534,10 +4451,10 @@ not_in_argv (NSString *arg) /* Don't open files from the command line unconditionally, Cocoa parses the command line wrong, --option value tries to open value if --option is the last option. */ - while ((file = [files nextObject]) != nil) + while ((file = [files nextObject]) != nil) if (ns_do_open_file || not_in_argv (file)) [ns_pending_files addObject: file]; - + [self replyToOpenOrPrint: NSApplicationDelegateReplySuccess]; } @@ -4604,7 +4521,7 @@ not_in_argv (NSString *arg) /* NSTRACE (fd_handler); */ - for (;;) + for (;;) { [pool release]; pool = [[NSAutoreleasePool alloc] init]; @@ -4744,6 +4661,8 @@ not_in_argv (NSString *arg) { NSTRACE (EmacsView_dealloc); [toolbar release]; + if (fs_state == FULLSCREEN_BOTH) + [nonfs_window release]; [super dealloc]; } @@ -4889,7 +4808,7 @@ not_in_argv (NSString *arg) is_right_key = (flags & NSRightCommandKeyMask) == NSRightCommandKeyMask; is_left_key = (flags & NSLeftCommandKeyMask) == NSLeftCommandKeyMask || (! is_right_key && (flags & NSCommandKeyMask) == NSCommandKeyMask); - + if (is_right_key) emacs_event->modifiers |= parse_solitary_modifier (EQ (ns_right_command_modifier, Qleft) @@ -5420,6 +5339,51 @@ not_in_argv (NSString *arg) return NO; } +- (void) updateFrameSize: (BOOL) delay; +{ + NSWindow *window = [self window]; + NSRect wr = [window frame]; +#ifdef NS_IMPL_GNUSTEP + int extra = 3; +#else + int extra = 0; +#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 + extra); + + if (cols < MINWIDTH) + cols = MINWIDTH; + + rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES + (emacsframe, wr.size.height + - FRAME_NS_TITLEBAR_HEIGHT (emacsframe) + extra + - FRAME_TOOLBAR_HEIGHT (emacsframe)); + + if (rows < MINHEIGHT) + rows = MINHEIGHT; + + neww = (int)wr.size.width - emacsframe->border_width; + newh = ((int)wr.size.height + - FRAME_NS_TITLEBAR_HEIGHT (emacsframe) + - FRAME_TOOLBAR_HEIGHT (emacsframe)); + + if (oldr != rows || oldc != cols || neww != oldw || newh != oldh) + { + NSView *view = FRAME_NS_VIEW (emacsframe); + FRAME_PIXEL_WIDTH (emacsframe) = neww; + FRAME_PIXEL_HEIGHT (emacsframe) = newh; + change_frame_size (emacsframe, rows, cols, 0, delay, 0); + SET_FRAME_GARBAGED (emacsframe); + cancel_mouse_face (emacsframe); + [view setFrame: NSMakeRect (0, 0, neww, newh)]; + [self windowDidMove:nil]; // Update top/left. + } +} - (NSSize)windowWillResize: (NSWindow *)sender toSize: (NSSize)frameSize /* normalize frame to gridded text size */ @@ -5427,6 +5391,19 @@ not_in_argv (NSString *arg) NSTRACE (windowWillResize); /*fprintf (stderr,"Window will resize: %.0f x %.0f\n",frameSize.width,frameSize.height); */ + if (fs_state == FULLSCREEN_MAXIMIZED + && (maximized_width != (int)frameSize.width + || maximized_height != (int)frameSize.height)) + [self setFSValue: FULLSCREEN_NONE]; + else if (fs_state == FULLSCREEN_WIDTH + && maximized_width != (int)frameSize.width) + [self setFSValue: FULLSCREEN_NONE]; + else if (fs_state == FULLSCREEN_HEIGHT + && maximized_height != (int)frameSize.height) + [self setFSValue: FULLSCREEN_NONE]; + if (fs_state == FULLSCREEN_NONE) + maximized_width = maximized_height = -1; + cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (emacsframe, #ifdef NS_IMPL_GNUSTEP frameSize.width + 3); @@ -5486,10 +5463,17 @@ not_in_argv (NSString *arg) - (void)windowDidResize: (NSNotification *)notification { + +#if !defined (NEW_STYLE_FS) && ! defined (NS_IMPL_GNUSTEP) + NSWindow *theWindow = [notification object]; + /* We can get notification on the non-FS window when in fullscreen mode. */ + if ([self window] != theWindow) return; +#endif + #ifdef NS_IMPL_GNUSTEP NSWindow *theWindow = [notification object]; - /* in GNUstep, at least currently, it's possible to get a didResize + /* In GNUstep, at least currently, it's possible to get a didResize without getting a willResize.. therefore we need to act as if we got the willResize now */ NSSize sz = [theWindow frame].size; @@ -5507,29 +5491,10 @@ not_in_argv (NSString *arg) } #endif /* NS_IMPL_COCOA */ - /* Avoid loop under GNUstep due to call at beginning of this function. - (x_set_window_size causes a resize which causes - a "windowDidResize" which calls x_set_window_size). */ -#ifndef NS_IMPL_GNUSTEP if (cols > 0 && rows > 0) { - 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); - } + [self updateFrameSize: YES]; } -#endif ns_send_appdefined (-1); } @@ -5617,6 +5582,10 @@ not_in_argv (NSString *arg) windowClosing = NO; processingCompose = NO; scrollbarsNeedingUpdate = 0; + fs_state = FULLSCREEN_NONE; + fs_before_fs = next_maximized = -1; + maximized_width = maximized_height = -1; + nonfs_window = nil; /*fprintf (stderr,"init with %d, %d\n",f->text_cols, f->text_lines); */ @@ -5641,9 +5610,13 @@ not_in_argv (NSString *arg) backing: NSBackingStoreBuffered defer: YES]; +#ifdef NEW_STYLE_FS + [win setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary]; +#endif + wr = [win frame]; - f->border_width = wr.size.width - r.size.width; - FRAME_NS_TITLEBAR_HEIGHT (f) = wr.size.height - r.size.height; + bwidth = f->border_width = wr.size.width - r.size.width; + tibar_height = FRAME_NS_TITLEBAR_HEIGHT (f) = wr.size.height - r.size.height; [win setAcceptsMouseMovedEvents: YES]; [win setDelegate: self]; @@ -5749,27 +5722,50 @@ not_in_argv (NSString *arg) NSTRACE (windowWillUseStandardFrame); - if (abs (defaultFrame.size.height - result.size.height) - > FRAME_LINE_HEIGHT (emacsframe)) + if (fs_before_fs != -1) /* Entering fullscreen */ + { + result = defaultFrame; + } + else if (next_maximized == FULLSCREEN_HEIGHT + || (next_maximized == -1 + && abs (defaultFrame.size.height - result.size.height) + > FRAME_LINE_HEIGHT (emacsframe))) { /* first click */ ns_userRect = result; - result.size.height = defaultFrame.size.height; + maximized_height = result.size.height = defaultFrame.size.height; + maximized_width = -1; result.origin.y = defaultFrame.origin.y; + [self setFSValue: FULLSCREEN_HEIGHT]; + } + else if (next_maximized == FULLSCREEN_WIDTH) + { + ns_userRect = result; + maximized_width = result.size.width = defaultFrame.size.width; + maximized_height = -1; + result.origin.x = defaultFrame.origin.x; + [self setFSValue: FULLSCREEN_WIDTH]; + } + else if (next_maximized == FULLSCREEN_MAXIMIZED + || (next_maximized == -1 + && abs (defaultFrame.size.width - result.size.width) + > FRAME_COLUMN_WIDTH (emacsframe))) + { + result = defaultFrame; /* second click */ + maximized_width = result.size.width; + maximized_height = result.size.height; + [self setFSValue: FULLSCREEN_MAXIMIZED]; } else { - if (abs (defaultFrame.size.width - result.size.width) - > FRAME_COLUMN_WIDTH (emacsframe)) - result = defaultFrame; /* second click */ - else - { - /* restore */ - result = ns_userRect.size.height ? ns_userRect : result; - ns_userRect = NSMakeRect (0, 0, 0, 0); - } + /* restore */ + result = ns_userRect.size.height ? ns_userRect : result; + ns_userRect = NSMakeRect (0, 0, 0, 0); + [self setFSValue: FULLSCREEN_NONE]; + maximized_width = maximized_width = -1; } + if (fs_before_fs == -1) next_maximized = -1; [self windowWillResize: sender toSize: result.size]; return result; } @@ -5821,6 +5817,211 @@ not_in_argv (NSString *arg) } } +- (void)windowWillEnterFullScreen:(NSNotification *)notification +{ + fs_before_fs = fs_state; +} + +- (void)windowDidEnterFullScreen:(NSNotification *)notification +{ + [self setFSValue: FULLSCREEN_BOTH]; +#ifdef NEW_STYLE_FS + // Fix bad background. + if ([toolbar isVisible]) + { + [toolbar setVisible:NO]; + [toolbar setVisible:YES]; + } +#else + [self windowDidBecomeKey:notification]; + [nonfs_window orderOut:self]; +#endif +} + +- (void)windowWillExitFullScreen:(NSNotification *)notification +{ + if (next_maximized != -1) + fs_before_fs = next_maximized; +} + +- (void)windowDidExitFullScreen:(NSNotification *)notification +{ + [self setFSValue: fs_before_fs]; + fs_before_fs = -1; + if (next_maximized != -1) + [[self window] performZoom:self]; +} + +- (void)toggleFullScreen: (id)sender +{ +#ifdef NEW_STYLE_FS + [[self window] toggleFullScreen:sender]; +#else + NSWindow *w = [self window], *fw; + BOOL onFirstScreen = [[w screen] + isEqual:[[NSScreen screens] objectAtIndex:0]]; + struct frame *f = emacsframe; + NSSize sz; + NSRect r, wr = [w frame]; + NSColor *col = ns_lookup_indexed_color (NS_FACE_BACKGROUND + (FRAME_DEFAULT_FACE (f)), + f); + + sz.width = FRAME_COLUMN_WIDTH (f); + sz.height = FRAME_LINE_HEIGHT (f); + + if (fs_state != FULLSCREEN_BOTH) + { + /* Hide dock and menubar if we are on the primary screen. */ + if (onFirstScreen) + { +#if defined (NS_IMPL_COCOA) && \ + MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 + NSApplicationPresentationOptions options + = NSApplicationPresentationAutoHideDock + | NSApplicationPresentationAutoHideMenuBar; + + [NSApp setPresentationOptions: options]; +#else + [NSMenu setMenuBarVisible:NO]; +#endif + } + + fw = [[EmacsFSWindow alloc] + initWithContentRect:[w contentRectForFrameRect:wr] + styleMask:NSBorderlessWindowMask + backing:NSBackingStoreBuffered + defer:YES + screen:[w screen]]; + + [fw setContentView:[w contentView]]; + [fw setTitle:[w title]]; + [fw setDelegate:self]; + [fw setAcceptsMouseMovedEvents: YES]; + [fw useOptimizedDrawing: YES]; + [fw setResizeIncrements: sz]; + [fw setBackgroundColor: col]; + if ([col alphaComponent] != 1.0) + [fw setOpaque: NO]; + + f->border_width = 0; + FRAME_NS_TITLEBAR_HEIGHT (f) = 0; + tobar_height = FRAME_TOOLBAR_HEIGHT (f); + FRAME_TOOLBAR_HEIGHT (f) = 0; + FRAME_EXTERNAL_TOOL_BAR (f) = 0; + + nonfs_window = w; + + [self windowWillEnterFullScreen:nil]; + [fw makeKeyAndOrderFront:NSApp]; + [fw makeFirstResponder:self]; + [w orderOut:self]; + r = [fw frameRectForContentRect:[[fw screen] frame]]; + [fw setFrame: r display:YES animate:YES]; + [self windowDidEnterFullScreen:nil]; + [fw display]; + } + else + { + fw = w; + w = nonfs_window; + nonfs_window = nil; + + if (onFirstScreen) + { +#if defined (NS_IMPL_COCOA) && \ + MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 + [NSApp setPresentationOptions: NSApplicationPresentationDefault]; +#else + [NSMenu setMenuBarVisible:YES]; +#endif + } + + [w setContentView:[fw contentView]]; + [w setResizeIncrements: sz]; + [w setBackgroundColor: col]; + if ([col alphaComponent] != 1.0) + [w setOpaque: NO]; + + f->border_width = bwidth; + FRAME_NS_TITLEBAR_HEIGHT (f) = tibar_height; + FRAME_TOOLBAR_HEIGHT (f) = tobar_height; + if (tobar_height) + FRAME_EXTERNAL_TOOL_BAR (f) = 1; + + [self windowWillExitFullScreen:nil]; + [fw setFrame: [w frame] display:YES animate:YES]; + [fw close]; + [w makeKeyAndOrderFront:NSApp]; + [self windowDidExitFullScreen:nil]; + } +#endif +} + +- (void)handleFS +{ + if (fs_state != emacsframe->want_fullscreen) + { + if (fs_state == FULLSCREEN_BOTH) + { + [self toggleFullScreen:self]; + } + + switch (emacsframe->want_fullscreen) + { + case FULLSCREEN_BOTH: + [self toggleFullScreen:self]; + break; + case FULLSCREEN_WIDTH: + next_maximized = FULLSCREEN_WIDTH; + if (fs_state != FULLSCREEN_BOTH) + [[self window] performZoom:self]; + break; + case FULLSCREEN_HEIGHT: + next_maximized = FULLSCREEN_HEIGHT; + if (fs_state != FULLSCREEN_BOTH) + [[self window] performZoom:self]; + break; + case FULLSCREEN_MAXIMIZED: + next_maximized = FULLSCREEN_MAXIMIZED; + if (fs_state != FULLSCREEN_BOTH) + [[self window] performZoom:self]; + break; + case FULLSCREEN_NONE: + if (fs_state != FULLSCREEN_BOTH) + { + next_maximized = FULLSCREEN_NONE; + [[self window] performZoom:self]; + } + break; + } + + emacsframe->want_fullscreen = FULLSCREEN_NONE; + } + +} + +- (void) setFSValue: (int)value +{ + Lisp_Object lval = Qnil; + switch (value) + { + case FULLSCREEN_BOTH: + lval = Qfullboth; + break; + case FULLSCREEN_WIDTH: + lval = Qfullwidth; + break; + case FULLSCREEN_HEIGHT: + lval = Qfullheight; + break; + case FULLSCREEN_MAXIMIZED: + lval = Qmaximized; + break; + } + store_frame_param (emacsframe, Qfullscreen, lval); + fs_state = value; +} - (void)mouseEntered: (NSEvent *)theEvent { @@ -5853,7 +6054,7 @@ not_in_argv (NSString *arg) NSTRACE (menuDown); if (context_menu_value == -1) context_menu_value = [sender tag]; - else + else { NSInteger tag = [sender tag]; find_and_call_menu_selection (emacsframe, emacsframe->menu_bar_items_used, @@ -5918,7 +6119,7 @@ not_in_argv (NSString *arg) NSTRACE (drawRect); - if (!emacsframe || !emacsframe->output_data.ns || ns_in_resize) + if (!emacsframe || !emacsframe->output_data.ns) return; ns_clear_frame_area (emacsframe, x, y, width, height); @@ -6180,7 +6381,7 @@ not_in_argv (NSString *arg) Lisp_Object str = Qnil; struct frame *f = SELECTED_FRAME (); struct buffer *curbuf = XBUFFER (XWINDOW (f->selected_window)->buffer); - + if ([attribute isEqualToString:NSAccessibilityRoleAttribute]) return NSAccessibilityTextFieldRole; @@ -6193,13 +6394,13 @@ not_in_argv (NSString *arg) { if (! NILP (BVAR (curbuf, mark_active))) str = ns_get_local_selection (QPRIMARY, QUTF8_STRING); - + if (NILP (str)) { ptrdiff_t start_byte = BUF_BEGV_BYTE (curbuf); ptrdiff_t byte_range = BUF_ZV_BYTE (curbuf) - start_byte; ptrdiff_t range = BUF_ZV (curbuf) - BUF_BEGV (curbuf); - + if (! NILP (BVAR (curbuf, enable_multibyte_characters))) str = make_uninit_multibyte_string (range, byte_range); else @@ -6209,9 +6410,9 @@ not_in_argv (NSString *arg) memcpy (SDATA (str), BYTE_POS_ADDR (start_byte), byte_range); } } - - - if (! NILP (str)) + + + if (! NILP (str)) { if (CONSP (str) && SYMBOLP (XCAR (str))) { @@ -6226,7 +6427,7 @@ not_in_argv (NSString *arg) return nsStr; } } - + return [super accessibilityAttributeValue:attribute]; } #endif /* NS_IMPL_COCOA */ @@ -6242,7 +6443,10 @@ not_in_argv (NSString *arg) NSTRACE (constrainFrameRect); if (nr_screens == 1) - return [super constrainFrameRect:frameRect toScreen:screen]; + { + NSRect r = [super constrainFrameRect:frameRect toScreen:screen]; + return r; + } if (f->output_data.ns->dont_constrain || ns_menu_bar_should_be_hidden ()) @@ -6252,62 +6456,22 @@ not_in_argv (NSString *arg) return [super constrainFrameRect:frameRect toScreen:screen]; } +@end /* EmacsWindow */ -/* called only on resize clicks by special case in EmacsApp-sendEvent */ -- (void)mouseDown: (NSEvent *)theEvent -{ - if (ns_in_resize) - { - NSSize size = [[theEvent window] frame].size; - grabOffset = [theEvent locationInWindow]; - grabOffset.x = size.width - grabOffset.x; - } - else - [super mouseDown: theEvent]; -} +@implementation EmacsFSWindow -/* stop resizing */ -- (void)mouseUp: (NSEvent *)theEvent +- (BOOL)canBecomeKeyWindow { - if (ns_in_resize) - { - struct frame *f = ((EmacsView *)[self delegate])->emacsframe; - ns_in_resize = NO; - ns_set_name_as_filename (f); - [self display]; - ns_send_appdefined (-1); - } - else - [super mouseUp: theEvent]; + return YES; } - -/* send resize events */ -- (void)mouseDragged: (NSEvent *)theEvent +- (BOOL)canBecomeMainWindow { - if (ns_in_resize) - { - NSPoint p = [theEvent locationInWindow]; - NSSize size, vettedSize, origSize = [self frame].size; - - size.width = p.x + grabOffset.x; - size.height = origSize.height - p.y + grabOffset.y; - - if (size.width == origSize.width && size.height == origSize.height) - return; - - vettedSize = [[self delegate] windowWillResize: self toSize: size]; - [[NSNotificationCenter defaultCenter] - postNotificationName: NSWindowDidResizeNotification - object: self]; - } - else - [super mouseDragged: theEvent]; + return YES; } -@end /* EmacsWindow */ - +@end /* ========================================================================== @@ -6379,13 +6543,13 @@ not_in_argv (NSString *arg) - (void)setFrame: (NSRect)newRect { NSTRACE (EmacsScroller_setFrame); -/* BLOCK_INPUT; */ +/* block_input (); */ pixel_height = NSHeight (newRect); if (pixel_height == 0) pixel_height = 1; min_portion = 20 / pixel_height; [super setFrame: newRect]; [self display]; -/* UNBLOCK_INPUT; */ +/* unblock_input (); */ } @@ -6420,14 +6584,14 @@ not_in_argv (NSString *arg) if (condemned) { EmacsView *view; - BLOCK_INPUT; + block_input (); /* ensure other scrollbar updates after deletion */ view = (EmacsView *)FRAME_NS_VIEW (frame); if (view != nil) view->scrollbarsNeedingUpdate++; [self removeFromSuperview]; [self release]; - UNBLOCK_INPUT; + unblock_input (); } return self; } @@ -6922,7 +7086,7 @@ allowing it to be used at a lower level for accented character entry."); ns_function_modifier = Qnone; DEFVAR_LISP ("ns-antialias-text", ns_antialias_text, - "Non-nil (the default) means to render text antialiased. Only has an effect on OS X Panther and above."); + "Non-nil (the default) means to render text antialiased."); ns_antialias_text = Qt; DEFVAR_LISP ("ns-confirm-quit", ns_confirm_quit,