X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/cfbf790d80eaa399afceecd9a6c3e2e76bca59b0..9d3f2fc2866c3e39c668eeb36078f7f8f9b6dba9:/src/nsfns.m diff --git a/src/nsfns.m b/src/nsfns.m index fac61d2ab5..1e075995c1 100644 --- a/src/nsfns.m +++ b/src/nsfns.m @@ -44,6 +44,10 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu) #include "fontset.h" #include "font.h" +#ifdef NS_IMPL_COCOA +#include +#endif + #if 0 int fns_trace_num = 1; #define NSTRACE(x) fprintf (stderr, "%s:%d: [%d] " #x "\n", \ @@ -88,7 +92,7 @@ Lisp_Object Qfontsize; /* hack for OS X file panels */ char panelOK = 0; -EmacsTooltip *ns_tooltip; +EmacsTooltip *ns_tooltip = nil; /* Need forward declaration here to preserve organizational integrity of file */ Lisp_Object Fx_open_connection (Lisp_Object, Lisp_Object, Lisp_Object); @@ -101,87 +105,52 @@ static int as_status; static ptrdiff_t image_cache_refcount; #endif + /* ========================================================================== Internal utility functions ========================================================================== */ +/* Let the user specify a Nextstep display with a Lisp object. + OBJECT may be nil, a frame or a terminal object. + nil stands for the selected frame--or, if that is not a Nextstep frame, + the first Nextstep display on the list. */ -void -check_ns (void) -{ - if (NSApp == nil) - error ("OpenStep is not in use or not initialized"); -} - - -/* Nonzero if we can use mouse menus. */ -int -have_menus_p (void) -{ - return NSApp != nil; -} - - -/* Extract a frame as a FRAME_PTR, defaulting to the selected frame - and checking validity for NS. */ -static FRAME_PTR -check_ns_frame (Lisp_Object frame) +static struct ns_display_info * +check_ns_display_info (Lisp_Object object) { - FRAME_PTR f; + struct ns_display_info *dpyinfo = NULL; - if (NILP (frame)) - f = SELECTED_FRAME (); - else + if (NILP (object)) { - CHECK_LIVE_FRAME (frame); - f = XFRAME (frame); - } - if (! FRAME_NS_P (f)) - error ("non-Nextstep frame used"); - return f; -} + struct frame *sf = XFRAME (selected_frame); - -/* Let the user specify an Nextstep display with a frame. - nil stands for the selected frame--or, if that is not an Nextstep frame, - the first Nextstep display on the list. */ -static struct ns_display_info * -check_ns_display_info (Lisp_Object frame) -{ - if (NILP (frame)) - { - struct frame *f = SELECTED_FRAME (); - if (FRAME_NS_P (f) && FRAME_LIVE_P (f) ) - return FRAME_NS_DISPLAY_INFO (f); + if (FRAME_NS_P (sf) && FRAME_LIVE_P (sf)) + dpyinfo = FRAME_NS_DISPLAY_INFO (sf); else if (x_display_list != 0) - return x_display_list; + dpyinfo = x_display_list; else error ("Nextstep windows are not in use or not initialized"); } - else if (INTEGERP (frame)) + else if (TERMINALP (object)) { - struct terminal *t = get_terminal (frame, 1); + struct terminal *t = get_terminal (object, 1); if (t->type != output_ns) - error ("Terminal %"pI"d is not a Nextstep display", XINT (frame)); + error ("Terminal %d is not a Nextstep display", t->id); - return t->display_info.ns; + dpyinfo = t->display_info.ns; } - else if (STRINGP (frame)) - return ns_display_info_for_name (frame); + else if (STRINGP (object)) + dpyinfo = ns_display_info_for_name (object); else { - FRAME_PTR f; - - CHECK_LIVE_FRAME (frame); - f = XFRAME (frame); - if (! FRAME_NS_P (f)) - error ("non-Nextstep frame used"); - return FRAME_NS_DISPLAY_INFO (f); + FRAME_PTR f = decode_window_system_frame (object); + dpyinfo = FRAME_NS_DISPLAY_INFO (f); } - return NULL; /* shut compiler up */ + + return dpyinfo; } @@ -201,35 +170,6 @@ ns_get_window (Lisp_Object maybeFrame) } -static NSScreen * -ns_get_screen (Lisp_Object screen) -{ - struct frame *f; - struct terminal *terminal; - - if (EQ (Qt, screen)) /* not documented */ - return [NSScreen mainScreen]; - - terminal = get_terminal (screen, 1); - if (terminal->type != output_ns) - return NULL; - - if (NILP (screen)) - f = SELECTED_FRAME (); - else if (FRAMEP (screen)) - f = XFRAME (screen); - else - { - struct ns_display_info *dpyinfo = terminal->display_info.ns; - f = dpyinfo->x_focus_frame - ? dpyinfo->x_focus_frame : dpyinfo->x_highlight_frame; - } - - return ((f && FRAME_NS_P (f)) ? [[FRAME_NS_VIEW (f) window] screen] - : NULL); -} - - /* Return the X display structure for the display named NAME. Open a new connection if necessary. */ struct ns_display_info * @@ -261,6 +201,29 @@ ns_display_info_for_name (Lisp_Object name) return dpyinfo; } +static NSString * +ns_filename_from_panel (NSSavePanel *panel) +{ +#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 + NSURL *url = [panel URL]; + NSString *str = [url path]; + return str; +#else + return [panel filename]; +#endif +} + +static NSString * +ns_directory_from_panel (NSSavePanel *panel) +{ +#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 + NSURL *url = [panel directoryURL]; + NSString *str = [url path]; + return str; +#else + return [panel directory]; +#endif +} static Lisp_Object interpret_services_menu (NSMenu *menu, Lisp_Object prefix, Lisp_Object old) @@ -324,7 +287,7 @@ static void x_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { NSColor *col; - CGFloat r, g, b, alpha; + EmacsCGFloat r, g, b, alpha; if (ns_lisp_to_color (arg, &col)) { @@ -356,7 +319,7 @@ x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) struct face *face; NSColor *col; NSView *view = FRAME_NS_VIEW (f); - CGFloat r, g, b, alpha; + EmacsCGFloat r, g, b, alpha; if (ns_lisp_to_color (arg, &col)) { @@ -381,7 +344,7 @@ x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval) { [[view window] setBackgroundColor: col]; - if (alpha != 1.0) + if (alpha != (EmacsCGFloat) 1.0) [[view window] setOpaque: NO]; else [[view window] setOpaque: YES]; @@ -596,7 +559,7 @@ ns_set_name_as_filename (struct frame *f) { NSView *view; Lisp_Object name, filename; - Lisp_Object buf = XWINDOW (f->selected_window)->buffer; + Lisp_Object buf = XWINDOW (f->selected_window)->contents; const char *title; NSAutoreleasePool *pool; struct gcpro gcpro1; @@ -751,7 +714,7 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) } -void +static void ns_implicitly_set_icon_type (struct frame *f) { Lisp_Object tem; @@ -896,7 +859,7 @@ ns_cursor_type_to_lisp (int arg) } /* This is the same as the xfns.c definition. */ -void +static void x_set_cursor_type (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval) { set_frame_cursor_types (f, arg); @@ -1119,11 +1082,8 @@ This function is an internal primitive--use `make-frame' instead. */) struct ns_display_info *dpyinfo = NULL; Lisp_Object parent; struct kboard *kb; - Lisp_Object tfont, tfontsize; static int desc_ctr = 1; - check_ns (); - /* x_get_arg modifies parms. */ parms = Fcopy_alist (parms); @@ -1220,9 +1180,6 @@ This function is an internal primitive--use `make-frame' instead. */) specbind (Qx_resource_name, name); } - f->resx = dpyinfo->resx; - f->resy = dpyinfo->resy; - block_input (); register_font_driver (&nsfont_driver, f); x_default_parameter (f, parms, Qfont_backend, Qnil, @@ -1231,10 +1188,10 @@ This function is an internal primitive--use `make-frame' instead. */) { /* use for default font name */ id font = [NSFont userFixedPitchFontOfSize: -1.0]; /* default */ - tfontsize = x_default_parameter (f, parms, Qfontsize, + x_default_parameter (f, parms, Qfontsize, make_number (0 /*(int)[font pointSize]*/), "fontSize", "FontSize", RES_TYPE_NUMBER); - tfont = x_default_parameter (f, parms, Qfont, + x_default_parameter (f, parms, Qfont, build_string ([[font fontName] UTF8String]), "font", "Font", RES_TYPE_STRING); } @@ -1398,7 +1355,7 @@ DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0, FRAME nil means use the selected frame. */) (Lisp_Object frame) { - struct frame *f = check_ns_frame (frame); + struct frame *f = decode_window_system_frame (frame); struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (f); if (dpyinfo->x_focus_frame != f) @@ -1419,18 +1376,8 @@ DEFUN ("ns-popup-font-panel", Fns_popup_font_panel, Sns_popup_font_panel, doc: /* Pop up the font panel. */) (Lisp_Object frame) { - id fm; - struct frame *f; - - check_ns (); - fm = [NSFontManager sharedFontManager]; - if (NILP (frame)) - f = SELECTED_FRAME (); - else - { - CHECK_FRAME (frame); - f = XFRAME (frame); - } + struct frame *f = decode_window_system_frame (frame); + id fm = [NSFontManager sharedFontManager]; [fm setSelectedFont: ((struct nsfont_info *)f->output_data.ns->font)->nsfont isMultiple: NO]; @@ -1444,17 +1391,7 @@ DEFUN ("ns-popup-color-panel", Fns_popup_color_panel, Sns_popup_color_panel, doc: /* Pop up the color panel. */) (Lisp_Object frame) { - struct frame *f; - - check_ns (); - if (NILP (frame)) - f = SELECTED_FRAME (); - else - { - CHECK_FRAME (frame); - f = XFRAME (frame); - } - + check_window_system (NULL); [NSApp orderFrontColorPanel: NSApp]; return Qnil; } @@ -1471,7 +1408,8 @@ Optional arg DIR_ONLY_P, if non-nil, means choose only directories. */) Lisp_Object init, Lisp_Object dir_only_p) { static id fileDelegate = nil; - int ret; + BOOL ret; + BOOL isSave = NILP (mustmatch) && NILP (dir_only_p); id panel; Lisp_Object fname; @@ -1483,7 +1421,7 @@ Optional arg DIR_ONLY_P, if non-nil, means choose only directories. */) NSString *initS = NILP (init) || !STRINGP (init) ? nil : [NSString stringWithUTF8String: SSDATA (init)]; - check_ns (); + check_window_system (NULL); if (fileDelegate == nil) fileDelegate = [EmacsFileDelegate new]; @@ -1493,7 +1431,7 @@ Optional arg DIR_ONLY_P, if non-nil, means choose only directories. */) if ([dirS characterAtIndex: 0] == '~') dirS = [dirS stringByExpandingTildeInPath]; - panel = NILP (mustmatch) && NILP (dir_only_p) ? + panel = isSave ? (id)[EmacsSavePanel savePanel] : (id)[EmacsOpenPanel openPanel]; [panel setTitle: promptS]; @@ -1508,8 +1446,15 @@ Optional arg DIR_ONLY_P, if non-nil, means choose only directories. */) [panel setCanChooseDirectories: YES]; [panel setCanChooseFiles: NO]; } + else if (! isSave) + { + /* This is not quite what the documentation says, but it is compatible + with the Gtk+ code. Also, the menu entry says "Open File...". */ + [panel setCanChooseDirectories: NO]; + [panel setCanChooseFiles: YES]; + } - block_input (); + block_input (); #if defined (NS_IMPL_COCOA) && \ MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 if (! NILP (mustmatch) || ! NILP (dir_only_p)) @@ -1528,7 +1473,6 @@ Optional arg DIR_ONLY_P, if non-nil, means choose only directories. */) } else { - [panel setCanChooseDirectories: YES]; ret = [panel runModalForDirectory: dirS file: initS types: nil]; } #endif @@ -1536,7 +1480,12 @@ Optional arg DIR_ONLY_P, if non-nil, means choose only directories. */) ret = (ret == NSOKButton) || panelOK; if (ret) - fname = build_string ([[panel filename] UTF8String]); + { + NSString *str = ns_filename_from_panel (panel); + if (! str) str = ns_directory_from_panel (panel); + if (! str) ret = NO; + else fname = build_string ([str UTF8String]); + } [[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow]; unblock_input (); @@ -1563,11 +1512,10 @@ If OWNER is nil, Emacs is assumed. */) { const char *value; - check_ns (); + check_window_system (NULL); if (NILP (owner)) owner = build_string([ns_app_name UTF8String]); CHECK_STRING (name); -/*fprintf (stderr, "ns-get-resource checking resource '%s'\n", SSDATA (name)); */ value = ns_get_defaults_value (SSDATA (name)); @@ -1583,7 +1531,7 @@ If OWNER is nil, Emacs is assumed. If VALUE is nil, the default is removed. */) (Lisp_Object owner, Lisp_Object name, Lisp_Object value) { - check_ns (); + check_window_system (NULL); if (NILP (owner)) owner = build_string ([ns_app_name UTF8String]); CHECK_STRING (name); @@ -1609,9 +1557,9 @@ DEFUN ("x-server-max-request-size", Fx_server_max_request_size, Sx_server_max_request_size, 0, 1, 0, doc: /* This function is a no-op. It is only present for completeness. */) - (Lisp_Object display) + (Lisp_Object terminal) { - check_ns (); + check_ns_display_info (terminal); /* This function has no real equivalent under NeXTstep. Return nil to indicate this. */ return Qnil; @@ -1619,11 +1567,15 @@ DEFUN ("x-server-max-request-size", Fx_server_max_request_size, DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0, - doc: /* Return the vendor ID string of Nextstep display server DISPLAY. -DISPLAY should be either a frame or a display name (a string). -If omitted or nil, the selected frame's display is used. */) - (Lisp_Object display) + doc: /* Return the "vendor ID" string of Nextstep display server TERMINAL. +\(Labeling every distributor as a "vendor" embodies the false assumption +that operating systems cannot be developed and distributed noncommercially.) +The optional argument TERMINAL specifies which display to ask about. +TERMINAL should be a terminal object, a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. */) + (Lisp_Object terminal) { + check_ns_display_info (terminal); #ifdef NS_IMPL_GNUSTEP return build_string ("GNU"); #else @@ -1633,79 +1585,88 @@ If omitted or nil, the selected frame's display is used. */) DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0, - doc: /* Return the version numbers of the server of DISPLAY. + doc: /* Return the version numbers of the server of display TERMINAL. The value is a list of three integers: the major and minor -version numbers of the X Protocol in use, and the distributor-specific -release number. See also the function `x-server-vendor'. +version numbers of the X Protocol in use, and the distributor-specific release +number. See also the function `x-server-vendor'. -The optional argument DISPLAY specifies which display to ask about. -DISPLAY should be either a frame or a display name (a string). +The optional argument TERMINAL specifies which display to ask about. +TERMINAL should be a terminal object, a frame or a display name (a string). If omitted or nil, that stands for the selected frame's display. */) - (Lisp_Object display) + (Lisp_Object terminal) { + check_ns_display_info (terminal); /*NOTE: it is unclear what would best correspond with "protocol"; we return 10.3, meaning Panther, since this is roughly the level that GNUstep's APIs correspond to. The last number is where we distinguish between the Apple and GNUstep implementations ("distributor-specific release number") and give int'ized versions of major.minor. */ - return Fcons (make_number (10), - Fcons (make_number (3), - Fcons (make_number (ns_appkit_version_int()), Qnil))); + return list3i (10, 3, ns_appkit_version_int ()); } DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0, - doc: /* Return the number of screens on Nextstep display server DISPLAY. -DISPLAY should be a frame, the display name as a string, or a terminal ID. -If omitted or nil, the selected frame's display is used. */) - (Lisp_Object display) -{ - int num; - - check_ns (); - num = [[NSScreen screens] count]; + doc: /* Return the number of screens on Nextstep display server TERMINAL. +The optional argument TERMINAL specifies which display to ask about. +TERMINAL should be a terminal object, a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. - return (num != 0) ? make_number (num) : Qnil; +Note: "screen" here is not in Nextstep terminology but in X11's. For +the number of physical monitors, use `(length +(display-monitor-attributes-list TERMINAL))' instead. */) + (Lisp_Object terminal) +{ + check_ns_display_info (terminal); + return make_number (1); } -DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, - 0, 1, 0, - doc: /* Return the height of Nextstep display server DISPLAY, in millimeters. -DISPLAY should be a frame, the display name as a string, or a terminal ID. -If omitted or nil, the selected frame's display is used. */) - (Lisp_Object display) +DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0, + doc: /* Return the height in millimeters of the Nextstep display TERMINAL. +The optional argument TERMINAL specifies which display to ask about. +TERMINAL should be a terminal object, a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. + +On \"multi-monitor\" setups this refers to the height in millimeters for +all physical monitors associated with TERMINAL. To get information +for each physical monitor, use `display-monitor-attributes-list'. */) + (Lisp_Object terminal) { - check_ns (); - return make_number ((int) - ([ns_get_screen (display) frame].size.height/(92.0/25.4))); + struct ns_display_info *dpyinfo = check_ns_display_info (terminal); + + return make_number (x_display_pixel_height (dpyinfo) / (92.0/25.4)); } -DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, - 0, 1, 0, - doc: /* Return the width of Nextstep display server DISPLAY, in millimeters. -DISPLAY should be a frame, the display name as a string, or a terminal ID. -If omitted or nil, the selected frame's display is used. */) - (Lisp_Object display) +DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0, + doc: /* Return the width in millimeters of the Nextstep display TERMINAL. +The optional argument TERMINAL specifies which display to ask about. +TERMINAL should be a terminal object, a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. + +On \"multi-monitor\" setups this refers to the width in millimeters for +all physical monitors associated with TERMINAL. To get information +for each physical monitor, use `display-monitor-attributes-list'. */) + (Lisp_Object terminal) { - check_ns (); - return make_number ((int) - ([ns_get_screen (display) frame].size.width/(92.0/25.4))); + struct ns_display_info *dpyinfo = check_ns_display_info (terminal); + + return make_number (x_display_pixel_width (dpyinfo) / (92.0/25.4)); } DEFUN ("x-display-backing-store", Fx_display_backing_store, Sx_display_backing_store, 0, 1, 0, - doc: /* Return whether the Nextstep display DISPLAY supports backing store. + doc: /* Return an indication of whether the Nextstep display TERMINAL does backing store. The value may be `buffered', `retained', or `non-retained'. -DISPLAY should be a frame, the display name as a string, or a terminal ID. -If omitted or nil, the selected frame's display is used. */) - (Lisp_Object display) +The optional argument TERMINAL specifies which display to ask about. +TERMINAL should be a terminal object, a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. */) + (Lisp_Object terminal) { - check_ns (); - switch ([ns_get_window (display) backingType]) + check_ns_display_info (terminal); + switch ([ns_get_window (terminal) backingType]) { case NSBackingStoreBuffered: return intern ("buffered"); @@ -1722,16 +1683,19 @@ If omitted or nil, the selected frame's display is used. */) DEFUN ("x-display-visual-class", Fx_display_visual_class, Sx_display_visual_class, 0, 1, 0, - doc: /* Return the visual class of the Nextstep display server DISPLAY. + doc: /* Return the visual class of the Nextstep display TERMINAL. The value is one of the symbols `static-gray', `gray-scale', `static-color', `pseudo-color', `true-color', or `direct-color'. -DISPLAY should be a frame, the display name as a string, or a terminal ID. -If omitted or nil, the selected frame's display is used. */) - (Lisp_Object display) + +The optional argument TERMINAL specifies which display to ask about. +TERMINAL should a terminal object, a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. */) + (Lisp_Object terminal) { NSWindowDepth depth; - check_ns (); - depth = [ns_get_screen (display) depth]; + + check_ns_display_info (terminal); + depth = [[[NSScreen screens] objectAtIndex:0] depth]; if ( depth == NSBestDepth (NSCalibratedWhiteColorSpace, 2, 2, YES, NULL)) return intern ("static-gray"); @@ -1751,14 +1715,14 @@ If omitted or nil, the selected frame's display is used. */) DEFUN ("x-display-save-under", Fx_display_save_under, Sx_display_save_under, 0, 1, 0, - doc: /* Return t if DISPLAY supports the save-under feature. -The optional argument DISPLAY specifies which display to ask about. -DISPLAY should be a frame, the display name as a string, or a terminal ID. -If omitted or nil, the selected frame's display is used. */) - (Lisp_Object display) -{ - check_ns (); - switch ([ns_get_window (display) backingType]) + doc: /* Return t if TERMINAL supports the save-under feature. +The optional argument TERMINAL specifies which display to ask about. +TERMINAL should be a terminal object, a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. */) + (Lisp_Object terminal) +{ + check_ns_display_info (terminal); + switch ([ns_get_window (terminal) backingType]) { case NSBackingStoreBuffered: return Qt; @@ -1806,12 +1770,13 @@ terminate Emacs if we can't open the connection. DEFUN ("x-close-connection", Fx_close_connection, Sx_close_connection, 1, 1, 0, - doc: /* Close the connection to the current Nextstep display server. -The argument DISPLAY is currently ignored. */) - (Lisp_Object display) + doc: /* Close the connection to TERMINAL's Nextstep display server. +For TERMINAL, specify a terminal object, a frame or a display name (a +string). If TERMINAL is nil, that stands for the selected frame's +terminal. */) + (Lisp_Object terminal) { - check_ns (); - /*ns_delete_terminal (dpyinfo->terminal); */ + check_ns_display_info (terminal); [NSApp terminate: NSApp]; return Qnil; } @@ -1836,7 +1801,7 @@ DEFUN ("ns-hide-others", Fns_hide_others, Sns_hide_others, doc: /* Hides all applications other than Emacs. */) (void) { - check_ns (); + check_window_system (NULL); [NSApp hideOtherApplications: NSApp]; return Qnil; } @@ -1849,7 +1814,7 @@ If ON is equal to `activate', Emacs is unhidden and becomes the active application. */) (Lisp_Object on) { - check_ns (); + check_window_system (NULL); if (EQ (on, intern ("activate"))) { [NSApp unhide: NSApp]; @@ -1868,7 +1833,7 @@ DEFUN ("ns-emacs-info-panel", Fns_emacs_info_panel, Sns_emacs_info_panel, doc: /* Shows the 'Info' or 'About' panel for Emacs. */) (void) { - check_ns (); + check_window_system (NULL); [NSApp orderFrontStandardAboutPanel: nil]; return Qnil; } @@ -1944,9 +1909,11 @@ DEFUN ("ns-list-services", Fns_list_services, Sns_list_services, 0, 0, 0, #else Lisp_Object ret = Qnil; NSMenu *svcs; +#ifdef NS_IMPL_COCOA id delegate; +#endif - check_ns (); + check_window_system (NULL); svcs = [[NSMenu alloc] initWithTitle: @"Services"]; [NSApp setServicesMenu: svcs]; [NSApp registerServicesMenuSendTypes: ns_send_types @@ -1999,7 +1966,7 @@ there was no result. */) char *utfStr; CHECK_STRING (service); - check_ns (); + check_window_system (NULL); utfStr = SSDATA (service); svcName = [NSString stringWithUTF8String: utfStr]; @@ -2027,15 +1994,9 @@ DEFUN ("ns-convert-utf8-nfd-to-nfc", Fns_convert_utf8_nfd_to_nfc, CHECK_STRING (str); utfStr = [NSString stringWithUTF8String: SSDATA (str)]; - if (![utfStr respondsToSelector: - @selector (precomposedStringWithCanonicalMapping)]) - { - message1 - ("Warning: ns-convert-utf8-nfd-to-nfc unsupported under GNUstep.\n"); - return Qnil; - } - else +#ifdef NS_IMPL_COCOA utfStr = [utfStr precomposedStringWithCanonicalMapping]; +#endif return build_string ([utfStr UTF8String]); } @@ -2123,7 +2084,7 @@ In case the execution fails, an error is signaled. */) NSEvent *nxev; CHECK_STRING (script); - check_ns (); + check_window_system (NULL); block_input (); @@ -2172,15 +2133,6 @@ In case the execution fails, an error is signaled. */) ========================================================================== */ - -/* called from image.c */ -FRAME_PTR -check_x_frame (Lisp_Object frame) -{ - return check_ns_frame (frame); -} - - /* called from frame.c */ struct ns_display_info * check_x_display_info (Lisp_Object frame) @@ -2199,6 +2151,9 @@ x_set_scroll_bar_default_width (struct frame *f) } +extern const char *x_get_string_resource (XrmDatabase, char *, char *); + + /* terms impl this instead of x-get-resource directly */ const char * x_get_string_resource (XrmDatabase rdb, char *name, char *class) @@ -2206,7 +2161,7 @@ x_get_string_resource (XrmDatabase rdb, char *name, char *class) /* remove appname prefix; TODO: allow for !="Emacs" */ char *toCheck = class + (!strncmp (class, "Emacs.", 6) ? 6 : 0); const char *res; - check_ns (); + check_window_system (NULL); if (inhibit_x_resources) /* --quick was passed, so this is a no-op. */ @@ -2247,13 +2202,6 @@ x_pixel_height (struct frame *f) } -int -x_screen_planes (struct frame *f) -{ - return FRAME_NS_DISPLAY_INFO (f)->n_planes; -} - - void x_sync (struct frame *f) { @@ -2276,7 +2224,7 @@ DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0, (Lisp_Object color, Lisp_Object frame) { NSColor * col; - check_ns (); + check_window_system (NULL); return ns_lisp_to_color (color, &col) ? Qnil : Qt; } @@ -2286,9 +2234,9 @@ DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0, (Lisp_Object color, Lisp_Object frame) { NSColor * col; - CGFloat red, green, blue, alpha; + EmacsCGFloat red, green, blue, alpha; - check_ns (); + check_window_system (NULL); CHECK_STRING (color); if (ns_lisp_to_color (color, &col)) @@ -2296,20 +2244,20 @@ DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0, [[col colorUsingColorSpaceName: NSCalibratedRGBColorSpace] getRed: &red green: &green blue: &blue alpha: &alpha]; - return list3 (make_number (lrint (red*65280)), - make_number (lrint (green*65280)), - make_number (lrint (blue*65280))); + return list3i (lrint (red * 65280), lrint (green * 65280), + lrint (blue * 65280)); } DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0, doc: /* Internal function called by `display-color-p', which see. */) - (Lisp_Object display) + (Lisp_Object terminal) { NSWindowDepth depth; NSString *colorSpace; - check_ns (); - depth = [ns_get_screen (display) depth]; + + check_ns_display_info (terminal); + depth = [[[NSScreen screens] objectAtIndex:0] depth]; colorSpace = NSColorSpaceFromDepth (depth); return [colorSpace isEqualToString: NSDeviceWhiteColorSpace] @@ -2318,18 +2266,19 @@ DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0, } -DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, - Sx_display_grayscale_p, 0, 1, 0, +DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p, + 0, 1, 0, doc: /* Return t if the Nextstep display supports shades of gray. Note that color displays do support shades of gray. -The optional argument DISPLAY specifies which display to ask about. -DISPLAY should be either a frame, a display name (a string), or terminal ID. -If omitted or nil, that stands for the selected frame's display. */) - (Lisp_Object display) +The optional argument TERMINAL specifies which display to ask about. +TERMINAL should be a terminal object, a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. */) + (Lisp_Object terminal) { NSWindowDepth depth; - check_ns (); - depth = [ns_get_screen (display) depth]; + + check_ns_display_info (terminal); + depth = [[[NSScreen screens] objectAtIndex:0] depth]; return NSBitsPerPixelFromDepth (depth) > 1 ? Qt : Qnil; } @@ -2337,88 +2286,230 @@ If omitted or nil, that stands for the selected frame's display. */) DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width, 0, 1, 0, - doc: /* Return the width in pixels of the Nextstep display DISPLAY. -The optional argument DISPLAY specifies which display to ask about. -DISPLAY should be either a frame, a display name (a string), or terminal ID. -If omitted or nil, that stands for the selected frame's display. */) - (Lisp_Object display) + doc: /* Return the width in pixels of the Nextstep display TERMINAL. +The optional argument TERMINAL specifies which display to ask about. +TERMINAL should be a terminal object, a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. + +On \"multi-monitor\" setups this refers to the pixel width for all +physical monitors associated with TERMINAL. To get information for +each physical monitor, use `display-monitor-attributes-list'. */) + (Lisp_Object terminal) { - check_ns (); - return make_number ((int) [ns_get_screen (display) frame].size.width); + struct ns_display_info *dpyinfo = check_ns_display_info (terminal); + + return make_number (x_display_pixel_width (dpyinfo)); } DEFUN ("x-display-pixel-height", Fx_display_pixel_height, Sx_display_pixel_height, 0, 1, 0, - doc: /* Return the height in pixels of the Nextstep display DISPLAY. -The optional argument DISPLAY specifies which display to ask about. -DISPLAY should be either a frame, a display name (a string), or terminal ID. -If omitted or nil, that stands for the selected frame's display. */) - (Lisp_Object display) + doc: /* Return the height in pixels of the Nextstep display TERMINAL. +The optional argument TERMINAL specifies which display to ask about. +TERMINAL should be a terminal object, a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. + +On \"multi-monitor\" setups this refers to the pixel height for all +physical monitors associated with TERMINAL. To get information for +each physical monitor, use `display-monitor-attributes-list'. */) + (Lisp_Object terminal) { - check_ns (); - return make_number ((int) [ns_get_screen (display) frame].size.height); + struct ns_display_info *dpyinfo = check_ns_display_info (terminal); + + return make_number (x_display_pixel_height (dpyinfo)); } +#ifdef NS_IMPL_COCOA +/* Returns the name for the screen that DICT came from, or NULL. + Caller must free return value. +*/ + +static char * +ns_screen_name (CGDirectDisplayID did) +{ + char *name = NULL; + NSDictionary *info = (NSDictionary *) + IODisplayCreateInfoDictionary (CGDisplayIOServicePort (did), + kIODisplayOnlyPreferredName); + NSDictionary *names + = [info objectForKey: + [NSString stringWithUTF8String:kDisplayProductName]]; + + if ([names count] > 0) { + NSString *n = [names objectForKey: [[names allKeys] objectAtIndex:0]]; + if (n != nil) + name = xstrdup ([n UTF8String]); + } -DEFUN ("display-usable-bounds", Fns_display_usable_bounds, - Sns_display_usable_bounds, 0, 1, 0, - doc: /* Return the bounds of the usable part of the screen. -The return value is a list of integers (LEFT TOP WIDTH HEIGHT), which -are the boundaries of the usable part of the screen, excluding areas -reserved for the Mac menu, dock, and so forth. + [info release]; + return name; +} +#endif -The screen queried corresponds to DISPLAY, which should be either a -frame, a display name (a string), or terminal ID. If omitted or nil, -that stands for the selected frame's display. */) - (Lisp_Object display) +static Lisp_Object +ns_make_monitor_attribute_list (struct MonitorInfo *monitors, + int n_monitors, + int primary_monitor, + const char *source) +{ + Lisp_Object monitor_frames = Fmake_vector (make_number (n_monitors), Qnil); + Lisp_Object frame, rest; + NSArray *screens = [NSScreen screens]; + int i; + + FOR_EACH_FRAME (rest, frame) + { + struct frame *f = XFRAME (frame); + + if (FRAME_NS_P (f)) + { + NSView *view = FRAME_NS_VIEW (f); + NSScreen *screen = [[view window] screen]; + NSUInteger k; + + i = -1; + for (k = 0; i == -1 && k < [screens count]; ++k) + { + if ([screens objectAtIndex: k] == screen) + i = (int)k; + } + + if (i > -1) + ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i))); + } + } + + return make_monitor_attribute_list (monitors, n_monitors, primary_monitor, + monitor_frames, source); +} + +DEFUN ("ns-display-monitor-attributes-list", + Fns_display_monitor_attributes_list, + Sns_display_monitor_attributes_list, + 0, 1, 0, + doc: /* Return a list of physical monitor attributes on the X display TERMINAL. + +The optional argument TERMINAL specifies which display to ask about. +TERMINAL should be a terminal object, a frame or a display name (a string). +If omitted or nil, that stands for the selected frame's display. + +In addition to the standard attribute keys listed in +`display-monitor-attributes-list', the following keys are contained in +the attributes: + + source -- String describing the source from which multi-monitor + information is obtained, \"NS\" is always the source." + +Internal use only, use `display-monitor-attributes-list' instead. */) + (Lisp_Object terminal) { - NSScreen *screen; - NSRect vScreen; + struct terminal *term = get_terminal (terminal, 1); + NSArray *screens; + NSUInteger i, n_monitors; + struct MonitorInfo *monitors; + Lisp_Object attributes_list = Qnil; + CGFloat primary_display_height = 0; + + if (term->type != output_ns) + return Qnil; - check_ns (); - screen = ns_get_screen (display); - if (!screen) + screens = [NSScreen screens]; + n_monitors = [screens count]; + if (n_monitors == 0) return Qnil; - vScreen = [screen visibleFrame]; + monitors = (struct MonitorInfo *) xzalloc (n_monitors * sizeof (*monitors)); + + for (i = 0; i < [screens count]; ++i) + { + NSScreen *s = [screens objectAtIndex:i]; + struct MonitorInfo *m = &monitors[i]; + NSRect fr = [s frame]; + NSRect vfr = [s visibleFrame]; + short y, vy; + +#ifdef NS_IMPL_COCOA + NSDictionary *dict = [s deviceDescription]; + NSNumber *nid = [dict objectForKey:@"NSScreenNumber"]; + CGDirectDisplayID did = [nid unsignedIntValue]; +#endif + if (i == 0) + { + primary_display_height = fr.size.height; + y = (short) fr.origin.y; + vy = (short) vfr.origin.y; + } + else + { + // Flip y coordinate as NS has y starting from the bottom. + y = (short) (primary_display_height - fr.size.height - fr.origin.y); + vy = (short) (primary_display_height - + vfr.size.height - vfr.origin.y); + } + + m->geom.x = (short) fr.origin.x; + m->geom.y = y; + m->geom.width = (unsigned short) fr.size.width; + m->geom.height = (unsigned short) fr.size.height; + + m->work.x = (short) vfr.origin.x; + // y is flipped on NS, so vy - y are pixels missing at the bottom, + // and fr.size.height - vfr.size.height are pixels missing in total. + // Pixels missing at top are + // fr.size.height - vfr.size.height - vy + y. + // work.y is then pixels missing at top + y. + m->work.y = (short) (fr.size.height - vfr.size.height) - vy + y + y; + m->work.width = (unsigned short) vfr.size.width; + m->work.height = (unsigned short) vfr.size.height; + +#ifdef NS_IMPL_COCOA + m->name = ns_screen_name (did); + + { + CGSize mms = CGDisplayScreenSize (did); + m->mm_width = (int) mms.width; + m->mm_height = (int) mms.height; + } + +#else + // Assume 92 dpi as x-display-mm-height/x-display-mm-width does. + m->mm_width = (int) (25.4 * fr.size.width / 92.0); + m->mm_height = (int) (25.4 * fr.size.height / 92.0); +#endif + } + + // Primary monitor is always first for NS. + attributes_list = ns_make_monitor_attribute_list (monitors, n_monitors, + 0, "NS"); - /* NS coordinate system is upside-down. - Transform to screen-specific coordinates. */ - return list4 (make_number ((int) vScreen.origin.x), - make_number ((int) [screen frame].size.height - - vScreen.size.height - vScreen.origin.y), - make_number ((int) vScreen.size.width), - make_number ((int) vScreen.size.height)); + free_monitors (monitors, n_monitors); + return attributes_list; } DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes, 0, 1, 0, - doc: /* Return the number of bitplanes of the Nextstep display DISPLAY. -The optional argument DISPLAY specifies which display to ask about. -DISPLAY should be either a frame, a display name (a string), or terminal ID. + doc: /* Return the number of bitplanes of the Nextstep display TERMINAL. +The optional argument TERMINAL specifies which display to ask about. +TERMINAL should be a terminal object, a frame or a display name (a string). If omitted or nil, that stands for the selected frame's display. */) - (Lisp_Object display) + (Lisp_Object terminal) { - check_ns (); + check_ns_display_info (terminal); return make_number - (NSBitsPerPixelFromDepth ([ns_get_screen (display) depth])); + (NSBitsPerPixelFromDepth ([[[NSScreen screens] objectAtIndex:0] depth])); } -DEFUN ("x-display-color-cells", Fx_display_color_cells, - Sx_display_color_cells, 0, 1, 0, - doc: /* Returns the number of color cells of the Nextstep display DISPLAY. -The optional argument DISPLAY specifies which display to ask about. -DISPLAY should be either a frame, a display name (a string), or terminal ID. +DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells, + 0, 1, 0, + doc: /* Returns the number of color cells of the Nextstep display TERMINAL. +The optional argument TERMINAL specifies which display to ask about. +TERMINAL should be a terminal object, a frame or a display name (a string). If omitted or nil, that stands for the selected frame's display. */) - (Lisp_Object display) + (Lisp_Object terminal) { - struct ns_display_info *dpyinfo; - check_ns (); - - dpyinfo = check_ns_display_info (display); + struct ns_display_info *dpyinfo = check_ns_display_info (terminal); /* We force 24+ bit depths to 24-bit to prevent an overflow. */ return make_number (1 << min (dpyinfo->n_planes, 24)); } @@ -2531,7 +2622,7 @@ Text larger than the specified size is clipped. */) CHECK_STRING (string); str = SSDATA (string); - f = check_x_frame (frame); + f = decode_window_system_frame (frame); if (NILP (timeout)) timeout = make_number (5); else @@ -2587,6 +2678,81 @@ Value is t if tooltip was open, nil otherwise. */) ========================================================================== */ +/* + Handle arrow/function/control keys and copy/paste/cut in file dialogs. + Return YES if handled, NO if not. + */ +static BOOL +handlePanelKeys (NSSavePanel *panel, NSEvent *theEvent) +{ + NSString *s; + int i; + BOOL ret = NO; + + if ([theEvent type] != NSKeyDown) return NO; + s = [theEvent characters]; + + for (i = 0; i < [s length]; ++i) + { + int ch = (int) [s characterAtIndex: i]; + switch (ch) + { + case NSHomeFunctionKey: + case NSDownArrowFunctionKey: + case NSUpArrowFunctionKey: + case NSLeftArrowFunctionKey: + case NSRightArrowFunctionKey: + case NSPageUpFunctionKey: + case NSPageDownFunctionKey: + case NSEndFunctionKey: + /* Don't send command modified keys, as those are handled in the + performKeyEquivalent method of the super class. + */ + if (! ([theEvent modifierFlags] & NSCommandKeyMask)) + { + [panel sendEvent: theEvent]; + ret = YES; + } + break; + /* As we don't have the standard key commands for + copy/paste/cut/select-all in our edit menu, we must handle + them here. TODO: handle Emacs key bindings for copy/cut/select-all + here, paste works, because we have that in our Edit menu. + I.e. refactor out code in nsterm.m, keyDown: to figure out the + correct modifier. + */ + case 'x': // Cut + case 'c': // Copy + case 'v': // Paste + case 'a': // Select all + if ([theEvent modifierFlags] & NSCommandKeyMask) + { + [NSApp sendAction: + (ch == 'x' + ? @selector(cut:) + : (ch == 'c' + ? @selector(copy:) + : (ch == 'v' + ? @selector(paste:) + : @selector(selectAll:)))) + to:nil from:panel]; + ret = YES; + } + default: + // Send all control keys, as the text field supports C-a, C-f, C-e + // C-b and more. + if ([theEvent modifierFlags] & NSControlKeyMask) + { + [panel sendEvent: theEvent]; + ret = YES; + } + break; + } + } + + + return ret; +} @implementation EmacsSavePanel #ifdef NS_IMPL_COCOA @@ -2607,6 +2773,14 @@ Value is t if tooltip was open, nil otherwise. */) [NSApp stop: self]; } #endif + +- (BOOL)performKeyEquivalent:(NSEvent *)theEvent +{ + BOOL ret = handlePanelKeys (self, theEvent); + if (! ret) + ret = [super performKeyEquivalent:theEvent]; + return ret; +} @end @@ -2620,6 +2794,12 @@ Value is t if tooltip was open, nil otherwise. */) - (void) ok: (id)sender { [super ok: sender]; + + // If not choosing directories, and Open is pressed on a directory, return. + if (! [self canChooseDirectories] && ns_directory_from_panel (self) && + ! ns_filename_from_panel (self)) + return; + panelOK = 1; [NSApp stop: self]; } @@ -2628,7 +2808,16 @@ Value is t if tooltip was open, nil otherwise. */) [super cancel: sender]; [NSApp stop: self]; } + #endif +- (BOOL)performKeyEquivalent:(NSEvent *)theEvent +{ + // NSOpenPanel inherits NSSavePanel, so passing self is OK. + BOOL ret = handlePanelKeys (self, theEvent); + if (! ret) + ret = [super performKeyEquivalent:theEvent]; + return ret; +} @end @@ -2709,7 +2898,7 @@ be used as the image of the icon representing the frame. */); defsubr (&Sx_server_version); defsubr (&Sx_display_pixel_width); defsubr (&Sx_display_pixel_height); - defsubr (&Sns_display_usable_bounds); + defsubr (&Sns_display_monitor_attributes_list); defsubr (&Sx_display_mm_width); defsubr (&Sx_display_mm_height); defsubr (&Sx_display_screens); @@ -2736,9 +2925,6 @@ be used as the image of the icon representing the frame. */); defsubr (&Sx_show_tip); defsubr (&Sx_hide_tip); - /* used only in fontset.c */ - check_window_system_func = check_ns; - as_status = 0; as_script = Qnil; as_result = 0;