diff options
Diffstat (limited to 'src/nsterm.m')
-rw-r--r-- | src/nsterm.m | 962 |
1 files changed, 523 insertions, 439 deletions
diff --git a/src/nsterm.m b/src/nsterm.m index c09f684daf4..016c0447609 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -27,7 +27,7 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu) */ /* This should be the first include, as it may set up #defines affecting - interpretation of even the system includes. */ + interpretation of even the system includes. */ #include <config.h> #include <fcntl.h> @@ -37,6 +37,7 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu) #include <time.h> #include <signal.h> #include <unistd.h> +#include <stdbool.h> #include <c-ctype.h> #include <c-strcase.h> @@ -66,6 +67,7 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu) #ifdef NS_IMPL_COCOA #include "macfont.h" +#include <Carbon/Carbon.h> #endif static EmacsMenu *dockMenu; @@ -82,7 +84,7 @@ static EmacsMenu *mainMenu; #if NSTRACE_ENABLED /* The following use "volatile" since they can be accessed from - parallel threads. */ + parallel threads. */ volatile int nstrace_num = 0; volatile int nstrace_depth = 0; @@ -91,10 +93,10 @@ volatile int nstrace_depth = 0; TODO: This should really be a thread-local variable, to avoid that a function with disabled trace thread silence trace output in - another. However, in practice this seldom is a problem. */ + another. However, in practice this seldom is a problem. */ volatile int nstrace_enabled_global = 1; -/* Called when nstrace_enabled goes out of scope. */ +/* Called when nstrace_enabled goes out of scope. */ void nstrace_leave(int * pointer_to_nstrace_enabled) { if (*pointer_to_nstrace_enabled) @@ -104,7 +106,7 @@ void nstrace_leave(int * pointer_to_nstrace_enabled) } -/* Called when nstrace_saved_enabled_global goes out of scope. */ +/* Called when nstrace_saved_enabled_global goes out of scope. */ void nstrace_restore_global_trace_state(int * pointer_to_saved_enabled_global) { nstrace_enabled_global = *pointer_to_saved_enabled_global; @@ -159,7 +161,7 @@ char const * nstrace_fullscreen_type_name (int fs_type) { /* FIXMES: We're checking for colorWithSRGBRed here so this will only work in the same place as in the method above. It should - really be a check whether we're on macOS 10.7 or above. */ + really be a check whether we're on macOS 10.7 or above. */ #if defined (NS_IMPL_COCOA) \ && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 if (ns_use_srgb_colorspace @@ -183,7 +185,7 @@ char const * nstrace_fullscreen_type_name (int fs_type) /* Convert a symbol indexed with an NSxxx value to a value as defined in keyboard.c (lispy_function_key). I hope this is a correct way - of doing things... */ + of doing things... */ static unsigned convert_ns_to_X_keysym[] = { NSHomeFunctionKey, 0x50, @@ -232,9 +234,9 @@ static unsigned convert_ns_to_X_keysym[] = NSF23FunctionKey, 0xD4, NSF24FunctionKey, 0xD5, - NSBackspaceCharacter, 0x08, /* 8: Not on some KBs. */ - NSDeleteCharacter, 0xFF, /* 127: Big 'delete' key upper right. */ - NSDeleteFunctionKey, 0x9F, /* 63272: Del forw key off main array. */ + NSBackspaceCharacter, 0x08, /* 8: Not on some KBs. */ + NSDeleteCharacter, 0xFF, /* 127: Big 'delete' key upper right. */ + NSDeleteFunctionKey, 0x9F, /* 63272: Del forw key off main array. */ NSTabCharacter, 0x09, 0x19, 0x09, /* left tab->regular since pass shift */ @@ -264,7 +266,7 @@ static unsigned convert_ns_to_X_keysym[] = /* On macOS picks up the default NSGlobalDomain AppleAntiAliasingThreshold, the maximum font size to NOT antialias. On GNUstep there is currently - no way to control this behavior. */ + no way to control this behavior. */ float ns_antialias_threshold; NSArray *ns_send_types = 0, *ns_return_types = 0; @@ -280,8 +282,11 @@ static int ns_window_num = 0; static BOOL ns_fake_keydown = NO; #ifdef NS_IMPL_COCOA static BOOL ns_menu_bar_is_hidden = NO; + +/* The number of times NSDisableScreenUpdates has been called. */ +static int disable_screen_updates_count = 0; #endif -/*static int debug_lock = 0; */ +/* static int debug_lock = 0; */ /* event loop */ static BOOL send_appdefined = YES; @@ -316,9 +321,6 @@ static struct { NULL, 0, 0 }; -static NSString *represented_filename = nil; -static struct frame *represented_frame = 0; - #ifdef NS_IMPL_COCOA /* * State for pending menu activation: @@ -345,31 +347,56 @@ static CGPoint menu_mouse_point; #define NSRightCommandKeyMask (0x000010 | NSEventModifierFlagCommand) #define NSLeftAlternateKeyMask (0x000020 | NSEventModifierFlagOption) #define NSRightAlternateKeyMask (0x000040 | NSEventModifierFlagOption) -#define EV_MODIFIERS2(flags) \ - (((flags & NSEventModifierFlagHelp) ? \ - hyper_modifier : 0) \ - | (!EQ (ns_right_alternate_modifier, Qleft) && \ - ((flags & NSRightAlternateKeyMask) \ - == NSRightAlternateKeyMask) ? \ - parse_solitary_modifier (ns_right_alternate_modifier) : 0) \ - | ((flags & NSEventModifierFlagOption) ? \ - parse_solitary_modifier (ns_alternate_modifier) : 0) \ - | ((flags & NSEventModifierFlagShift) ? \ - shift_modifier : 0) \ - | (!EQ (ns_right_control_modifier, Qleft) && \ - ((flags & NSRightControlKeyMask) \ - == NSRightControlKeyMask) ? \ - parse_solitary_modifier (ns_right_control_modifier) : 0) \ - | ((flags & NSEventModifierFlagControl) ? \ - parse_solitary_modifier (ns_control_modifier) : 0) \ - | ((flags & NS_FUNCTION_KEY_MASK) ? \ - parse_solitary_modifier (ns_function_modifier) : 0) \ - | (!EQ (ns_right_command_modifier, Qleft) && \ - ((flags & NSRightCommandKeyMask) \ - == NSRightCommandKeyMask) ? \ - parse_solitary_modifier (ns_right_command_modifier) : 0) \ - | ((flags & NSEventModifierFlagCommand) ? \ - parse_solitary_modifier (ns_command_modifier):0)) + +static unsigned int +ev_modifiers_helper (unsigned int flags, unsigned int left_mask, + unsigned int right_mask, unsigned int either_mask, + Lisp_Object left_modifier, Lisp_Object right_modifier) +{ + unsigned int modifiers = 0; + + if (flags & either_mask) + { + BOOL left_key = (flags & left_mask) == left_mask; + BOOL right_key = (flags & right_mask) == right_mask + && ! EQ (right_modifier, Qleft); + + if (right_key) + modifiers |= parse_solitary_modifier (right_modifier); + + /* GNUstep (and possibly macOS in certain circumstances) doesn't + differentiate between the left and right keys, so if we can't + identify which key it is, we use the left key setting. */ + if (left_key || ! right_key) + modifiers |= parse_solitary_modifier (left_modifier); + } + + return modifiers; +} + +#define EV_MODIFIERS2(flags) \ + (((flags & NSEventModifierFlagHelp) ? \ + hyper_modifier : 0) \ + | ((flags & NSEventModifierFlagShift) ? \ + shift_modifier : 0) \ + | ((flags & NS_FUNCTION_KEY_MASK) ? \ + parse_solitary_modifier (ns_function_modifier) : 0) \ + | ev_modifiers_helper (flags, NSLeftControlKeyMask, \ + NSRightControlKeyMask, \ + NSEventModifierFlagControl, \ + ns_control_modifier, \ + ns_right_control_modifier) \ + | ev_modifiers_helper (flags, NSLeftCommandKeyMask, \ + NSRightCommandKeyMask, \ + NSEventModifierFlagCommand, \ + ns_command_modifier, \ + ns_right_command_modifier) \ + | ev_modifiers_helper (flags, NSLeftAlternateKeyMask, \ + NSRightAlternateKeyMask, \ + NSEventModifierFlagOption, \ + ns_alternate_modifier, \ + ns_right_alternate_modifier)) + #define EV_MODIFIERS(e) EV_MODIFIERS2 ([e modifierFlags]) #define EV_UDMODIFIERS(e) \ @@ -388,7 +415,7 @@ static CGPoint menu_mouse_point; (([e type] == NSEventTypeRightMouseDown) || ([e type] == NSEventTypeRightMouseUp)) ? 2 : \ [e buttonNumber] - 1) -/* Convert the time field to a timestamp in milliseconds. */ +/* Convert the time field to a timestamp in milliseconds. */ #define EV_TIMESTAMP(e) ([e timestamp] * 1000) /* This is a piece of code which is common to all the event handling @@ -418,14 +445,14 @@ static CGPoint menu_mouse_point; /* These flags will be OR'd or XOR'd with the NSWindow's styleMask - property depending on what we're doing. */ + property depending on what we're doing. */ #define FRAME_DECORATED_FLAGS (NSWindowStyleMaskTitled \ | NSWindowStyleMaskResizable \ | NSWindowStyleMaskMiniaturizable \ | NSWindowStyleMaskClosable) #define FRAME_UNDECORATED_FLAGS NSWindowStyleMaskBorderless -/* TODO: get rid of need for these forward declarations */ +/* TODO: Get rid of need for these forward declarations. */ static void ns_condemn_scroll_bars (struct frame *f); static void ns_judge_scroll_bars (struct frame *f); @@ -437,13 +464,6 @@ static void ns_judge_scroll_bars (struct frame *f); ========================================================================== */ void -ns_set_represented_filename (NSString *fstr, struct frame *f) -{ - represented_filename = [fstr retain]; - represented_frame = f; -} - -void ns_init_events (struct input_event *ev) { EVENT_INIT (*ev); @@ -602,7 +622,7 @@ ns_load_path (void) void ns_init_locale (void) /* macOS doesn't set any environment variables for the locale when run - from the GUI. Get the locale from the OS and set LANG. */ + from the GUI. Get the locale from the OS and set LANG. */ { NSLocale *locale = [NSLocale currentLocale]; @@ -613,11 +633,11 @@ ns_init_locale (void) /* It seems macOS should probably use UTF-8 everywhere. 'localeIdentifier' does not specify the encoding, and I can't find any way to get the OS to tell us which encoding to use, - so hard-code '.UTF-8'. */ + so hard-code '.UTF-8'. */ NSString *localeID = [NSString stringWithFormat:@"%@.UTF-8", [locale localeIdentifier]]; - /* Set LANG to locale, but not if LANG is already set. */ + /* Set LANG to locale, but not if LANG is already set. */ setenv("LANG", [localeID UTF8String], 0); } @catch (NSException *e) @@ -640,7 +660,7 @@ ns_release_object (void *obj) void ns_retain_object (void *obj) /* -------------------------------------------------------------------------- - Retain an object (callable from C) + Retain an object (callable from C) -------------------------------------------------------------------------- */ { [(id)obj retain]; @@ -667,6 +687,40 @@ ns_release_autorelease_pool (void *pool) } +#ifdef NS_IMPL_COCOA +/* Disabling screen updates can be used to make several actions appear + "atomic" to the end user. It seems some actions can still update + the display, though. + + When we re-enable screen updates the number of calls to + NSEnableScreenUpdates should match the number to + NSDisableScreenUpdates. + + We use these functions to prevent the user seeing a blank frame + after it has been resized. x_set_window_size disables updates and + when redisplay completes unwind_redisplay enables them again + (bug#30699). */ + +static void +ns_disable_screen_updates (void) +{ + NSDisableScreenUpdates (); + disable_screen_updates_count++; +} + +void +ns_enable_screen_updates (void) +/* Re-enable screen updates. Called from unwind_redisplay. */ +{ + while (disable_screen_updates_count > 0) + { + NSEnableScreenUpdates (); + disable_screen_updates_count--; + } +} +#endif + + static BOOL ns_menu_bar_should_be_hidden (void) /* True, if the menu bar should be hidden. */ @@ -739,7 +793,7 @@ ns_screen_margins (NSScreen *screen) static struct EmacsMargins ns_screen_margins_ignoring_hidden_dock (NSScreen *screen) /* The parts of SCREEN used by the operating system, excluding the parts -reserved for an hidden dock. */ + reserved for a hidden dock. */ { NSTRACE ("ns_screen_margins_ignoring_hidden_dock"); @@ -1233,7 +1287,7 @@ ns_reset_clipping (struct frame *f) @interface EmacsBell : NSImageView { - // Number of currently active bell:s. + // Number of currently active bells. unsigned int nestCount; NSView * mView; bool isAttached; @@ -1494,7 +1548,7 @@ x_make_frame_visible (struct frame *f) NSTRACE ("x_make_frame_visible"); /* XXX: at some points in past this was not needed, as the only place that called this (frame.c:Fraise_frame ()) also called raise_lower; - if this ends up the case again, comment this out again. */ + if this ends up the case again, comment this out again. */ if (!FRAME_VISIBLE_P (f)) { EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f); @@ -1517,7 +1571,7 @@ x_make_frame_visible (struct frame *f) } /* Making a frame invisible seems to break the parent->child - relationship, so reinstate it. */ + relationship, so reinstate it. */ if ([window parentWindow] == nil && FRAME_PARENT_FRAME (f) != NULL) { NSWindow *parent = [FRAME_NS_VIEW (FRAME_PARENT_FRAME (f)) window]; @@ -1529,7 +1583,7 @@ x_make_frame_visible (struct frame *f) /* If the parent frame moved while the child frame was invisible, the child frame's position won't have been - updated. Make sure it's in the right place now. */ + updated. Make sure it's in the right place now. */ x_set_offset(f, f->left_pos, f->top_pos, 0); } } @@ -1571,8 +1625,8 @@ x_iconify_frame (struct frame *f) if ([[view window] windowNumber] <= 0) { - /* the window is still deferred. Make it very small, bring it - on screen and order it out. */ + /* The window is still deferred. Make it very small, bring it + on screen and order it out. */ NSRect s = { { 100, 100}, {0, 0} }; NSRect t; t = [[view window] frame]; @@ -1583,7 +1637,7 @@ x_iconify_frame (struct frame *f) } /* Processing input while Emacs is being minimized can cause a - crash, so block it for the duration. */ + crash, so block it for the duration. */ block_input(); [[view window] miniaturize: NSApp]; unblock_input(); @@ -1617,10 +1671,6 @@ x_free_frame_resources (struct frame *f) dpyinfo->x_highlight_frame = 0; if (f == hlinfo->mouse_face_mouse_frame) reset_mouse_highlight (hlinfo); - /* Ensure that sendEvent does not attempt to dereference a freed - frame. (bug#30800) */ - if (represented_frame == f) - represented_frame = NULL; if (f->output_data.ns->miniimage != nil) [f->output_data.ns->miniimage release]; @@ -1642,7 +1692,7 @@ x_destroy_window (struct frame *f) NSTRACE ("x_destroy_window"); /* If this frame has a parent window, detach it as not doing so can - cause a crash in GNUStep. */ + cause a crash in GNUStep. */ if (FRAME_PARENT_FRAME (f) != NULL) { NSWindow *child = [FRAME_NS_VIEW (f) window]; @@ -1664,7 +1714,6 @@ x_set_offset (struct frame *f, int xoff, int yoff, int change_grav) -------------------------------------------------------------------------- */ { NSView *view = FRAME_NS_VIEW (f); - NSArray *screens = [NSScreen screens]; NSScreen *screen = [[view window] screen]; NSTRACE ("x_set_offset"); @@ -1753,6 +1802,15 @@ x_set_window_size (struct frame *f, block_input (); +#ifdef NS_IMPL_COCOA + /* To prevent showing the user a blank frame, stop updates being + flushed to the screen until after redisplay has completed. This + breaks live resize (resizing with a mouse), so don't do it if + we're in a live resize loop. */ + if (![view inLiveResize]) + ns_disable_screen_updates (); +#endif + if (pixelwise) { pixelwidth = FRAME_TEXT_TO_PIXEL_WIDTH (f, width); @@ -1780,11 +1838,11 @@ x_set_window_size (struct frame *f, frame_size_history_add (f, Qx_set_window_size_1, width, height, - list5 (Fcons (make_number (pixelwidth), make_number (pixelheight)), - Fcons (make_number (wr.size.width), make_number (wr.size.height)), - make_number (f->border_width), - make_number (FRAME_NS_TITLEBAR_HEIGHT (f)), - make_number (FRAME_TOOLBAR_HEIGHT (f)))); + list5 (Fcons (make_fixnum (pixelwidth), make_fixnum (pixelheight)), + Fcons (make_fixnum (wr.size.width), make_fixnum (wr.size.height)), + make_fixnum (f->border_width), + make_fixnum (FRAME_NS_TITLEBAR_HEIGHT (f)), + make_fixnum (FRAME_TOOLBAR_HEIGHT (f)))); [window setFrame: wr display: YES]; @@ -1826,7 +1884,7 @@ x_set_undecorated (struct frame *f, Lisp_Object new_value, Lisp_Object old_value else { [window setToolbar: nil]; - /* Do I need to release the toolbar here? */ + /* Do I need to release the toolbar here? */ FRAME_UNDECORATED (f) = true; [window setStyleMask: ((window.styleMask | FRAME_UNDECORATED_FLAGS) @@ -1834,7 +1892,7 @@ x_set_undecorated (struct frame *f, Lisp_Object new_value, Lisp_Object old_value } /* At this point it seems we don't have an active NSResponder, - so some key presses (TAB) are swallowed by the system. */ + so some key presses (TAB) are swallowed by the system. */ [window makeFirstResponder: view]; [view updateFrameSize: NO]; @@ -1925,7 +1983,7 @@ x_set_no_focus_on_map (struct frame *f, Lisp_Object new_value, Lisp_Object old_v * displayed for the first time and when the frame changes its state * from `iconified' or `invisible' to `visible'.) * - * Some window managers may not honor this parameter. */ + * Some window managers may not honor this parameter. */ { NSTRACE ("x_set_no_focus_on_map"); @@ -1944,7 +2002,7 @@ x_set_no_accept_focus (struct frame *f, Lisp_Object new_value, Lisp_Object old_v * If non-nil, this may have the unwanted side-effect that a user cannot * scroll a non-selected frame with the mouse. * - * Some window managers may not honor this parameter. */ + * Some window managers may not honor this parameter. */ { NSTRACE ("x_set_no_accept_focus"); @@ -1961,7 +2019,7 @@ x_set_z_group (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) `below' property set. If `below', F's window is displayed below all windows that do. - Some window managers may not honor this parameter. */ + Some window managers may not honor this parameter. */ { EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f); NSWindow *window = [view window]; @@ -1980,7 +2038,7 @@ x_set_z_group (struct frame *f, Lisp_Object new_value, Lisp_Object old_value) } else if (EQ (new_value, Qabove_suspended)) { - /* Not sure what level this should be. */ + /* Not sure what level this should be. */ window.level = NSNormalWindowLevel + 1; FRAME_Z_GROUP (f) = z_group_above_suspended; } @@ -2058,8 +2116,7 @@ ns_fullscreen_hook (struct frame *f) if (! [view fsIsNative] && 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...). - */ + init/default-frame alist, so use a timer (not nice...). */ [NSTimer scheduledTimerWithTimeInterval: 0.5 target: view selector: @selector (handleFS) userInfo: nil repeats: NO]; @@ -2126,7 +2183,7 @@ ns_index_color (NSColor *color, struct frame *f) color_table->colors[idx] = color; [color retain]; -/*fprintf(stderr, "color_table: allocated %d\n",idx);*/ + /* fprintf(stderr, "color_table: allocated %d\n",idx); */ return idx; } @@ -2138,7 +2195,7 @@ ns_get_color (const char *name, NSColor **col) -------------------------------------------------------------------------- */ /* On *Step, we attempt to mimic the X11 platform here, down to installing an X11 rgb.txt-compatible color list in Emacs.clr (see ns_term_init()). - See: http://thread.gmane.org/gmane.emacs.devel/113050/focus=113272). */ + See https://lists.gnu.org/r/emacs-devel/2009-07/msg01203.html. */ { NSColor *new = nil; static char hex[20]; @@ -2173,8 +2230,7 @@ ns_get_color (const char *name, NSColor **col) else if ([nsname isEqualToString: @"ns_selection_fg_color"]) { /* NOTE: macOS applications normally don't set foreground - selection, but text may be unreadable if we don't. - */ + selection, but text may be unreadable if we don't. */ if ((new = [NSColor selectedTextColor]) != nil) { *col = [new colorUsingDefaultColorSpace]; @@ -2186,7 +2242,7 @@ ns_get_color (const char *name, NSColor **col) name = [nsname UTF8String]; } - /* First, check for some sort of numeric specification. */ + /* First, check for some sort of numeric specification. */ hex[0] = '\0'; if (name[0] == '0' || name[0] == '1' || name[0] == '.') /* RGB decimal */ @@ -2236,7 +2292,7 @@ ns_get_color (const char *name, NSColor **col) NSColorList *clist; #ifdef NS_IMPL_GNUSTEP - /* XXX: who is wrong, the requestor or the implementation? */ + /* XXX: who is wrong, the requestor or the implementation? */ if ([nsname compare: @"Highlight" options: NSCaseInsensitiveSearch] == NSOrderedSame) nsname = @"highlightColor"; @@ -2265,7 +2321,7 @@ ns_get_color (const char *name, NSColor **col) int ns_lisp_to_color (Lisp_Object color, NSColor **col) /* -------------------------------------------------------------------------- - Convert a Lisp string object to a NS color + Convert a Lisp string object to a NS color. -------------------------------------------------------------------------- */ { NSTRACE ("ns_lisp_to_color"); @@ -2276,6 +2332,22 @@ ns_lisp_to_color (Lisp_Object color, NSColor **col) return 1; } +/* Convert an index into the color table into an RGBA value. Used in + xdisp.c:extend_face_to_end_of_line when comparing faces and frame + color values. */ + +unsigned long +ns_color_index_to_rgba(int idx, struct frame *f) +{ + NSColor *col; + col = ns_lookup_indexed_color (idx, f); + + EmacsCGFloat r, g, b, a; + [col getRed: &r green: &g blue: &b alpha: &a]; + + return ARGB_TO_ULONG((int)(a*255), + (int)(r*255), (int)(g*255), (int)(b*255)); +} void ns_query_color(void *col, XColor *color_def, int setPixel) @@ -2310,7 +2382,7 @@ ns_defined_color (struct frame *f, 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 false if not found + Return false if not found. -------------------------------------------------------------------------- */ { NSColor *col; @@ -2349,8 +2421,8 @@ x_set_frame_alpha (struct frame *f) if (FLOATP (Vframe_alpha_lower_limit)) alpha_min = XFLOAT_DATA (Vframe_alpha_lower_limit); - else if (INTEGERP (Vframe_alpha_lower_limit)) - alpha_min = (XINT (Vframe_alpha_lower_limit)) / 100.0; + else if (FIXNUMP (Vframe_alpha_lower_limit)) + alpha_min = (XFIXNUM (Vframe_alpha_lower_limit)) / 100.0; if (alpha < 0.0) return; @@ -2383,7 +2455,7 @@ frame_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y) { NSTRACE ("frame_set_mouse_pixel_position"); - /* FIXME: what about GNUstep? */ + /* FIXME: what about GNUstep? */ #ifdef NS_IMPL_COCOA CGPoint mouse_pos = CGPointMake(f->left_pos + pix_x, @@ -2404,15 +2476,15 @@ note_mouse_movement (struct frame *frame, CGFloat x, CGFloat y) struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame); NSRect *r; -// NSTRACE ("note_mouse_movement"); + // NSTRACE ("note_mouse_movement"); dpyinfo->last_mouse_motion_frame = frame; r = &dpyinfo->last_mouse_glyph; /* Note, this doesn't get called for enter/leave, since we don't have a - position. Those are taken care of in the corresponding NSView methods. */ + position. Those are taken care of in the corresponding NSView methods. */ - /* has movement gone beyond last rect we were tracking? */ + /* Has movement gone beyond last rect we were tracking? */ if (x < r->origin.x || x >= r->origin.x + r->size.width || y < r->origin.y || y >= r->origin.y + r->size.height) { @@ -2436,7 +2508,7 @@ ns_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window, External (hook): inform emacs about mouse position and hit parts. If a scrollbar is being dragged, set bar_window, part, x, y, time. x & y should be position in the scrollbar (the whole bar, not the handle) - and length of scrollbar respectively + and length of scrollbar respectively. -------------------------------------------------------------------------- */ { id view; @@ -2555,7 +2627,7 @@ ns_convert_key (unsigned code) { const unsigned last_keysym = ARRAYELTS (convert_ns_to_X_keysym); unsigned keysym; - /* An array would be faster, but less easy to read. */ + /* An array would be faster, but less easy to read. */ for (keysym = 0; keysym < last_keysym; keysym += 2) if (code == convert_ns_to_X_keysym[keysym]) return 0xFF00 | convert_ns_to_X_keysym[keysym+1]; @@ -2578,7 +2650,78 @@ x_get_keysym_name (int keysym) return value; } +#ifdef NS_IMPL_COCOA +static UniChar +ns_get_shifted_character (NSEvent *event) +/* Look up the character corresponding to the key pressed on the + current keyboard layout and the currently configured shift-like + modifiers. This ignores the control-like modifiers that cause + [event characters] to give us the wrong result. + + Although UCKeyTranslate doesn't require the Carbon framework, some + of the surrounding paraphernalia does, so this function makes + Carbon a requirement. */ +{ + static UInt32 dead_key_state; + + /* UCKeyTranslate may return up to 255 characters. If the buffer + isn't large enough then it produces an error. What kind of + keyboard inputs 255 characters in a single keypress? */ + UniChar buf[255]; + UniCharCount max_string_length = 255; + UniCharCount actual_string_length = 0; + OSStatus result; + + CFDataRef layout_ref = (CFDataRef) TISGetInputSourceProperty + (TISCopyCurrentKeyboardLayoutInputSource (), kTISPropertyUnicodeKeyLayoutData); + UCKeyboardLayout* layout = (UCKeyboardLayout*) CFDataGetBytePtr (layout_ref); + + UInt32 flags = [event modifierFlags]; + UInt32 modifiers = (flags & NSEventModifierFlagShift) ? shiftKey : 0; + + NSTRACE ("ns_get_shifted_character"); + + if ((flags & NSRightAlternateKeyMask) == NSRightAlternateKeyMask + && (EQ (ns_right_alternate_modifier, Qnone) + || (EQ (ns_right_alternate_modifier, Qleft) + && EQ (ns_alternate_modifier, Qnone)))) + modifiers |= rightOptionKey; + + if ((flags & NSLeftAlternateKeyMask) == NSLeftAlternateKeyMask + && EQ (ns_alternate_modifier, Qnone)) + modifiers |= optionKey; + + if ((flags & NSRightCommandKeyMask) == NSRightCommandKeyMask + && (EQ (ns_right_command_modifier, Qnone) + || (EQ (ns_right_command_modifier, Qleft) + && EQ (ns_command_modifier, Qnone)))) + /* Carbon doesn't differentiate between left and right command + keys. */ + modifiers |= cmdKey; + + if ((flags & NSLeftCommandKeyMask) == NSLeftCommandKeyMask + && EQ (ns_command_modifier, Qnone)) + modifiers |= cmdKey; + + result = UCKeyTranslate (layout, [event keyCode], kUCKeyActionDown, + (modifiers >> 8) & 0xFF, LMGetKbdType (), + kUCKeyTranslateNoDeadKeysBit, &dead_key_state, + max_string_length, &actual_string_length, buf); + + if (result != 0) + { + NSLog(@"Failed to translate character '%@' with modifiers %x", + [event characters], modifiers); + return 0; + } + + /* FIXME: What do we do if more than one code unit is returned? */ + if (actual_string_length > 0) + return buf[0]; + return 0; +} +#endif /* NS_IMPL_COCOA */ /* ========================================================================== @@ -2698,7 +2841,7 @@ ns_copy_bits (struct frame *f, NSRect src, NSRect dest) static void ns_scroll_run (struct window *w, struct run *run) /* -------------------------------------------------------------------------- - External (RIF): Insert or delete n lines at line vpos + External (RIF): Insert or delete n lines at line vpos. -------------------------------------------------------------------------- */ { struct frame *f = XFRAME (w->frame); @@ -3057,17 +3200,17 @@ ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row, get_phys_cursor_geometry (w, glyph_row, phys_cursor_glyph, &fx, &fy, &h); /* The above get_phys_cursor_geometry call set w->phys_cursor_width - to the glyph width; replace with CURSOR_WIDTH for (V)BAR cursors. */ + to the glyph width; replace with CURSOR_WIDTH for (V)BAR cursors. */ if (cursor_type == BAR_CURSOR) { if (cursor_width < 1) cursor_width = max (FRAME_CURSOR_WIDTH (f), 1); - /* The bar cursor should never be wider than the glyph. */ + /* The bar cursor should never be wider than the glyph. */ if (cursor_width < w->phys_cursor_width) w->phys_cursor_width = cursor_width; } - /* If we have an HBAR, "cursor_width" MAY specify height. */ + /* If we have an HBAR, "cursor_width" MAY specify height. */ else if (cursor_type == HBAR_CURSOR) { cursor_height = (cursor_width < 1) ? lrint (0.25 * h) : cursor_width; @@ -3319,7 +3462,7 @@ ns_draw_text_decoration (struct glyph_string *s, struct face *face, if (s->for_overlaps) return; - /* Do underline. */ + /* Do underline. */ if (face->underline_p) { if (s->face->underline_type == FACE_UNDER_WAVE) @@ -3337,7 +3480,7 @@ ns_draw_text_decoration (struct glyph_string *s, struct face *face, NSRect r; unsigned long thickness, position; - /* If the prev was underlined, match its appearance. */ + /* If the prev was underlined, match its appearance. */ if (s->prev && s->prev->face->underline_p && s->prev->face->underline_type == FACE_UNDER_LINE && s->prev->underline_thickness > 0) @@ -3349,25 +3492,40 @@ ns_draw_text_decoration (struct glyph_string *s, struct face *face, { struct font *font = font_for_underline_metrics (s); unsigned long descent = s->y + s->height - s->ybase; - - /* Use underline thickness of font, defaulting to 1. */ + unsigned long minimum_offset; + BOOL underline_at_descent_line, use_underline_position_properties; + Lisp_Object val = buffer_local_value (Qunderline_minimum_offset, + s->w->contents); + if (FIXNUMP (val)) + minimum_offset = XFIXNAT (val); + else + minimum_offset = 1; + val = buffer_local_value (Qx_underline_at_descent_line, + s->w->contents); + underline_at_descent_line = !(NILP (val) || EQ (val, Qunbound)); + val = buffer_local_value (Qx_use_underline_position_properties, + s->w->contents); + use_underline_position_properties = + !(NILP (val) || EQ (val, Qunbound)); + + /* Use underline thickness of font, defaulting to 1. */ thickness = (font && font->underline_thickness > 0) ? font->underline_thickness : 1; - /* Determine the offset of underlining from the baseline. */ - if (x_underline_at_descent_line) + /* Determine the offset of underlining from the baseline. */ + if (underline_at_descent_line) position = descent - thickness; - else if (x_use_underline_position_properties + else if (use_underline_position_properties && font && font->underline_position >= 0) position = font->underline_position; else if (font) position = lround (font->descent / 2); else - position = underline_minimum_offset; + position = minimum_offset; - position = max (position, underline_minimum_offset); + position = max (position, minimum_offset); - /* Ensure underlining is not cropped. */ + /* Ensure underlining is not cropped. */ if (descent <= position) { position = descent - 1; @@ -3390,7 +3548,7 @@ ns_draw_text_decoration (struct glyph_string *s, struct face *face, } } /* Do overline. We follow other terms in using a thickness of 1 - and ignoring overline_margin. */ + and ignoring overline_margin. */ if (face->overline_p) { NSRect r; @@ -3404,7 +3562,7 @@ ns_draw_text_decoration (struct glyph_string *s, struct face *face, } /* Do strike-through. We follow other terms for thickness and - vertical position.*/ + vertical position. */ if (face->strike_through_p) { NSRect r; @@ -3511,7 +3669,7 @@ ns_draw_relief (NSRect r, int thickness, char raised_p, [(raised_p ? lightCol : darkCol) set]; - /* TODO: mitering. Using NSBezierPath doesn't work because of color switch. */ + /* TODO: mitering. Using NSBezierPath doesn't work because of color switch. */ /* top */ sr.size.height = thickness; @@ -3585,7 +3743,7 @@ ns_dumpglyphs_box_or_relief (struct glyph_string *s) r = NSMakeRect (s->x, s->y, right_x - s->x + 1, s->height); - /* TODO: Sometimes box_color is 0 and this seems wrong; should investigate. */ + /* TODO: Sometimes box_color is 0 and this seems wrong; should investigate. */ if (s->face->box == FACE_SIMPLE_BOX && s->face->box_color) { ns_draw_box (r, abs (thickness), @@ -3688,7 +3846,7 @@ ns_dumpglyphs_image (struct glyph_string *s, NSRect r) /* Draw BG: if we need larger area than image itself cleared, do that, otherwise, since we composite the image under NS (instead of mucking - with its background color), we must clear just the image area. */ + with its background color), we must clear just the image area. */ if (s->hl == DRAW_MOUSE_FACE) { face = FACE_FROM_ID_OR_NULL (s->f, @@ -3714,7 +3872,7 @@ ns_dumpglyphs_image (struct glyph_string *s, NSRect r) NSRectFill (br); - /* Draw the image.. do we need to draw placeholder if img ==nil? */ + /* Draw the image... do we need to draw placeholder if img == nil? */ if (img != nil) { #ifdef NS_IMPL_COCOA @@ -3740,11 +3898,11 @@ ns_dumpglyphs_image (struct glyph_string *s, NSRect r) if (s->w->phys_cursor_type == FILLED_BOX_CURSOR) tdCol = ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f); else - /* Currently on NS img->mask is always 0. Since + /* Currently on NS img->mask is always 0. Since get_window_cursor_type specifies a hollow box cursor when on - a non-masked image we never reach this clause. But we put it + a non-masked image we never reach this clause. But we put it in, in anticipation of better support for image masks on - NS. */ + NS. */ tdCol = ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), s->f); } else @@ -3752,7 +3910,7 @@ ns_dumpglyphs_image (struct glyph_string *s, NSRect r) tdCol = ns_lookup_indexed_color (NS_FACE_FOREGROUND (face), s->f); } - /* Draw underline, overline, strike-through. */ + /* Draw underline, overline, strike-through. */ ns_draw_text_decoration (s, face, tdCol, br.size.width, br.origin.x); /* Draw relief, if requested */ @@ -4148,7 +4306,7 @@ ns_draw_glyph_string (struct glyph_string *s) emacs_abort (); } - /* Draw box if not done already. */ + /* Draw box if not done already. */ if (!s->for_overlaps && !box_drawn_p && s->face->box != FACE_NO_BOX) { n = ns_get_glyph_string_clip_rect (s, r); @@ -4193,8 +4351,8 @@ ns_send_appdefined (int value) } /* Only post this event if we haven't already posted one. This will end - the [NXApp run] main loop after having processed all events queued at - this moment. */ + the [NXApp run] main loop after having processed all events queued at + this moment. */ #ifdef NS_IMPL_COCOA if (! send_appdefined) @@ -4217,7 +4375,7 @@ ns_send_appdefined (int value) /* We only need one NX_APPDEFINED event to stop NXApp from running. */ send_appdefined = NO; - /* Don't need wakeup timer any more */ + /* Don't need wakeup timer any more. */ if (timed_entry) { [timed_entry invalidate]; @@ -4271,7 +4429,7 @@ check_native_fs () void ns_check_menu_open (NSMenu *menu) { - /* Click in menu bar? */ + /* Click in menu bar? */ NSArray *a = [[NSApp mainMenu] itemArray]; int i; BOOL found = NO; @@ -4367,19 +4525,19 @@ ns_read_socket (struct terminal *terminal, struct input_event *hold_quit) ns_init_events (&ev); q_event_ptr = hold_quit; - /* we manage autorelease pools by allocate/reallocate each time around + /* We manage autorelease pools by allocate/reallocate each time around the loop; strict nesting is occasionally violated but seems not to - matter.. earlier methods using full nesting caused major memory leaks */ + matter... earlier methods using full nesting caused major memory leaks. */ [outerpool release]; outerpool = [[NSAutoreleasePool alloc] init]; - /* If have pending open-file requests, attend to the next one of those. */ + /* If have pending open-file requests, attend to the next one of those. */ if (ns_pending_files && [ns_pending_files count] != 0 && [(EmacsApp *)NSApp openFile: [ns_pending_files objectAtIndex: 0]]) { [ns_pending_files removeObjectAtIndex: 0]; } - /* Deal with pending service requests. */ + /* Deal with pending service requests. */ else if (ns_pending_service_names && [ns_pending_service_names count] != 0 && [(EmacsApp *) NSApp fulfillService: [ns_pending_service_names objectAtIndex: 0] @@ -4432,7 +4590,7 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds, if (hold_event_q.nr > 0) { - /* We already have events pending. */ + /* We already have events pending. */ raise (SIGIO); errno = EINTR; return -1; @@ -4484,13 +4642,13 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds, pthread_mutex_unlock (&select_mutex); - /* Inform fd_handler that select should be called */ + /* Inform fd_handler that select should be called. */ c = 'g'; emacs_write_sig (selfds[1], &c, 1); } else if (nr == 0 && timeout) { - /* No file descriptor, just a timeout, no need to wake fd_handler */ + /* No file descriptor, just a timeout, no need to wake fd_handler. */ double time = timespectod (*timeout); timed_entry = [[NSTimer scheduledTimerWithTimeInterval: time target: NSApp @@ -4502,7 +4660,7 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds, } else /* No timeout and no file descriptors, can this happen? */ { - /* Send appdefined so we exit from the loop */ + /* Send appdefined so we exit from the loop. */ ns_send_appdefined (-1); } @@ -4527,7 +4685,7 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds, if (t == -2) { - /* The NX_APPDEFINED event we received was a timeout. */ + /* The NX_APPDEFINED event we received was a timeout. */ result = 0; } else if (t == -1) @@ -4539,7 +4697,7 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds, } else { - /* Received back from select () in fd_handler; copy the results */ + /* 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; @@ -4559,11 +4717,11 @@ ns_select (int nfds, fd_set *readfds, fd_set *writefds, #ifdef HAVE_PTHREAD void ns_run_loop_break () -/* Break out of the NS run loop in ns_select or ns_read_socket. */ +/* Break out of the NS run loop in ns_select or ns_read_socket. */ { NSTRACE_WHEN (NSTRACE_GROUP_EVENTS, "ns_run_loop_break"); - /* If we don't have a GUI, don't send the event. */ + /* If we don't have a GUI, don't send the event. */ if (NSApp != NULL) ns_send_appdefined(-1); } @@ -4593,7 +4751,7 @@ ns_set_vertical_scroll_bar (struct window *window, int top, left, height, width; BOOL update_p = YES; - /* optimization; display engine sends WAY too many of these.. */ + /* Optimization; display engine sends WAY too many of these. */ if (!NILP (window->vertical_scroll_bar)) { bar = XNS_SCROLL_BAR (window->vertical_scroll_bar); @@ -4620,14 +4778,14 @@ ns_set_vertical_scroll_bar (struct window *window, left = WINDOW_SCROLL_BAR_AREA_X (window); r = NSMakeRect (left, top, width, height); - /* the parent view is flipped, so we need to flip y value */ + /* 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); XSETWINDOW (win, window); block_input (); - /* we want at least 5 lines to display a scrollbar */ + /* We want at least 5 lines to display a scrollbar. */ if (WINDOW_TOTAL_LINES (window) < 5) { if (!NILP (window->vertical_scroll_bar)) @@ -4648,7 +4806,7 @@ ns_set_vertical_scroll_bar (struct window *window, ns_clear_frame_area (f, left, top, width, height); bar = [[EmacsScroller alloc] initFrame: r window: win]; - wset_vertical_scroll_bar (window, make_save_ptr (bar)); + wset_vertical_scroll_bar (window, make_mint_ptr (bar)); update_p = YES; } else @@ -4675,7 +4833,7 @@ static void ns_set_horizontal_scroll_bar (struct window *window, int portion, int whole, int position) /* -------------------------------------------------------------------------- - External (hook): Update or add scrollbar + External (hook): Update or add scrollbar. -------------------------------------------------------------------------- */ { Lisp_Object win; @@ -4687,7 +4845,7 @@ ns_set_horizontal_scroll_bar (struct window *window, int window_x, window_width; BOOL update_p = YES; - /* optimization; display engine sends WAY too many of these.. */ + /* Optimization; display engine sends WAY too many of these. */ if (!NILP (window->horizontal_scroll_bar)) { bar = XNS_SCROLL_BAR (window->horizontal_scroll_bar); @@ -4714,7 +4872,7 @@ ns_set_horizontal_scroll_bar (struct window *window, top = WINDOW_SCROLL_BAR_AREA_Y (window); r = NSMakeRect (left, top, width, height); - /* the parent view is flipped, so we need to flip y value */ + /* 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); @@ -4727,7 +4885,7 @@ ns_set_horizontal_scroll_bar (struct window *window, ns_clear_frame_area (f, left, top, width, height); bar = [[EmacsScroller alloc] initFrame: r window: win]; - wset_horizontal_scroll_bar (window, make_save_ptr (bar)); + wset_horizontal_scroll_bar (window, make_mint_ptr (bar)); update_p = YES; } else @@ -4746,7 +4904,7 @@ ns_set_horizontal_scroll_bar (struct window *window, /* If there are both horizontal and vertical scroll-bars they leave a square that belongs to neither. We need to clear it otherwise - it fills with junk. */ + it fills with junk. */ if (!NILP (window->vertical_scroll_bar)) ns_clear_frame_area (f, WINDOW_SCROLL_BAR_AREA_X (window), top, NS_SCROLL_BAR_HEIGHT (f), height); @@ -4869,7 +5027,7 @@ x_display_pixel_width (struct ns_display_info *dpyinfo) static Lisp_Object ns_string_to_lispmod (const char *s) /* -------------------------------------------------------------------------- - Convert modifier name to lisp symbol + Convert modifier name to lisp symbol. -------------------------------------------------------------------------- */ { if (!strncmp (SSDATA (SYMBOL_NAME (Qmeta)), s, 10)) @@ -4894,7 +5052,7 @@ ns_default (const char *parameter, Lisp_Object *result, Lisp_Object yesval, Lisp_Object noval, BOOL is_float, BOOL is_modstring) /* -------------------------------------------------------------------------- - Check a parameter value in user's preferences + Check a parameter value in user's preferences. -------------------------------------------------------------------------- */ { const char *value = ns_get_defaults_value (parameter); @@ -4935,7 +5093,7 @@ ns_initialize_display_info (struct ns_display_info *dpyinfo) dpyinfo->n_planes = NSBitsPerPixelFromDepth (depth); dpyinfo->color_table = xmalloc (sizeof *dpyinfo->color_table); dpyinfo->color_table->colors = NULL; - dpyinfo->root_window = 42; /* a placeholder.. */ + dpyinfo->root_window = 42; /* A placeholder. */ dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame = NULL; dpyinfo->n_fonts = 0; dpyinfo->smallest_font_height = 1; @@ -4945,11 +5103,11 @@ ns_initialize_display_info (struct ns_display_info *dpyinfo) } -/* This and next define (many of the) public functions in this file. */ +/* This and next define (many of the) public functions in this file. */ /* x_... are generic versions in xdisp.c that we, and other terms, get away with using despite presence in the "system dependent" redisplay interface. In addition, many of the ns_ methods have code that is - shared with all terms, indicating need for further refactoring. */ + shared with all terms, indicating need for further refactoring. */ extern frame_parm_handler ns_frame_parm_handlers[]; static struct redisplay_interface ns_redisplay_interface = { @@ -4985,11 +5143,11 @@ static struct redisplay_interface ns_redisplay_interface = static void ns_delete_display (struct ns_display_info *dpyinfo) { - /* TODO... */ + /* TODO... */ } -/* This function is called when the last frame on a display is deleted. */ +/* This function is called when the last frame on a display is deleted. */ static void ns_delete_terminal (struct terminal *terminal) { @@ -5097,9 +5255,9 @@ ns_term_init (Lisp_Object display_name) 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. */ + The view will then ask the NSApp to stop and return to Emacs. */ [EmacsApp sharedApplication]; if (NSApp == nil) return NULL; @@ -5171,7 +5329,7 @@ ns_term_init (Lisp_Object display_name) { color = XCAR (color_map); name = SSDATA (XCAR (color)); - c = XINT (XCDR (color)); + c = XFIXNUM (XCDR (color)); [cl setColor: [NSColor colorForEmacsRed: RED_FROM_ULONG (c) / 255.0 green: GREEN_FROM_ULONG (c) / 255.0 @@ -5203,7 +5361,7 @@ ns_term_init (Lisp_Object display_name) #ifdef NS_IMPL_GNUSTEP Vwindow_system_version = build_string (gnustep_base_version); #else - /*PSnextrelease (128, c); */ + /* PSnextrelease (128, c); */ char c[DBL_BUFSIZE_BOUND]; int len = dtoastr (c, sizeof c, 0, 0, NSAppKitVersionNumber); Vwindow_system_version = make_unibyte_string (c, len); @@ -5289,7 +5447,7 @@ ns_term_init (Lisp_Object display_name) #endif /* macOS menu setup */ /* Register our external input/output types, used for determining - applicable services and also drag/drop eligibility. */ + applicable services and also drag/drop eligibility. */ NSTRACE_MSG ("Input/output types"); @@ -5454,23 +5612,6 @@ ns_term_shutdown (int sig) } #endif - if (represented_filename != nil && represented_frame) - { - NSString *fstr = represented_filename; - NSView *view = FRAME_NS_VIEW (represented_frame); -#ifdef NS_IMPL_COCOA - /* work around a bug observed on 10.3 and later where - setTitleWithRepresentedFilename does not clear out previous state - if given filename does not exist */ - if (! [[NSFileManager defaultManager] fileExistsAtPath: fstr]) - [[view window] setRepresentedFilename: @""]; -#endif - [[view window] setRepresentedFilename: fstr]; - [represented_filename release]; - represented_filename = nil; - represented_frame = NULL; - } - if (type == NSEventTypeApplicationDefined) { switch ([theEvent data2]) @@ -5499,7 +5640,7 @@ ns_term_shutdown (int sig) /* Events posted by ns_send_appdefined interrupt the run loop here. But, if a modal window is up, an appdefined can still come through, (e.g., from a makeKeyWindow event) but stopping self also stops the - modal loop. Just defer it until later. */ + modal loop. Just defer it until later. */ if ([NSApp modalWindow] == nil) { last_appdefined_event_data = [theEvent data1]; @@ -5564,7 +5705,7 @@ ns_term_shutdown (int sig) } -/* Open a file (used by below, after going into queue read by ns_read_socket) */ +/* Open a file (used by below, after going into queue read by ns_read_socket). */ - (BOOL) openFile: (NSString *)fileName { NSTRACE ("[EmacsApp openFile:]"); @@ -5594,7 +5735,7 @@ ns_term_shutdown (int sig) - (void)applicationDidFinishLaunching: (NSNotification *)notification /* -------------------------------------------------------------------------- - When application is loaded, terminate event loop in ns_term_init + When application is loaded, terminate event loop in ns_term_init. -------------------------------------------------------------------------- */ { NSTRACE ("[EmacsApp applicationDidFinishLaunching:]"); @@ -5617,7 +5758,7 @@ ns_term_shutdown (int sig) if ([NSApp activationPolicy] == NSApplicationActivationPolicyProhibited) { /* Set the app's activation policy to regular when we run outside of a bundle. This is already done for us by Info.plist when we - run inside a bundle. */ + run inside a bundle. */ [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; [NSApp setApplicationIconImage: [EmacsImage @@ -5721,7 +5862,7 @@ not_in_argv (NSString *arg) return 1; } -/* Notification from the Workspace to open a file */ +/* Notification from the Workspace to open a file. */ - (BOOL)application: sender openFile: (NSString *)file { if (ns_do_open_file || not_in_argv (file)) @@ -5730,7 +5871,7 @@ not_in_argv (NSString *arg) } -/* Open a file as a temporary file */ +/* Open a file as a temporary file. */ - (BOOL)application: sender openTempFile: (NSString *)file { if (ns_do_open_file || not_in_argv (file)) @@ -5739,7 +5880,7 @@ not_in_argv (NSString *arg) } -/* Notification from the Workspace to open a file noninteractively (?) */ +/* Notification from the Workspace to open a file noninteractively (?). */ - (BOOL)application: sender openFileWithoutUI: (NSString *)file { if (ns_do_open_file || not_in_argv (file)) @@ -5747,7 +5888,7 @@ not_in_argv (NSString *arg) return YES; } -/* Notification from the Workspace to open multiple files */ +/* Notification from the Workspace to open multiple files. */ - (void)application: sender openFiles: (NSArray *)fileList { NSEnumerator *files = [fileList objectEnumerator]; @@ -5771,11 +5912,11 @@ not_in_argv (NSString *arg) } -/* TODO: these may help w/IO switching btwn terminal and NSApp */ +/* TODO: these may help w/IO switching between terminal and NSApp. */ - (void)applicationWillBecomeActive: (NSNotification *)notification { NSTRACE ("[EmacsApp applicationWillBecomeActive:]"); - //ns_app_active=YES; + // ns_app_active=YES; } - (void)applicationDidBecomeActive: (NSNotification *)notification @@ -5786,7 +5927,7 @@ not_in_argv (NSString *arg) if (! applicationDidFinishLaunchingCalled) [self applicationDidFinishLaunching:notification]; #endif - //ns_app_active=YES; + // ns_app_active=YES; ns_update_auto_hide_menu_bar (); // No constraining takes place when the application is not active. @@ -5796,7 +5937,7 @@ not_in_argv (NSString *arg) { NSTRACE ("[EmacsApp applicationDidResignActive:]"); - //ns_app_active=NO; + // ns_app_active=NO; ns_send_appdefined (-1); } @@ -5814,7 +5955,7 @@ not_in_argv (NSString *arg) The timeout specified to ns_select has passed. -------------------------------------------------------------------------- */ { - /*NSTRACE ("timeout_handler"); */ + /* NSTRACE ("timeout_handler"); */ ns_send_appdefined (-2); } @@ -5825,7 +5966,7 @@ not_in_argv (NSString *arg) - (void)fd_handler:(id)unused /* -------------------------------------------------------------------------- - Check data waiting on file descriptors and terminate if so + Check data waiting on file descriptors and terminate if so. -------------------------------------------------------------------------- */ { int result; @@ -5920,7 +6061,7 @@ not_in_argv (NSString *arg) ========================================================================== */ -/* called from system: queue for next pass through event loop */ +/* Called from system: queue for next pass through event loop. */ - (void)requestService: (NSPasteboard *)pboard userData: (NSString *)userData error: (NSString **)error @@ -5931,7 +6072,7 @@ not_in_argv (NSString *arg) } -/* called from ns_read_socket to clear queue */ +/* Called from ns_read_socket to clear queue. */ - (BOOL)fulfillService: (NSString *)name withArg: (NSString *)arg { struct frame *emacsframe = SELECTED_FRAME (); @@ -5956,7 +6097,6 @@ not_in_argv (NSString *arg) @end /* EmacsApp */ - /* ========================================================================== EmacsView implementation @@ -5966,7 +6106,7 @@ not_in_argv (NSString *arg) @implementation EmacsView -/* needed to inform when window closed from LISP */ +/* Needed to inform when window closed from lisp. */ - (void) setWindowClosing: (BOOL)closing { NSTRACE ("[EmacsView setWindowClosing:%d]", closing); @@ -5985,7 +6125,7 @@ not_in_argv (NSString *arg) } -/* called on font panel selection */ +/* Called on font panel selection. */ - (void)changeFont: (id)sender { NSEvent *e = [[self window] currentEvent]; @@ -6016,7 +6156,7 @@ not_in_argv (NSString *arg) emacs_event->code = KEY_NS_CHANGE_FONT; size = [newFont pointSize]; - ns_input_fontsize = make_number (lrint (size)); + ns_input_fontsize = make_fixnum (lrint (size)); ns_input_font = build_string ([[newFont familyName] UTF8String]); EV_TRAILER (e); } @@ -6041,13 +6181,19 @@ not_in_argv (NSString *arg) if (!NSIsEmptyRect (visible)) [self addCursorRect: visible cursor: currentCursor]; - [currentCursor setOnMouseEntered: YES]; + +#if defined (NS_IMPL_GNUSTEP) || MAC_OS_X_VERSION_MIN_REQUIRED < 101300 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 + if ([currentCursor respondsToSelector: @selector(setOnMouseEntered)]) +#endif + [currentCursor setOnMouseEntered: YES]; +#endif } /*****************************************************************************/ -/* Keyboard handling. */ +/* Keyboard handling. */ #define NS_KEYLOG 0 - (void)keyDown: (NSEvent *)theEvent @@ -6056,12 +6202,11 @@ not_in_argv (NSString *arg) int code; unsigned fnKeysym = 0; static NSMutableArray *nsEvArray; - int left_is_none; unsigned int flags = [theEvent modifierFlags]; NSTRACE ("[EmacsView keyDown:]"); - /* Rhapsody and macOS give up and down events for the arrow keys */ + /* Rhapsody and macOS give up and down events for the arrow keys. */ if (ns_fake_keydown == YES) ns_fake_keydown = NO; else if ([theEvent type] != NSEventTypeKeyDown) @@ -6072,7 +6217,7 @@ not_in_argv (NSString *arg) if (![[self window] isKeyWindow] && [[theEvent window] isKindOfClass: [EmacsWindow class]] - /* we must avoid an infinite loop here. */ + /* We must avoid an infinite loop here. */ && (EmacsView *)[[theEvent window] delegate] != self) { /* XXX: There is an occasional condition in which, when Emacs display @@ -6080,7 +6225,7 @@ not_in_argv (NSString *arg) selects it, then processes some interrupt-driven input (dispnew.c:3878), OS will send the event to the correct NSWindow, but for some reason that window has its first responder set to the NSView - most recently updated (I guess), which is not the correct one. */ + most recently updated (I guess), which is not the correct one. */ [(EmacsView *)[[theEvent window] delegate] keyDown: theEvent]; return; } @@ -6090,7 +6235,7 @@ not_in_argv (NSString *arg) [NSCursor setHiddenUntilMouseMoves: YES]; - if (hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)) + if (hlinfo->mouse_face_hidden && FIXNUMP (Vmouse_highlight)) { clear_mouse_face (hlinfo); hlinfo->mouse_face_hidden = 1; @@ -6098,19 +6243,14 @@ not_in_argv (NSString *arg) 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; - + /* FIXME: What should happen for key sequences with more than + one character? */ code = ([[theEvent charactersIgnoringModifiers] length] == 0) ? 0 : [[theEvent charactersIgnoringModifiers] characterAtIndex: 0]; - /* (Carbon way: [theEvent keyCode]) */ - - /* is it a "function key"? */ + /* Is it a "function key"? */ /* Note: Sometimes a plain key will have the NSEventModifierFlagNumericPad - flag set (this is probably a bug in the OS). - */ + flag set (this is probably a bug in the OS). */ if (code < 0x00ff && (flags&NSEventModifierFlagNumericPad)) { fnKeysym = ns_convert_key ([theEvent keyCode] | NSEventModifierFlagNumericPad); @@ -6123,14 +6263,13 @@ not_in_argv (NSString *arg) if (fnKeysym) { /* COUNTERHACK: map 'Delete' on upper-right main KB to 'Backspace', - because Emacs treats Delete and KP-Delete same (in simple.el). */ + because Emacs treats Delete and KP-Delete same (in simple.el). */ if ((fnKeysym == 0xFFFF && [theEvent keyCode] == 0x33) #ifdef NS_IMPL_GNUSTEP /* GNUstep uses incompatible keycodes, even for those that are supposed to be hardware independent. Just check for delete. Keypad delete does not have keysym 0xFFFF. - See https://savannah.gnu.org/bugs/?25395 - */ + See https://savannah.gnu.org/bugs/?25395 */ || (fnKeysym == 0xFFFF && code == 127) #endif ) @@ -6139,142 +6278,65 @@ not_in_argv (NSString *arg) code = fnKeysym; } - /* are there modifiers? */ - emacs_event->modifiers = 0; - - if (flags & NSEventModifierFlagHelp) - emacs_event->modifiers |= hyper_modifier; - - if (flags & NSEventModifierFlagShift) - emacs_event->modifiers |= shift_modifier; - - is_right_key = (flags & NSRightCommandKeyMask) == NSRightCommandKeyMask; - is_left_key = (flags & NSLeftCommandKeyMask) == NSLeftCommandKeyMask - || (! is_right_key && (flags & NSEventModifierFlagCommand) == NSEventModifierFlagCommand); - - if (is_right_key) - emacs_event->modifiers |= parse_solitary_modifier - (EQ (ns_right_command_modifier, Qleft) - ? ns_command_modifier - : ns_right_command_modifier); - - if (is_left_key) - { - emacs_event->modifiers |= parse_solitary_modifier - (ns_command_modifier); - - /* if super (default), take input manager's word so things like - dvorak / qwerty layout work */ - if (EQ (ns_command_modifier, Qsuper) - && !fnKeysym - && [[theEvent characters] length] != 0) - { - /* XXX: the code we get will be unshifted, so if we have - a shift modifier, must convert ourselves */ - if (!(flags & NSEventModifierFlagShift)) - code = [[theEvent characters] characterAtIndex: 0]; -#if 0 - /* this is ugly and also requires linking w/Carbon framework - (for LMGetKbdType) so for now leave this rare (?) case - undealt with.. in future look into CGEvent methods */ - else - { - long smv = GetScriptManagerVariable (smKeyScript); - Handle uchrHandle = GetResource - ('uchr', GetScriptVariable (smv, smScriptKeys)); - UInt32 dummy = 0; - UCKeyTranslate ((UCKeyboardLayout *) *uchrHandle, - [[theEvent characters] characterAtIndex: 0], - kUCKeyActionDisplay, - (flags & ~NSEventModifierFlagCommand) >> 8, - LMGetKbdType (), kUCKeyTranslateNoDeadKeysMask, - &dummy, 1, &dummy, &code); - code &= 0xFF; - } -#endif - } - } - - is_right_key = (flags & NSRightControlKeyMask) == NSRightControlKeyMask; - is_left_key = (flags & NSLeftControlKeyMask) == NSLeftControlKeyMask - || (! is_right_key && (flags & NSEventModifierFlagControl) == NSEventModifierFlagControl); - - if (is_right_key) - emacs_event->modifiers |= parse_solitary_modifier - (EQ (ns_right_control_modifier, Qleft) - ? ns_control_modifier - : ns_right_control_modifier); - - if (is_left_key) - emacs_event->modifiers |= parse_solitary_modifier - (ns_control_modifier); - - if (flags & NS_FUNCTION_KEY_MASK && !fnKeysym) - emacs_event->modifiers |= - parse_solitary_modifier (ns_function_modifier); - - left_is_none = NILP (ns_alternate_modifier) - || EQ (ns_alternate_modifier, Qnone); - - is_right_key = (flags & NSRightAlternateKeyMask) - == NSRightAlternateKeyMask; - is_left_key = (flags & NSLeftAlternateKeyMask) == NSLeftAlternateKeyMask - || (! is_right_key - && (flags & NSEventModifierFlagOption) == NSEventModifierFlagOption); - - if (is_right_key) - { - if ((NILP (ns_right_alternate_modifier) - || EQ (ns_right_alternate_modifier, Qnone) - || (EQ (ns_right_alternate_modifier, Qleft) && left_is_none)) - && !fnKeysym) - { /* accept pre-interp alt comb */ - if ([[theEvent characters] length] > 0) - code = [[theEvent characters] characterAtIndex: 0]; - /*HACK: clear lone shift modifier to stop next if from firing */ - if (emacs_event->modifiers == shift_modifier) - emacs_event->modifiers = 0; - } - else - emacs_event->modifiers |= parse_solitary_modifier - (EQ (ns_right_alternate_modifier, Qleft) - ? ns_alternate_modifier - : ns_right_alternate_modifier); - } - - if (is_left_key) /* default = meta */ - { - if (left_is_none && !fnKeysym) - { /* accept pre-interp alt comb */ - if ([[theEvent characters] length] > 0) - code = [[theEvent characters] characterAtIndex: 0]; - /*HACK: clear lone shift modifier to stop next if from firing */ - if (emacs_event->modifiers == shift_modifier) - emacs_event->modifiers = 0; - } - else - emacs_event->modifiers |= - parse_solitary_modifier (ns_alternate_modifier); - } - - if (NS_KEYLOG) - fprintf (stderr, "keyDown: code =%x\tfnKey =%x\tflags = %x\tmods = %x\n", - (unsigned) code, fnKeysym, flags, emacs_event->modifiers); - - /* if it was a function key or had modifiers, pass it directly to emacs */ + /* The ⌘ and ⌥ modifiers can be either shift-like (for alternate + character input) or control-like (as command prefix). If we + have only shift-like modifiers, then we should use the + translated characters (returned by the characters method); if + we have only control-like modifiers, then we should use the + untranslated characters (returned by the + charactersIgnoringModifiers method). An annoyance happens if + we have both shift-like and control-like modifiers because + the NSEvent API doesn’t let us ignore only some modifiers. + In that case we use UCKeyTranslate (ns_get_shifted_character) + to look up the correct character. */ + + /* EV_MODIFIERS2 uses parse_solitary_modifier on all known + modifier keys, which returns 0 for shift-like modifiers. + Therefore its return value is the set of control-like + modifiers. */ + emacs_event->modifiers = EV_MODIFIERS2 (flags); + + /* Function keys (such as the F-keys, arrow keys, etc.) set + modifiers as though the fn key has been pressed when it + hasn't. Also some combinations of fn and a function key + return a different key than was pressed (e.g. fn-<left> gives + <home>). We need to unset the fn modifier in these cases. + FIXME: Can we avoid setting it in the first place? */ + if (fnKeysym && (flags & NS_FUNCTION_KEY_MASK)) + emacs_event->modifiers ^= parse_solitary_modifier (ns_function_modifier); + + if (NS_KEYLOG) + fprintf (stderr, "keyDown: code =%x\tfnKey =%x\tflags = %x\tmods = %x\n", + code, fnKeysym, flags, emacs_event->modifiers); + + /* If it was a function key or had control-like modifiers, pass + it directly to Emacs. */ if (fnKeysym || (emacs_event->modifiers && (emacs_event->modifiers != shift_modifier) && [[theEvent charactersIgnoringModifiers] length] > 0)) -/*[[theEvent characters] length] */ { emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT; + /* FIXME: What are the next four lines supposed to do? */ if (code < 0x20) code |= (1<<28)|(3<<16); else if (code == 0x7f) code |= (1<<28)|(3<<16); else if (!fnKeysym) - emacs_event->kind = code > 0xFF - ? MULTIBYTE_CHAR_KEYSTROKE_EVENT : ASCII_KEYSTROKE_EVENT; + { +#ifdef NS_IMPL_COCOA + /* We potentially have both shift- and control-like + modifiers in use, so find the correct character + ignoring any control-like ones. */ + code = ns_get_shifted_character (theEvent); +#endif + + /* FIXME: This seems wrong, characters in the range + [0x80, 0xFF] are not ASCII characters. Can’t we just + use MULTIBYTE_CHAR_KEYSTROKE_EVENT here for all kinds + of characters? */ + emacs_event->kind = code > 0xFF + ? MULTIBYTE_CHAR_KEYSTROKE_EVENT : ASCII_KEYSTROKE_EVENT; + } emacs_event->code = code; EV_TRAILER (theEvent); @@ -6283,23 +6345,44 @@ not_in_argv (NSString *arg) } } + /* If we get here, a non-function key without control-like modifiers + was hit. Use interpretKeyEvents, which in turn will call + insertText; see + https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/EventOverview/HandlingKeyEvents/HandlingKeyEvents.html. */ if (NS_KEYLOG && !processingCompose) fprintf (stderr, "keyDown: Begin compose sequence.\n"); + /* FIXME: interpretKeyEvents doesn’t seem to send insertText if ⌘ is + used as shift-like modifier, at least on El Capitan. Mask it + out. This shouldn’t be needed though; we should figure out what + the correct way of handling ⌘ is. */ + if ([theEvent modifierFlags] & NSEventModifierFlagCommand) + theEvent = [NSEvent keyEventWithType:[theEvent type] + location:[theEvent locationInWindow] + modifierFlags:[theEvent modifierFlags] & ~NSEventModifierFlagCommand + timestamp:[theEvent timestamp] + windowNumber:[theEvent windowNumber] + context:nil + characters:[theEvent characters] + charactersIgnoringModifiers:[theEvent charactersIgnoringModifiers] + isARepeat:[theEvent isARepeat] + keyCode:[theEvent keyCode]]; + processingCompose = YES; + /* FIXME: Use [NSArray arrayWithObject:theEvent]? */ [nsEvArray addObject: theEvent]; [self interpretKeyEvents: nsEvArray]; [nsEvArray removeObject: theEvent]; } -/* <NSTextInput> implementation (called through super interpretKeyEvents:]). */ +/* <NSTextInput> implementation (called through [super interpretKeyEvents:]). */ /* <NSTextInput>: called when done composing; - NOTE: also called when we delete over working text, followed immed. - by doCommandBySelector: deleteBackward: */ + NOTE: also called when we delete over working text, followed + immediately by doCommandBySelector: deleteBackward: */ - (void)insertText: (id)aString { NSString *s; @@ -6321,7 +6404,7 @@ not_in_argv (NSString *arg) if (!emacs_event) return; - /* first, clear any working text */ + /* First, clear any working text. */ if (workingText != nil) [self deleteWorkingText]; @@ -6330,7 +6413,7 @@ not_in_argv (NSString *arg) However, we probably can't use SAFE_NALLOCA here because it might exit nonlocally. */ - /* now insert the string as keystrokes */ + /* Now insert the string as keystrokes. */ for (NSUInteger i = 0; i < len; i++) { NSUInteger code = [s characterAtIndex:i]; @@ -6343,7 +6426,7 @@ not_in_argv (NSString *arg) ++i; } } - /* TODO: still need this? */ + /* TODO: still need this? */ if (code == 0x2DC) code = '~'; /* 0x7E */ if (code != 32) /* Space */ @@ -6356,7 +6439,7 @@ not_in_argv (NSString *arg) } -/* <NSTextInput>: inserts display of composing characters */ +/* <NSTextInput>: inserts display of composing characters. */ - (void)setMarkedText: (id)aString selectedRange: (NSRange)selRange { NSString *str = [aString respondsToSelector: @selector (string)] ? @@ -6388,7 +6471,7 @@ not_in_argv (NSString *arg) } -/* delete display of composing characters [not in <NSTextInput>] */ +/* Delete display of composing characters [not in <NSTextInput>]. */ - (void)deleteWorkingText { NSTRACE ("[EmacsView deleteWorkingText]"); @@ -6441,7 +6524,7 @@ not_in_argv (NSString *arg) } -/* used to position char selection windows, etc. */ +/* Used to position char selection windows, etc. */ - (NSRect)firstRectForCharacterRange: (NSRange)theRange { NSRect rect; @@ -6501,8 +6584,8 @@ not_in_argv (NSString *arg) processingCompose = NO; if (aSelector == @selector (deleteBackward:)) { - /* happens when user backspaces over an ongoing composition: - throw a 'delete' into the event queue */ + /* Happens when user backspaces over an ongoing composition: + throw a 'delete' into the event queue. */ if (!emacs_event) return; emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT; @@ -6547,7 +6630,7 @@ not_in_argv (NSString *arg) return str; } -/* End <NSTextInput> impl. */ +/* End <NSTextInput> implementation. */ /*****************************************************************************/ @@ -6565,8 +6648,8 @@ not_in_argv (NSString *arg) return; dpyinfo->last_mouse_frame = emacsframe; - /* appears to be needed to prevent spurious movement events generated on - button clicks */ + /* Appears to be needed to prevent spurious movement events generated on + button clicks. */ emacsframe->mouse_moved = 0; if ([theEvent type] == NSEventTypeScrollWheel) @@ -6602,8 +6685,8 @@ not_in_argv (NSString *arg) static int totalDeltaX, totalDeltaY; int lineHeight; - if (NUMBERP (ns_mwheel_line_height)) - lineHeight = XINT (ns_mwheel_line_height); + if (FIXNUMP (ns_mwheel_line_height)) + lineHeight = XFIXNUM (ns_mwheel_line_height); else { /* FIXME: Use actual line height instead of the default. */ @@ -6672,7 +6755,7 @@ not_in_argv (NSString *arg) return; emacs_event->kind = horizontal ? HORIZ_WHEEL_EVENT : WHEEL_EVENT; - emacs_event->arg = (make_number (lines)); + emacs_event->arg = (make_fixnum (lines)); emacs_event->code = 0; emacs_event->modifiers = EV_MODIFIERS (theEvent) | @@ -6685,7 +6768,8 @@ not_in_argv (NSString *arg) #if defined (NS_IMPL_GNUSTEP) || MAC_OS_X_VERSION_MIN_REQUIRED < 1070 { CGFloat delta = [theEvent deltaY]; - /* Mac notebooks send wheel events w/delta =0 when trackpad scrolling */ + /* Mac notebooks send wheel events with delta equal to 0 + when trackpad scrolling. */ if (delta == 0) { delta = [theEvent deltaX]; @@ -6762,7 +6846,7 @@ not_in_argv (NSString *arg) } -/* Tell emacs the mouse has moved. */ +/* Tell emacs the mouse has moved. */ - (void)mouseMoved: (NSEvent *)e { Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (emacsframe); @@ -6777,14 +6861,14 @@ not_in_argv (NSString *arg) dpyinfo->last_mouse_motion_x = pt.x; dpyinfo->last_mouse_motion_y = pt.y; - /* update any mouse face */ + /* Update any mouse face. */ if (hlinfo->mouse_face_hidden) { hlinfo->mouse_face_hidden = 0; clear_mouse_face (hlinfo); } - /* tooltip handling */ + /* Tooltip handling. */ previous_help_echo_string = help_echo_string; help_echo_string = Qnil; @@ -6819,7 +6903,7 @@ not_in_argv (NSString *arg) { /* NOTE: help_echo_{window,pos,object} are set in xdisp.c (note_mouse_highlight), which is called through the - note_mouse_movement () call above */ + note_mouse_movement () call above. */ any_help_event_p = YES; gen_help_event (help_echo_string, frame, help_echo_window, help_echo_object, help_echo_pos); @@ -6903,7 +6987,7 @@ not_in_argv (NSString *arg) if (wait_for_tool_bar) { /* The toolbar height is always 0 in fullscreen and undecorated - frames, so don't wait for it to become available. */ + frames, so don't wait for it to become available. */ if (FRAME_TOOLBAR_HEIGHT (emacsframe) == 0 && FRAME_UNDECORATED (emacsframe) == false && ! [self isFullscreen]) @@ -6951,7 +7035,7 @@ not_in_argv (NSString *arg) wr = NSMakeRect (0, 0, neww, newh); [view setFrame: wr]; - // to do: consider using [NSNotificationCenter postNotificationName:]. + // To do: consider using [NSNotificationCenter postNotificationName:]. [self windowDidMove: // Update top/left. [NSNotification notificationWithName:NSWindowDidMoveNotification object:[view window]]]; @@ -6963,7 +7047,7 @@ not_in_argv (NSString *arg) } - (NSSize)windowWillResize: (NSWindow *)sender toSize: (NSSize)frameSize -/* normalize frame to gridded text size */ +/* Normalize frame to gridded text size. */ { int extra = 0; @@ -7005,7 +7089,7 @@ not_in_argv (NSString *arg) rows = MINHEIGHT; #ifdef NS_IMPL_COCOA { - /* this sets window title to have size in it; the wm does this under GS */ + /* This sets window title to have size in it; the wm does this under GS. */ NSRect r = [[self window] frame]; if (r.size.height == frameSize.height && r.size.width == frameSize.width) { @@ -7038,12 +7122,12 @@ not_in_argv (NSString *arg) NSTRACE_MSG ("cols: %d rows: %d", cols, rows); - /* Restrict the new size to the text gird. + /* Restrict the new size to the text grid. Don't restrict the width if the user only adjusted the height, and vice versa. (Without this, the frame would shrink, and move slightly, if the window was resized by dragging one of its - borders.) */ + borders.) */ if (!frame_resize_pixelwise) { NSRect r = [[self window] frame]; @@ -7095,8 +7179,8 @@ not_in_argv (NSString *arg) 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 */ + without getting a willResize, therefore we need to act as if we got + the willResize now. */ NSSize sz = [theWindow frame].size; sz = [self windowWillResize: theWindow toSize: sz]; #endif /* NS_IMPL_GNUSTEP */ @@ -7167,7 +7251,7 @@ not_in_argv (NSString *arg) ns_frame_rehighlight (emacsframe); /* FIXME: for some reason needed on second and subsequent clicks away - from sole-frame Emacs to get hollow box to show */ + from sole-frame Emacs to get hollow box to show. */ if (!windowClosing && [[self window] isVisible] == YES) { x_update_cursor (emacsframe, 1); @@ -7399,7 +7483,7 @@ not_in_argv (NSString *arg) /* macOS Sierra automatically enables tabbed windows. We can't allow this to be enabled until it's available on a Free system. - Currently it only happens by accident and is buggy anyway. */ + Currently it only happens by accident and is buggy anyway. */ #if defined (NS_IMPL_COCOA) \ && MAC_OS_X_VERSION_MAX_ALLOWED >= 101200 #if MAC_OS_X_VERSION_MIN_REQUIRED < 101200 @@ -7441,7 +7525,7 @@ not_in_argv (NSString *arg) /* Called AFTER method below, but before our windowWillResize call there leads to windowDidResize -> x_set_window_size. Update emacs' notion of frame - location so set_window_size moves the frame. */ + location so set_window_size moves the frame. */ - (BOOL)windowShouldZoom: (NSWindow *)sender toFrame: (NSRect)newFrame { NSTRACE (("[EmacsView windowShouldZoom:toFrame:" NSTRACE_FMT_RECT "]" @@ -7455,7 +7539,7 @@ not_in_argv (NSString *arg) /* Override to do something slightly nonstandard, but nice. First click on zoom button will zoom vertically. Second will zoom completely. Third - returns to original. */ + returns to original. */ - (NSRect)windowWillUseStandardFrame:(NSWindow *)sender defaultFrame:(NSRect)defaultFrame { @@ -7536,7 +7620,7 @@ not_in_argv (NSString *arg) { NSTRACE_MSG ("FULLSCREEN_MAXIMIZED"); - result = defaultFrame; /* second click */ + result = defaultFrame; /* second click */ maximized_width = result.size.width; maximized_height = result.size.height; [self setFSValue: FULLSCREEN_MAXIMIZED]; @@ -7817,7 +7901,7 @@ not_in_argv (NSString *arg) NSScreen *screen = [w screen]; #if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1090 - /* Hide ghost menu bar on secondary monitor? */ + /* Hide ghost menu bar on secondary monitor? */ if (! onFirstScreen #if MAC_OS_X_VERSION_MIN_REQUIRED < 1090 && [NSScreen respondsToSelector: @selector(screensHaveSeparateSpaces)] @@ -7896,7 +7980,8 @@ not_in_argv (NSString *arg) f->border_width = bwidth; - // to do: consider using [NSNotificationCenter postNotificationName:] to send notifications. + // To do: consider using [NSNotificationCenter postNotificationName:] to + // send notifications. [self windowWillExitFullScreen]; [fw setFrame: [w frame] display:YES animate:ns_use_fullscreen_animation]; @@ -8036,7 +8121,7 @@ not_in_argv (NSString *arg) } -/* this gets called on toolbar button click */ +/* This gets called on toolbar button click. */ - (instancetype)toolbarClicked: (id)item { NSEvent *theEvent; @@ -8047,14 +8132,14 @@ not_in_argv (NSString *arg) if (!emacs_event) return self; - /* send first event (for some reason two needed) */ + /* Send first event (for some reason two needed). */ theEvent = [[self window] currentEvent]; emacs_event->kind = TOOL_BAR_EVENT; XSETFRAME (emacs_event->arg, emacsframe); EV_TRAILER (theEvent); emacs_event->kind = TOOL_BAR_EVENT; -/* XSETINT (emacs_event->code, 0); */ + /* XSETINT (emacs_event->code, 0); */ emacs_event->arg = AREF (emacsframe->tool_bar_items, idx + TOOL_BAR_ITEM_KEY); emacs_event->modifiers = EV_MODIFIERS (theEvent); @@ -8263,13 +8348,13 @@ not_in_argv (NSString *arg) But this should not happen because we override the services menu with our own entries which call ns-perform-service. Nonetheless, it appeared to happen (under strange circumstances): bug#1435. - So let's at least stub them out until further investigation can be done. */ + So let's at least stub them out until further investigation can be done. */ - (BOOL) readSelectionFromPasteboard: (NSPasteboard *)pb { - /* we could call ns_string_from_pasteboard(pboard) here but then it should - be written into the buffer in place of the existing selection.. - ordinary service calls go through functions defined in ns-win.el */ + /* We could call ns_string_from_pasteboard(pboard) here but then it should + be written into the buffer in place of the existing selection. + Ordinary service calls go through functions defined in ns-win.el. */ return NO; } @@ -8280,7 +8365,7 @@ not_in_argv (NSString *arg) NSTRACE ("[EmacsView writeSelectionToPasteboard:types:]"); - /* We only support NSStringPboardType */ + /* We only support NSStringPboardType. */ if ([types containsObject:NSStringPboardType] == NO) { return NO; } @@ -8302,10 +8387,10 @@ not_in_argv (NSString *arg) } -/* setMini =YES means set from internal (gives a finder icon), NO means set nil +/* setMini = YES means set from internal (gives a finder icon), NO means set nil (gives a miniaturized version of the window); currently we use the latter for frames whose active buffer doesn't correspond to any file - (e.g., '*scratch*') */ + (e.g., '*scratch*'). */ - (instancetype)setMiniwindowImage: (BOOL) setMini { id image = [[self window] miniwindowImage]; @@ -8313,7 +8398,7 @@ not_in_argv (NSString *arg) /* NOTE: under Cocoa miniwindowImage always returns nil, documentation about "AppleDockIconEnabled" notwithstanding, however the set message - below has its effect nonetheless. */ + below has its effect nonetheless. */ if (image != emacsframe->output_data.ns->miniimage) { if (image && [image isKindOfClass: [EmacsImage class]]) @@ -8424,7 +8509,7 @@ not_in_argv (NSString *arg) Note that this should work in situations where multiple monitors are present. Common configurations are side-by-side monitors and a monitor on top of another (e.g. when a laptop is placed under a - large screen). */ + large screen). */ - (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen { NSTRACE ("[EmacsWindow constrainFrameRect:" NSTRACE_FMT_RECT " toScreen:]", @@ -8651,7 +8736,7 @@ not_in_argv (NSString *arg) + (CGFloat) scrollerWidth { /* TODO: if we want to allow variable widths, this is the place to do it, - however neither GNUstep nor Cocoa support it very well */ + however neither GNUstep nor Cocoa support it very well. */ CGFloat r; #if defined (NS_IMPL_COCOA) \ && MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 @@ -8687,7 +8772,7 @@ not_in_argv (NSString *arg) /* Ensure auto resizing of scrollbars occurs within the emacs frame's view locked against the top and bottom edges, and right edge on macOS, where - scrollers are on right. */ + scrollers are on right. */ #ifdef NS_IMPL_GNUSTEP [self setAutoresizingMask: NSViewMaxXMargin | NSViewHeightSizable]; #else @@ -8711,7 +8796,7 @@ not_in_argv (NSString *arg) NSView *sview = [[view window] contentView]; NSArray *subs = [sview subviews]; - /* disable optimization stopping redraw of other scrollbars */ + /* Disable optimization stopping redraw of other scrollbars. */ view->scrollbarsNeedingUpdate = 0; for (i =[subs count]-1; i >= 0; i--) if ([[subs objectAtIndex: i] isKindOfClass: [EmacsScroller class]]) @@ -8719,7 +8804,7 @@ not_in_argv (NSString *arg) [sview addSubview: self]; } -/* [self setFrame: r]; */ + /* [self setFrame: r]; */ return self; } @@ -8729,7 +8814,7 @@ not_in_argv (NSString *arg) { NSTRACE ("[EmacsScroller setFrame:]"); -/* block_input (); */ + /* block_input (); */ if (horizontal) pixel_length = NSWidth (newRect); else @@ -8737,7 +8822,7 @@ not_in_argv (NSString *arg) if (pixel_length == 0) pixel_length = 1; min_portion = 20 / pixel_length; [super setFrame: newRect]; -/* unblock_input (); */ + /* unblock_input (); */ } @@ -8780,7 +8865,7 @@ not_in_argv (NSString *arg) { EmacsView *view; block_input (); - /* ensure other scrollbar updates after deletion */ + /* Ensure other scrollbar updates after deletion. */ view = (EmacsView *)FRAME_NS_VIEW (frame); if (view != nil) view->scrollbarsNeedingUpdate++; @@ -8807,7 +8892,14 @@ not_in_argv (NSString *arg) if (!NSIsEmptyRect (visible)) [self addCursorRect: visible cursor: [NSCursor arrowCursor]]; - [[NSCursor arrowCursor] setOnMouseEntered: YES]; + +#if defined (NS_IMPL_GNUSTEP) || MAC_OS_X_VERSION_MIN_REQUIRED < 101300 +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101300 + if ([[NSCursor arrowCursor] respondsToSelector: + @selector(setOnMouseEntered)]) +#endif + [[NSCursor arrowCursor] setOnMouseEntered: YES]; +#endif } @@ -8815,7 +8907,7 @@ not_in_argv (NSString *arg) whole: (int) whole { return em_position ==position && em_portion ==portion && em_whole ==whole - && portion != whole; /* needed for resize empty buf */ + && portion != whole; /* Needed for resizing empty buffer. */ } @@ -8854,7 +8946,7 @@ not_in_argv (NSString *arg) return self; } -/* set up emacs_event */ +/* Set up emacs_event. */ - (void) sendScrollEventAtLoc: (float)loc fromEvent: (NSEvent *)e { Lisp_Object win; @@ -8897,7 +8989,8 @@ not_in_argv (NSString *arg) } -/* called manually thru timer to implement repeated button action w/hold-down */ +/* Called manually through timer to implement repeated button action + with hold-down. */ - (instancetype)repeatScroll: (NSTimer *)scrollEntry { NSEvent *e = [[self window] currentEvent]; @@ -8906,7 +8999,7 @@ not_in_argv (NSString *arg) NSTRACE ("[EmacsScroller repeatScroll:]"); - /* clear timer if need be */ + /* Clear timer if need be. */ if (inKnob || [scroll_repeat_entry timeInterval] == SCROLL_BAR_FIRST_DELAY) { [scroll_repeat_entry invalidate]; @@ -8932,11 +9025,11 @@ not_in_argv (NSString *arg) /* Asynchronous mouse tracking for scroller. This allows us to dispatch - mouseDragged events without going into a modal loop. */ + mouseDragged events without going into a modal loop. */ - (void)mouseDown: (NSEvent *)e { NSRect sr, kr; - /* hitPart is only updated AFTER event is passed on */ + /* hitPart is only updated AFTER event is passed on. */ NSScrollerPart part = [self testPart: [e locationInWindow]]; CGFloat loc, kloc, pos UNINIT; int edge = 0; @@ -9035,9 +9128,9 @@ not_in_argv (NSString *arg) } else { - pos = 0; /* ignored */ + pos = 0; /* ignored */ - /* set a timer to repeat, as we can't let superclass do this modally */ + /* Set a timer to repeat, as we can't let superclass do this modally. */ scroll_repeat_entry = [[NSTimer scheduledTimerWithTimeInterval: SCROLL_BAR_FIRST_DELAY target: self @@ -9052,7 +9145,7 @@ not_in_argv (NSString *arg) } -/* Called as we manually track scroller drags, rather than superclass. */ +/* Called as we manually track scroller drags, rather than superclass. */ - (void)mouseDragged: (NSEvent *)e { NSRect sr; @@ -9110,7 +9203,7 @@ not_in_argv (NSString *arg) } -/* treat scrollwheel events in the bar as though they were in the main window */ +/* Treat scrollwheel events in the bar as though they were in the main window. */ - (void) scrollWheel: (NSEvent *)theEvent { NSTRACE ("[EmacsScroller scrollWheel:]"); @@ -9198,7 +9291,7 @@ x_new_font (struct frame *f, Lisp_Object font_object, int fontset) /* XLFD: -foundry-family-weight-slant-swidth-adstyle-pxlsz-ptSz-resx-resy-spc-avgWidth-rgstry-encoding */ /* Note: ns_font_to_xlfd and ns_fontname_to_xlfd no longer needed, removed - in 1.43. */ + in 1.43. */ const char * ns_xlfd_to_fontname (const char *xlfd) @@ -9239,7 +9332,7 @@ ns_xlfd_to_fontname (const char *xlfd) name[i+1] = c_toupper (name[i+1]); } } -/*fprintf (stderr, "converted '%s' to '%s'\n",xlfd,name); */ + /* fprintf (stderr, "converted '%s' to '%s'\n",xlfd,name); */ ret = [[NSString stringWithUTF8String: name] UTF8String]; xfree (name); return ret; @@ -9253,7 +9346,7 @@ syms_of_nsterm (void) ns_antialias_threshold = 10.0; - /* from 23+ we need to tell emacs what modifiers there are.. */ + /* From 23+ we need to tell emacs what modifiers there are. */ DEFSYM (Qmodifier_value, "modifier-value"); DEFSYM (Qalt, "alt"); DEFSYM (Qhyper, "hyper"); @@ -9265,11 +9358,11 @@ syms_of_nsterm (void) DEFSYM (Qfile, "file"); DEFSYM (Qurl, "url"); - Fput (Qalt, Qmodifier_value, make_number (alt_modifier)); - Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier)); - Fput (Qmeta, Qmodifier_value, make_number (meta_modifier)); - Fput (Qsuper, Qmodifier_value, make_number (super_modifier)); - Fput (Qcontrol, Qmodifier_value, make_number (ctrl_modifier)); + Fput (Qalt, Qmodifier_value, make_fixnum (alt_modifier)); + Fput (Qhyper, Qmodifier_value, make_fixnum (hyper_modifier)); + Fput (Qmeta, Qmodifier_value, make_fixnum (meta_modifier)); + Fput (Qsuper, Qmodifier_value, make_fixnum (super_modifier)); + Fput (Qcontrol, Qmodifier_value, make_fixnum (ctrl_modifier)); DEFVAR_LISP ("ns-input-file", ns_input_file, "The file specified in the last NS event."); @@ -9368,11 +9461,11 @@ allowing it to be used at a lower level for accented character entry."); DEFVAR_LISP ("ns-auto-hide-menu-bar", ns_auto_hide_menu_bar, doc: /* Non-nil means that the menu bar is hidden, but appears when the mouse is near. -Only works on Mac OS X 10.6 or later. */); +Only works on Mac OS X. */); ns_auto_hide_menu_bar = Qnil; DEFVAR_BOOL ("ns-use-native-fullscreen", ns_use_native_fullscreen, - doc: /*Non-nil means to use native fullscreen on Mac OS X 10.7 and later. + doc: /* Non-nil means to use native fullscreen on Mac OS X 10.7 and later. Nil means use fullscreen the old (< 10.7) way. The old way works better with multiple monitors, but lacks tool bar. This variable is ignored on Mac OS X < 10.7. Default is t. */); @@ -9380,60 +9473,51 @@ Mac OS X < 10.7. Default is t. */); ns_last_use_native_fullscreen = ns_use_native_fullscreen; DEFVAR_BOOL ("ns-use-fullscreen-animation", ns_use_fullscreen_animation, - doc: /*Non-nil means use animation on non-native fullscreen. + doc: /* Non-nil means use animation on non-native fullscreen. For native fullscreen, this does nothing. Default is nil. */); ns_use_fullscreen_animation = NO; DEFVAR_BOOL ("ns-use-srgb-colorspace", ns_use_srgb_colorspace, - doc: /*Non-nil means to use sRGB colorspace on Mac OS X 10.7 and later. + doc: /* Non-nil means to use sRGB colorspace on Mac OS X 10.7 and later. Note that this does not apply to images. This variable is ignored on Mac OS X < 10.7 and GNUstep. */); ns_use_srgb_colorspace = YES; DEFVAR_BOOL ("ns-use-mwheel-acceleration", ns_use_mwheel_acceleration, - doc: /*Non-nil means use macOS's standard mouse wheel acceleration. + doc: /* Non-nil means use macOS's standard mouse wheel acceleration. This variable is ignored on macOS < 10.7 and GNUstep. Default is t. */); ns_use_mwheel_acceleration = YES; DEFVAR_LISP ("ns-mwheel-line-height", ns_mwheel_line_height, - doc: /*The number of pixels touchpad scrolling considers one line. + doc: /* The number of pixels touchpad scrolling considers one line. Nil or a non-number means use the default frame line height. This variable is ignored on macOS < 10.7 and GNUstep. Default is nil. */); ns_mwheel_line_height = Qnil; DEFVAR_BOOL ("ns-use-mwheel-momentum", ns_use_mwheel_momentum, - doc: /*Non-nil means mouse wheel scrolling uses momentum. + doc: /* Non-nil means mouse wheel scrolling uses momentum. This variable is ignored on macOS < 10.7 and GNUstep. Default is t. */); ns_use_mwheel_momentum = YES; - /* TODO: move to common code */ + /* TODO: Move to common code. */ DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars, - doc: /* Which toolkit scroll bars Emacs uses, if any. -A value of nil means Emacs doesn't use toolkit scroll bars. -With the X Window system, the value is a symbol describing the -X toolkit. Possible values are: gtk, motif, xaw, or xaw3d. -With MS Windows or Nextstep, the value is t. */); + doc: /* SKIP: real doc in xterm.c. */); Vx_toolkit_scroll_bars = Qt; DEFVAR_BOOL ("x-use-underline-position-properties", x_use_underline_position_properties, - doc: /*Non-nil means make use of UNDERLINE_POSITION font properties. -A value of nil means ignore them. If you encounter fonts with bogus -UNDERLINE_POSITION font properties, for example 7x13 on XFree prior -to 4.1, set this to nil. */); + doc: /* SKIP: real doc in xterm.c. */); x_use_underline_position_properties = 0; + DEFSYM (Qx_use_underline_position_properties, + "x-use-underline-position-properties"); DEFVAR_BOOL ("x-underline-at-descent-line", x_underline_at_descent_line, - doc: /* Non-nil means to draw the underline at the same place as the descent line. -(If `line-spacing' is in effect, that moves the underline lower by -that many pixels.) -A value of nil means to draw the underline according to the value of the -variable `x-use-underline-position-properties', which is usually at the -baseline level. The default value is nil. */); + doc: /* SKIP: real doc in xterm.c. */); x_underline_at_descent_line = 0; + DEFSYM (Qx_underline_at_descent_line, "x-underline-at-descent-line"); /* Tell Emacs about this window system. */ Fprovide (Qns, Qnil); |