X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/40e727619ad0e815dab636a6a969862cee9a0638..ab422c4d6899b1442cb6954c1829c1fb656b006c:/src/nsterm.m diff --git a/src/nsterm.m b/src/nsterm.m index fde02f3ec9..d9ebf714a9 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-2012 - Free Software Foundation, Inc. +Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2013 Free Software +Foundation, Inc. This file is part of GNU Emacs. @@ -35,8 +35,14 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu) #include #include #include -#include + +#include #include +#include + +#ifdef HAVE_FCNTL_H +#include +#endif #include "lisp.h" #include "blockinput.h" @@ -49,12 +55,11 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu) #include "ccl.h" #include "termhooks.h" -#include "termopts.h" #include "termchar.h" #include "window.h" #include "keyboard.h" - +#include "buffer.h" #include "font.h" /* call tracing */ @@ -66,6 +71,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; /* ========================================================================== @@ -138,7 +148,7 @@ static unsigned convert_ns_to_X_keysym[] = }; static Lisp_Object Qmodifier_value; -Lisp_Object Qalt, Qcontrol, Qhyper, Qmeta, Qsuper, Qnone; +Lisp_Object Qalt, Qcontrol, Qhyper, Qmeta, Qsuper; extern Lisp_Object Qcursor_color, Qcursor_type, Qns, Qleft; static Lisp_Object QUTF8_STRING; @@ -168,9 +178,10 @@ static EmacsScroller *last_mouse_scroll_bar = nil; static struct frame *ns_updating_frame; static NSView *focus_view = NULL; static int ns_window_num = 0; +#ifdef NS_IMPL_GNUSTEP 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 */ @@ -179,19 +190,31 @@ static BOOL ns_menu_bar_is_hidden = NO; /* event loop */ static BOOL send_appdefined = YES; -static NSEvent *last_appdefined_event = 0; +#define NO_APPDEFINED_DATA (-8) +static int last_appdefined_event_data = NO_APPDEFINED_DATA; static NSTimer *timed_entry = 0; -static NSTimer *fd_entry = nil; static NSTimer *scroll_repeat_entry = nil; -static fd_set select_readfds, t_readfds; -static int select_nfds; +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 int selfds[2] = { -1, -1 }; +static pthread_mutex_t select_mutex; +static int apploopnr = 0; static NSAutoreleasePool *outerpool; static struct input_event *emacs_event = NULL; static struct input_event *q_event_ptr = NULL; static int n_emacs_events_pending = 0; static NSMutableArray *ns_pending_files, *ns_pending_service_names, *ns_pending_service_args; -static BOOL inNsSelect = 0; +static BOOL ns_do_open_file = NO; + +static struct { + struct input_event *q; + int nr, cap; +} hold_event_q = { + NULL, 0, 0 +}; /* Convert modifiers in a NeXTstep event to emacs style modifiers. */ #define NS_FUNCTION_KEY_MASK 0x800000 @@ -248,15 +271,20 @@ static BOOL inNsSelect = 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); \ - if (e) emacs_event->timestamp = EV_TIMESTAMP (e); \ - n_emacs_events_pending++; \ - kbd_buffer_store_event_hold (emacs_event, q_event_ptr); \ - EVENT_INIT (*emacs_event); \ - ns_send_appdefined (-1); \ - } +#define EV_TRAILER(e) \ + { \ + XSETFRAME (emacs_event->frame_or_window, emacsframe); \ + if (e) emacs_event->timestamp = EV_TIMESTAMP (e); \ + if (q_event_ptr) \ + { \ + n_emacs_events_pending++; \ + kbd_buffer_store_event_hold (emacs_event, q_event_ptr); \ + } \ + else \ + hold_event (emacs_event); \ + EVENT_INIT (*emacs_event); \ + ns_send_appdefined (-1); \ + } void x_set_cursor_type (struct frame *, Lisp_Object, Lisp_Object); @@ -272,6 +300,22 @@ void x_set_frame_alpha (struct frame *f); ========================================================================== */ +static void +hold_event (struct input_event *event) +{ + if (hold_event_q.nr == hold_event_q.cap) + { + 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[hold_event_q.nr++] = *event; + /* Make sure ns_read_socket is called, i.e. we have input. */ + kill (0, SIGIO); + send_appdefined = YES; +} static Lisp_Object append2 (Lisp_Object list, Lisp_Object item) @@ -325,8 +369,7 @@ ns_exec_path (void) NSString *binDir = [bundle bundlePath]; NSString *resourcePath, *resourcePaths; NSRange range; - BOOL onWindows = NO; /* FIXME determine this somehow */ - NSString *pathSeparator = onWindows ? @";" : @":"; + NSString *pathSeparator = [NSString stringWithFormat: @"%c", SEPCHAR]; NSFileManager *fileManager = [NSFileManager defaultManager]; NSArray *paths; NSEnumerator *pathEnum; @@ -346,7 +389,7 @@ ns_exec_path (void) pathEnum = [paths objectEnumerator]; resourcePaths = @""; - while (resourcePath = [pathEnum nextObject]) + while ((resourcePath = [pathEnum nextObject])) { if ([fileManager fileExistsAtPath: resourcePath isDirectory: &isDir]) if (isDir) @@ -373,8 +416,7 @@ ns_load_path (void) NSBundle *bundle = [NSBundle mainBundle]; NSString *resourceDir = [bundle resourcePath]; NSString *resourcePath, *resourcePaths; - BOOL onWindows = NO; /* FIXME determine this somehow */ - NSString *pathSeparator = onWindows ? @";" : @":"; + NSString *pathSeparator = [NSString stringWithFormat: @"%c", SEPCHAR]; NSFileManager *fileManager = [NSFileManager defaultManager]; BOOL isDir; NSArray *paths = [resourceDir stringsByAppendingPaths: @@ -386,7 +428,7 @@ ns_load_path (void) /* Hack to skip site-lisp. */ if (no_site_lisp) resourcePath = [pathEnum nextObject]; - while (resourcePath = [pathEnum nextObject]) + while ((resourcePath = [pathEnum nextObject])) { if ([fileManager fileExistsAtPath: resourcePath isDirectory: &isDir]) if (isDir) @@ -409,21 +451,16 @@ ns_timeout (int usecs) Blocking timer utility used by ns_ring_bell -------------------------------------------------------------------------- */ { - EMACS_TIME wakeup, delay; - - EMACS_GET_TIME (wakeup); - EMACS_SET_SECS_USECS (delay, 0, usecs); - EMACS_ADD_TIME (wakeup, wakeup, delay); + EMACS_TIME wakeup = add_emacs_time (current_emacs_time (), + make_emacs_time (0, usecs * 1000)); /* Keep waiting until past the time wakeup. */ while (1) { - EMACS_TIME timeout; - - EMACS_GET_TIME (timeout); - if (EMACS_TIME_LE (wakeup, timeout)) + EMACS_TIME timeout, now = current_emacs_time (); + if (EMACS_TIME_LE (wakeup, now)) break; - EMACS_SUB_TIME (timeout, wakeup, timeout); + timeout = sub_emacs_time (wakeup, now); /* Try to wait that long--but we might wake up sooner. */ pselect (0, NULL, NULL, NULL, &timeout, NULL); @@ -478,17 +515,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 // ------------------- @@ -566,12 +592,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); @@ -602,7 +625,7 @@ ns_update_auto_hide_menu_bar (void) } } - UNBLOCK_INPUT; + unblock_input (); #endif #endif } @@ -616,6 +639,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 (); @@ -623,6 +648,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 @@ -639,11 +672,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) { @@ -658,7 +690,7 @@ ns_update_window_begin (struct window *w) /* (further code for mouse faces ifdef'd out in other terms elided) */ } - UNBLOCK_INPUT; + unblock_input (); } @@ -675,7 +707,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, @@ -685,7 +717,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 @@ -714,7 +746,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 */ @@ -726,7 +758,7 @@ ns_update_end (struct frame *f) [view unlockFocus]; [[view window] flushWindow]; - UNBLOCK_INPUT; + unblock_input (); ns_updating_frame = NULL; NSTRACE (ns_update_end); } @@ -860,25 +892,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); } @@ -896,7 +915,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); @@ -923,7 +942,7 @@ ns_ring_bell (struct frame *f) ns_unfocus (frame); } [pool release]; - UNBLOCK_INPUT; + unblock_input (); } else { @@ -964,13 +983,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 (); } @@ -982,9 +1001,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 (); } @@ -1021,7 +1040,7 @@ ns_frame_rehighlight (struct frame *frame) : dpyinfo->x_focus_frame); if (!FRAME_LIVE_P (dpyinfo->x_highlight_frame)) { - FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil; + fset_focus_frame (dpyinfo->x_focus_frame, Qnil); dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame; } } @@ -1057,8 +1076,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 (); + } } } @@ -1115,12 +1149,12 @@ x_free_frame_resources (struct frame *f) NSView *view = FRAME_NS_VIEW (f); struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (f); Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f); - NSTRACE (x_destroy_window); + NSTRACE (x_free_frame_resources); check_ns (); [(EmacsView *)view setWindowClosing: YES]; /* may not have been informed */ - BLOCK_INPUT; + block_input (); free_frame_menubar (f); @@ -1148,7 +1182,7 @@ x_free_frame_resources (struct frame *f) xfree (f->output_data.ns); - UNBLOCK_INPUT; + unblock_input (); } void @@ -1177,7 +1211,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; @@ -1209,7 +1243,7 @@ x_set_offset (struct frame *f, int xoff, int yoff, int change_grav) f->size_hint_flags &= ~(XNegative|YNegative); } - UNBLOCK_INPUT; + unblock_input (); } @@ -1222,36 +1256,21 @@ x_set_window_size (struct frame *f, int change_grav, int cols, int rows) -------------------------------------------------------------------------- */ { EmacsView *view = FRAME_NS_VIEW (f); - EmacsToolbar *toolbar = [view toolbar]; NSWindow *window = [view window]; 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); @@ -1311,10 +1330,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 (); +} /* ========================================================================== @@ -1423,7 +1465,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"]) { @@ -1442,21 +1484,16 @@ ns_get_color (const char *name, NSColor **col) [scanner scanFloat: &b]; } else if (!strncmp(name, "rgb:", 4)) /* A newer X11 format -- rgb:r/g/b */ - { - strncpy (hex, name + 4, 19); - hex[19] = '\0'; - scaling = (strlen(hex) - 2) / 3; - } + scaling = (snprintf (hex, sizeof hex, "%s", name + 4) - 2) / 3; else if (name[0] == '#') /* An old X11 format; convert to newer */ { int len = (strlen(name) - 1); int start = (len % 3 == 0) ? 1 : len / 4 + 1; int i; scaling = strlen(name+start) / 3; - for (i=0; i<3; i++) { - strncpy(hex + i * (scaling + 1), name + start + i * scaling, scaling); - hex[(i+1) * (scaling + 1) - 1] = '/'; - } + for (i = 0; i < 3; i++) + sprintf (hex + i * (scaling + 1), "%.*s/", scaling, + name + start + i * scaling); hex[3 * (scaling + 1) - 1] = '\0'; } @@ -1475,7 +1512,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; } @@ -1507,26 +1544,11 @@ ns_get_color (const char *name, NSColor **col) if (new) *col = [new colorUsingColorSpaceName: NSCalibratedRGBColorSpace]; - UNBLOCK_INPUT; + unblock_input (); return new ? 0 : 1; } -static NSColor * -ns_get_color_default (const char *name, NSColor *dflt) -/* -------------------------------------------------------------------------- - Parse a color or use a default value - -------------------------------------------------------------------------- */ -{ - NSColor * col; - - if (ns_get_color (name, &col)) - return dflt; - else - return col; -} - - int ns_lisp_to_color (Lisp_Object color, NSColor **col) /* -------------------------------------------------------------------------- @@ -1535,9 +1557,9 @@ ns_lisp_to_color (Lisp_Object color, NSColor **col) { NSTRACE (ns_lisp_to_color); if (STRINGP (color)) - return ns_get_color (SDATA (color), col); + return ns_get_color (SSDATA (color), col); else if (SYMBOLP (color)) - return ns_get_color (SDATA (SYMBOL_NAME (color)), col); + return ns_get_color (SSDATA (SYMBOL_NAME (color)), col); return 1; } @@ -1553,12 +1575,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); } @@ -1570,14 +1592,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); } @@ -1604,33 +1626,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; } @@ -1782,7 +1804,6 @@ ns_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, { id view; NSPoint position; - int xchar, ychar; Lisp_Object frame, tail; struct frame *f; struct ns_display_info *dpyinfo; @@ -1797,7 +1818,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) { @@ -1842,7 +1863,7 @@ ns_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, } } - UNBLOCK_INPUT; + unblock_input (); } @@ -1862,7 +1883,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, @@ -1870,13 +1891,13 @@ 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 (); } } } -void +static void ns_define_frame_cursor (struct frame *f, Cursor cursor) /* -------------------------------------------------------------------------- External (RIF): set frame mouse pointer type. @@ -1950,7 +1971,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]; @@ -1970,8 +1991,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 */ @@ -1985,23 +2004,19 @@ 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 (); } -void +static void ns_clear_frame_area (struct frame *f, int x, int y, int width, int height) /* -------------------------------------------------------------------------- External (RIF): Clear section of frame @@ -2020,35 +2035,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; } @@ -2098,7 +2086,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); @@ -2113,7 +2101,7 @@ ns_scroll_run (struct window *w, struct run *run) ns_unfocus (f); } - UNBLOCK_INPUT; + unblock_input (); } @@ -2136,9 +2124,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) @@ -2147,25 +2135,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 (); } } @@ -2198,14 +2173,13 @@ 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 -------------------------------------------------------------------------- */ { - struct face *face = FACE_FROM_ID (s->f, s->first_glyph->face_id); - struct font *font = s->font; /*face->font; */ + struct font *font = s->font; if (s->char2b) { @@ -2250,17 +2224,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) @@ -2275,23 +2238,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); - NSPoint pt = r.origin; + NSRect r = NSMakeRect (p->x, p->y, p->wd, p->h); EmacsImage *img = bimgs[p->which - 1]; if (!img) @@ -2301,7 +2309,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]; @@ -2314,15 +2322,27 @@ ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row, to erase the whole background. */ [ns_lookup_indexed_color(face->background, f) set]; NSRectFill (r); - pt.y += p->h; [img setXBMColor: ns_lookup_indexed_color(face->foreground, f)]; - [img compositeToPoint: pt operation: NSCompositeSourceOver]; +#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); } -void +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) @@ -2395,14 +2415,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 */ @@ -2495,12 +2507,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 (); } @@ -2510,12 +2522,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 (); } @@ -2526,31 +2538,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) /* -------------------------------------------------------------------------- @@ -2560,14 +2547,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; } @@ -2892,11 +2871,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) { @@ -2952,26 +2926,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); } @@ -3037,30 +2991,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 compositeToPoint: NSMakePoint (x, y + s->slice.height) - operation: NSCompositeSourceOver]; + { +#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) { @@ -3148,7 +3098,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) { @@ -3178,13 +3128,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 @@ -3345,7 +3288,7 @@ ns_draw_glyph_string (struct glyph_string *s) break; default: - abort (); + emacs_abort (); } /* Draw box if not done already. */ @@ -3396,14 +3339,6 @@ ns_send_appdefined (int value) timed_entry = nil; } - /* Ditto for file descriptor poller */ - if (fd_entry) - { - [fd_entry invalidate]; - [fd_entry release]; - fd_entry = nil; - } - nxev = [NSEvent otherEventWithType: NSApplicationDefined location: NSMakePoint (0, 0) modifierFlags: 0 @@ -3421,10 +3356,8 @@ 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. @@ -3436,21 +3369,19 @@ ns_read_socket (struct terminal *terminal, int expected, /* NSTRACE (ns_read_socket); */ - if (interrupt_input_blocked) + if ([NSApp modalWindow] != nil) + return -1; + + if (hold_event_q.nr > 0) { - interrupt_input_pending = 1; -#ifdef SYNC_INPUT - pending_signals = 1; -#endif - return -1; + int i; + for (i = 0; i < hold_event_q.nr; ++i) + kbd_buffer_store_event_hold (&hold_event_q.q[i], hold_quit); + hold_event_q.nr = 0; + return i; } - 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; @@ -3482,30 +3413,20 @@ ns_read_socket (struct terminal *terminal, int expected, /* Run and wait for events. We must always send one NX_APPDEFINED event to ourself, otherwise [NXApp run] will never exit. */ send_appdefined = YES; + ns_send_appdefined (-1); - /* If called via ns_select, this is called once with expected=1, - because we expect either the timeout or file descriptor activity. - In this case the first event through will either be real input or - one of these. read_avail_input() then calls once more with expected=0 - and in that case we need to return quickly if there is nothing. - If we're being called outside of that, it's also OK to return quickly - after one iteration through the event loop, since other terms do - this and emacs expects it. */ - if (!(inNsSelect && expected)) + if (++apploopnr != 1) { - /* Post an application defined event on the event queue. When this is - received the [NXApp run] will return, thus having processed all - events which are currently queued, if any. */ - ns_send_appdefined (-1); + emacs_abort (); } - [NSApp run]; + --apploopnr; } nevents = n_emacs_events_pending; n_emacs_events_pending = 0; emacs_event = q_event_ptr = NULL; - UNBLOCK_INPUT; + unblock_input (); return nevents; } @@ -3519,97 +3440,129 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds, -------------------------------------------------------------------------- */ { int result; - double time; - NSEvent *ev; - struct timespec select_timeout; + int t, k, nr = 0; + struct input_event event; + char c; /* NSTRACE (ns_select); */ - if (NSApp == nil || inNsSelect == 1 /* || ([NSApp isActive] == NO && - [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:nil - inMode:NSDefaultRunLoopMode dequeue:NO] == nil) */) + if (hold_event_q.nr > 0) + { + /* We already have events pending. */ + kill (0, SIGIO); + errno = EINTR; + return -1; + } + + for (k = 0; k < nfds+1; k++) + { + if (readfds && FD_ISSET(k, readfds)) ++nr; + if (writefds && FD_ISSET(k, writefds)) ++nr; + } + + if (NSApp == nil + || (timeout && timeout->tv_sec == 0 && timeout->tv_nsec == 0)) return pselect (nfds, readfds, writefds, exceptfds, timeout, sigmask); - /* Save file descriptor set, which gets overwritten in calls to select () - Note, this is called from process.c, and only readfds is ever set */ - if (readfds) + [outerpool release]; + outerpool = [[NSAutoreleasePool alloc] init]; + + + send_appdefined = YES; + if (nr > 0) { - memcpy (&select_readfds, readfds, sizeof (fd_set)); + pthread_mutex_lock (&select_mutex); select_nfds = nfds; + select_valid = 0; + if (readfds) + { + select_readfds = *readfds; + select_valid += SELECT_HAVE_READ; + } + if (writefds) + { + select_writefds = *writefds; + select_valid += SELECT_HAVE_WRITE; + } + + if (timeout) + { + select_timeout = *timeout; + select_valid += SELECT_HAVE_TMO; + } + + pthread_mutex_unlock (&select_mutex); + + /* Inform fd_handler that select should be called */ + c = 'g'; + write (selfds[1], &c, 1); + } + else if (nr == 0 && timeout) + { + /* No file descriptor, just a timeout, no need to wake fd_handler */ + double time = EMACS_TIME_TO_DOUBLE (*timeout); + timed_entry = [[NSTimer scheduledTimerWithTimeInterval: time + target: NSApp + selector: + @selector (timeout_handler:) + userInfo: 0 + repeats: NO] + retain]; + } + else /* No timeout and no file descriptors, can this happen? */ + { + /* Send appdefined so we exit from the loop */ + ns_send_appdefined (-1); } - else - select_nfds = 0; - - /* Try an initial select for pending data on input files */ - select_timeout.tv_sec = select_timeout.tv_nsec = 0; - result = pselect (nfds, readfds, writefds, exceptfds, - &select_timeout, sigmask); - if (result) - return result; - - /* if (!timeout || timed_entry || fd_entry) - fprintf (stderr, "assertion failed: timeout null or timed_entry/fd_entry non-null in ns_select\n"); */ - - /* set a timeout and run the main AppKit event loop while continuing - to monitor the files */ - time = EMACS_TIME_TO_DOUBLE (*timeout); - timed_entry = [[NSTimer scheduledTimerWithTimeInterval: time - target: NSApp - selector: @selector (timeout_handler:) - userInfo: 0 - repeats: YES] /* for safe removal */ - retain]; - - /* set a periodic task to try the pselect () again */ - fd_entry = [[NSTimer scheduledTimerWithTimeInterval: 0.1 - target: NSApp - selector: @selector (fd_handler:) - userInfo: 0 - repeats: YES] - retain]; - - /* Let Application dispatch events until it receives an event of the type - NX_APPDEFINED, which should only be sent by timeout_handler. - We tell read_avail_input() that input is "expected" because we do expect - either the timeout or fd handler to fire, and if they don't, the original - call from process.c that got us here expects us to wait until some input - comes. */ - inNsSelect = 1; - gobble_input (1); - ev = last_appdefined_event; - inNsSelect = 0; - - if (ev) - { - int t; - if ([ev type] != NSApplicationDefined) - abort (); - - t = [ev data1]; - last_appdefined_event = 0; + + EVENT_INIT (event); + block_input (); + emacs_event = &event; + if (++apploopnr != 1) + { + emacs_abort (); + } + [NSApp run]; + --apploopnr; + emacs_event = NULL; + if (nr > 0 && readfds) + { + c = 's'; + write (selfds[1], &c, 1); + } + unblock_input (); + + t = last_appdefined_event_data; + + if (t != NO_APPDEFINED_DATA) + { + last_appdefined_event_data = NO_APPDEFINED_DATA; if (t == -2) { /* The NX_APPDEFINED event we received was a timeout. */ - return 0; + result = 0; } else if (t == -1) { /* The NX_APPDEFINED event we received was the result of at least one real input event arriving. */ errno = EINTR; - return -1; + result = -1; } else { - /* Received back from pselect () in fd_handler; copy the results */ - if (readfds) - memcpy (readfds, &select_readfds, sizeof (fd_set)); - return t; + /* Received back from select () in fd_handler; copy the results */ + 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; } } - /* never reached, shut compiler up */ - return 0; + + return result; } @@ -3633,10 +3586,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; -static int count = 0; + BOOL fringe_extended_p; /* optimization; display engine sends WAY too many of these.. */ if (!NILP (window->vertical_scroll_bar)) @@ -3663,28 +3615,29 @@ static int count = 0; 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) @@ -3693,18 +3646,25 @@ static int count = 0; { bar = XNS_SCROLL_BAR (window->vertical_scroll_bar); [bar removeFromSuperview]; - window->vertical_scroll_bar = Qnil; + 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]; - window->vertical_scroll_bar = make_save_value (bar, 0); + wset_vertical_scroll_bar (window, make_save_value (bar, 0)); } else { @@ -3721,7 +3681,7 @@ static int count = 0; } [bar setPosition: position portion: portion whole: whole]; - UNBLOCK_INPUT; + unblock_input (); } @@ -3758,7 +3718,7 @@ ns_redeem_scroll_bar (struct window *window) NSTRACE (ns_redeem_scroll_bar); if (!NILP (window->vertical_scroll_bar)) { - bar =XNS_SCROLL_BAR (window->vertical_scroll_bar); + bar = XNS_SCROLL_BAR (window->vertical_scroll_bar); [bar reprieve]; } } @@ -3773,14 +3733,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]; } @@ -3818,43 +3785,23 @@ static Lisp_Object ns_string_to_lispmod (const char *s) Convert modifier name to lisp symbol -------------------------------------------------------------------------- */ { - if (!strncmp (SDATA (SYMBOL_NAME (Qmeta)), s, 10)) + if (!strncmp (SSDATA (SYMBOL_NAME (Qmeta)), s, 10)) return Qmeta; - else if (!strncmp (SDATA (SYMBOL_NAME (Qsuper)), s, 10)) + else if (!strncmp (SSDATA (SYMBOL_NAME (Qsuper)), s, 10)) return Qsuper; - else if (!strncmp (SDATA (SYMBOL_NAME (Qcontrol)), s, 10)) + else if (!strncmp (SSDATA (SYMBOL_NAME (Qcontrol)), s, 10)) return Qcontrol; - else if (!strncmp (SDATA (SYMBOL_NAME (Qalt)), s, 10)) + else if (!strncmp (SSDATA (SYMBOL_NAME (Qalt)), s, 10)) return Qalt; - else if (!strncmp (SDATA (SYMBOL_NAME (Qhyper)), s, 10)) + else if (!strncmp (SSDATA (SYMBOL_NAME (Qhyper)), s, 10)) return Qhyper; - else if (!strncmp (SDATA (SYMBOL_NAME (Qnone)), s, 10)) + else if (!strncmp (SSDATA (SYMBOL_NAME (Qnone)), s, 10)) return Qnone; else return Qnil; } -static Lisp_Object ns_mod_to_lisp (int m) -/* -------------------------------------------------------------------------- - Convert modifier code (see lisp.h) to lisp symbol - -------------------------------------------------------------------------- */ -{ - if (m == CHAR_META) - return Qmeta; - else if (m == CHAR_SUPER) - return Qsuper; - else if (m == CHAR_CTL) - return Qcontrol; - else if (m == CHAR_ALT) - return Qalt; - else if (m == CHAR_HYPER) - return Qhyper; - else /* if (m == 0) */ - return Qnone; -} - - static void ns_default (const char *parameter, Lisp_Object *result, Lisp_Object yesval, Lisp_Object noval, @@ -3883,7 +3830,7 @@ ns_default (const char *parameter, Lisp_Object *result, } -void +static void ns_initialize_display_info (struct ns_display_info *dpyinfo) /* -------------------------------------------------------------------------- Initialize global info and storage for display. @@ -3972,18 +3919,17 @@ static void ns_delete_terminal (struct terminal *terminal) { struct ns_display_info *dpyinfo = terminal->display_info.ns; - int i; /* Protect against recursive calls. delete_frame in delete_terminal calls us back when it deletes our last frame. */ if (!terminal->name) return; - BLOCK_INPUT; + block_input (); x_destroy_all_bitmaps (dpyinfo); ns_delete_display (dpyinfo); - UNBLOCK_INPUT; + unblock_input (); } @@ -4020,7 +3966,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; @@ -4051,25 +3997,41 @@ 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 (); + + baud_rate = 38400; + Fset_input_interrupt_mode (Qnil); - if (!ns_initialized) + if (selfds[0] == -1) { - baud_rate = 38400; - Fset_input_interrupt_mode (Qnil); - ns_initialized = 1; + if (pipe (selfds) == -1) + { + fprintf (stderr, "Failed to create pipe: %s\n", + emacs_strerror (errno)); + emacs_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); } ns_pending_files = [[NSMutableArray alloc] init]; ns_pending_service_names = [[NSMutableArray alloc] init]; ns_pending_service_args = [[NSMutableArray alloc] init]; - /* Start app and create the main menu, window, view. +/* Start app and create the main menu, window, view. Needs to be here because ns_initialize_display_info () uses AppKit classes. The view will then ask the NSApp to stop and return to Emacs. */ [EmacsApp sharedApplication]; @@ -4077,6 +4039,11 @@ ns_term_init (Lisp_Object display_name) return NULL; [NSApp setDelegate: NSApp]; + /* Start the select thread. */ + [NSThread detachNewThreadSelector:@selector (fd_handler:) + toTarget:NSApp + withObject:nil]; + /* debugging: log all notifications */ /* [[NSNotificationCenter defaultCenter] addObserver: NSApp selector: @selector (logNotification:) @@ -4089,7 +4056,7 @@ ns_term_init (Lisp_Object display_name) terminal->kboard = xmalloc (sizeof *terminal->kboard); init_kboard (terminal->kboard); - KVAR (terminal->kboard, Vwindow_system) = Qns; + kset_window_system (terminal->kboard, Qns); terminal->kboard->next_kboard = all_kboards; all_kboards = terminal->kboard; /* Don't let the initial kboard remain current longer than necessary. @@ -4107,12 +4074,9 @@ ns_term_init (Lisp_Object display_name) ns_display_name_list); dpyinfo->name_list_element = XCAR (ns_display_name_list); - /* Set the name of the terminal. */ - terminal->name = xmalloc (SBYTES (display_name) + 1); - strncpy (terminal->name, SDATA (display_name), SBYTES (display_name)); - terminal->name[SBYTES (display_name)] = 0; + terminal->name = xstrdup (SSDATA (display_name)); - UNBLOCK_INPUT; + unblock_input (); if (!inhibit_x_resources) { @@ -4136,7 +4100,6 @@ ns_term_init (Lisp_Object display_name) if ( cl == nil ) { Lisp_Object color_file, color_map, color; - int r,g,b; unsigned long c; char *name; @@ -4153,7 +4116,7 @@ ns_term_init (Lisp_Object display_name) for ( ; CONSP (color_map); color_map = XCDR (color_map)) { color = XCAR (color_map); - name = SDATA (XCAR (color)); + name = SSDATA (XCAR (color)); c = XINT (XCDR (color)); [cl setColor: [NSColor colorWithCalibratedRed: RED_FROM_ULONG (c) / 255.0 @@ -4167,14 +4130,14 @@ ns_term_init (Lisp_Object display_name) } { - char c[128]; #ifdef NS_IMPL_GNUSTEP - strncpy (c, gnustep_base_version, sizeof (c)); + Vwindow_system_version = build_string (gnustep_base_version); #else /*PSnextrelease (128, c); */ - snprintf (c, sizeof (c), "%g", NSAppKitVersionNumber); + char c[DBL_BUFSIZE_BOUND]; + int len = dtoastr (c, sizeof c, 0, 0, NSAppKitVersionNumber); + Vwindow_system_version = make_unibyte_string (c, len); #endif - Vwindow_system_version = build_string (c); } delete_keyboard_wait_descriptor (0); @@ -4252,8 +4215,27 @@ ns_term_init (Lisp_Object display_name) } #endif /* MAC OS X menu setup */ - [NSApp run]; + /* 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; } @@ -4265,7 +4247,7 @@ ns_term_shutdown (int sig) /* 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)); + unlink (SSDATA (Vauto_save_list_file_name)); if (sig == 0 || sig == SIGTERM) { @@ -4273,7 +4255,7 @@ ns_term_shutdown (int sig) } else // force a stack trace to happen { - abort(); + emacs_abort (); } } @@ -4323,34 +4305,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. @@ -4359,7 +4313,7 @@ ns_term_shutdown (int sig) modal loop. Just defer it until later. */ if ([NSApp modalWindow] == nil) { - last_appdefined_event = theEvent; + last_appdefined_event_data = [theEvent data1]; [self stop: self]; } else @@ -4480,7 +4434,7 @@ ns_term_shutdown (int sig) return NSTerminateNow; ret = NSRunAlertPanel(ns_app_name, - [NSString stringWithUTF8String:"Exit requested. Would you like to Save Buffers and Exit, or Cancel the request?"], + @"Exit requested. Would you like to Save Buffers and Exit, or Cancel the request?", @"Save Buffers and Exit", @"Cancel", nil); if (ret == NSAlertDefaultReturn) @@ -4490,11 +4444,21 @@ ns_term_shutdown (int sig) return NSTerminateNow; /* just in case */ } +static int +not_in_argv (NSString *arg) +{ + int k; + const char *a = [arg UTF8String]; + for (k = 1; k < initial_argc; ++k) + if (strcmp (a, initial_argv[k]) == 0) return 0; + return 1; +} /* Notification from the Workspace to open a file */ - (BOOL)application: sender openFile: (NSString *)file { - [ns_pending_files addObject: file]; + if (ns_do_open_file || not_in_argv (file)) + [ns_pending_files addObject: file]; return YES; } @@ -4502,7 +4466,8 @@ ns_term_shutdown (int sig) /* Open a file as a temporary file */ - (BOOL)application: sender openTempFile: (NSString *)file { - [ns_pending_files addObject: file]; + if (ns_do_open_file || not_in_argv (file)) + [ns_pending_files addObject: file]; return YES; } @@ -4510,18 +4475,22 @@ ns_term_shutdown (int sig) /* Notification from the Workspace to open a file noninteractively (?) */ - (BOOL)application: sender openFileWithoutUI: (NSString *)file { - [ns_pending_files addObject: file]; + if (ns_do_open_file || not_in_argv (file)) + [ns_pending_files addObject: file]; return YES; } - /* Notification from the Workspace to open multiple files */ - (void)application: sender openFiles: (NSArray *)fileList { NSEnumerator *files = [fileList objectEnumerator]; NSString *file; + /* 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) - [ns_pending_files addObject: file]; + if (ns_do_open_file || not_in_argv (file)) + [ns_pending_files addObject: file]; [self replyToOpenOrPrint: NSApplicationDelegateReplySuccess]; @@ -4574,26 +4543,95 @@ ns_term_shutdown (int sig) ns_send_appdefined (-2); } -- (void)fd_handler: (NSTimer *) fdEntry +- (void)fd_handler:(id)unused /* -------------------------------------------------------------------------- Check data waiting on file descriptors and terminate if so -------------------------------------------------------------------------- */ { int result; - struct timespec select_timeout; - /* NSTRACE (fd_handler); */ + int waiting = 1, nfds; + char c; - if (select_nfds == 0) - return; + SELECT_TYPE readfds, writefds, *wfds; + EMACS_TIME timeout, *tmo; + NSAutoreleasePool *pool = nil; - memcpy (&t_readfds, &select_readfds, sizeof (fd_set)); + /* NSTRACE (fd_handler); */ - select_timeout.tv_sec = select_timeout.tv_nsec = 0; - result = pselect (select_nfds, &t_readfds, NULL, NULL, &select_timeout, NULL); - if (result) + for (;;) { - memcpy (&select_readfds, &t_readfds, sizeof (fd_set)); - ns_send_appdefined (result); + [pool release]; + pool = [[NSAutoreleasePool alloc] init]; + + if (waiting) + { + SELECT_TYPE fds; + FD_ZERO (&fds); + FD_SET (selfds[0], &fds); + result = select (selfds[0]+1, &fds, NULL, NULL, NULL); + if (result > 0) + { + read (selfds[0], &c, 1); + if (c == 'g') waiting = 0; + } + } + else + { + pthread_mutex_lock (&select_mutex); + nfds = select_nfds; + + if (select_valid & SELECT_HAVE_READ) + readfds = select_readfds; + else + FD_ZERO (&readfds); + + if (select_valid & SELECT_HAVE_WRITE) + { + writefds = select_writefds; + wfds = &writefds; + } + else + wfds = NULL; + if (select_valid & SELECT_HAVE_TMO) + { + timeout = select_timeout; + tmo = &timeout; + } + else + tmo = NULL; + + pthread_mutex_unlock (&select_mutex); + + FD_SET (selfds[0], &readfds); + if (selfds[0] >= nfds) nfds = selfds[0]+1; + + result = pselect (nfds, &readfds, wfds, NULL, tmo, NULL); + + if (result == 0) + ns_send_appdefined (-2); + else if (result > 0) + { + if (FD_ISSET (selfds[0], &readfds)) + { + read (selfds[0], &c, 1); + if (c == 's') waiting = 1; + } + else + { + pthread_mutex_lock (&select_mutex); + if (select_valid & SELECT_HAVE_READ) + select_readfds = readfds; + if (select_valid & SELECT_HAVE_WRITE) + select_writefds = writefds; + if (select_valid & SELECT_HAVE_TMO) + select_timeout = timeout; + pthread_mutex_unlock (&select_mutex); + + ns_send_appdefined (result); + } + } + waiting = 1; + } } } @@ -4612,7 +4650,7 @@ ns_term_shutdown (int sig) { [ns_pending_service_names addObject: userData]; [ns_pending_service_args addObject: [NSString stringWithUTF8String: - SDATA (ns_string_from_pasteboard (pboard))]]; + SSDATA (ns_string_from_pasteboard (pboard))]]; } @@ -4660,6 +4698,8 @@ ns_term_shutdown (int sig) { NSTRACE (EmacsView_dealloc); [toolbar release]; + if (fs_state == FULLSCREEN_BOTH) + [nonfs_window release]; [super dealloc]; } @@ -4676,8 +4716,8 @@ ns_term_shutdown (int sig) if (!emacs_event) return; - if (newFont = [sender convertFont: - ((struct nsfont_info *)face->font)->nsfont]) + if ((newFont = [sender convertFont: + ((struct nsfont_info *)face->font)->nsfont])) { SET_FRAME_GARBAGED (emacsframe); /* now needed as of 2008/10 */ @@ -4771,8 +4811,13 @@ ns_term_shutdown (int sig) if (!processingCompose) { + /* When using screen sharing, no left or right information is sent, + so use Left key in those cases. */ + int is_left_key, is_right_key; + code = ([[theEvent charactersIgnoringModifiers] length] == 0) ? 0 : [[theEvent charactersIgnoringModifiers] characterAtIndex: 0]; + /* (Carbon way: [theEvent keyCode]) */ /* is it a "function key"? */ @@ -4797,13 +4842,17 @@ ns_term_shutdown (int sig) if (flags & NSShiftKeyMask) emacs_event->modifiers |= shift_modifier; - if ((flags & NSRightCommandKeyMask) == NSRightCommandKeyMask) + 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) ? ns_command_modifier : ns_right_command_modifier); - if ((flags & NSLeftCommandKeyMask) == NSLeftCommandKeyMask) + if (is_left_key) { emacs_event->modifiers |= parse_solitary_modifier (ns_command_modifier); @@ -4840,13 +4889,17 @@ ns_term_shutdown (int sig) } } - if ((flags & NSRightControlKeyMask) == NSRightControlKeyMask) + is_right_key = (flags & NSRightControlKeyMask) == NSRightControlKeyMask; + is_left_key = (flags & NSLeftControlKeyMask) == NSLeftControlKeyMask + || (! is_right_key && (flags & NSControlKeyMask) == NSControlKeyMask); + + if (is_right_key) emacs_event->modifiers |= parse_solitary_modifier (EQ (ns_right_control_modifier, Qleft) ? ns_control_modifier : ns_right_control_modifier); - if ((flags & NSLeftControlKeyMask) == NSLeftControlKeyMask) + if (is_left_key) emacs_event->modifiers |= parse_solitary_modifier (ns_control_modifier); @@ -4857,7 +4910,13 @@ ns_term_shutdown (int sig) left_is_none = NILP (ns_alternate_modifier) || EQ (ns_alternate_modifier, Qnone); - if ((flags & NSRightAlternateKeyMask) == NSRightAlternateKeyMask) + is_right_key = (flags & NSRightAlternateKeyMask) + == NSRightAlternateKeyMask; + is_left_key = (flags & NSLeftAlternateKeyMask) == NSLeftAlternateKeyMask + || (! is_right_key + && (flags & NSAlternateKeyMask) == NSAlternateKeyMask); + + if (is_right_key) { if ((NILP (ns_right_alternate_modifier) || EQ (ns_right_alternate_modifier, Qnone) @@ -4877,7 +4936,7 @@ ns_term_shutdown (int sig) : ns_right_alternate_modifier); } - if ((flags & NSLeftAlternateKeyMask) == NSLeftAlternateKeyMask) /* default = meta */ + if (is_left_key) /* default = meta */ { if (left_is_none && !fnKeysym) { /* accept pre-interp alt comb */ @@ -4988,7 +5047,8 @@ ns_term_shutdown (int sig) /* TODO: still need this? */ if (code == 0x2DC) code = '~'; /* 0x7E */ - emacs_event->modifiers = 0; + if (code != 32) /* Space */ + emacs_event->modifiers = 0; emacs_event->kind = code > 0xFF ? MULTIBYTE_CHAR_KEYSTROKE_EVENT : ASCII_KEYSTROKE_EVENT; emacs_event->code = code; @@ -5091,9 +5151,9 @@ ns_term_shutdown (int sig) } -- (long)conversationIdentifier +- (NSInteger)conversationIdentifier { - return (long)self; + return (NSInteger)self; } @@ -5153,7 +5213,6 @@ ns_term_shutdown (int sig) - (void)mouseDown: (NSEvent *)theEvent { NSPoint p = [self convertPoint: [theEvent locationInWindow] fromView: nil]; - Lisp_Object window; NSTRACE (mouseDown); @@ -5317,6 +5376,51 @@ ns_term_shutdown (int sig) 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 */ @@ -5324,6 +5428,19 @@ ns_term_shutdown (int sig) 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); @@ -5383,10 +5500,17 @@ ns_term_shutdown (int sig) - (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 - /* in GNUstep, at least currently, it's possible to get a didResize + NSWindow *theWindow = [notification object]; + + /* 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; @@ -5404,29 +5528,10 @@ ns_term_shutdown (int sig) } #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); } @@ -5505,7 +5610,6 @@ ns_term_shutdown (int sig) Lisp_Object tem; NSWindow *win; NSButton *toggleButton; - int vbextra = NS_SCROLL_BAR_WIDTH (f); NSSize sz; NSColor *col; NSString *name; @@ -5515,6 +5619,10 @@ ns_term_shutdown (int sig) 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); */ @@ -5539,9 +5647,13 @@ ns_term_shutdown (int sig) 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]; @@ -5558,7 +5670,7 @@ ns_term_shutdown (int sig) tem = f->name; name = [NSString stringWithUTF8String: - NILP (tem) ? (unsigned char *)"Emacs" : SDATA (tem)]; + NILP (tem) ? "Emacs" : SSDATA (tem)]; [win setTitle: name]; /* toolbar support */ @@ -5577,7 +5689,7 @@ ns_term_shutdown (int sig) tem = f->icon_name; if (!NILP (tem)) [win setMiniwindowTitle: - [NSString stringWithUTF8String: SDATA (tem)]]; + [NSString stringWithUTF8String: SSDATA (tem)]]; { NSScreen *screen = [win screen]; @@ -5647,27 +5759,50 @@ ns_term_shutdown (int sig) 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; } @@ -5719,21 +5854,221 @@ ns_term_shutdown (int sig) } } +- (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 { - NSPoint p = [self convertPoint: [theEvent locationInWindow] fromView: nil]; - struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (emacsframe); NSTRACE (mouseEntered); - last_mouse_movement_time = EV_TIMESTAMP (theEvent); } - (void)mouseExited: (NSEvent *)theEvent { - NSPoint p = [self convertPoint: [theEvent locationInWindow] fromView: nil]; - NSRect r; Mouse_HLInfo *hlinfo = emacsframe ? MOUSE_HL_INFO (emacsframe) : NULL; NSTRACE (mouseExited); @@ -5757,9 +6092,13 @@ ns_term_shutdown (int sig) if (context_menu_value == -1) context_menu_value = [sender tag]; else - find_and_call_menu_selection (emacsframe, emacsframe->menu_bar_items_used, - emacsframe->menu_bar_vector, - (void *)[sender tag]); + { + NSInteger tag = [sender tag]; + find_and_call_menu_selection (emacsframe, emacsframe->menu_bar_items_used, + emacsframe->menu_bar_vector, + (void *)tag); + } + ns_send_appdefined (-1); return self; } @@ -5791,7 +6130,7 @@ ns_term_shutdown (int sig) emacs_event->kind = TOOL_BAR_EVENT; /* XSETINT (emacs_event->code, 0); */ emacs_event->arg = AREF (emacsframe->tool_bar_items, - idx + TOOL_BAR_ITEM_KEY); + idx + TOOL_BAR_ITEM_KEY); emacs_event->modifiers = EV_MODIFIERS (theEvent); EV_TRAILER (theEvent); return self; @@ -5817,7 +6156,7 @@ ns_term_shutdown (int sig) 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); @@ -6073,6 +6412,63 @@ ns_term_shutdown (int sig) @implementation EmacsWindow +#ifdef NS_IMPL_COCOA +- (id)accessibilityAttributeValue:(NSString *)attribute +{ + Lisp_Object str = Qnil; + struct frame *f = SELECTED_FRAME (); + struct buffer *curbuf = XBUFFER (XWINDOW (f->selected_window)->buffer); + + if ([attribute isEqualToString:NSAccessibilityRoleAttribute]) + return NSAccessibilityTextFieldRole; + + if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute] + && curbuf && ! NILP (BVAR (curbuf, mark_active))) + { + str = ns_get_local_selection (QPRIMARY, QUTF8_STRING); + } + else if (curbuf && [attribute isEqualToString:NSAccessibilityValueAttribute]) + { + 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 + str = make_uninit_string (range); + /* To check: This returns emacs-utf-8, which is a superset of utf-8. + Is this a problem? */ + memcpy (SDATA (str), BYTE_POS_ADDR (start_byte), byte_range); + } + } + + + if (! NILP (str)) + { + if (CONSP (str) && SYMBOLP (XCAR (str))) + { + str = XCDR (str); + if (CONSP (str) && NILP (XCDR (str))) + str = XCAR (str); + } + if (STRINGP (str)) + { + const char *utfStr = SSDATA (str); + NSString *nsStr = [NSString stringWithUTF8String: utfStr]; + return nsStr; + } + } + + return [super accessibilityAttributeValue:attribute]; +} +#endif /* NS_IMPL_COCOA */ + /* If we have multiple monitors, one above the other, we don't want to restrict the height to just one monitor. So we override this. */ - (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen @@ -6084,7 +6480,10 @@ ns_term_shutdown (int sig) 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 ()) @@ -6094,62 +6493,22 @@ ns_term_shutdown (int sig) 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 /* ========================================================================== @@ -6221,13 +6580,13 @@ ns_term_shutdown (int sig) - (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 (); */ } @@ -6235,7 +6594,7 @@ ns_term_shutdown (int sig) { NSTRACE (EmacsScroller_dealloc); if (!NILP (win)) - XWINDOW (win)->vertical_scroll_bar = Qnil; + wset_vertical_scroll_bar (XWINDOW (win), Qnil); [super dealloc]; } @@ -6262,14 +6621,14 @@ ns_term_shutdown (int sig) 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; } @@ -6324,6 +6683,12 @@ ns_term_shutdown (int sig) [self setFloatValue: pos knobProportion: por]; #endif } + + /* Events may come here even if the event loop is not running. + If we don't enter the event loop, the scroll bar will not update. + So send SIGIO to ourselves. */ + if (apploopnr == 0) kill (0, SIGIO); + return self; } @@ -6358,8 +6723,13 @@ ns_term_shutdown (int sig) XSETINT (emacs_event->x, loc * pixel_height); XSETINT (emacs_event->y, pixel_height-20); - n_emacs_events_pending++; - kbd_buffer_store_event_hold (emacs_event, q_event_ptr); + if (q_event_ptr) + { + n_emacs_events_pending++; + kbd_buffer_store_event_hold (emacs_event, q_event_ptr); + } + else + hold_event (emacs_event); EVENT_INIT (*emacs_event); ns_send_appdefined (-1); } @@ -6629,20 +6999,20 @@ ns_xlfd_to_fontname (const char *xlfd) /* undo hack in ns_fontname_to_xlfd, converting '$' to '-', '_' to ' ' also uppercase after '-' or ' ' */ - name[0] = toupper (name[0]); + name[0] = c_toupper (name[0]); for (len =strlen (name), i =0; i