X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/b1cb82edff21abfefd68af18370dddfd8cc1fec0..9d3f2fc2866c3e39c668eeb36078f7f8f9b6dba9:/src/nsfns.m diff --git a/src/nsfns.m b/src/nsfns.m index 0d9ebe0ef5..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", \ @@ -101,50 +105,52 @@ static int as_status; static ptrdiff_t image_cache_refcount; #endif + /* ========================================================================== Internal utility functions ========================================================================== */ -/* Let the user specify an Nextstep display with a frame. - nil stands for the selected frame--or, if that is not an Nextstep frame, +/* 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. */ + static struct ns_display_info * -check_ns_display_info (Lisp_Object frame) +check_ns_display_info (Lisp_Object object) { - if (NILP (frame)) + struct ns_display_info *dpyinfo = NULL; + + if (NILP (object)) { - struct frame *f = SELECTED_FRAME (); - if (FRAME_NS_P (f) && FRAME_LIVE_P (f) ) - return FRAME_NS_DISPLAY_INFO (f); + struct frame *sf = XFRAME (selected_frame); + + 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; } @@ -164,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 * @@ -310,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)) { @@ -342,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)) { @@ -367,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]; @@ -737,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; @@ -882,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); @@ -1105,7 +1082,6 @@ 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; /* x_get_arg modifies parms. */ @@ -1212,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); } @@ -1433,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; @@ -1454,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]; @@ -1469,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...". */ @@ -1502,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]); } @@ -1580,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_display_info (display); + check_ns_display_info (terminal); /* This function has no real equivalent under NeXTstep. Return nil to indicate this. */ return Qnil; @@ -1590,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 @@ -1604,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. @@ -1625,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; + 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. - check_ns_display_info (display); - num = [[NSScreen screens] count]; - - 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_display_info (display); - 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_display_info (display); - 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_display_info (display); - switch ([ns_get_window (display) backingType]) + check_ns_display_info (terminal); + switch ([ns_get_window (terminal) backingType]) { case NSBackingStoreBuffered: return intern ("buffered"); @@ -1691,17 +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_display_info (display); - 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"); @@ -1721,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_display_info (display); - 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; @@ -1776,11 +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. -DISPLAY should be a frame, the display name as a string, or a terminal ID. */) - (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_display_info (display); + check_ns_display_info (terminal); [NSApp terminate: NSApp]; return Qnil; } @@ -1913,7 +1909,9 @@ 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_window_system (NULL); svcs = [[NSMenu alloc] initWithTitle: @"Services"]; @@ -1996,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]); } @@ -2159,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) @@ -2207,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) { @@ -2246,7 +2234,7 @@ 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_window_system (NULL); CHECK_STRING (color); @@ -2263,13 +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_display_info (display); - depth = [ns_get_screen (display) depth]; + + check_ns_display_info (terminal); + depth = [[[NSScreen screens] objectAtIndex:0] depth]; colorSpace = NSColorSpaceFromDepth (depth); return [colorSpace isEqualToString: NSDeviceWhiteColorSpace] @@ -2278,19 +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_display_info (display); - depth = [ns_get_screen (display) depth]; + check_ns_display_info (terminal); + depth = [[[NSScreen screens] objectAtIndex:0] depth]; return NSBitsPerPixelFromDepth (depth) > 1 ? Qt : Qnil; } @@ -2298,84 +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_display_info (display); - 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_display_info (display); - 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 + +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: -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. + source -- String describing the source from which multi-monitor + information is obtained, \"NS\" is always the source." -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) +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_display_info (display); - 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_display_info (display); + 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_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)); } @@ -2546,7 +2680,7 @@ Value is t if tooltip was open, nil otherwise. */) /* Handle arrow/function/control keys and copy/paste/cut in file dialogs. - Return YES if handeled, NO if not. + Return YES if handled, NO if not. */ static BOOL handlePanelKeys (NSSavePanel *panel, NSEvent *theEvent) @@ -2571,8 +2705,14 @@ handlePanelKeys (NSSavePanel *panel, NSEvent *theEvent) case NSPageUpFunctionKey: case NSPageDownFunctionKey: case NSEndFunctionKey: - [panel sendEvent: theEvent]; - ret = YES; + /* 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 @@ -2633,14 +2773,6 @@ handlePanelKeys (NSSavePanel *panel, NSEvent *theEvent) [NSApp stop: self]; } #endif -- (NSString *) getFilename -{ - return ns_filename_from_panel (self); -} -- (NSString *) getDirectory -{ - return ns_directory_from_panel (self); -} - (BOOL)performKeyEquivalent:(NSEvent *)theEvent { @@ -2664,8 +2796,8 @@ handlePanelKeys (NSSavePanel *panel, NSEvent *theEvent) [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; @@ -2678,14 +2810,6 @@ handlePanelKeys (NSSavePanel *panel, NSEvent *theEvent) } #endif -- (NSString *) getFilename -{ - return ns_filename_from_panel (self); -} -- (NSString *) getDirectory -{ - return ns_directory_from_panel (self); -} - (BOOL)performKeyEquivalent:(NSEvent *)theEvent { // NSOpenPanel inherits NSSavePanel, so passing self is OK. @@ -2774,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);