1 /* Functions for the NeXT/Open/GNUstep and MacOSX window system.
3 Copyright (C) 1989, 1992-1994, 2005-2006, 2008-2014 Free Software
6 This file is part of GNU Emacs.
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
22 Originally by Carl Edman
23 Updated by Christian Limpach (chris@nice.ch)
24 OpenStep/Rhapsody port by Scott Bender (sbender@harmony-ds.com)
25 MacOSX/Aqua port by Christophe de Dinechin (descubes@earthlink.net)
26 GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu)
29 /* This should be the first include, as it may set up #defines affecting
30 interpretation of even the system includes. */
34 #include <c-strcase.h>
37 #include "blockinput.h"
40 #include "character.h"
43 #include "termhooks.h"
48 #include <IOKit/graphics/IOGraphicsLib.h>
49 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
55 int fns_trace_num = 1;
56 #define NSTRACE(x) fprintf (stderr, "%s:%d: [%d] " #x "\n", \
57 __FILE__, __LINE__, ++fns_trace_num)
64 extern NSArray *ns_send_types, *ns_return_types, *ns_drag_types;
66 extern Lisp_Object Qforeground_color;
67 extern Lisp_Object Qbackground_color;
68 extern Lisp_Object Qcursor_color;
69 extern Lisp_Object Qinternal_border_width;
70 extern Lisp_Object Qvisibility;
71 extern Lisp_Object Qcursor_type;
72 extern Lisp_Object Qicon_type;
73 extern Lisp_Object Qicon_name;
74 extern Lisp_Object Qicon_left;
75 extern Lisp_Object Qicon_top;
76 extern Lisp_Object Qleft;
77 extern Lisp_Object Qright;
78 extern Lisp_Object Qtop;
79 extern Lisp_Object Qdisplay;
80 extern Lisp_Object Qvertical_scroll_bars;
81 extern Lisp_Object Qauto_raise;
82 extern Lisp_Object Qauto_lower;
83 extern Lisp_Object Qbox;
84 extern Lisp_Object Qscroll_bar_width;
85 extern Lisp_Object Qx_resource_name;
86 extern Lisp_Object Qface_set_after_frame_default;
87 extern Lisp_Object Qunderline, Qundefined;
88 extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
89 extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle;
92 Lisp_Object Qbuffered;
93 Lisp_Object Qfontsize;
95 EmacsTooltip *ns_tooltip = nil;
97 /* Need forward declaration here to preserve organizational integrity of file */
98 Lisp_Object Fx_open_connection (Lisp_Object, Lisp_Object, Lisp_Object);
100 /* Static variables to handle applescript execution. */
101 static Lisp_Object as_script, *as_result;
102 static int as_status;
105 static ptrdiff_t image_cache_refcount;
109 /* ==========================================================================
111 Internal utility functions
113 ========================================================================== */
115 /* Let the user specify a Nextstep display with a Lisp object.
116 OBJECT may be nil, a frame or a terminal object.
117 nil stands for the selected frame--or, if that is not a Nextstep frame,
118 the first Nextstep display on the list. */
120 static struct ns_display_info *
121 check_ns_display_info (Lisp_Object object)
123 struct ns_display_info *dpyinfo = NULL;
127 struct frame *sf = XFRAME (selected_frame);
129 if (FRAME_NS_P (sf) && FRAME_LIVE_P (sf))
130 dpyinfo = FRAME_DISPLAY_INFO (sf);
131 else if (x_display_list != 0)
132 dpyinfo = x_display_list;
134 error ("Nextstep windows are not in use or not initialized");
136 else if (TERMINALP (object))
138 struct terminal *t = get_terminal (object, 1);
140 if (t->type != output_ns)
141 error ("Terminal %d is not a Nextstep display", t->id);
143 dpyinfo = t->display_info.ns;
145 else if (STRINGP (object))
146 dpyinfo = ns_display_info_for_name (object);
149 struct frame *f = decode_window_system_frame (object);
150 dpyinfo = FRAME_DISPLAY_INFO (f);
158 ns_get_window (Lisp_Object maybeFrame)
160 id view =nil, window =nil;
162 if (!FRAMEP (maybeFrame) || !FRAME_NS_P (XFRAME (maybeFrame)))
163 maybeFrame = selected_frame;/*wrong_type_argument (Qframep, maybeFrame); */
165 if (!NILP (maybeFrame))
166 view = FRAME_NS_VIEW (XFRAME (maybeFrame));
167 if (view) window =[view window];
173 /* Return the X display structure for the display named NAME.
174 Open a new connection if necessary. */
175 struct ns_display_info *
176 ns_display_info_for_name (Lisp_Object name)
178 struct ns_display_info *dpyinfo;
182 for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
183 if (!NILP (Fstring_equal (XCAR (dpyinfo->name_list_element), name)))
186 error ("Emacs for Nextstep does not yet support multi-display");
188 Fx_open_connection (name, Qnil, Qnil);
189 dpyinfo = x_display_list;
192 error ("Display on %s not responding.\n", SDATA (name));
198 ns_filename_from_panel (NSSavePanel *panel)
200 #if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
201 NSURL *url = [panel URL];
202 NSString *str = [url path];
205 return [panel filename];
210 ns_directory_from_panel (NSSavePanel *panel)
212 #if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
213 NSURL *url = [panel directoryURL];
214 NSString *str = [url path];
217 return [panel directory];
222 interpret_services_menu (NSMenu *menu, Lisp_Object prefix, Lisp_Object old)
223 /* --------------------------------------------------------------------------
224 Turn the input menu (an NSMenu) into a lisp list for tracking on lisp side
225 -------------------------------------------------------------------------- */
235 count = [menu numberOfItems];
236 for (i = 0; i<count; i++)
238 item = [menu itemAtIndex: i];
239 name = [[item title] UTF8String];
242 nameStr = build_string (name);
244 if ([item hasSubmenu])
246 old = interpret_services_menu ([item submenu],
247 Fcons (nameStr, prefix), old);
251 keys = [item keyEquivalent];
252 if (keys && [keys length] )
254 key = [keys characterAtIndex: 0];
255 res = make_number (key|super_modifier);
261 old = Fcons (Fcons (res,
262 Freverse (Fcons (nameStr,
272 /* ==========================================================================
274 Frame parameter setters
276 ========================================================================== */
280 x_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
283 EmacsCGFloat r, g, b, alpha;
285 if (ns_lisp_to_color (arg, &col))
287 store_frame_param (f, Qforeground_color, oldval);
288 error ("Unknown color");
292 [f->output_data.ns->foreground_color release];
293 f->output_data.ns->foreground_color = col;
295 [col getRed: &r green: &g blue: &b alpha: &alpha];
296 FRAME_FOREGROUND_PIXEL (f) =
297 ARGB_TO_ULONG ((int)(alpha*0xff), (int)(r*0xff), (int)(g*0xff), (int)(b*0xff));
299 if (FRAME_NS_VIEW (f))
301 update_face_from_frame_parameter (f, Qforeground_color, arg);
302 /*recompute_basic_faces (f); */
303 if (FRAME_VISIBLE_P (f))
310 x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
314 NSView *view = FRAME_NS_VIEW (f);
315 EmacsCGFloat r, g, b, alpha;
317 if (ns_lisp_to_color (arg, &col))
319 store_frame_param (f, Qbackground_color, oldval);
320 error ("Unknown color");
323 /* clear the frame; in some instances the NS-internal GC appears not to
324 update, or it does update and cannot clear old text properly */
325 if (FRAME_VISIBLE_P (f))
329 [f->output_data.ns->background_color release];
330 f->output_data.ns->background_color = col;
332 [col getRed: &r green: &g blue: &b alpha: &alpha];
333 FRAME_BACKGROUND_PIXEL (f) =
334 ARGB_TO_ULONG ((int)(alpha*0xff), (int)(r*0xff), (int)(g*0xff), (int)(b*0xff));
338 [[view window] setBackgroundColor: col];
340 if (alpha != (EmacsCGFloat) 1.0)
341 [[view window] setOpaque: NO];
343 [[view window] setOpaque: YES];
345 face = FRAME_DEFAULT_FACE (f);
348 col = ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), f);
349 face->background = ns_index_color
350 ([col colorWithAlphaComponent: alpha], f);
352 update_face_from_frame_parameter (f, Qbackground_color, arg);
355 if (FRAME_VISIBLE_P (f))
362 x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
366 if (ns_lisp_to_color (arg, &col))
368 store_frame_param (f, Qcursor_color, oldval);
369 error ("Unknown color");
372 [FRAME_CURSOR_COLOR (f) release];
373 FRAME_CURSOR_COLOR (f) = [col retain];
375 if (FRAME_VISIBLE_P (f))
377 x_update_cursor (f, 0);
378 x_update_cursor (f, 1);
380 update_face_from_frame_parameter (f, Qcursor_color, arg);
385 x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
387 NSView *view = FRAME_NS_VIEW (f);
388 NSTRACE (x_set_icon_name);
390 /* see if it's changed */
393 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
396 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
399 fset_icon_name (f, arg);
403 if (!NILP (f->title))
406 /* Explicit name and no icon-name -> explicit_name. */
407 if (f->explicit_name)
411 /* No explicit name and no icon-name ->
412 name has to be rebuild from icon_title_format. */
413 windows_or_buffers_changed = 62;
418 /* Don't change the name if it's already NAME. */
419 if ([[view window] miniwindowTitle]
420 && ([[[view window] miniwindowTitle]
421 isEqualToString: [NSString stringWithUTF8String:
425 [[view window] setMiniwindowTitle:
426 [NSString stringWithUTF8String: SSDATA (arg)]];
430 ns_set_name_internal (struct frame *f, Lisp_Object name)
433 Lisp_Object encoded_name, encoded_icon_name;
435 NSView *view = FRAME_NS_VIEW (f);
438 encoded_name = ENCODE_UTF_8 (name);
441 str = [NSString stringWithUTF8String: SSDATA (encoded_name)];
443 /* Don't change the name if it's already NAME. */
444 if (! [[[view window] title] isEqualToString: str])
445 [[view window] setTitle: str];
447 if (!STRINGP (f->icon_name))
448 encoded_icon_name = encoded_name;
450 encoded_icon_name = ENCODE_UTF_8 (f->icon_name);
452 str = [NSString stringWithUTF8String: SSDATA (encoded_icon_name)];
454 if ([[view window] miniwindowTitle]
455 && ! [[[view window] miniwindowTitle] isEqualToString: str])
456 [[view window] setMiniwindowTitle: str];
461 ns_set_name (struct frame *f, Lisp_Object name, int explicit)
463 NSTRACE (ns_set_name);
465 /* Make sure that requests from lisp code override requests from
466 Emacs redisplay code. */
469 /* If we're switching from explicit to implicit, we had better
470 update the mode lines and thereby update the title. */
471 if (f->explicit_name && NILP (name))
472 update_mode_lines = 21;
474 f->explicit_name = ! NILP (name);
476 else if (f->explicit_name)
480 name = build_string ([ns_app_name UTF8String]);
484 /* Don't change the name if it's already NAME. */
485 if (! NILP (Fstring_equal (name, f->name)))
490 /* Title overrides explicit name. */
491 if (! NILP (f->title))
494 ns_set_name_internal (f, name);
498 /* This function should be called when the user's lisp code has
499 specified a name for the frame; the name will override any set by the
502 x_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
504 NSTRACE (x_explicitly_set_name);
505 ns_set_name (f, arg, 1);
509 /* This function should be called by Emacs redisplay code to set the
510 name; names set this way will never override names set by the user's
513 x_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
515 NSTRACE (x_implicitly_set_name);
517 /* Deal with NS specific format t. */
518 if (FRAME_NS_P (f) && ((FRAME_ICONIFIED_P (f) && EQ (Vicon_title_format, Qt))
519 || EQ (Vframe_title_format, Qt)))
520 ns_set_name_as_filename (f);
522 ns_set_name (f, arg, 0);
526 /* Change the title of frame F to NAME.
527 If NAME is nil, use the frame name as the title. */
530 x_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name)
532 NSTRACE (x_set_title);
533 /* Don't change the title if it's already NAME. */
534 if (EQ (name, f->title))
537 update_mode_lines = 22;
539 fset_title (f, name);
546 ns_set_name_internal (f, name);
551 ns_set_name_as_filename (struct frame *f)
554 Lisp_Object name, filename;
555 Lisp_Object buf = XWINDOW (f->selected_window)->contents;
557 NSAutoreleasePool *pool;
559 Lisp_Object encoded_name, encoded_filename;
561 NSTRACE (ns_set_name_as_filename);
563 if (f->explicit_name || ! NILP (f->title))
567 pool = [[NSAutoreleasePool alloc] init];
568 filename = BVAR (XBUFFER (buf), filename);
569 name = BVAR (XBUFFER (buf), name);
573 if (! NILP (filename))
574 name = Ffile_name_nondirectory (filename);
576 name = build_string ([ns_app_name UTF8String]);
580 encoded_name = ENCODE_UTF_8 (name);
583 view = FRAME_NS_VIEW (f);
585 title = FRAME_ICONIFIED_P (f) ? [[[view window] miniwindowTitle] UTF8String]
586 : [[[view window] title] UTF8String];
588 if (title && (! strcmp (title, SSDATA (encoded_name))))
595 str = [NSString stringWithUTF8String: SSDATA (encoded_name)];
596 if (str == nil) str = @"Bad coding";
598 if (FRAME_ICONIFIED_P (f))
599 [[view window] setMiniwindowTitle: str];
604 if (! NILP (filename))
607 encoded_filename = ENCODE_UTF_8 (filename);
610 fstr = [NSString stringWithUTF8String: SSDATA (encoded_filename)];
611 if (fstr == nil) fstr = @"";
613 /* work around a bug observed on 10.3 and later where
614 setTitleWithRepresentedFilename does not clear out previous state
615 if given filename does not exist */
616 if (! [[NSFileManager defaultManager] fileExistsAtPath: fstr])
617 [[view window] setRepresentedFilename: @""];
623 [[view window] setRepresentedFilename: fstr];
624 [[view window] setTitle: str];
634 ns_set_doc_edited (void)
636 NSAutoreleasePool *pool;
637 Lisp_Object tail, frame;
639 pool = [[NSAutoreleasePool alloc] init];
640 FOR_EACH_FRAME (tail, frame)
643 struct frame *f = XFRAME (frame);
647 if (! FRAME_NS_P (f)) continue;
648 w = XWINDOW (FRAME_SELECTED_WINDOW (f));
649 view = FRAME_NS_VIEW (f);
650 if (!MINI_WINDOW_P (w))
651 edited = ! NILP (Fbuffer_modified_p (w->contents)) &&
652 ! NILP (Fbuffer_file_name (w->contents));
653 [[view window] setDocumentEdited: edited];
662 x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
665 if (FRAME_MINIBUF_ONLY_P (f))
668 if (TYPE_RANGED_INTEGERP (int, value))
669 nlines = XINT (value);
673 FRAME_MENU_BAR_LINES (f) = 0;
676 FRAME_EXTERNAL_MENU_BAR (f) = 1;
677 /* does for all frames, whereas we just want for one frame
678 [NSMenu setMenuBarVisible: YES]; */
682 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
683 free_frame_menubar (f);
684 /* [NSMenu setMenuBarVisible: NO]; */
685 FRAME_EXTERNAL_MENU_BAR (f) = 0;
690 /* toolbar support */
692 x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
696 if (FRAME_MINIBUF_ONLY_P (f))
699 if (RANGED_INTEGERP (0, value, INT_MAX))
700 nlines = XFASTINT (value);
706 FRAME_EXTERNAL_TOOL_BAR (f) = 1;
707 update_frame_tool_bar (f);
711 if (FRAME_EXTERNAL_TOOL_BAR (f))
713 free_frame_tool_bar (f);
714 FRAME_EXTERNAL_TOOL_BAR (f) = 0;
718 x_set_window_size (f, 0, f->text_cols, f->text_lines, 0);
723 ns_implicitly_set_icon_type (struct frame *f)
726 EmacsView *view = FRAME_NS_VIEW (f);
728 Lisp_Object chain, elt;
729 NSAutoreleasePool *pool;
732 NSTRACE (ns_implicitly_set_icon_type);
735 pool = [[NSAutoreleasePool alloc] init];
736 if (f->output_data.ns->miniimage
737 && [[NSString stringWithUTF8String: SSDATA (f->name)]
738 isEqualToString: [(NSImage *)f->output_data.ns->miniimage name]])
745 tem = assq_no_quit (Qicon_type, f->param_alist);
746 if (CONSP (tem) && ! NILP (XCDR (tem)))
753 for (chain = Vns_icon_type_alist;
754 image == nil && CONSP (chain);
755 chain = XCDR (chain))
758 /* special case: 't' means go by file type */
759 if (SYMBOLP (elt) && EQ (elt, Qt) && SSDATA (f->name)[0] == '/')
762 = [NSString stringWithUTF8String: SSDATA (f->name)];
763 if ([[NSFileManager defaultManager] fileExistsAtPath: str])
764 image = [[[NSWorkspace sharedWorkspace] iconForFile: str] retain];
766 else if (CONSP (elt) &&
767 STRINGP (XCAR (elt)) &&
768 STRINGP (XCDR (elt)) &&
769 fast_string_match (XCAR (elt), f->name) >= 0)
771 image = [EmacsImage allocInitFromFile: XCDR (elt)];
773 image = [[NSImage imageNamed:
774 [NSString stringWithUTF8String:
775 SSDATA (XCDR (elt))]] retain];
781 image = [[[NSWorkspace sharedWorkspace] iconForFileType: @"text"] retain];
785 [f->output_data.ns->miniimage release];
786 f->output_data.ns->miniimage = image;
787 [view setMiniwindowImage: setMini];
794 x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
796 EmacsView *view = FRAME_NS_VIEW (f);
800 NSTRACE (x_set_icon_type);
802 if (!NILP (arg) && SYMBOLP (arg))
804 arg =build_string (SSDATA (SYMBOL_NAME (arg)));
805 store_frame_param (f, Qicon_type, arg);
808 /* do it the implicit way */
811 ns_implicitly_set_icon_type (f);
817 image = [EmacsImage allocInitFromFile: arg];
819 image =[NSImage imageNamed: [NSString stringWithUTF8String:
824 image = [NSImage imageNamed: @"text"];
828 f->output_data.ns->miniimage = image;
829 [view setMiniwindowImage: setMini];
833 /* TODO: move to nsterm? */
835 ns_lisp_to_cursor_type (Lisp_Object arg)
838 if (XTYPE (arg) == Lisp_String)
840 else if (XTYPE (arg) == Lisp_Symbol)
841 str = SSDATA (SYMBOL_NAME (arg));
843 if (!strcmp (str, "box")) return FILLED_BOX_CURSOR;
844 if (!strcmp (str, "hollow")) return HOLLOW_BOX_CURSOR;
845 if (!strcmp (str, "hbar")) return HBAR_CURSOR;
846 if (!strcmp (str, "bar")) return BAR_CURSOR;
847 if (!strcmp (str, "no")) return NO_CURSOR;
853 ns_cursor_type_to_lisp (int arg)
857 case FILLED_BOX_CURSOR: return Qbox;
858 case HOLLOW_BOX_CURSOR: return intern ("hollow");
859 case HBAR_CURSOR: return intern ("hbar");
860 case BAR_CURSOR: return intern ("bar");
862 default: return intern ("no");
866 /* This is the same as the xfns.c definition. */
868 x_set_cursor_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
870 set_frame_cursor_types (f, arg);
873 /* called to set mouse pointer color, but all other terms use it to
874 initialize pointer types (and don't set the color ;) */
876 x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
878 /* don't think we can do this on Nextstep */
883 #define Xstr(x) Str(x)
886 ns_appkit_version_str (void)
890 #ifdef NS_IMPL_GNUSTEP
891 sprintf(tmp, "gnustep-gui-%s", Xstr(GNUSTEP_GUI_VERSION));
892 #elif defined (NS_IMPL_COCOA)
893 sprintf(tmp, "apple-appkit-%.2f", NSAppKitVersionNumber);
897 return build_string (tmp);
901 /* This is for use by x-server-version and collapses all version info we
902 have into a single int. For a better picture of the implementation
903 running, use ns_appkit_version_str.*/
905 ns_appkit_version_int (void)
907 #ifdef NS_IMPL_GNUSTEP
908 return GNUSTEP_GUI_MAJOR_VERSION * 100 + GNUSTEP_GUI_MINOR_VERSION;
909 #elif defined (NS_IMPL_COCOA)
910 return (int)NSAppKitVersionNumber;
917 x_icon (struct frame *f, Lisp_Object parms)
918 /* --------------------------------------------------------------------------
919 Strangely-named function to set icon position parameters in frame.
920 This is irrelevant under OS X, but might be needed under GNUstep,
921 depending on the window manager used. Note, this is not a standard
922 frame parameter-setter; it is called directly from x-create-frame.
923 -------------------------------------------------------------------------- */
925 Lisp_Object icon_x, icon_y;
926 struct ns_display_info *dpyinfo = check_ns_display_info (Qnil);
928 f->output_data.ns->icon_top = -1;
929 f->output_data.ns->icon_left = -1;
931 /* Set the position of the icon. */
932 icon_x = x_get_arg (dpyinfo, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
933 icon_y = x_get_arg (dpyinfo, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
934 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
936 CHECK_NUMBER (icon_x);
937 CHECK_NUMBER (icon_y);
938 f->output_data.ns->icon_top = XINT (icon_y);
939 f->output_data.ns->icon_left = XINT (icon_x);
941 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
942 error ("Both left and top icon corners of icon must be specified");
946 /* Note: see frame.c for template, also where generic functions are impl */
947 frame_parm_handler ns_frame_parm_handlers[] =
949 x_set_autoraise, /* generic OK */
950 x_set_autolower, /* generic OK */
951 x_set_background_color,
952 0, /* x_set_border_color, may be impossible under Nextstep */
953 0, /* x_set_border_width, may be impossible under Nextstep */
956 x_set_font, /* generic OK */
957 x_set_foreground_color,
960 x_set_internal_border_width, /* generic OK */
961 0, /* x_set_right_divider_width */
962 0, /* x_set_bottom_divider_width */
963 x_set_menu_bar_lines,
965 x_explicitly_set_name,
966 x_set_scroll_bar_width, /* generic OK */
968 x_set_unsplittable, /* generic OK */
969 x_set_vertical_scroll_bars, /* generic OK */
970 x_set_visibility, /* generic OK */
971 x_set_tool_bar_lines,
972 0, /* x_set_scroll_bar_foreground, will ignore (not possible on NS) */
973 0, /* x_set_scroll_bar_background, will ignore (not possible on NS) */
974 x_set_screen_gamma, /* generic OK */
975 x_set_line_spacing, /* generic OK, sets f->extra_line_spacing to int */
976 x_set_fringe_width, /* generic OK */
977 x_set_fringe_width, /* generic OK */
978 0, /* x_set_wait_for_wm, will ignore */
979 x_set_fullscreen, /* generic OK */
980 x_set_font_backend, /* generic OK */
982 0, /* x_set_sticky */
983 0, /* x_set_tool_bar_position */
987 /* Handler for signals raised during x_create_frame.
988 FRAME is the frame which is partially constructed. */
991 unwind_create_frame (Lisp_Object frame)
993 struct frame *f = XFRAME (frame);
995 /* If frame is already dead, nothing to do. This can happen if the
996 display is disconnected after the frame has become official, but
997 before x_create_frame removes the unwind protect. */
998 if (!FRAME_LIVE_P (f))
1001 /* If frame is ``official'', nothing to do. */
1002 if (NILP (Fmemq (frame, Vframe_list)))
1004 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
1005 struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
1008 x_free_frame_resources (f);
1012 /* Check that reference counts are indeed correct. */
1013 eassert (dpyinfo->terminal->image_cache->refcount == image_cache_refcount);
1019 * Read geometry related parameters from preferences if not in PARMS.
1020 * Returns the union of parms and any preferences read.
1024 get_geometry_from_preferences (struct ns_display_info *dpyinfo,
1032 { "width", "Width", Qwidth },
1033 { "height", "Height", Qheight },
1034 { "left", "Left", Qleft },
1035 { "top", "Top", Qtop },
1039 for (i = 0; i < sizeof (r)/sizeof (r[0]); ++i)
1041 if (NILP (Fassq (r[i].tem, parms)))
1044 = x_get_arg (dpyinfo, parms, r[i].tem, r[i].val, r[i].cls,
1046 if (! EQ (value, Qunbound))
1047 parms = Fcons (Fcons (r[i].tem, value), parms);
1054 /* ==========================================================================
1058 ========================================================================== */
1060 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
1062 doc: /* Make a new Nextstep window, called a "frame" in Emacs terms.
1063 Return an Emacs frame object.
1064 PARMS is an alist of frame parameters.
1065 If the parameters specify that the frame should not have a minibuffer,
1066 and do not specify a specific minibuffer window to use,
1067 then `default-minibuffer-frame' must be a frame whose minibuffer can
1068 be shared by the new frame.
1070 This function is an internal primitive--use `make-frame' instead. */)
1074 Lisp_Object frame, tem;
1076 int minibuffer_only = 0;
1077 long window_prompting = 0;
1079 ptrdiff_t count = specpdl_ptr - specpdl;
1080 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
1081 Lisp_Object display;
1082 struct ns_display_info *dpyinfo = NULL;
1085 static int desc_ctr = 1;
1087 /* x_get_arg modifies parms. */
1088 parms = Fcopy_alist (parms);
1090 /* Use this general default value to start with
1091 until we know if this frame has a specified name. */
1092 Vx_resource_name = Vinvocation_name;
1094 display = x_get_arg (dpyinfo, parms, Qterminal, 0, 0, RES_TYPE_STRING);
1095 if (EQ (display, Qunbound))
1097 dpyinfo = check_ns_display_info (display);
1098 kb = dpyinfo->terminal->kboard;
1100 if (!dpyinfo->terminal->name)
1101 error ("Terminal is not live, can't create new frames on it");
1103 name = x_get_arg (dpyinfo, parms, Qname, 0, 0, RES_TYPE_STRING);
1105 && ! EQ (name, Qunbound)
1107 error ("Invalid frame name--not a string or nil");
1110 Vx_resource_name = name;
1112 parent = x_get_arg (dpyinfo, parms, Qparent_id, 0, 0, RES_TYPE_NUMBER);
1113 if (EQ (parent, Qunbound))
1115 if (! NILP (parent))
1116 CHECK_NUMBER (parent);
1118 /* make_frame_without_minibuffer can run Lisp code and garbage collect. */
1119 /* No need to protect DISPLAY because that's not used after passing
1120 it to make_frame_without_minibuffer. */
1122 GCPRO4 (parms, parent, name, frame);
1123 tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
1125 if (EQ (tem, Qnone) || NILP (tem))
1126 f = make_frame_without_minibuffer (Qnil, kb, display);
1127 else if (EQ (tem, Qonly))
1129 f = make_minibuffer_frame ();
1130 minibuffer_only = 1;
1132 else if (WINDOWP (tem))
1133 f = make_frame_without_minibuffer (tem, kb, display);
1137 XSETFRAME (frame, f);
1139 f->terminal = dpyinfo->terminal;
1141 f->output_method = output_ns;
1142 f->output_data.ns = xzalloc (sizeof *f->output_data.ns);
1144 FRAME_FONTSET (f) = -1;
1146 fset_icon_name (f, x_get_arg (dpyinfo, parms, Qicon_name,
1147 "iconName", "Title",
1149 if (! STRINGP (f->icon_name))
1150 fset_icon_name (f, Qnil);
1152 FRAME_DISPLAY_INFO (f) = dpyinfo;
1154 /* With FRAME_DISPLAY_INFO set up, this unwind-protect is safe. */
1155 record_unwind_protect (unwind_create_frame, frame);
1157 f->output_data.ns->window_desc = desc_ctr++;
1158 if (TYPE_RANGED_INTEGERP (Window, parent))
1160 f->output_data.ns->parent_desc = XFASTINT (parent);
1161 f->output_data.ns->explicit_parent = 1;
1165 f->output_data.ns->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
1166 f->output_data.ns->explicit_parent = 0;
1169 /* Set the name; the functions to which we pass f expect the name to
1171 if (EQ (name, Qunbound) || NILP (name) || ! STRINGP (name))
1173 fset_name (f, build_string ([ns_app_name UTF8String]));
1174 f->explicit_name = 0;
1178 fset_name (f, name);
1179 f->explicit_name = 1;
1180 specbind (Qx_resource_name, name);
1185 #ifdef NS_IMPL_COCOA
1186 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
1187 if (CTGetCoreTextVersion != NULL
1188 && CTGetCoreTextVersion () >= kCTVersionNumber10_5)
1189 mac_register_font_driver (f);
1192 register_font_driver (&nsfont_driver, f);
1194 x_default_parameter (f, parms, Qfont_backend, Qnil,
1195 "fontBackend", "FontBackend", RES_TYPE_STRING);
1198 /* use for default font name */
1199 id font = [NSFont userFixedPitchFontOfSize: -1.0]; /* default */
1200 x_default_parameter (f, parms, Qfontsize,
1201 make_number (0 /*(int)[font pointSize]*/),
1202 "fontSize", "FontSize", RES_TYPE_NUMBER);
1203 // Remove ' Regular', not handled by backends.
1204 char *fontname = xstrdup ([[font displayName] UTF8String]);
1205 int len = strlen (fontname);
1206 if (len > 8 && strcmp (fontname + len - 8, " Regular") == 0)
1207 fontname[len-8] = '\0';
1208 x_default_parameter (f, parms, Qfont,
1209 build_string (fontname),
1210 "font", "Font", RES_TYPE_STRING);
1215 x_default_parameter (f, parms, Qborder_width, make_number (0),
1216 "borderwidth", "BorderWidth", RES_TYPE_NUMBER);
1217 x_default_parameter (f, parms, Qinternal_border_width, make_number (2),
1218 "internalBorderWidth", "InternalBorderWidth",
1221 /* default scrollbars on right on Mac */
1224 #ifdef NS_IMPL_GNUSTEP
1229 x_default_parameter (f, parms, Qvertical_scroll_bars, spos,
1230 "verticalScrollBars", "VerticalScrollBars",
1233 x_default_parameter (f, parms, Qforeground_color, build_string ("Black"),
1234 "foreground", "Foreground", RES_TYPE_STRING);
1235 x_default_parameter (f, parms, Qbackground_color, build_string ("White"),
1236 "background", "Background", RES_TYPE_STRING);
1237 /* FIXME: not supported yet in Nextstep */
1238 x_default_parameter (f, parms, Qline_spacing, Qnil,
1239 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
1240 x_default_parameter (f, parms, Qleft_fringe, Qnil,
1241 "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
1242 x_default_parameter (f, parms, Qright_fringe, Qnil,
1243 "rightFringe", "RightFringe", RES_TYPE_NUMBER);
1246 image_cache_refcount =
1247 FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
1250 init_frame_faces (f);
1252 /* Read comment about this code in corresponding place in xfns.c. */
1253 width = FRAME_TEXT_WIDTH (f);
1254 height = FRAME_TEXT_HEIGHT (f);
1255 FRAME_TEXT_HEIGHT (f) = 0;
1256 SET_FRAME_WIDTH (f, 0);
1257 change_frame_size (f, width, height, 1, 0, 0, 1);
1259 /* The resources controlling the menu-bar and tool-bar are
1260 processed specially at startup, and reflected in the mode
1261 variables; ignore them here. */
1262 x_default_parameter (f, parms, Qmenu_bar_lines,
1263 NILP (Vmenu_bar_mode)
1264 ? make_number (0) : make_number (1),
1265 NULL, NULL, RES_TYPE_NUMBER);
1266 x_default_parameter (f, parms, Qtool_bar_lines,
1267 NILP (Vtool_bar_mode)
1268 ? make_number (0) : make_number (1),
1269 NULL, NULL, RES_TYPE_NUMBER);
1271 x_default_parameter (f, parms, Qbuffer_predicate, Qnil, "bufferPredicate",
1272 "BufferPredicate", RES_TYPE_SYMBOL);
1273 x_default_parameter (f, parms, Qtitle, Qnil, "title", "Title",
1276 parms = get_geometry_from_preferences (dpyinfo, parms);
1277 window_prompting = x_figure_window_size (f, parms, 1);
1279 tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
1280 f->no_split = minibuffer_only || (!EQ (tem, Qunbound) && !EQ (tem, Qnil));
1282 /* NOTE: on other terms, this is done in set_mouse_color, however this
1283 was not getting called under Nextstep */
1284 f->output_data.ns->text_cursor = [NSCursor IBeamCursor];
1285 f->output_data.ns->nontext_cursor = [NSCursor arrowCursor];
1286 f->output_data.ns->modeline_cursor = [NSCursor pointingHandCursor];
1287 f->output_data.ns->hand_cursor = [NSCursor pointingHandCursor];
1288 f->output_data.ns->hourglass_cursor = [NSCursor disappearingItemCursor];
1289 f->output_data.ns->horizontal_drag_cursor = [NSCursor resizeLeftRightCursor];
1290 f->output_data.ns->vertical_drag_cursor = [NSCursor resizeUpDownCursor];
1291 FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor
1292 = [NSCursor arrowCursor];
1293 f->output_data.ns->current_pointer = f->output_data.ns->text_cursor;
1295 [[EmacsView alloc] initFrameFromEmacs: f];
1299 /* ns_display_info does not have a reference_count. */
1300 f->terminal->reference_count++;
1302 /* It is now ok to make the frame official even if we get an error below.
1303 The frame needs to be on Vframe_list or making it visible won't work. */
1304 Vframe_list = Fcons (frame, Vframe_list);
1306 x_default_parameter (f, parms, Qicon_type, Qnil,
1307 "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
1309 x_default_parameter (f, parms, Qauto_raise, Qnil,
1310 "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
1311 x_default_parameter (f, parms, Qauto_lower, Qnil,
1312 "autoLower", "AutoLower", RES_TYPE_BOOLEAN);
1313 x_default_parameter (f, parms, Qcursor_type, Qbox,
1314 "cursorType", "CursorType", RES_TYPE_SYMBOL);
1315 x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
1316 "scrollBarWidth", "ScrollBarWidth",
1318 x_default_parameter (f, parms, Qalpha, Qnil,
1319 "alpha", "Alpha", RES_TYPE_NUMBER);
1320 x_default_parameter (f, parms, Qfullscreen, Qnil,
1321 "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
1323 width = FRAME_TEXT_WIDTH (f);
1324 height = FRAME_TEXT_HEIGHT (f);
1325 FRAME_TEXT_HEIGHT (f) = 0;
1326 SET_FRAME_WIDTH (f, 0);
1327 change_frame_size (f, width, height, 1, 0, 0, 1);
1329 if (! f->output_data.ns->explicit_parent)
1331 Lisp_Object visibility;
1333 visibility = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
1335 if (EQ (visibility, Qunbound))
1338 if (EQ (visibility, Qicon))
1339 x_iconify_frame (f);
1340 else if (! NILP (visibility))
1342 x_make_frame_visible (f);
1343 [[FRAME_NS_VIEW (f) window] makeKeyWindow];
1347 /* Must have been Qnil. */
1351 if (FRAME_HAS_MINIBUF_P (f)
1352 && (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame))
1353 || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame)))))
1354 kset_default_minibuffer_frame (kb, frame);
1356 /* All remaining specified parameters, which have not been "used"
1357 by x_get_arg and friends, now go in the misc. alist of the frame. */
1358 for (tem = parms; CONSP (tem); tem = XCDR (tem))
1359 if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
1360 fset_param_alist (f, Fcons (XCAR (tem), f->param_alist));
1364 if (window_prompting & USPosition)
1365 x_set_offset (f, f->left_pos, f->top_pos, 1);
1367 /* Make sure windows on this frame appear in calls to next-window
1368 and similar functions. */
1369 Vwindow_list = Qnil;
1371 return unbind_to (count, frame);
1375 x_focus_frame (struct frame *f)
1377 struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
1379 if (dpyinfo->x_focus_frame != f)
1381 EmacsView *view = FRAME_NS_VIEW (f);
1383 [NSApp activateIgnoringOtherApps: YES];
1384 [[view window] makeKeyAndOrderFront: view];
1390 DEFUN ("ns-popup-font-panel", Fns_popup_font_panel, Sns_popup_font_panel,
1392 doc: /* Pop up the font panel. */)
1395 struct frame *f = decode_window_system_frame (frame);
1396 id fm = [NSFontManager sharedFontManager];
1397 struct font *font = f->output_data.ns->font;
1399 if (EQ (font->driver->type, Qns))
1400 nsfont = ((struct nsfont_info *)font)->nsfont;
1401 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
1403 nsfont = (NSFont *) macfont_get_nsctfont (font);
1405 [fm setSelectedFont: nsfont isMultiple: NO];
1406 [fm orderFrontFontPanel: NSApp];
1411 DEFUN ("ns-popup-color-panel", Fns_popup_color_panel, Sns_popup_color_panel,
1413 doc: /* Pop up the color panel. */)
1416 check_window_system (NULL);
1417 [NSApp orderFrontColorPanel: NSApp];
1425 #if ! defined (NS_IMPL_COCOA) || \
1426 MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6
1427 NSString *dirS, *initS;
1433 ns_run_file_dialog (void)
1435 if (ns_fd_data.panel == nil) return;
1436 #if defined (NS_IMPL_COCOA) && \
1437 MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
1438 ns_fd_data.ret = [ns_fd_data.panel runModal];
1440 if (ns_fd_data.no_types)
1442 ns_fd_data.ret = [ns_fd_data.panel
1443 runModalForDirectory: ns_fd_data.dirS
1444 file: ns_fd_data.initS];
1448 ns_fd_data.ret = [ns_fd_data.panel
1449 runModalForDirectory: ns_fd_data.dirS
1450 file: ns_fd_data.initS
1454 ns_fd_data.panel = nil;
1457 DEFUN ("ns-read-file-name", Fns_read_file_name, Sns_read_file_name, 1, 5, 0,
1458 doc: /* Use a graphical panel to read a file name, using prompt PROMPT.
1459 Optional arg DIR, if non-nil, supplies a default directory.
1460 Optional arg MUSTMATCH, if non-nil, means the returned file or
1461 directory must exist.
1462 Optional arg INIT, if non-nil, provides a default file name to use.
1463 Optional arg DIR_ONLY_P, if non-nil, means choose only directories. */)
1464 (Lisp_Object prompt, Lisp_Object dir, Lisp_Object mustmatch,
1465 Lisp_Object init, Lisp_Object dir_only_p)
1467 static id fileDelegate = nil;
1469 BOOL isSave = NILP (mustmatch) && NILP (dir_only_p);
1473 NSString *promptS = NILP (prompt) || !STRINGP (prompt) ? nil :
1474 [NSString stringWithUTF8String: SSDATA (prompt)];
1475 NSString *dirS = NILP (dir) || !STRINGP (dir) ?
1476 [NSString stringWithUTF8String: SSDATA (BVAR (current_buffer, directory))] :
1477 [NSString stringWithUTF8String: SSDATA (dir)];
1478 NSString *initS = NILP (init) || !STRINGP (init) ? nil :
1479 [NSString stringWithUTF8String: SSDATA (init)];
1482 check_window_system (NULL);
1484 if (fileDelegate == nil)
1485 fileDelegate = [EmacsFileDelegate new];
1487 [NSCursor setHiddenUntilMouseMoves: NO];
1489 if ([dirS characterAtIndex: 0] == '~')
1490 dirS = [dirS stringByExpandingTildeInPath];
1493 (id)[EmacsSavePanel savePanel] : (id)[EmacsOpenPanel openPanel];
1495 [panel setTitle: promptS];
1497 [panel setAllowsOtherFileTypes: YES];
1498 [panel setTreatsFilePackagesAsDirectories: YES];
1499 [panel setDelegate: fileDelegate];
1501 if (! NILP (dir_only_p))
1503 [panel setCanChooseDirectories: YES];
1504 [panel setCanChooseFiles: NO];
1508 /* This is not quite what the documentation says, but it is compatible
1509 with the Gtk+ code. Also, the menu entry says "Open File...". */
1510 [panel setCanChooseDirectories: NO];
1511 [panel setCanChooseFiles: YES];
1515 ns_fd_data.panel = panel;
1516 ns_fd_data.ret = NO;
1517 #if defined (NS_IMPL_COCOA) && \
1518 MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
1519 if (! NILP (mustmatch) || ! NILP (dir_only_p))
1520 [panel setAllowedFileTypes: nil];
1521 if (dirS) [panel setDirectoryURL: [NSURL fileURLWithPath: dirS]];
1522 if (initS && NILP (Ffile_directory_p (init)))
1523 [panel setNameFieldStringValue: [initS lastPathComponent]];
1525 [panel setNameFieldStringValue: @""];
1528 ns_fd_data.no_types = NILP (mustmatch) && NILP (dir_only_p);
1529 ns_fd_data.dirS = dirS;
1530 ns_fd_data.initS = initS;
1533 /* runModalForDirectory/runModal restarts the main event loop when done,
1534 so we must start an event loop and then pop up the file dialog.
1535 The file dialog may pop up a confirm dialog after Ok has been pressed,
1536 so we can not simply pop down on the Ok/Cancel press.
1538 nxev = [NSEvent otherEventWithType: NSApplicationDefined
1539 location: NSMakePoint (0, 0)
1542 windowNumber: [[NSApp mainWindow] windowNumber]
1543 context: [NSApp context]
1546 data2: NSAPP_DATA2_RUNFILEDIALOG];
1548 [NSApp postEvent: nxev atStart: NO];
1549 while (ns_fd_data.panel != nil)
1552 ret = (ns_fd_data.ret == NSOKButton);
1556 NSString *str = ns_filename_from_panel (panel);
1557 if (! str) str = ns_directory_from_panel (panel);
1558 if (! str) ret = NO;
1559 else fname = build_string ([str UTF8String]);
1562 [[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow];
1565 return ret ? fname : Qnil;
1569 ns_get_defaults_value (const char *key)
1571 NSObject *obj = [[NSUserDefaults standardUserDefaults]
1572 objectForKey: [NSString stringWithUTF8String: key]];
1574 if (!obj) return NULL;
1576 return [[NSString stringWithFormat: @"%@", obj] UTF8String];
1580 DEFUN ("ns-get-resource", Fns_get_resource, Sns_get_resource, 2, 2, 0,
1581 doc: /* Return the value of the property NAME of OWNER from the defaults database.
1582 If OWNER is nil, Emacs is assumed. */)
1583 (Lisp_Object owner, Lisp_Object name)
1587 check_window_system (NULL);
1589 owner = build_string([ns_app_name UTF8String]);
1590 CHECK_STRING (name);
1592 value = ns_get_defaults_value (SSDATA (name));
1595 return build_string (value);
1600 DEFUN ("ns-set-resource", Fns_set_resource, Sns_set_resource, 3, 3, 0,
1601 doc: /* Set property NAME of OWNER to VALUE, from the defaults database.
1602 If OWNER is nil, Emacs is assumed.
1603 If VALUE is nil, the default is removed. */)
1604 (Lisp_Object owner, Lisp_Object name, Lisp_Object value)
1606 check_window_system (NULL);
1608 owner = build_string ([ns_app_name UTF8String]);
1609 CHECK_STRING (name);
1612 [[NSUserDefaults standardUserDefaults] removeObjectForKey:
1613 [NSString stringWithUTF8String: SSDATA (name)]];
1617 CHECK_STRING (value);
1618 [[NSUserDefaults standardUserDefaults] setObject:
1619 [NSString stringWithUTF8String: SSDATA (value)]
1620 forKey: [NSString stringWithUTF8String:
1628 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
1629 Sx_server_max_request_size,
1631 doc: /* This function is a no-op. It is only present for completeness. */)
1632 (Lisp_Object terminal)
1634 check_ns_display_info (terminal);
1635 /* This function has no real equivalent under NeXTstep. Return nil to
1641 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
1642 doc: /* Return the "vendor ID" string of Nextstep display server TERMINAL.
1643 \(Labeling every distributor as a "vendor" embodies the false assumption
1644 that operating systems cannot be developed and distributed noncommercially.)
1645 The optional argument TERMINAL specifies which display to ask about.
1646 TERMINAL should be a terminal object, a frame or a display name (a string).
1647 If omitted or nil, that stands for the selected frame's display. */)
1648 (Lisp_Object terminal)
1650 check_ns_display_info (terminal);
1651 #ifdef NS_IMPL_GNUSTEP
1652 return build_string ("GNU");
1654 return build_string ("Apple");
1659 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
1660 doc: /* Return the version numbers of the server of display TERMINAL.
1661 The value is a list of three integers: the major and minor
1662 version numbers of the X Protocol in use, and the distributor-specific release
1663 number. See also the function `x-server-vendor'.
1665 The optional argument TERMINAL specifies which display to ask about.
1666 TERMINAL should be a terminal object, a frame or a display name (a string).
1667 If omitted or nil, that stands for the selected frame's display. */)
1668 (Lisp_Object terminal)
1670 check_ns_display_info (terminal);
1671 /*NOTE: it is unclear what would best correspond with "protocol";
1672 we return 10.3, meaning Panther, since this is roughly the
1673 level that GNUstep's APIs correspond to.
1674 The last number is where we distinguish between the Apple
1675 and GNUstep implementations ("distributor-specific release
1676 number") and give int'ized versions of major.minor. */
1677 return list3i (10, 3, ns_appkit_version_int ());
1681 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
1682 doc: /* Return the number of screens on Nextstep display server TERMINAL.
1683 The optional argument TERMINAL specifies which display to ask about.
1684 TERMINAL should be a terminal object, a frame or a display name (a string).
1685 If omitted or nil, that stands for the selected frame's display.
1687 Note: "screen" here is not in Nextstep terminology but in X11's. For
1688 the number of physical monitors, use `(length
1689 (display-monitor-attributes-list TERMINAL))' instead. */)
1690 (Lisp_Object terminal)
1692 check_ns_display_info (terminal);
1693 return make_number (1);
1697 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
1698 doc: /* Return the height in millimeters of the Nextstep display TERMINAL.
1699 The optional argument TERMINAL specifies which display to ask about.
1700 TERMINAL should be a terminal object, a frame or a display name (a string).
1701 If omitted or nil, that stands for the selected frame's display.
1703 On \"multi-monitor\" setups this refers to the height in millimeters for
1704 all physical monitors associated with TERMINAL. To get information
1705 for each physical monitor, use `display-monitor-attributes-list'. */)
1706 (Lisp_Object terminal)
1708 struct ns_display_info *dpyinfo = check_ns_display_info (terminal);
1710 return make_number (x_display_pixel_height (dpyinfo) / (92.0/25.4));
1714 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
1715 doc: /* Return the width in millimeters of the Nextstep display TERMINAL.
1716 The optional argument TERMINAL specifies which display to ask about.
1717 TERMINAL should be a terminal object, a frame or a display name (a string).
1718 If omitted or nil, that stands for the selected frame's display.
1720 On \"multi-monitor\" setups this refers to the width in millimeters for
1721 all physical monitors associated with TERMINAL. To get information
1722 for each physical monitor, use `display-monitor-attributes-list'. */)
1723 (Lisp_Object terminal)
1725 struct ns_display_info *dpyinfo = check_ns_display_info (terminal);
1727 return make_number (x_display_pixel_width (dpyinfo) / (92.0/25.4));
1731 DEFUN ("x-display-backing-store", Fx_display_backing_store,
1732 Sx_display_backing_store, 0, 1, 0,
1733 doc: /* Return an indication of whether the Nextstep display TERMINAL does backing store.
1734 The value may be `buffered', `retained', or `non-retained'.
1735 The optional argument TERMINAL specifies which display to ask about.
1736 TERMINAL should be a terminal object, a frame or a display name (a string).
1737 If omitted or nil, that stands for the selected frame's display. */)
1738 (Lisp_Object terminal)
1740 check_ns_display_info (terminal);
1741 switch ([ns_get_window (terminal) backingType])
1743 case NSBackingStoreBuffered:
1744 return intern ("buffered");
1745 case NSBackingStoreRetained:
1746 return intern ("retained");
1747 case NSBackingStoreNonretained:
1748 return intern ("non-retained");
1750 error ("Strange value for backingType parameter of frame");
1752 return Qnil; /* not reached, shut compiler up */
1756 DEFUN ("x-display-visual-class", Fx_display_visual_class,
1757 Sx_display_visual_class, 0, 1, 0,
1758 doc: /* Return the visual class of the Nextstep display TERMINAL.
1759 The value is one of the symbols `static-gray', `gray-scale',
1760 `static-color', `pseudo-color', `true-color', or `direct-color'.
1762 The optional argument TERMINAL specifies which display to ask about.
1763 TERMINAL should a terminal object, a frame or a display name (a string).
1764 If omitted or nil, that stands for the selected frame's display. */)
1765 (Lisp_Object terminal)
1767 NSWindowDepth depth;
1769 check_ns_display_info (terminal);
1770 depth = [[[NSScreen screens] objectAtIndex:0] depth];
1772 if ( depth == NSBestDepth (NSCalibratedWhiteColorSpace, 2, 2, YES, NULL))
1773 return intern ("static-gray");
1774 else if (depth == NSBestDepth (NSCalibratedWhiteColorSpace, 8, 8, YES, NULL))
1775 return intern ("gray-scale");
1776 else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 8, 8, YES, NULL))
1777 return intern ("pseudo-color");
1778 else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 4, 12, NO, NULL))
1779 return intern ("true-color");
1780 else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 8, 24, NO, NULL))
1781 return intern ("direct-color");
1783 /* color mgmt as far as we do it is really handled by Nextstep itself anyway */
1784 return intern ("direct-color");
1788 DEFUN ("x-display-save-under", Fx_display_save_under,
1789 Sx_display_save_under, 0, 1, 0,
1790 doc: /* Return t if TERMINAL supports the save-under feature.
1791 The optional argument TERMINAL specifies which display to ask about.
1792 TERMINAL should be a terminal object, a frame or a display name (a string).
1793 If omitted or nil, that stands for the selected frame's display. */)
1794 (Lisp_Object terminal)
1796 check_ns_display_info (terminal);
1797 switch ([ns_get_window (terminal) backingType])
1799 case NSBackingStoreBuffered:
1802 case NSBackingStoreRetained:
1803 case NSBackingStoreNonretained:
1807 error ("Strange value for backingType parameter of frame");
1809 return Qnil; /* not reached, shut compiler up */
1813 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
1815 doc: /* Open a connection to a display server.
1816 DISPLAY is the name of the display to connect to.
1817 Optional second arg XRM-STRING is a string of resources in xrdb format.
1818 If the optional third arg MUST-SUCCEED is non-nil,
1819 terminate Emacs if we can't open the connection.
1820 \(In the Nextstep version, the last two arguments are currently ignored.) */)
1821 (Lisp_Object display, Lisp_Object resource_string, Lisp_Object must_succeed)
1823 struct ns_display_info *dpyinfo;
1825 CHECK_STRING (display);
1827 nxatoms_of_nsselect ();
1828 dpyinfo = ns_term_init (display);
1831 if (!NILP (must_succeed))
1832 fatal ("Display on %s not responding.\n",
1835 error ("Display on %s not responding.\n",
1843 DEFUN ("x-close-connection", Fx_close_connection, Sx_close_connection,
1845 doc: /* Close the connection to TERMINAL's Nextstep display server.
1846 For TERMINAL, specify a terminal object, a frame or a display name (a
1847 string). If TERMINAL is nil, that stands for the selected frame's
1849 (Lisp_Object terminal)
1851 check_ns_display_info (terminal);
1852 [NSApp terminate: NSApp];
1857 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
1858 doc: /* Return the list of display names that Emacs has connections to. */)
1861 Lisp_Object result = Qnil;
1862 struct ns_display_info *ndi;
1864 for (ndi = x_display_list; ndi; ndi = ndi->next)
1865 result = Fcons (XCAR (ndi->name_list_element), result);
1871 DEFUN ("ns-hide-others", Fns_hide_others, Sns_hide_others,
1873 doc: /* Hides all applications other than Emacs. */)
1876 check_window_system (NULL);
1877 [NSApp hideOtherApplications: NSApp];
1881 DEFUN ("ns-hide-emacs", Fns_hide_emacs, Sns_hide_emacs,
1883 doc: /* If ON is non-nil, the entire Emacs application is hidden.
1884 Otherwise if Emacs is hidden, it is unhidden.
1885 If ON is equal to `activate', Emacs is unhidden and becomes
1886 the active application. */)
1889 check_window_system (NULL);
1890 if (EQ (on, intern ("activate")))
1892 [NSApp unhide: NSApp];
1893 [NSApp activateIgnoringOtherApps: YES];
1896 [NSApp unhide: NSApp];
1898 [NSApp hide: NSApp];
1903 DEFUN ("ns-emacs-info-panel", Fns_emacs_info_panel, Sns_emacs_info_panel,
1905 doc: /* Shows the 'Info' or 'About' panel for Emacs. */)
1908 check_window_system (NULL);
1909 [NSApp orderFrontStandardAboutPanel: nil];
1914 DEFUN ("ns-font-name", Fns_font_name, Sns_font_name, 1, 1, 0,
1915 doc: /* Determine font PostScript or family name for font NAME.
1916 NAME should be a string containing either the font name or an XLFD
1917 font descriptor. If string contains `fontset' and not
1918 `fontset-startup', it is left alone. */)
1922 CHECK_STRING (name);
1927 if (strstr (nm, "fontset") && !strstr (nm, "fontset-startup"))
1930 return build_string (ns_xlfd_to_fontname (SSDATA (name)));
1934 DEFUN ("ns-list-colors", Fns_list_colors, Sns_list_colors, 0, 1, 0,
1935 doc: /* Return a list of all available colors.
1936 The optional argument FRAME is currently ignored. */)
1939 Lisp_Object list = Qnil;
1940 NSEnumerator *colorlists;
1945 CHECK_FRAME (frame);
1946 if (! FRAME_NS_P (XFRAME (frame)))
1947 error ("non-Nextstep frame used in `ns-list-colors'");
1952 colorlists = [[NSColorList availableColorLists] objectEnumerator];
1953 while ((clist = [colorlists nextObject]))
1955 if ([[clist name] length] < 7 ||
1956 [[clist name] rangeOfString: @"PANTONE"].location == 0)
1958 NSEnumerator *cnames = [[clist allKeys] reverseObjectEnumerator];
1960 while ((cname = [cnames nextObject]))
1961 list = Fcons (build_string ([cname UTF8String]), list);
1962 /* for (i = [[clist allKeys] count] - 1; i >= 0; i--)
1963 list = Fcons (build_string ([[[clist allKeys] objectAtIndex: i]
1964 UTF8String]), list); */
1974 DEFUN ("ns-list-services", Fns_list_services, Sns_list_services, 0, 0, 0,
1975 doc: /* List available Nextstep services by querying NSApp. */)
1978 #if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
1979 /* You can't get services like this in 10.6+. */
1982 Lisp_Object ret = Qnil;
1984 #ifdef NS_IMPL_COCOA
1988 check_window_system (NULL);
1989 svcs = [[NSMenu alloc] initWithTitle: @"Services"];
1990 [NSApp setServicesMenu: svcs];
1991 [NSApp registerServicesMenuSendTypes: ns_send_types
1992 returnTypes: ns_return_types];
1994 /* On Tiger, services menu updating was made lazier (waits for user to
1995 actually click on the menu), so we have to force things along: */
1996 #ifdef NS_IMPL_COCOA
1997 delegate = [svcs delegate];
1998 if (delegate != nil)
2000 if ([delegate respondsToSelector: @selector (menuNeedsUpdate:)])
2001 [delegate menuNeedsUpdate: svcs];
2002 if ([delegate respondsToSelector:
2003 @selector (menu:updateItem:atIndex:shouldCancel:)])
2005 int i, len = [delegate numberOfItemsInMenu: svcs];
2006 for (i =0; i<len; i++)
2007 [svcs addItemWithTitle: @"" action: NULL keyEquivalent: @""];
2008 for (i =0; i<len; i++)
2009 if (![delegate menu: svcs
2010 updateItem: (NSMenuItem *)[svcs itemAtIndex: i]
2011 atIndex: i shouldCancel: NO])
2017 [svcs setAutoenablesItems: NO];
2018 #ifdef NS_IMPL_COCOA
2019 [svcs update]; /* on OS X, converts from '/' structure */
2022 ret = interpret_services_menu (svcs, Qnil, ret);
2028 DEFUN ("ns-perform-service", Fns_perform_service, Sns_perform_service,
2030 doc: /* Perform Nextstep SERVICE on SEND.
2031 SEND should be either a string or nil.
2032 The return value is the result of the service, as string, or nil if
2033 there was no result. */)
2034 (Lisp_Object service, Lisp_Object send)
2040 CHECK_STRING (service);
2041 check_window_system (NULL);
2043 utfStr = SSDATA (service);
2044 svcName = [NSString stringWithUTF8String: utfStr];
2046 pb =[NSPasteboard pasteboardWithUniqueName];
2047 ns_string_to_pasteboard (pb, send);
2049 if (NSPerformService (svcName, pb) == NO)
2050 Fsignal (Qquit, list1 (build_string ("service not available")));
2052 if ([[pb types] count] == 0)
2053 return build_string ("");
2054 return ns_string_from_pasteboard (pb);
2058 DEFUN ("ns-convert-utf8-nfd-to-nfc", Fns_convert_utf8_nfd_to_nfc,
2059 Sns_convert_utf8_nfd_to_nfc, 1, 1, 0,
2060 doc: /* Return an NFC string that matches the UTF-8 NFD string STR. */)
2063 /* TODO: If GNUstep ever implements precomposedStringWithCanonicalMapping,
2066 Lisp_Object ret = Qnil;
2067 NSAutoreleasePool *pool;
2070 pool = [[NSAutoreleasePool alloc] init];
2071 utfStr = [NSString stringWithUTF8String: SSDATA (str)];
2072 #ifdef NS_IMPL_COCOA
2074 utfStr = [utfStr precomposedStringWithCanonicalMapping];
2078 const char *cstr = [utfStr UTF8String];
2080 ret = build_string (cstr);
2085 error ("Invalid UTF-8");
2091 #ifdef NS_IMPL_COCOA
2093 /* Compile and execute the AppleScript SCRIPT and return the error
2094 status as function value. A zero is returned if compilation and
2095 execution is successful, in which case *RESULT is set to a Lisp
2096 string or a number containing the resulting script value. Otherwise,
2099 ns_do_applescript (Lisp_Object script, Lisp_Object *result)
2101 NSAppleEventDescriptor *desc;
2102 NSDictionary* errorDict;
2103 NSAppleEventDescriptor* returnDescriptor = NULL;
2105 NSAppleScript* scriptObject =
2106 [[NSAppleScript alloc] initWithSource:
2107 [NSString stringWithUTF8String: SSDATA (script)]];
2109 returnDescriptor = [scriptObject executeAndReturnError: &errorDict];
2110 [scriptObject release];
2114 if (returnDescriptor != NULL)
2116 // successful execution
2117 if (kAENullEvent != [returnDescriptor descriptorType])
2120 // script returned an AppleScript result
2121 if ((typeUnicodeText == [returnDescriptor descriptorType]) ||
2122 #if defined (NS_IMPL_COCOA)
2123 (typeUTF16ExternalRepresentation
2124 == [returnDescriptor descriptorType]) ||
2126 (typeUTF8Text == [returnDescriptor descriptorType]) ||
2127 (typeCString == [returnDescriptor descriptorType]))
2129 desc = [returnDescriptor coerceToDescriptorType: typeUTF8Text];
2131 *result = build_string([[desc stringValue] UTF8String]);
2135 /* use typeUTF16ExternalRepresentation? */
2136 // coerce the result to the appropriate ObjC type
2137 desc = [returnDescriptor coerceToDescriptorType: typeUTF8Text];
2139 *result = make_number([desc int32Value]);
2145 // no script result, return error
2151 /* Helper function called from sendEvent to run applescript
2152 from within the main event loop. */
2155 ns_run_ascript (void)
2157 if (! NILP (as_script))
2158 as_status = ns_do_applescript (as_script, as_result);
2162 DEFUN ("ns-do-applescript", Fns_do_applescript, Sns_do_applescript, 1, 1, 0,
2163 doc: /* Execute AppleScript SCRIPT and return the result.
2164 If compilation and execution are successful, the resulting script value
2165 is returned as a string, a number or, in the case of other constructs, t.
2166 In case the execution fails, an error is signaled. */)
2167 (Lisp_Object script)
2173 CHECK_STRING (script);
2174 check_window_system (NULL);
2179 as_result = &result;
2181 /* executing apple script requires the event loop to run, otherwise
2182 errors aren't returned and executeAndReturnError hangs forever.
2183 Post an event that runs applescript and then start the event loop.
2184 The event loop is exited when the script is done. */
2185 nxev = [NSEvent otherEventWithType: NSApplicationDefined
2186 location: NSMakePoint (0, 0)
2189 windowNumber: [[NSApp mainWindow] windowNumber]
2190 context: [NSApp context]
2193 data2: NSAPP_DATA2_RUNASSCRIPT];
2195 [NSApp postEvent: nxev atStart: NO];
2197 // If there are other events, the event loop may exit. Keep running
2198 // until the script has been handled. */
2199 while (! NILP (as_script))
2208 else if (!STRINGP (result))
2209 error ("AppleScript error %d", status);
2211 error ("%s", SSDATA (result));
2217 /* ==========================================================================
2219 Miscellaneous functions not called through hooks
2221 ========================================================================== */
2223 /* called from frame.c */
2224 struct ns_display_info *
2225 check_x_display_info (Lisp_Object frame)
2227 return check_ns_display_info (frame);
2232 x_set_scroll_bar_default_width (struct frame *f)
2234 int wid = FRAME_COLUMN_WIDTH (f);
2235 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = NS_SCROLL_BAR_WIDTH_DEFAULT;
2236 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) +
2240 /* terms impl this instead of x-get-resource directly */
2242 x_get_string_resource (XrmDatabase rdb, const char *name, const char *class)
2244 /* remove appname prefix; TODO: allow for !="Emacs" */
2245 const char *res, *toCheck = class + (!strncmp (class, "Emacs.", 6) ? 6 : 0);
2247 check_window_system (NULL);
2249 if (inhibit_x_resources)
2250 /* --quick was passed, so this is a no-op. */
2253 res = ns_get_defaults_value (toCheck);
2254 return (!res ? NULL :
2255 (!c_strncasecmp (res, "YES", 3) ? "true" :
2256 (!c_strncasecmp (res, "NO", 2) ? "false" : (char *) res)));
2261 x_get_focus_frame (struct frame *frame)
2263 struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame);
2264 Lisp_Object nsfocus;
2266 if (!dpyinfo->x_focus_frame)
2269 XSETFRAME (nsfocus, dpyinfo->x_focus_frame);
2273 /* ==========================================================================
2275 Lisp definitions that, for whatever reason, we can't alias as 'ns-XXX'.
2277 ========================================================================== */
2280 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
2281 doc: /* Internal function called by `color-defined-p', which see.
2282 \(Note that the Nextstep version of this function ignores FRAME.) */)
2283 (Lisp_Object color, Lisp_Object frame)
2286 check_window_system (NULL);
2287 return ns_lisp_to_color (color, &col) ? Qnil : Qt;
2291 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
2292 doc: /* Internal function called by `color-values', which see. */)
2293 (Lisp_Object color, Lisp_Object frame)
2296 EmacsCGFloat red, green, blue, alpha;
2298 check_window_system (NULL);
2299 CHECK_STRING (color);
2301 if (ns_lisp_to_color (color, &col))
2304 [[col colorUsingDefaultColorSpace]
2305 getRed: &red green: &green blue: &blue alpha: &alpha];
2306 return list3i (lrint (red * 65280), lrint (green * 65280),
2307 lrint (blue * 65280));
2311 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
2312 doc: /* Internal function called by `display-color-p', which see. */)
2313 (Lisp_Object terminal)
2315 NSWindowDepth depth;
2316 NSString *colorSpace;
2318 check_ns_display_info (terminal);
2319 depth = [[[NSScreen screens] objectAtIndex:0] depth];
2320 colorSpace = NSColorSpaceFromDepth (depth);
2322 return [colorSpace isEqualToString: NSDeviceWhiteColorSpace]
2323 || [colorSpace isEqualToString: NSCalibratedWhiteColorSpace]
2328 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
2330 doc: /* Return t if the Nextstep display supports shades of gray.
2331 Note that color displays do support shades of gray.
2332 The optional argument TERMINAL specifies which display to ask about.
2333 TERMINAL should be a terminal object, a frame or a display name (a string).
2334 If omitted or nil, that stands for the selected frame's display. */)
2335 (Lisp_Object terminal)
2337 NSWindowDepth depth;
2339 check_ns_display_info (terminal);
2340 depth = [[[NSScreen screens] objectAtIndex:0] depth];
2342 return NSBitsPerPixelFromDepth (depth) > 1 ? Qt : Qnil;
2346 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
2348 doc: /* Return the width in pixels of the Nextstep display TERMINAL.
2349 The optional argument TERMINAL specifies which display to ask about.
2350 TERMINAL should be a terminal object, a frame or a display name (a string).
2351 If omitted or nil, that stands for the selected frame's display.
2353 On \"multi-monitor\" setups this refers to the pixel width for all
2354 physical monitors associated with TERMINAL. To get information for
2355 each physical monitor, use `display-monitor-attributes-list'. */)
2356 (Lisp_Object terminal)
2358 struct ns_display_info *dpyinfo = check_ns_display_info (terminal);
2360 return make_number (x_display_pixel_width (dpyinfo));
2364 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
2365 Sx_display_pixel_height, 0, 1, 0,
2366 doc: /* Return the height in pixels of the Nextstep display TERMINAL.
2367 The optional argument TERMINAL specifies which display to ask about.
2368 TERMINAL should be a terminal object, a frame or a display name (a string).
2369 If omitted or nil, that stands for the selected frame's display.
2371 On \"multi-monitor\" setups this refers to the pixel height for all
2372 physical monitors associated with TERMINAL. To get information for
2373 each physical monitor, use `display-monitor-attributes-list'. */)
2374 (Lisp_Object terminal)
2376 struct ns_display_info *dpyinfo = check_ns_display_info (terminal);
2378 return make_number (x_display_pixel_height (dpyinfo));
2381 #ifdef NS_IMPL_COCOA
2383 /* Returns the name for the screen that OBJ represents, or NULL.
2384 Caller must free return value.
2388 ns_get_name_from_ioreg (io_object_t obj)
2392 NSDictionary *info = (NSDictionary *)
2393 IODisplayCreateInfoDictionary (obj, kIODisplayOnlyPreferredName);
2394 NSDictionary *names = [info objectForKey:
2395 [NSString stringWithUTF8String:
2396 kDisplayProductName]];
2398 if ([names count] > 0)
2400 NSString *n = [names objectForKey: [[names allKeys]
2402 if (n != nil) name = xstrdup ([n UTF8String]);
2410 /* Returns the name for the screen that DID came from, or NULL.
2411 Caller must free return value.
2415 ns_screen_name (CGDirectDisplayID did)
2419 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
2420 mach_port_t masterPort;
2424 // CGDisplayIOServicePort is deprecated. Do it another (harder) way.
2426 if (IOMasterPort (MACH_PORT_NULL, &masterPort) != kIOReturnSuccess
2427 || IOServiceGetMatchingServices (masterPort,
2428 IOServiceMatching ("IONDRVDevice"),
2429 &it) != kIOReturnSuccess)
2432 /* Must loop until we find a name. Many devices can have the same unit
2433 number (represents different GPU parts), but only one has a name. */
2434 while (! name && (obj = IOIteratorNext (it)))
2436 CFMutableDictionaryRef props;
2439 if (IORegistryEntryCreateCFProperties (obj,
2441 kCFAllocatorDefault,
2442 kNilOptions) == kIOReturnSuccess
2444 && (val = CFDictionaryGetValue(props, @"IOFBDependentIndex")))
2446 unsigned nr = [(NSNumber *)val unsignedIntegerValue];
2447 if (nr == CGDisplayUnitNumber (did))
2448 name = ns_get_name_from_ioreg (obj);
2452 IOObjectRelease (obj);
2455 IOObjectRelease (it);
2459 name = ns_get_name_from_ioreg (CGDisplayIOServicePort (did));
2467 ns_make_monitor_attribute_list (struct MonitorInfo *monitors,
2469 int primary_monitor,
2472 Lisp_Object monitor_frames = Fmake_vector (make_number (n_monitors), Qnil);
2473 Lisp_Object frame, rest;
2474 NSArray *screens = [NSScreen screens];
2477 FOR_EACH_FRAME (rest, frame)
2479 struct frame *f = XFRAME (frame);
2483 NSView *view = FRAME_NS_VIEW (f);
2484 NSScreen *screen = [[view window] screen];
2488 for (k = 0; i == -1 && k < [screens count]; ++k)
2490 if ([screens objectAtIndex: k] == screen)
2495 ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i)));
2499 return make_monitor_attribute_list (monitors, n_monitors, primary_monitor,
2500 monitor_frames, source);
2503 DEFUN ("ns-display-monitor-attributes-list",
2504 Fns_display_monitor_attributes_list,
2505 Sns_display_monitor_attributes_list,
2507 doc: /* Return a list of physical monitor attributes on the X display TERMINAL.
2509 The optional argument TERMINAL specifies which display to ask about.
2510 TERMINAL should be a terminal object, a frame or a display name (a string).
2511 If omitted or nil, that stands for the selected frame's display.
2513 In addition to the standard attribute keys listed in
2514 `display-monitor-attributes-list', the following keys are contained in
2517 source -- String describing the source from which multi-monitor
2518 information is obtained, \"NS\" is always the source."
2520 Internal use only, use `display-monitor-attributes-list' instead. */)
2521 (Lisp_Object terminal)
2523 struct terminal *term = get_terminal (terminal, 1);
2525 NSUInteger i, n_monitors;
2526 struct MonitorInfo *monitors;
2527 Lisp_Object attributes_list = Qnil;
2528 CGFloat primary_display_height = 0;
2530 if (term->type != output_ns)
2533 screens = [NSScreen screens];
2534 n_monitors = [screens count];
2535 if (n_monitors == 0)
2538 monitors = xzalloc (n_monitors * sizeof *monitors);
2540 for (i = 0; i < [screens count]; ++i)
2542 NSScreen *s = [screens objectAtIndex:i];
2543 struct MonitorInfo *m = &monitors[i];
2544 NSRect fr = [s frame];
2545 NSRect vfr = [s visibleFrame];
2548 #ifdef NS_IMPL_COCOA
2549 NSDictionary *dict = [s deviceDescription];
2550 NSNumber *nid = [dict objectForKey:@"NSScreenNumber"];
2551 CGDirectDisplayID did = [nid unsignedIntValue];
2555 primary_display_height = fr.size.height;
2556 y = (short) fr.origin.y;
2557 vy = (short) vfr.origin.y;
2561 // Flip y coordinate as NS has y starting from the bottom.
2562 y = (short) (primary_display_height - fr.size.height - fr.origin.y);
2563 vy = (short) (primary_display_height -
2564 vfr.size.height - vfr.origin.y);
2567 m->geom.x = (short) fr.origin.x;
2569 m->geom.width = (unsigned short) fr.size.width;
2570 m->geom.height = (unsigned short) fr.size.height;
2572 m->work.x = (short) vfr.origin.x;
2573 // y is flipped on NS, so vy - y are pixels missing at the bottom,
2574 // and fr.size.height - vfr.size.height are pixels missing in total.
2575 // Pixels missing at top are
2576 // fr.size.height - vfr.size.height - vy + y.
2577 // work.y is then pixels missing at top + y.
2578 m->work.y = (short) (fr.size.height - vfr.size.height) - vy + y + y;
2579 m->work.width = (unsigned short) vfr.size.width;
2580 m->work.height = (unsigned short) vfr.size.height;
2582 #ifdef NS_IMPL_COCOA
2583 m->name = ns_screen_name (did);
2586 CGSize mms = CGDisplayScreenSize (did);
2587 m->mm_width = (int) mms.width;
2588 m->mm_height = (int) mms.height;
2592 // Assume 92 dpi as x-display-mm-height/x-display-mm-width does.
2593 m->mm_width = (int) (25.4 * fr.size.width / 92.0);
2594 m->mm_height = (int) (25.4 * fr.size.height / 92.0);
2598 // Primary monitor is always first for NS.
2599 attributes_list = ns_make_monitor_attribute_list (monitors, n_monitors,
2602 free_monitors (monitors, n_monitors);
2603 return attributes_list;
2607 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
2609 doc: /* Return the number of bitplanes of the Nextstep display TERMINAL.
2610 The optional argument TERMINAL specifies which display to ask about.
2611 TERMINAL should be a terminal object, a frame or a display name (a string).
2612 If omitted or nil, that stands for the selected frame's display. */)
2613 (Lisp_Object terminal)
2615 check_ns_display_info (terminal);
2617 (NSBitsPerPixelFromDepth ([[[NSScreen screens] objectAtIndex:0] depth]));
2621 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
2623 doc: /* Returns the number of color cells of the Nextstep display TERMINAL.
2624 The optional argument TERMINAL specifies which display to ask about.
2625 TERMINAL should be a terminal object, a frame or a display name (a string).
2626 If omitted or nil, that stands for the selected frame's display. */)
2627 (Lisp_Object terminal)
2629 struct ns_display_info *dpyinfo = check_ns_display_info (terminal);
2630 /* We force 24+ bit depths to 24-bit to prevent an overflow. */
2631 return make_number (1 << min (dpyinfo->n_planes, 24));
2635 /* Unused dummy def needed for compatibility. */
2636 Lisp_Object tip_frame;
2638 /* TODO: move to xdisp or similar */
2640 compute_tip_xy (struct frame *f,
2649 Lisp_Object left, top;
2650 EmacsView *view = FRAME_NS_VIEW (f);
2651 struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
2654 /* Start with user-specified or mouse position. */
2655 left = Fcdr (Fassq (Qleft, parms));
2656 top = Fcdr (Fassq (Qtop, parms));
2658 if (!INTEGERP (left) || !INTEGERP (top))
2660 pt.x = dpyinfo->last_mouse_motion_x;
2661 pt.y = dpyinfo->last_mouse_motion_y;
2662 /* Convert to screen coordinates */
2663 pt = [view convertPoint: pt toView: nil];
2664 pt = [[view window] convertBaseToScreen: pt];
2668 /* Absolute coordinates. */
2670 pt.y = x_display_pixel_height (FRAME_DISPLAY_INFO (f)) - XINT (top)
2674 /* Ensure in bounds. (Note, screen origin = lower left.) */
2675 if (INTEGERP (left))
2677 else if (pt.x + XINT (dx) <= 0)
2678 *root_x = 0; /* Can happen for negative dx */
2679 else if (pt.x + XINT (dx) + width
2680 <= x_display_pixel_width (FRAME_DISPLAY_INFO (f)))
2681 /* It fits to the right of the pointer. */
2682 *root_x = pt.x + XINT (dx);
2683 else if (width + XINT (dx) <= pt.x)
2684 /* It fits to the left of the pointer. */
2685 *root_x = pt.x - width - XINT (dx);
2687 /* Put it left justified on the screen -- it ought to fit that way. */
2692 else if (pt.y - XINT (dy) - height >= 0)
2693 /* It fits below the pointer. */
2694 *root_y = pt.y - height - XINT (dy);
2695 else if (pt.y + XINT (dy) + height
2696 <= x_display_pixel_height (FRAME_DISPLAY_INFO (f)))
2697 /* It fits above the pointer */
2698 *root_y = pt.y + XINT (dy);
2700 /* Put it on the top. */
2701 *root_y = x_display_pixel_height (FRAME_DISPLAY_INFO (f)) - height;
2705 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
2706 doc: /* Show STRING in a \"tooltip\" window on frame FRAME.
2707 A tooltip window is a small window displaying a string.
2709 This is an internal function; Lisp code should call `tooltip-show'.
2711 FRAME nil or omitted means use the selected frame.
2713 PARMS is an optional list of frame parameters which can be used to
2714 change the tooltip's appearance.
2716 Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
2717 means use the default timeout of 5 seconds.
2719 If the list of frame parameters PARMS contains a `left' parameter,
2720 the tooltip is displayed at that x-position. Otherwise it is
2721 displayed at the mouse position, with offset DX added (default is 5 if
2722 DX isn't specified). Likewise for the y-position; if a `top' frame
2723 parameter is specified, it determines the y-position of the tooltip
2724 window, otherwise it is displayed at the mouse position, with offset
2725 DY added (default is -10).
2727 A tooltip's maximum size is specified by `x-max-tooltip-size'.
2728 Text larger than the specified size is clipped. */)
2729 (Lisp_Object string, Lisp_Object frame, Lisp_Object parms, Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy)
2732 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
2733 ptrdiff_t count = SPECPDL_INDEX ();
2738 specbind (Qinhibit_redisplay, Qt);
2740 GCPRO4 (string, parms, frame, timeout);
2742 CHECK_STRING (string);
2743 str = SSDATA (string);
2744 f = decode_window_system_frame (frame);
2746 timeout = make_number (5);
2748 CHECK_NATNUM (timeout);
2751 dx = make_number (5);
2756 dy = make_number (-10);
2761 if (ns_tooltip == nil)
2762 ns_tooltip = [[EmacsTooltip alloc] init];
2766 [ns_tooltip setText: str];
2767 size = [ns_tooltip frame].size;
2769 /* Move the tooltip window where the mouse pointer is. Resize and
2771 compute_tip_xy (f, parms, dx, dy, (int)size.width, (int)size.height,
2774 [ns_tooltip showAtX: root_x Y: root_y for: XINT (timeout)];
2778 return unbind_to (count, Qnil);
2782 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
2783 doc: /* Hide the current tooltip window, if there is any.
2784 Value is t if tooltip was open, nil otherwise. */)
2787 if (ns_tooltip == nil || ![ns_tooltip isActive])
2794 /* ==========================================================================
2796 Class implementations
2798 ========================================================================== */
2801 Handle arrow/function/control keys and copy/paste/cut in file dialogs.
2802 Return YES if handled, NO if not.
2805 handlePanelKeys (NSSavePanel *panel, NSEvent *theEvent)
2811 if ([theEvent type] != NSKeyDown) return NO;
2812 s = [theEvent characters];
2814 for (i = 0; i < [s length]; ++i)
2816 int ch = (int) [s characterAtIndex: i];
2819 case NSHomeFunctionKey:
2820 case NSDownArrowFunctionKey:
2821 case NSUpArrowFunctionKey:
2822 case NSLeftArrowFunctionKey:
2823 case NSRightArrowFunctionKey:
2824 case NSPageUpFunctionKey:
2825 case NSPageDownFunctionKey:
2826 case NSEndFunctionKey:
2827 /* Don't send command modified keys, as those are handled in the
2828 performKeyEquivalent method of the super class.
2830 if (! ([theEvent modifierFlags] & NSCommandKeyMask))
2832 [panel sendEvent: theEvent];
2836 /* As we don't have the standard key commands for
2837 copy/paste/cut/select-all in our edit menu, we must handle
2838 them here. TODO: handle Emacs key bindings for copy/cut/select-all
2839 here, paste works, because we have that in our Edit menu.
2840 I.e. refactor out code in nsterm.m, keyDown: to figure out the
2846 case 'a': // Select all
2847 if ([theEvent modifierFlags] & NSCommandKeyMask)
2856 : @selector(selectAll:))))
2861 // Send all control keys, as the text field supports C-a, C-f, C-e
2863 if ([theEvent modifierFlags] & NSControlKeyMask)
2865 [panel sendEvent: theEvent];
2876 @implementation EmacsSavePanel
2877 - (BOOL)performKeyEquivalent:(NSEvent *)theEvent
2879 BOOL ret = handlePanelKeys (self, theEvent);
2881 ret = [super performKeyEquivalent:theEvent];
2887 @implementation EmacsOpenPanel
2888 - (BOOL)performKeyEquivalent:(NSEvent *)theEvent
2890 // NSOpenPanel inherits NSSavePanel, so passing self is OK.
2891 BOOL ret = handlePanelKeys (self, theEvent);
2893 ret = [super performKeyEquivalent:theEvent];
2899 @implementation EmacsFileDelegate
2900 /* --------------------------------------------------------------------------
2901 Delegate methods for Open/Save panels
2902 -------------------------------------------------------------------------- */
2903 - (BOOL)panel: (id)sender isValidFilename: (NSString *)filename
2907 - (BOOL)panel: (id)sender shouldShowFilename: (NSString *)filename
2911 - (NSString *)panel: (id)sender userEnteredFilename: (NSString *)filename
2912 confirmed: (BOOL)okFlag
2921 /* ==========================================================================
2923 Lisp interface declaration
2925 ========================================================================== */
2929 syms_of_nsfns (void)
2931 Qfontsize = intern_c_string ("fontsize");
2932 staticpro (&Qfontsize);
2934 DEFVAR_LISP ("ns-icon-type-alist", Vns_icon_type_alist,
2935 doc: /* Alist of elements (REGEXP . IMAGE) for images of icons associated to frames.
2936 If the title of a frame matches REGEXP, then IMAGE.tiff is
2937 selected as the image of the icon representing the frame when it's
2938 miniaturized. If an element is t, then Emacs tries to select an icon
2939 based on the filetype of the visited file.
2941 The images have to be installed in a folder called English.lproj in the
2942 Emacs folder. You have to restart Emacs after installing new icons.
2944 Example: Install an icon Gnus.tiff and execute the following code
2946 (setq ns-icon-type-alist
2947 (append ns-icon-type-alist
2948 '((\"^\\\\*\\\\(Group\\\\*$\\\\|Summary \\\\|Article\\\\*$\\\\)\"
2951 When you miniaturize a Group, Summary or Article frame, Gnus.tiff will
2952 be used as the image of the icon representing the frame. */);
2953 Vns_icon_type_alist = list1 (Qt);
2955 DEFVAR_LISP ("ns-version-string", Vns_version_string,
2956 doc: /* Toolkit version for NS Windowing. */);
2957 Vns_version_string = ns_appkit_version_str ();
2959 defsubr (&Sns_read_file_name);
2960 defsubr (&Sns_get_resource);
2961 defsubr (&Sns_set_resource);
2962 defsubr (&Sxw_display_color_p); /* this and next called directly by C code */
2963 defsubr (&Sx_display_grayscale_p);
2964 defsubr (&Sns_font_name);
2965 defsubr (&Sns_list_colors);
2966 #ifdef NS_IMPL_COCOA
2967 defsubr (&Sns_do_applescript);
2969 defsubr (&Sxw_color_defined_p);
2970 defsubr (&Sxw_color_values);
2971 defsubr (&Sx_server_max_request_size);
2972 defsubr (&Sx_server_vendor);
2973 defsubr (&Sx_server_version);
2974 defsubr (&Sx_display_pixel_width);
2975 defsubr (&Sx_display_pixel_height);
2976 defsubr (&Sns_display_monitor_attributes_list);
2977 defsubr (&Sx_display_mm_width);
2978 defsubr (&Sx_display_mm_height);
2979 defsubr (&Sx_display_screens);
2980 defsubr (&Sx_display_planes);
2981 defsubr (&Sx_display_color_cells);
2982 defsubr (&Sx_display_visual_class);
2983 defsubr (&Sx_display_backing_store);
2984 defsubr (&Sx_display_save_under);
2985 defsubr (&Sx_create_frame);
2986 defsubr (&Sx_open_connection);
2987 defsubr (&Sx_close_connection);
2988 defsubr (&Sx_display_list);
2990 defsubr (&Sns_hide_others);
2991 defsubr (&Sns_hide_emacs);
2992 defsubr (&Sns_emacs_info_panel);
2993 defsubr (&Sns_list_services);
2994 defsubr (&Sns_perform_service);
2995 defsubr (&Sns_convert_utf8_nfd_to_nfc);
2996 defsubr (&Sns_popup_font_panel);
2997 defsubr (&Sns_popup_color_panel);
2999 defsubr (&Sx_show_tip);
3000 defsubr (&Sx_hide_tip);