X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/78be8b64657aeca0472d708450ea1ce2bc142606..9d3f2fc2866c3e39c668eeb36078f7f8f9b6dba9:/src/nsfns.m diff --git a/src/nsfns.m b/src/nsfns.m index ef18acaa04..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 * @@ -347,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)) { @@ -379,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)) { @@ -404,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]; @@ -619,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; @@ -774,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; @@ -919,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); @@ -1142,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); @@ -1243,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, @@ -1254,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); } @@ -1421,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) @@ -1442,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]; @@ -1467,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; } @@ -1495,6 +1409,7 @@ Optional arg DIR_ONLY_P, if non-nil, means choose only directories. */) { static id fileDelegate = nil; BOOL ret; + BOOL isSave = NILP (mustmatch) && NILP (dir_only_p); id panel; Lisp_Object fname; @@ -1506,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]; @@ -1516,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]; @@ -1531,7 +1446,7 @@ Optional arg DIR_ONLY_P, if non-nil, means choose only directories. */) [panel setCanChooseDirectories: YES]; [panel setCanChooseFiles: NO]; } - else + 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...". */ @@ -1539,7 +1454,7 @@ Optional arg DIR_ONLY_P, if non-nil, means choose only directories. */) [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)) @@ -1564,10 +1479,10 @@ Optional arg DIR_ONLY_P, if non-nil, means choose only directories. */) ret = (ret == NSOKButton) || panelOK; - if (ret) + if (ret) { - NSString *str = [panel getFilename]; - if (! str) str = [panel getDirectory]; + 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]); } @@ -1597,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)); @@ -1617,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); @@ -1643,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; @@ -1653,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 @@ -1667,16 +1585,17 @@ 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. @@ -1688,56 +1607,66 @@ If omitted or nil, that stands for the selected frame's display. */) 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"); @@ -1754,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"); @@ -1783,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; @@ -1838,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; } @@ -1868,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; } @@ -1881,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]; @@ -1900,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; } @@ -1976,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 @@ -2031,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]; @@ -2059,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]); } @@ -2155,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 (); @@ -2204,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) @@ -2231,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) @@ -2238,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. */ @@ -2279,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) { @@ -2308,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; } @@ -2318,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)) @@ -2335,12 +2251,13 @@ DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0, 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] @@ -2349,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; } @@ -2368,87 +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]); + } + + [info release]; + return name; +} +#endif -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. +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; -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) + 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)); - /* NS coordinate system is upside-down. - Transform to screen-specific coordinates. */ - return list4i (vScreen.origin.x, - [screen frame].size.height - - vScreen.size.height - vScreen.origin.y, - vScreen.size.width, vScreen.size.height); + 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"); + + 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)); } @@ -2561,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 @@ -2617,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 @@ -2637,13 +2773,13 @@ Value is t if tooltip was open, nil otherwise. */) [NSApp stop: self]; } #endif -- (NSString *) getFilename -{ - return ns_filename_from_panel (self); -} -- (NSString *) getDirectory + +- (BOOL)performKeyEquivalent:(NSEvent *)theEvent { - return ns_directory_from_panel (self); + BOOL ret = handlePanelKeys (self, theEvent); + if (! ret) + ret = [super performKeyEquivalent:theEvent]; + return ret; } @end @@ -2660,8 +2796,8 @@ Value is t if tooltip was open, nil otherwise. */) [super ok: sender]; // If not choosing directories, and Open is pressed on a directory, return. - if (! [self canChooseDirectories] && [self getDirectory] && - ! [self getFilename]) + if (! [self canChooseDirectories] && ns_directory_from_panel (self) && + ! ns_filename_from_panel (self)) return; panelOK = 1; @@ -2674,15 +2810,14 @@ Value is t if tooltip was open, nil otherwise. */) } #endif -- (NSString *) getFilename +- (BOOL)performKeyEquivalent:(NSEvent *)theEvent { - return ns_filename_from_panel (self); -} -- (NSString *) getDirectory -{ - return ns_directory_from_panel (self); + // NSOpenPanel inherits NSSavePanel, so passing self is OK. + BOOL ret = handlePanelKeys (self, theEvent); + if (! ret) + ret = [super performKeyEquivalent:theEvent]; + return ret; } - @end @@ -2763,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); @@ -2790,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;