* lisp/emacs-lisp/package.el: New quickstart feature
[emacs.git] / src / nsfns.m
blob6df54b4eb50a56ae479db02de416118cea2d00f1
1 /* Functions for the NeXT/Open/GNUstep and macOS window system.
3 Copyright (C) 1989, 1992-1994, 2005-2006, 2008-2018 Free Software
4 Foundation, Inc.
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 (at
11 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 <https://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 macOS/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.  */
31 #include <config.h>
33 #include <math.h>
34 #include <c-strcase.h>
36 #include "lisp.h"
37 #include "blockinput.h"
38 #include "nsterm.h"
39 #include "window.h"
40 #include "character.h"
41 #include "buffer.h"
42 #include "keyboard.h"
43 #include "termhooks.h"
44 #include "fontset.h"
45 #include "font.h"
47 #ifdef NS_IMPL_COCOA
48 #include <IOKit/graphics/IOGraphicsLib.h>
49 #include "macfont.h"
50 #endif
53 #ifdef HAVE_NS
55 static EmacsTooltip *ns_tooltip = nil;
57 /* Static variables to handle AppleScript execution.  */
58 static Lisp_Object as_script, *as_result;
59 static int as_status;
61 static ptrdiff_t image_cache_refcount;
63 static struct ns_display_info *ns_display_info_for_name (Lisp_Object);
65 /* ==========================================================================
67     Internal utility functions
69    ========================================================================== */
71 /* Let the user specify a Nextstep display with a Lisp object.
72    OBJECT may be nil, a frame or a terminal object.
73    nil stands for the selected frame--or, if that is not a Nextstep frame,
74    the first Nextstep display on the list.  */
76 static struct ns_display_info *
77 check_ns_display_info (Lisp_Object object)
79   struct ns_display_info *dpyinfo = NULL;
81   if (NILP (object))
82     {
83       struct frame *sf = XFRAME (selected_frame);
85       if (FRAME_NS_P (sf) && FRAME_LIVE_P (sf))
86         dpyinfo = FRAME_DISPLAY_INFO (sf);
87       else if (x_display_list != 0)
88         dpyinfo = x_display_list;
89       else
90         error ("Nextstep windows are not in use or not initialized");
91     }
92   else if (TERMINALP (object))
93     {
94       struct terminal *t = decode_live_terminal (object);
96       if (t->type != output_ns)
97         error ("Terminal %d is not a Nextstep display", t->id);
99       dpyinfo = t->display_info.ns;
100     }
101   else if (STRINGP (object))
102     dpyinfo = ns_display_info_for_name (object);
103   else
104     {
105       struct frame *f = decode_window_system_frame (object);
106       dpyinfo = FRAME_DISPLAY_INFO (f);
107     }
109   return dpyinfo;
113 static id
114 ns_get_window (Lisp_Object maybeFrame)
116   id view =nil, window =nil;
118   if (!FRAMEP (maybeFrame) || !FRAME_NS_P (XFRAME (maybeFrame)))
119     maybeFrame = selected_frame; /* wrong_type_argument (Qframep, maybeFrame); */
121   if (!NILP (maybeFrame))
122     view = FRAME_NS_VIEW (XFRAME (maybeFrame));
123   if (view) window =[view window];
125   return window;
129 /* Return the X display structure for the display named NAME.
130    Open a new connection if necessary.  */
131 static struct ns_display_info *
132 ns_display_info_for_name (Lisp_Object name)
134   struct ns_display_info *dpyinfo;
136   CHECK_STRING (name);
138   for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
139     if (!NILP (Fstring_equal (XCAR (dpyinfo->name_list_element), name)))
140       return dpyinfo;
142   error ("Emacs for Nextstep does not yet support multi-display");
144   Fx_open_connection (name, Qnil, Qnil);
145   dpyinfo = x_display_list;
147   if (dpyinfo == 0)
148     error ("Display on %s not responding.\n", SDATA (name));
150   return dpyinfo;
153 static NSString *
154 ns_filename_from_panel (NSSavePanel *panel)
156 #ifdef NS_IMPL_COCOA
157   NSURL *url = [panel URL];
158   NSString *str = [url path];
159   return str;
160 #else
161   return [panel filename];
162 #endif
165 static NSString *
166 ns_directory_from_panel (NSSavePanel *panel)
168 #ifdef NS_IMPL_COCOA
169   NSURL *url = [panel directoryURL];
170   NSString *str = [url path];
171   return str;
172 #else
173   return [panel directory];
174 #endif
177 #ifndef NS_IMPL_COCOA
178 static Lisp_Object
179 interpret_services_menu (NSMenu *menu, Lisp_Object prefix, Lisp_Object old)
180 /* --------------------------------------------------------------------------
181    Turn the input menu (an NSMenu) into a lisp list for tracking on lisp side.
182    -------------------------------------------------------------------------- */
184   int i, count;
185   NSMenuItem *item;
186   const char *name;
187   Lisp_Object nameStr;
188   unsigned short key;
189   NSString *keys;
190   Lisp_Object res;
192   count = [menu numberOfItems];
193   for (i = 0; i<count; i++)
194     {
195       item = [menu itemAtIndex: i];
196       name = [[item title] UTF8String];
197       if (!name) continue;
199       nameStr = build_string (name);
201       if ([item hasSubmenu])
202         {
203           old = interpret_services_menu ([item submenu],
204                                         Fcons (nameStr, prefix), old);
205         }
206       else
207         {
208           keys = [item keyEquivalent];
209           if (keys && [keys length] )
210             {
211               key = [keys characterAtIndex: 0];
212               res = make_number (key|super_modifier);
213             }
214           else
215             {
216               res = Qundefined;
217             }
218           old = Fcons (Fcons (res,
219                             Freverse (Fcons (nameStr,
220                                            prefix))),
221                     old);
222         }
223     }
224   return old;
226 #endif
229 /* ==========================================================================
231     Frame parameter setters
233    ========================================================================== */
236 static void
237 x_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
239   NSColor *col;
240   EmacsCGFloat r, g, b, alpha;
242   /* Must block_input, because ns_lisp_to_color does block/unblock_input
243      which means that col may be deallocated in its unblock_input if there
244      is user input, unless we also block_input.  */
245   block_input ();
246   if (ns_lisp_to_color (arg, &col))
247     {
248       store_frame_param (f, Qforeground_color, oldval);
249       unblock_input ();
250       error ("Unknown color");
251     }
253   [col retain];
254   [f->output_data.ns->foreground_color release];
255   f->output_data.ns->foreground_color = col;
257   [col getRed: &r green: &g blue: &b alpha: &alpha];
258   FRAME_FOREGROUND_PIXEL (f) =
259     ARGB_TO_ULONG ((int)(alpha*0xff), (int)(r*0xff), (int)(g*0xff), (int)(b*0xff));
261   if (FRAME_NS_VIEW (f))
262     {
263       update_face_from_frame_parameter (f, Qforeground_color, arg);
264       /* recompute_basic_faces (f); */
265       if (FRAME_VISIBLE_P (f))
266         SET_FRAME_GARBAGED (f);
267     }
268   unblock_input ();
272 static void
273 x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
275   struct face *face;
276   NSColor *col;
277   NSView *view = FRAME_NS_VIEW (f);
278   EmacsCGFloat r, g, b, alpha;
280   block_input ();
281   if (ns_lisp_to_color (arg, &col))
282     {
283       store_frame_param (f, Qbackground_color, oldval);
284       unblock_input ();
285       error ("Unknown color");
286     }
288   /* Clear the frame; in some instances the NS-internal GC appears not
289      to update, or it does update and cannot clear old text
290      properly.  */
291   if (FRAME_VISIBLE_P (f))
292     ns_clear_frame (f);
294   [col retain];
295   [f->output_data.ns->background_color release];
296   f->output_data.ns->background_color = col;
298   [col getRed: &r green: &g blue: &b alpha: &alpha];
299   FRAME_BACKGROUND_PIXEL (f) =
300     ARGB_TO_ULONG ((int)(alpha*0xff), (int)(r*0xff), (int)(g*0xff), (int)(b*0xff));
302   if (view != nil)
303     {
304       [[view window] setBackgroundColor: col];
306       if (alpha != (EmacsCGFloat) 1.0)
307           [[view window] setOpaque: NO];
308       else
309           [[view window] setOpaque: YES];
311       face = FRAME_DEFAULT_FACE (f);
312       if (face)
313         {
314           col = ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), f);
315           face->background = ns_index_color
316             ([col colorWithAlphaComponent: alpha], f);
318           update_face_from_frame_parameter (f, Qbackground_color, arg);
319         }
321       if (FRAME_VISIBLE_P (f))
322         SET_FRAME_GARBAGED (f);
323     }
324   unblock_input ();
328 static void
329 x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
331   NSColor *col;
333   block_input ();
334   if (ns_lisp_to_color (arg, &col))
335     {
336       store_frame_param (f, Qcursor_color, oldval);
337       unblock_input ();
338       error ("Unknown color");
339     }
341   [FRAME_CURSOR_COLOR (f) release];
342   FRAME_CURSOR_COLOR (f) = [col retain];
344   if (FRAME_VISIBLE_P (f))
345     {
346       x_update_cursor (f, 0);
347       x_update_cursor (f, 1);
348     }
349   update_face_from_frame_parameter (f, Qcursor_color, arg);
350   unblock_input ();
354 static void
355 x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
357   NSView *view = FRAME_NS_VIEW (f);
358   NSTRACE ("x_set_icon_name");
360   /* See if it's changed.  */
361   if (STRINGP (arg))
362     {
363       if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
364         return;
365     }
366   else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
367     return;
369   fset_icon_name (f, arg);
371   if (NILP (arg))
372     {
373       if (!NILP (f->title))
374         arg = f->title;
375       else
376         /* Explicit name and no icon-name -> explicit_name.  */
377         if (f->explicit_name)
378           arg = f->name;
379         else
380           {
381             /* No explicit name and no icon-name ->
382                name has to be rebuild from icon_title_format.  */
383             windows_or_buffers_changed = 62;
384             return;
385           }
386     }
388   /* Don't change the name if it's already NAME.  */
389   if ([[view window] miniwindowTitle]
390       && ([[[view window] miniwindowTitle]
391              isEqualToString: [NSString stringWithUTF8String:
392                                           SSDATA (arg)]]))
393     return;
395   [[view window] setMiniwindowTitle:
396         [NSString stringWithUTF8String: SSDATA (arg)]];
399 static void
400 ns_set_name_internal (struct frame *f, Lisp_Object name)
402   Lisp_Object encoded_name, encoded_icon_name;
403   NSString *str;
404   NSView *view = FRAME_NS_VIEW (f);
407   encoded_name = ENCODE_UTF_8 (name);
409   str = [NSString stringWithUTF8String: SSDATA (encoded_name)];
412   /* Don't change the name if it's already NAME.  */
413   if (! [[[view window] title] isEqualToString: str])
414     [[view window] setTitle: str];
416   if (!STRINGP (f->icon_name))
417     encoded_icon_name = encoded_name;
418   else
419     encoded_icon_name = ENCODE_UTF_8 (f->icon_name);
421   str = [NSString stringWithUTF8String: SSDATA (encoded_icon_name)];
423   if ([[view window] miniwindowTitle]
424       && ! [[[view window] miniwindowTitle] isEqualToString: str])
425     [[view window] setMiniwindowTitle: str];
429 static void
430 ns_set_name (struct frame *f, Lisp_Object name, int explicit)
432   NSTRACE ("ns_set_name");
434   /* Make sure that requests from lisp code override requests from
435      Emacs redisplay code.  */
436   if (explicit)
437     {
438       /* If we're switching from explicit to implicit, we had better
439          update the mode lines and thereby update the title.  */
440       if (f->explicit_name && NILP (name))
441         update_mode_lines = 21;
443       f->explicit_name = ! NILP (name);
444     }
445   else if (f->explicit_name)
446     return;
448   if (NILP (name))
449     name = build_string ([ns_app_name UTF8String]);
450   else
451     CHECK_STRING (name);
453   /* Don't change the name if it's already NAME.  */
454   if (! NILP (Fstring_equal (name, f->name)))
455     return;
457   fset_name (f, name);
459   /* Title overrides explicit name.  */
460   if (! NILP (f->title))
461     name = f->title;
463   ns_set_name_internal (f, name);
467 /* This function should be called when the user's lisp code has
468    specified a name for the frame; the name will override any set by the
469    redisplay code.  */
470 static void
471 x_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
473   NSTRACE ("x_explicitly_set_name");
474   ns_set_name (f, arg, 1);
478 /* This function should be called by Emacs redisplay code to set the
479    name; names set this way will never override names set by the user's
480    lisp code.  */
481 void
482 x_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
484   NSTRACE ("x_implicitly_set_name");
486   if (ns_use_proxy_icon)
487     ns_set_represented_filename (f);
489   ns_set_name (f, arg, 0);
493 /* Change the title of frame F to NAME.
494    If NAME is nil, use the frame name as the title.  */
496 static void
497 x_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name)
499   NSTRACE ("x_set_title");
500   /* Don't change the title if it's already NAME.  */
501   if (EQ (name, f->title))
502     return;
504   update_mode_lines = 22;
506   fset_title (f, name);
508   if (NILP (name))
509     name = f->name;
510   else
511     CHECK_STRING (name);
513   ns_set_name_internal (f, name);
516 void
517 ns_set_doc_edited (void)
519   NSAutoreleasePool *pool;
520   Lisp_Object tail, frame;
521   block_input ();
522   pool = [[NSAutoreleasePool alloc] init];
523   FOR_EACH_FRAME (tail, frame)
524     {
525       BOOL edited = NO;
526       struct frame *f = XFRAME (frame);
527       struct window *w;
528       NSView *view;
530       if (! FRAME_NS_P (f)) continue;
531       w = XWINDOW (FRAME_SELECTED_WINDOW (f));
532       view = FRAME_NS_VIEW (f);
533       if (!MINI_WINDOW_P (w))
534         edited = ! NILP (Fbuffer_modified_p (w->contents)) &&
535           ! NILP (Fbuffer_file_name (w->contents));
536       [[view window] setDocumentEdited: edited];
537     }
539   [pool release];
540   unblock_input ();
544 static void
545 x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
547   int nlines;
548   if (FRAME_MINIBUF_ONLY_P (f))
549     return;
551   if (TYPE_RANGED_INTEGERP (int, value))
552     nlines = XINT (value);
553   else
554     nlines = 0;
556   FRAME_MENU_BAR_LINES (f) = 0;
557   if (nlines)
558     {
559       FRAME_EXTERNAL_MENU_BAR (f) = 1;
560       /* Does for all frames, whereas we just want for one frame
561          [NSMenu setMenuBarVisible: YES]; */
562     }
563   else
564     {
565       if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
566         free_frame_menubar (f);
567       /* [NSMenu setMenuBarVisible: NO]; */
568       FRAME_EXTERNAL_MENU_BAR (f) = 0;
569     }
573 /* toolbar support */
574 static void
575 x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
577   /* Currently, when the tool bar changes state, the frame is resized.
579      TODO: It would be better if this didn't occur when 1) the frame
580      is full height or maximized or 2) when specified by
581      `frame-inhibit-implied-resize'.  */
582   int nlines;
584   NSTRACE ("x_set_tool_bar_lines");
586   if (FRAME_MINIBUF_ONLY_P (f))
587     return;
589   if (RANGED_INTEGERP (0, value, INT_MAX))
590     nlines = XFASTINT (value);
591   else
592     nlines = 0;
594   if (nlines)
595     {
596       FRAME_EXTERNAL_TOOL_BAR (f) = 1;
597       update_frame_tool_bar (f);
598     }
599   else
600     {
601       if (FRAME_EXTERNAL_TOOL_BAR (f))
602         {
603           free_frame_tool_bar (f);
604           FRAME_EXTERNAL_TOOL_BAR (f) = 0;
606           {
607             EmacsView *view = FRAME_NS_VIEW (f);
608             int fs_state = [view fullscreenState];
610             if (fs_state == FULLSCREEN_MAXIMIZED)
611               {
612                 [view setFSValue:FULLSCREEN_WIDTH];
613               }
614             else if (fs_state == FULLSCREEN_HEIGHT)
615               {
616                 [view setFSValue:FULLSCREEN_NONE];
617               }
618           }
619        }
620     }
622   {
623     int inhibit
624       = ((f->after_make_frame
625           && !f->tool_bar_resized
626           && (EQ (frame_inhibit_implied_resize, Qt)
627               || (CONSP (frame_inhibit_implied_resize)
628                   && !NILP (Fmemq (Qtool_bar_lines,
629                                    frame_inhibit_implied_resize))))
630           && NILP (get_frame_param (f, Qfullscreen)))
631          ? 0
632          : 2);
634     NSTRACE_MSG ("inhibit:%d", inhibit);
636     frame_size_history_add (f, Qupdate_frame_tool_bar, 0, 0, Qnil);
637     adjust_frame_size (f, -1, -1, inhibit, 0, Qtool_bar_lines);
638   }
642 static void
643 x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
645   int old_width = FRAME_INTERNAL_BORDER_WIDTH (f);
647   CHECK_TYPE_RANGED_INTEGER (int, arg);
648   f->internal_border_width = XINT (arg);
649   if (FRAME_INTERNAL_BORDER_WIDTH (f) < 0)
650     f->internal_border_width = 0;
652   if (FRAME_INTERNAL_BORDER_WIDTH (f) == old_width)
653     return;
655   if (FRAME_X_WINDOW (f) != 0)
656     adjust_frame_size (f, -1, -1, 3, 0, Qinternal_border_width);
658   SET_FRAME_GARBAGED (f);
662 static void
663 ns_implicitly_set_icon_type (struct frame *f)
665   Lisp_Object tem;
666   EmacsView *view = FRAME_NS_VIEW (f);
667   id image = nil;
668   Lisp_Object chain, elt;
669   NSAutoreleasePool *pool;
670   BOOL setMini = YES;
672   NSTRACE ("ns_implicitly_set_icon_type");
674   block_input ();
675   pool = [[NSAutoreleasePool alloc] init];
676   if (f->output_data.ns->miniimage
677       && [[NSString stringWithUTF8String: SSDATA (f->name)]
678                isEqualToString: [(NSImage *)f->output_data.ns->miniimage name]])
679     {
680       [pool release];
681       unblock_input ();
682       return;
683     }
685   tem = assq_no_quit (Qicon_type, f->param_alist);
686   if (CONSP (tem) && ! NILP (XCDR (tem)))
687     {
688       [pool release];
689       unblock_input ();
690       return;
691     }
693   for (chain = Vns_icon_type_alist;
694        image == nil && CONSP (chain);
695        chain = XCDR (chain))
696     {
697       elt = XCAR (chain);
698       /* Special case: t means go by file type.  */
699       if (SYMBOLP (elt) && EQ (elt, Qt) && SSDATA (f->name)[0] == '/')
700         {
701           NSString *str
702              = [NSString stringWithUTF8String: SSDATA (f->name)];
703           if ([[NSFileManager defaultManager] fileExistsAtPath: str])
704             image = [[[NSWorkspace sharedWorkspace] iconForFile: str] retain];
705         }
706       else if (CONSP (elt) &&
707                STRINGP (XCAR (elt)) &&
708                STRINGP (XCDR (elt)) &&
709                fast_string_match (XCAR (elt), f->name) >= 0)
710         {
711           image = [EmacsImage allocInitFromFile: XCDR (elt)];
712           if (image == nil)
713             image = [[NSImage imageNamed:
714                                [NSString stringWithUTF8String:
715                                             SSDATA (XCDR (elt))]] retain];
716         }
717     }
719   if (image == nil)
720     {
721       image = [[[NSWorkspace sharedWorkspace] iconForFileType: @"text"] retain];
722       setMini = NO;
723     }
725   [f->output_data.ns->miniimage release];
726   f->output_data.ns->miniimage = image;
727   [view setMiniwindowImage: setMini];
728   [pool release];
729   unblock_input ();
733 static void
734 x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
736   EmacsView *view = FRAME_NS_VIEW (f);
737   id image = nil;
738   BOOL setMini = YES;
740   NSTRACE ("x_set_icon_type");
742   if (!NILP (arg) && SYMBOLP (arg))
743     {
744       arg =build_string (SSDATA (SYMBOL_NAME (arg)));
745       store_frame_param (f, Qicon_type, arg);
746     }
748   /* Do it the implicit way.  */
749   if (NILP (arg))
750     {
751       ns_implicitly_set_icon_type (f);
752       return;
753     }
755   CHECK_STRING (arg);
757   image = [EmacsImage allocInitFromFile: arg];
758   if (image == nil)
759     image =[NSImage imageNamed: [NSString stringWithUTF8String:
760                                             SSDATA (arg)]];
762   if (image == nil)
763     {
764       image = [NSImage imageNamed: @"text"];
765       setMini = NO;
766     }
768   f->output_data.ns->miniimage = image;
769   [view setMiniwindowImage: setMini];
772 /* This is the same as the xfns.c definition.  */
773 static void
774 x_set_cursor_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
776   set_frame_cursor_types (f, arg);
779 /* called to set mouse pointer color, but all other terms use it to
780    initialize pointer types (and don't set the color ;) */
781 static void
782 x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
784   /* Don't think we can do this on Nextstep.  */
788 #define Str(x) #x
789 #define Xstr(x) Str(x)
791 static Lisp_Object
792 ns_appkit_version_str (void)
794   char tmp[256];
796 #ifdef NS_IMPL_GNUSTEP
797   sprintf(tmp, "gnustep-gui-%s", Xstr(GNUSTEP_GUI_VERSION));
798 #elif defined (NS_IMPL_COCOA)
799   NSString *osversion
800     = [[NSProcessInfo processInfo] operatingSystemVersionString];
801   sprintf(tmp, "appkit-%.2f %s",
802           NSAppKitVersionNumber,
803           [osversion UTF8String]);
804 #else
805   tmp = "ns-unknown";
806 #endif
807   return build_string (tmp);
811 /* This is for use by x-server-version and collapses all version info we
812    have into a single int.  For a better picture of the implementation
813    running, use ns_appkit_version_str.  */
814 static int
815 ns_appkit_version_int (void)
817 #ifdef NS_IMPL_GNUSTEP
818   return GNUSTEP_GUI_MAJOR_VERSION * 100 + GNUSTEP_GUI_MINOR_VERSION;
819 #elif defined (NS_IMPL_COCOA)
820   return (int)NSAppKitVersionNumber;
821 #endif
822   return 0;
826 static void
827 x_icon (struct frame *f, Lisp_Object parms)
828 /* --------------------------------------------------------------------------
829    Strangely-named function to set icon position parameters in frame.
830    This is irrelevant under macOS, but might be needed under GNUstep,
831    depending on the window manager used.  Note, this is not a standard
832    frame parameter-setter; it is called directly from x-create-frame.
833    -------------------------------------------------------------------------- */
835   Lisp_Object icon_x, icon_y;
836   struct ns_display_info *dpyinfo = check_ns_display_info (Qnil);
838   f->output_data.ns->icon_top = -1;
839   f->output_data.ns->icon_left = -1;
841   /* Set the position of the icon.  */
842   icon_x = x_get_arg (dpyinfo, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
843   icon_y = x_get_arg (dpyinfo, parms, Qicon_top, 0, 0,  RES_TYPE_NUMBER);
844   if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
845     {
846       CHECK_NUMBER (icon_x);
847       CHECK_NUMBER (icon_y);
848       f->output_data.ns->icon_top = XINT (icon_y);
849       f->output_data.ns->icon_left = XINT (icon_x);
850     }
851   else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
852     error ("Both left and top icon corners of icon must be specified");
856 /* Note: see frame.c for template, also where generic functions are
857    implemented.  */
858 frame_parm_handler ns_frame_parm_handlers[] =
860   x_set_autoraise, /* generic OK */
861   x_set_autolower, /* generic OK */
862   x_set_background_color,
863   0, /* x_set_border_color,  may be impossible under Nextstep */
864   0, /* x_set_border_width,  may be impossible under Nextstep */
865   x_set_cursor_color,
866   x_set_cursor_type,
867   x_set_font, /* generic OK */
868   x_set_foreground_color,
869   x_set_icon_name,
870   x_set_icon_type,
871   x_set_internal_border_width, /* generic OK */
872   x_set_right_divider_width,
873   x_set_bottom_divider_width,
874   x_set_menu_bar_lines,
875   x_set_mouse_color,
876   x_explicitly_set_name,
877   x_set_scroll_bar_width, /* generic OK */
878   x_set_scroll_bar_height, /* generic OK */
879   x_set_title,
880   x_set_unsplittable, /* generic OK */
881   x_set_vertical_scroll_bars, /* generic OK */
882   x_set_horizontal_scroll_bars, /* generic OK */
883   x_set_visibility, /* generic OK */
884   x_set_tool_bar_lines,
885   0, /* x_set_scroll_bar_foreground, will ignore (not possible on NS) */
886   0, /* x_set_scroll_bar_background,  will ignore (not possible on NS) */
887   x_set_screen_gamma, /* generic OK */
888   x_set_line_spacing, /* generic OK, sets f->extra_line_spacing to int */
889   x_set_left_fringe, /* generic OK */
890   x_set_right_fringe, /* generic OK */
891   0, /* x_set_wait_for_wm, will ignore */
892   x_set_fullscreen, /* generic OK */
893   x_set_font_backend, /* generic OK */
894   x_set_alpha,
895   0, /* x_set_sticky */
896   0, /* x_set_tool_bar_position */
897   0, /* x_set_inhibit_double_buffering */
898 #ifdef NS_IMPL_COCOA
899   x_set_undecorated,
900 #else
901   0, /* x_set_undecorated */
902 #endif
903   x_set_parent_frame,
904   0, /* x_set_skip_taskbar */
905   x_set_no_focus_on_map,
906   x_set_no_accept_focus,
907   x_set_z_group, /* x_set_z_group */
908   0, /* x_set_override_redirect */
909   x_set_no_special_glyphs,
910 #ifdef NS_IMPL_COCOA
911   ns_set_appearance,
912   ns_set_transparent_titlebar,
913 #endif
917 /* Handler for signals raised during x_create_frame.
918    FRAME is the frame which is partially constructed.  */
920 static void
921 unwind_create_frame (Lisp_Object frame)
923   struct frame *f = XFRAME (frame);
925   /* If frame is already dead, nothing to do.  This can happen if the
926      display is disconnected after the frame has become official, but
927      before x_create_frame removes the unwind protect.  */
928   if (!FRAME_LIVE_P (f))
929     return;
931   /* If frame is ``official'', nothing to do.  */
932   if (NILP (Fmemq (frame, Vframe_list)))
933     {
934 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
935       struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
936 #endif
938       /* If the frame's image cache refcount is still the same as our
939          private shadow variable, it means we are unwinding a frame
940          for which we didn't yet call init_frame_faces, where the
941          refcount is incremented.  Therefore, we increment it here, so
942          that free_frame_faces, called in x_free_frame_resources
943          below, will not mistakenly decrement the counter that was not
944          incremented yet to account for this new frame.  */
945       if (FRAME_IMAGE_CACHE (f) != NULL
946           && FRAME_IMAGE_CACHE (f)->refcount == image_cache_refcount)
947         FRAME_IMAGE_CACHE (f)->refcount++;
949       x_free_frame_resources (f);
950       free_glyphs (f);
952 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
953       /* Check that reference counts are indeed correct.  */
954       eassert (dpyinfo->terminal->image_cache->refcount == image_cache_refcount);
955 #endif
956     }
960  * Read geometry related parameters from preferences if not in PARMS.
961  * Returns the union of parms and any preferences read.
962  */
964 static Lisp_Object
965 get_geometry_from_preferences (struct ns_display_info *dpyinfo,
966                                Lisp_Object parms)
968   struct {
969     const char *val;
970     const char *cls;
971     Lisp_Object tem;
972   } r[] = {
973     { "width",  "Width", Qwidth },
974     { "height", "Height", Qheight },
975     { "left", "Left", Qleft },
976     { "top", "Top", Qtop },
977   };
979   int i;
980   for (i = 0; i < ARRAYELTS (r); ++i)
981     {
982       if (NILP (Fassq (r[i].tem, parms)))
983         {
984           Lisp_Object value
985             = x_get_arg (dpyinfo, parms, r[i].tem, r[i].val, r[i].cls,
986                          RES_TYPE_NUMBER);
987           if (! EQ (value, Qunbound))
988             parms = Fcons (Fcons (r[i].tem, value), parms);
989         }
990     }
992   return parms;
995 /* ==========================================================================
997     Lisp definitions
999    ========================================================================== */
1001 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
1002        1, 1, 0,
1003        doc: /* SKIP: real doc in xfns.c.  */)
1004      (Lisp_Object parms)
1006   struct frame *f;
1007   Lisp_Object frame, tem;
1008   Lisp_Object name;
1009   int minibuffer_only = 0;
1010   long window_prompting = 0;
1011   ptrdiff_t count = specpdl_ptr - specpdl;
1012   Lisp_Object display;
1013   struct ns_display_info *dpyinfo = NULL;
1014   Lisp_Object parent, parent_frame;
1015   struct kboard *kb;
1016   static int desc_ctr = 1;
1017   int x_width = 0, x_height = 0;
1019   /* x_get_arg modifies parms.  */
1020   parms = Fcopy_alist (parms);
1022   /* Use this general default value to start with
1023      until we know if this frame has a specified name.  */
1024   Vx_resource_name = Vinvocation_name;
1026   display = x_get_arg (dpyinfo, parms, Qterminal, 0, 0, RES_TYPE_STRING);
1027   if (EQ (display, Qunbound))
1028     display = Qnil;
1029   dpyinfo = check_ns_display_info (display);
1030   kb = dpyinfo->terminal->kboard;
1032   if (!dpyinfo->terminal->name)
1033     error ("Terminal is not live, can't create new frames on it");
1035   name = x_get_arg (dpyinfo, parms, Qname, 0, 0, RES_TYPE_STRING);
1036   if (!STRINGP (name)
1037       && ! EQ (name, Qunbound)
1038       && ! NILP (name))
1039     error ("Invalid frame name--not a string or nil");
1041   if (STRINGP (name))
1042     Vx_resource_name = name;
1044   parent = x_get_arg (dpyinfo, parms, Qparent_id, 0, 0, RES_TYPE_NUMBER);
1045   if (EQ (parent, Qunbound))
1046     parent = Qnil;
1047   if (! NILP (parent))
1048     CHECK_NUMBER (parent);
1050   /* make_frame_without_minibuffer can run Lisp code and garbage collect.  */
1051   /* No need to protect DISPLAY because that's not used after passing
1052      it to make_frame_without_minibuffer.  */
1053   frame = Qnil;
1054   tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
1055                   RES_TYPE_SYMBOL);
1056   if (EQ (tem, Qnone) || NILP (tem))
1057       f = make_frame_without_minibuffer (Qnil, kb, display);
1058   else if (EQ (tem, Qonly))
1059     {
1060       f = make_minibuffer_frame ();
1061       minibuffer_only = 1;
1062     }
1063   else if (WINDOWP (tem))
1064       f = make_frame_without_minibuffer (tem, kb, display);
1065   else
1066       f = make_frame (1);
1068   XSETFRAME (frame, f);
1070   f->terminal = dpyinfo->terminal;
1072   f->output_method = output_ns;
1073   f->output_data.ns = xzalloc (sizeof *f->output_data.ns);
1075   FRAME_FONTSET (f) = -1;
1077   fset_icon_name (f, x_get_arg (dpyinfo, parms, Qicon_name,
1078                                 "iconName", "Title",
1079                                 RES_TYPE_STRING));
1080   if (! STRINGP (f->icon_name))
1081     fset_icon_name (f, Qnil);
1083   FRAME_DISPLAY_INFO (f) = dpyinfo;
1085   /* With FRAME_DISPLAY_INFO set up, this unwind-protect is safe.  */
1086   record_unwind_protect (unwind_create_frame, frame);
1088   f->output_data.ns->window_desc = desc_ctr++;
1089   if (TYPE_RANGED_INTEGERP (Window, parent))
1090     {
1091       f->output_data.ns->parent_desc = XFASTINT (parent);
1092       f->output_data.ns->explicit_parent = 1;
1093     }
1094   else
1095     {
1096       f->output_data.ns->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
1097       f->output_data.ns->explicit_parent = 0;
1098     }
1100   /* Set the name; the functions to which we pass f expect the name to
1101      be set.  */
1102   if (EQ (name, Qunbound) || NILP (name) || ! STRINGP (name))
1103     {
1104       fset_name (f, build_string ([ns_app_name UTF8String]));
1105       f->explicit_name = 0;
1106     }
1107   else
1108     {
1109       fset_name (f, name);
1110       f->explicit_name = 1;
1111       specbind (Qx_resource_name, name);
1112     }
1114   block_input ();
1116 #ifdef NS_IMPL_COCOA
1117     mac_register_font_driver (f);
1118 #else
1119     register_font_driver (&nsfont_driver, f);
1120 #endif
1122   image_cache_refcount =
1123     FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
1125   x_default_parameter (f, parms, Qfont_backend, Qnil,
1126                         "fontBackend", "FontBackend", RES_TYPE_STRING);
1128   {
1129     /* use for default font name */
1130     id font = [NSFont userFixedPitchFontOfSize: -1.0]; /* default */
1131     x_default_parameter (f, parms, Qfontsize,
1132                                     make_number (0 /* (int)[font pointSize] */),
1133                                     "fontSize", "FontSize", RES_TYPE_NUMBER);
1134     // Remove ' Regular', not handled by backends.
1135     char *fontname = xstrdup ([[font displayName] UTF8String]);
1136     int len = strlen (fontname);
1137     if (len > 8 && strcmp (fontname + len - 8, " Regular") == 0)
1138       fontname[len-8] = '\0';
1139     x_default_parameter (f, parms, Qfont,
1140                                  build_string (fontname),
1141                                  "font", "Font", RES_TYPE_STRING);
1142     xfree (fontname);
1143   }
1144   unblock_input ();
1146   x_default_parameter (f, parms, Qborder_width, make_number (0),
1147                        "borderwidth", "BorderWidth", RES_TYPE_NUMBER);
1148   x_default_parameter (f, parms, Qinternal_border_width, make_number (2),
1149                       "internalBorderWidth", "InternalBorderWidth",
1150                       RES_TYPE_NUMBER);
1151   x_default_parameter (f, parms, Qright_divider_width, make_number (0),
1152                        NULL, NULL, RES_TYPE_NUMBER);
1153   x_default_parameter (f, parms, Qbottom_divider_width, make_number (0),
1154                        NULL, NULL, RES_TYPE_NUMBER);
1156   /* default vertical scrollbars on right on Mac */
1157   {
1158       Lisp_Object spos
1159 #ifdef NS_IMPL_GNUSTEP
1160           = Qt;
1161 #else
1162           = Qright;
1163 #endif
1164       x_default_parameter (f, parms, Qvertical_scroll_bars, spos,
1165                            "verticalScrollBars", "VerticalScrollBars",
1166                            RES_TYPE_SYMBOL);
1167   }
1168   x_default_parameter (f, parms, Qhorizontal_scroll_bars, Qnil,
1169                        "horizontalScrollBars", "HorizontalScrollBars",
1170                        RES_TYPE_SYMBOL);
1171   x_default_parameter (f, parms, Qforeground_color, build_string ("Black"),
1172                       "foreground", "Foreground", RES_TYPE_STRING);
1173   x_default_parameter (f, parms, Qbackground_color, build_string ("White"),
1174                       "background", "Background", RES_TYPE_STRING);
1175   x_default_parameter (f, parms, Qline_spacing, Qnil,
1176                        "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
1177   x_default_parameter (f, parms, Qleft_fringe, Qnil,
1178                        "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
1179   x_default_parameter (f, parms, Qright_fringe, Qnil,
1180                        "rightFringe", "RightFringe", RES_TYPE_NUMBER);
1181   x_default_parameter (f, parms, Qno_special_glyphs, Qnil,
1182                        NULL, NULL, RES_TYPE_BOOLEAN);
1184   init_frame_faces (f);
1186   /* Read comment about this code in corresponding place in xfns.c.  */
1187   tem = x_get_arg (dpyinfo, parms, Qmin_width, NULL, NULL, RES_TYPE_NUMBER);
1188   if (NUMBERP (tem))
1189     store_frame_param (f, Qmin_width, tem);
1190   tem = x_get_arg (dpyinfo, parms, Qmin_height, NULL, NULL, RES_TYPE_NUMBER);
1191   if (NUMBERP (tem))
1192     store_frame_param (f, Qmin_height, tem);
1193   adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
1194                      FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, 1,
1195                      Qx_create_frame_1);
1197   tem = x_get_arg (dpyinfo, parms, Qundecorated, NULL, NULL, RES_TYPE_BOOLEAN);
1198   FRAME_UNDECORATED (f) = !NILP (tem) && !EQ (tem, Qunbound);
1199   store_frame_param (f, Qundecorated, FRAME_UNDECORATED (f) ? Qt : Qnil);
1201 #ifdef NS_IMPL_COCOA
1202   tem = x_get_arg (dpyinfo, parms, Qns_appearance, NULL, NULL, RES_TYPE_SYMBOL);
1203   FRAME_NS_APPEARANCE (f) = EQ (tem, Qdark)
1204     ? ns_appearance_vibrant_dark : ns_appearance_aqua;
1205   store_frame_param (f, Qns_appearance, tem);
1207   tem = x_get_arg (dpyinfo, parms, Qns_transparent_titlebar,
1208                    NULL, NULL, RES_TYPE_BOOLEAN);
1209   FRAME_NS_TRANSPARENT_TITLEBAR (f) = !NILP (tem) && !EQ (tem, Qunbound);
1210   store_frame_param (f, Qns_transparent_titlebar, tem);
1211 #endif
1213   parent_frame = x_get_arg (dpyinfo, parms, Qparent_frame, NULL, NULL,
1214                             RES_TYPE_SYMBOL);
1215   /* Accept parent-frame iff parent-id was not specified.  */
1216   if (!NILP (parent)
1217       || EQ (parent_frame, Qunbound)
1218       || NILP (parent_frame)
1219       || !FRAMEP (parent_frame)
1220       || !FRAME_LIVE_P (XFRAME (parent_frame)))
1221     parent_frame = Qnil;
1223   fset_parent_frame (f, parent_frame);
1224   store_frame_param (f, Qparent_frame, parent_frame);
1226   x_default_parameter (f, parms, Qz_group, Qnil, NULL, NULL, RES_TYPE_SYMBOL);
1227   x_default_parameter (f, parms, Qno_focus_on_map, Qnil,
1228                        NULL, NULL, RES_TYPE_BOOLEAN);
1229   x_default_parameter (f, parms, Qno_accept_focus, Qnil,
1230                        NULL, NULL, RES_TYPE_BOOLEAN);
1232   /* The resources controlling the menu-bar and tool-bar are
1233      processed specially at startup, and reflected in the mode
1234      variables; ignore them here.  */
1235   x_default_parameter (f, parms, Qmenu_bar_lines,
1236                        NILP (Vmenu_bar_mode)
1237                        ? make_number (0) : make_number (1),
1238                        NULL, NULL, RES_TYPE_NUMBER);
1239   x_default_parameter (f, parms, Qtool_bar_lines,
1240                        NILP (Vtool_bar_mode)
1241                        ? make_number (0) : make_number (1),
1242                        NULL, NULL, RES_TYPE_NUMBER);
1244   x_default_parameter (f, parms, Qbuffer_predicate, Qnil, "bufferPredicate",
1245                        "BufferPredicate", RES_TYPE_SYMBOL);
1246   x_default_parameter (f, parms, Qtitle, Qnil, "title", "Title",
1247                        RES_TYPE_STRING);
1249   parms = get_geometry_from_preferences (dpyinfo, parms);
1250   window_prompting = x_figure_window_size (f, parms, true, &x_width, &x_height);
1252   tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
1253   f->no_split = minibuffer_only || (!EQ (tem, Qunbound) && !EQ (tem, Qnil));
1255   /* NOTE: on other terms, this is done in set_mouse_color, however this
1256      was not getting called under Nextstep.  */
1257   f->output_data.ns->text_cursor = [NSCursor IBeamCursor];
1258   f->output_data.ns->nontext_cursor = [NSCursor arrowCursor];
1259   f->output_data.ns->modeline_cursor = [NSCursor pointingHandCursor];
1260   f->output_data.ns->hand_cursor = [NSCursor pointingHandCursor];
1261   f->output_data.ns->hourglass_cursor = [NSCursor disappearingItemCursor];
1262   f->output_data.ns->horizontal_drag_cursor = [NSCursor resizeLeftRightCursor];
1263   f->output_data.ns->vertical_drag_cursor = [NSCursor resizeUpDownCursor];
1264   f->output_data.ns->left_edge_cursor = [NSCursor resizeLeftRightCursor];
1265   f->output_data.ns->top_left_corner_cursor = [NSCursor arrowCursor];
1266   f->output_data.ns->top_edge_cursor = [NSCursor resizeUpDownCursor];
1267   f->output_data.ns->top_right_corner_cursor = [NSCursor arrowCursor];
1268   f->output_data.ns->right_edge_cursor = [NSCursor resizeLeftRightCursor];
1269   f->output_data.ns->bottom_right_corner_cursor = [NSCursor arrowCursor];
1270   f->output_data.ns->bottom_edge_cursor = [NSCursor resizeUpDownCursor];
1271   f->output_data.ns->bottom_left_corner_cursor = [NSCursor arrowCursor];
1273   FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor
1274      = [NSCursor arrowCursor];
1275   FRAME_DISPLAY_INFO (f)->horizontal_scroll_bar_cursor
1276      = [NSCursor arrowCursor];
1277   f->output_data.ns->current_pointer = f->output_data.ns->text_cursor;
1279   f->output_data.ns->in_animation = NO;
1281   [[EmacsView alloc] initFrameFromEmacs: f];
1283   x_icon (f, parms);
1285   /* ns_display_info does not have a reference_count.  */
1286   f->terminal->reference_count++;
1288   /* It is now ok to make the frame official even if we get an error
1289      below.  The frame needs to be on Vframe_list or making it visible
1290      won't work.  */
1291   Vframe_list = Fcons (frame, Vframe_list);
1293   x_default_parameter (f, parms, Qicon_type, Qnil,
1294                        "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
1296   x_default_parameter (f, parms, Qauto_raise, Qnil,
1297                        "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
1298   x_default_parameter (f, parms, Qauto_lower, Qnil,
1299                        "autoLower", "AutoLower", RES_TYPE_BOOLEAN);
1300   x_default_parameter (f, parms, Qcursor_type, Qbox,
1301                        "cursorType", "CursorType", RES_TYPE_SYMBOL);
1302   x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
1303                        "scrollBarWidth", "ScrollBarWidth",
1304                        RES_TYPE_NUMBER);
1305   x_default_parameter (f, parms, Qscroll_bar_height, Qnil,
1306                        "scrollBarHeight", "ScrollBarHeight",
1307                        RES_TYPE_NUMBER);
1308   x_default_parameter (f, parms, Qalpha, Qnil,
1309                        "alpha", "Alpha", RES_TYPE_NUMBER);
1310   x_default_parameter (f, parms, Qfullscreen, Qnil,
1311                        "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
1313   /* Allow x_set_window_size, now.  */
1314   f->can_x_set_window_size = true;
1316   if (x_width > 0)
1317     SET_FRAME_WIDTH (f, x_width);
1318   if (x_height > 0)
1319     SET_FRAME_HEIGHT (f, x_height);
1321   adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 0, 1,
1322                      Qx_create_frame_2);
1324   if (! f->output_data.ns->explicit_parent)
1325     {
1326       Lisp_Object visibility;
1328       visibility = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
1329                               RES_TYPE_SYMBOL);
1330       if (EQ (visibility, Qunbound))
1331         visibility = Qt;
1333       if (EQ (visibility, Qicon))
1334         x_iconify_frame (f);
1335       else if (! NILP (visibility))
1336         {
1337           x_make_frame_visible (f);
1338           [[FRAME_NS_VIEW (f) window] makeKeyWindow];
1339         }
1340       else
1341         {
1342           /* Must have been Qnil.  */
1343         }
1344     }
1346   if (FRAME_HAS_MINIBUF_P (f)
1347       && (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame))
1348           || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame)))))
1349     kset_default_minibuffer_frame (kb, frame);
1351   /* All remaining specified parameters, which have not been "used"
1352      by x_get_arg and friends, now go in the misc. alist of the frame.  */
1353   for (tem = parms; CONSP (tem); tem = XCDR (tem))
1354     if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
1355       fset_param_alist (f, Fcons (XCAR (tem), f->param_alist));
1357   if (window_prompting & USPosition)
1358     x_set_offset (f, f->left_pos, f->top_pos, 1);
1360   /* Make sure windows on this frame appear in calls to next-window
1361      and similar functions.  */
1362   Vwindow_list = Qnil;
1364   return unbind_to (count, frame);
1367 void
1368 x_focus_frame (struct frame *f, bool noactivate)
1370   struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
1372   if (dpyinfo->x_focus_frame != f)
1373     {
1374       EmacsView *view = FRAME_NS_VIEW (f);
1375       block_input ();
1376       [NSApp activateIgnoringOtherApps: YES];
1377       [[view window] makeKeyAndOrderFront: view];
1378       unblock_input ();
1379     }
1382 static BOOL
1383 ns_window_is_ancestor (NSWindow *win, NSWindow *candidate)
1384 /* Test whether CANDIDATE is an ancestor window of WIN.  */
1386   if (candidate == NULL)
1387     return NO;
1388   else if (win == candidate)
1389     return YES;
1390   else
1391     return ns_window_is_ancestor(win, [candidate parentWindow]);
1394 DEFUN ("ns-frame-list-z-order", Fns_frame_list_z_order,
1395        Sns_frame_list_z_order, 0, 1, 0,
1396        doc: /* Return list of Emacs' frames, in Z (stacking) order.
1397 If TERMINAL is non-nil and specifies a live frame, return the child
1398 frames of that frame in Z (stacking) order.
1400 Frames are listed from topmost (first) to bottommost (last).  */)
1401   (Lisp_Object terminal)
1403   Lisp_Object frames = Qnil;
1404   NSWindow *parent = nil;
1406   if (FRAMEP (terminal) && FRAME_LIVE_P (XFRAME (terminal)))
1407     parent = [FRAME_NS_VIEW (XFRAME (terminal)) window];
1409   for (NSWindow *win in [[NSApp orderedWindows] reverseObjectEnumerator])
1410     {
1411       Lisp_Object frame;
1413       /* Check against [win parentWindow] so that it doesn't match
1414          itself.  */
1415       if (parent == nil || ns_window_is_ancestor (parent, [win parentWindow]))
1416         {
1417           XSETFRAME (frame, ((EmacsView *)[win delegate])->emacsframe);
1418           frames = Fcons(frame, frames);
1419         }
1420     }
1422   return frames;
1425 DEFUN ("ns-frame-restack", Fns_frame_restack, Sns_frame_restack, 2, 3, 0,
1426        doc: /* Restack FRAME1 below FRAME2.
1427 This means that if both frames are visible and the display areas of
1428 these frames overlap, FRAME2 (partially) obscures FRAME1.  If optional
1429 third argument ABOVE is non-nil, restack FRAME1 above FRAME2.  This
1430 means that if both frames are visible and the display areas of these
1431 frames overlap, FRAME1 (partially) obscures FRAME2.
1433 Some window managers may refuse to restack windows.  */)
1434      (Lisp_Object frame1, Lisp_Object frame2, Lisp_Object above)
1436   struct frame *f1 = decode_live_frame (frame1);
1437   struct frame *f2 = decode_live_frame (frame2);
1439   if (FRAME_NS_VIEW (f1) && FRAME_NS_VIEW (f2))
1440     {
1441       NSWindow *window = [FRAME_NS_VIEW (f1) window];
1442       NSInteger window2 = [[FRAME_NS_VIEW (f2) window] windowNumber];
1443       NSWindowOrderingMode flag = NILP (above) ? NSWindowBelow : NSWindowAbove;
1445       [window orderWindow: flag
1446                relativeTo: window2];
1448       return Qt;
1449     }
1450   else
1451     {
1452       error ("Cannot restack frames");
1453       return Qnil;
1454     }
1457 DEFUN ("ns-popup-font-panel", Fns_popup_font_panel, Sns_popup_font_panel,
1458        0, 1, "",
1459        doc: /* Pop up the font panel.  */)
1460      (Lisp_Object frame)
1462   struct frame *f = decode_window_system_frame (frame);
1463   id fm = [NSFontManager sharedFontManager];
1464   struct font *font = f->output_data.ns->font;
1465   NSFont *nsfont;
1466 #ifdef NS_IMPL_GNUSTEP
1467   nsfont = ((struct nsfont_info *)font)->nsfont;
1468 #endif
1469 #ifdef NS_IMPL_COCOA
1470   nsfont = (NSFont *) macfont_get_nsctfont (font);
1471 #endif
1472   [fm setSelectedFont: nsfont isMultiple: NO];
1473   [fm orderFrontFontPanel: NSApp];
1474   return Qnil;
1478 DEFUN ("ns-popup-color-panel", Fns_popup_color_panel, Sns_popup_color_panel,
1479        0, 1, "",
1480        doc: /* Pop up the color panel.  */)
1481      (Lisp_Object frame)
1483   check_window_system (NULL);
1484   [NSApp orderFrontColorPanel: NSApp];
1485   return Qnil;
1488 static struct
1490   id panel;
1491   BOOL ret;
1492 #ifdef NS_IMPL_GNUSTEP
1493   NSString *dirS, *initS;
1494   BOOL no_types;
1495 #endif
1496 } ns_fd_data;
1498 void
1499 ns_run_file_dialog (void)
1501   if (ns_fd_data.panel == nil) return;
1502 #ifdef NS_IMPL_COCOA
1503   ns_fd_data.ret = [ns_fd_data.panel runModal];
1504 #else
1505   if (ns_fd_data.no_types)
1506     {
1507       ns_fd_data.ret = [ns_fd_data.panel
1508                            runModalForDirectory: ns_fd_data.dirS
1509                            file: ns_fd_data.initS];
1510     }
1511   else
1512     {
1513       ns_fd_data.ret = [ns_fd_data.panel
1514                            runModalForDirectory: ns_fd_data.dirS
1515                            file: ns_fd_data.initS
1516                            types: nil];
1517     }
1518 #endif
1519   ns_fd_data.panel = nil;
1522 #ifdef NS_IMPL_COCOA
1523 #if MAC_OS_X_VERSION_MAX_ALLOWED > 1090
1524 #define MODAL_OK_RESPONSE NSModalResponseOK
1525 #endif
1526 #endif
1527 #ifndef MODAL_OK_RESPONSE
1528 #define MODAL_OK_RESPONSE NSOKButton
1529 #endif
1531 DEFUN ("ns-read-file-name", Fns_read_file_name, Sns_read_file_name, 1, 5, 0,
1532        doc: /* Use a graphical panel to read a file name, using prompt PROMPT.
1533 Optional arg DIR, if non-nil, supplies a default directory.
1534 Optional arg MUSTMATCH, if non-nil, means the returned file or
1535 directory must exist.
1536 Optional arg INIT, if non-nil, provides a default file name to use.
1537 Optional arg DIR_ONLY_P, if non-nil, means choose only directories.  */)
1538   (Lisp_Object prompt, Lisp_Object dir, Lisp_Object mustmatch,
1539    Lisp_Object init, Lisp_Object dir_only_p)
1541   static id fileDelegate = nil;
1542   BOOL isSave = NILP (mustmatch) && NILP (dir_only_p);
1543   id panel;
1544   Lisp_Object fname = Qnil;
1546   NSString *promptS = NILP (prompt) || !STRINGP (prompt) ? nil :
1547     [NSString stringWithUTF8String: SSDATA (prompt)];
1548   NSString *dirS = NILP (dir) || !STRINGP (dir) ?
1549     [NSString stringWithUTF8String: SSDATA (BVAR (current_buffer, directory))] :
1550     [NSString stringWithUTF8String: SSDATA (dir)];
1551   NSString *initS = NILP (init) || !STRINGP (init) ? nil :
1552     [NSString stringWithUTF8String: SSDATA (init)];
1553   NSEvent *nxev;
1555   check_window_system (NULL);
1557   if (fileDelegate == nil)
1558     fileDelegate = [EmacsFileDelegate new];
1560   [NSCursor setHiddenUntilMouseMoves: NO];
1562   if ([dirS characterAtIndex: 0] == '~')
1563     dirS = [dirS stringByExpandingTildeInPath];
1565   panel = isSave ?
1566     (id)[EmacsSavePanel savePanel] : (id)[EmacsOpenPanel openPanel];
1568   [panel setTitle: promptS];
1570   [panel setAllowsOtherFileTypes: YES];
1571   [panel setTreatsFilePackagesAsDirectories: YES];
1572   [panel setDelegate: fileDelegate];
1574   if (! NILP (dir_only_p))
1575     {
1576       [panel setCanChooseDirectories: YES];
1577       [panel setCanChooseFiles: NO];
1578     }
1579   else if (! isSave)
1580     {
1581       /* This is not quite what the documentation says, but it is compatible
1582          with the Gtk+ code.  Also, the menu entry says "Open File...".  */
1583       [panel setCanChooseDirectories: NO];
1584       [panel setCanChooseFiles: YES];
1585     }
1587   block_input ();
1588   ns_fd_data.panel = panel;
1589   ns_fd_data.ret = NO;
1590 #ifdef NS_IMPL_COCOA
1591   if (! NILP (mustmatch) || ! NILP (dir_only_p))
1592     [panel setAllowedFileTypes: nil];
1593   if (dirS) [panel setDirectoryURL: [NSURL fileURLWithPath: dirS]];
1594   if (initS && NILP (Ffile_directory_p (init)))
1595     [panel setNameFieldStringValue: [initS lastPathComponent]];
1596   else
1597     [panel setNameFieldStringValue: @""];
1599 #else
1600   ns_fd_data.no_types = NILP (mustmatch) && NILP (dir_only_p);
1601   ns_fd_data.dirS = dirS;
1602   ns_fd_data.initS = initS;
1603 #endif
1605   /* runModalForDirectory/runModal restarts the main event loop when done,
1606      so we must start an event loop and then pop up the file dialog.
1607      The file dialog may pop up a confirm dialog after Ok has been pressed,
1608      so we can not simply pop down on the Ok/Cancel press.
1609    */
1610   nxev = [NSEvent otherEventWithType: NSEventTypeApplicationDefined
1611                             location: NSMakePoint (0, 0)
1612                        modifierFlags: 0
1613                            timestamp: 0
1614                         windowNumber: [[NSApp mainWindow] windowNumber]
1615                              context: [NSApp context]
1616                              subtype: 0
1617                                data1: 0
1618                                data2: NSAPP_DATA2_RUNFILEDIALOG];
1620   [NSApp postEvent: nxev atStart: NO];
1621   while (ns_fd_data.panel != nil)
1622     [NSApp run];
1624   if (ns_fd_data.ret == MODAL_OK_RESPONSE)
1625     {
1626       NSString *str = ns_filename_from_panel (panel);
1627       if (! str) str = ns_directory_from_panel (panel);
1628       if (str) fname = build_string ([str UTF8String]);
1629     }
1631   [[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow];
1632   unblock_input ();
1634   return fname;
1637 const char *
1638 ns_get_defaults_value (const char *key)
1640   NSObject *obj = [[NSUserDefaults standardUserDefaults]
1641                     objectForKey: [NSString stringWithUTF8String: key]];
1643   if (!obj) return NULL;
1645   return [[NSString stringWithFormat: @"%@", obj] UTF8String];
1649 DEFUN ("ns-get-resource", Fns_get_resource, Sns_get_resource, 2, 2, 0,
1650        doc: /* Return the value of the property NAME of OWNER from the defaults database.
1651 If OWNER is nil, Emacs is assumed.  */)
1652      (Lisp_Object owner, Lisp_Object name)
1654   const char *value;
1656   check_window_system (NULL);
1657   if (NILP (owner))
1658     owner = build_string([ns_app_name UTF8String]);
1659   CHECK_STRING (name);
1661   value = ns_get_defaults_value (SSDATA (name));
1663   if (value)
1664     return build_string (value);
1665   return Qnil;
1669 DEFUN ("ns-set-resource", Fns_set_resource, Sns_set_resource, 3, 3, 0,
1670        doc: /* Set property NAME of OWNER to VALUE, from the defaults database.
1671 If OWNER is nil, Emacs is assumed.
1672 If VALUE is nil, the default is removed.  */)
1673      (Lisp_Object owner, Lisp_Object name, Lisp_Object value)
1675   check_window_system (NULL);
1676   if (NILP (owner))
1677     owner = build_string ([ns_app_name UTF8String]);
1678   CHECK_STRING (name);
1679   if (NILP (value))
1680     {
1681       [[NSUserDefaults standardUserDefaults] removeObjectForKey:
1682                          [NSString stringWithUTF8String: SSDATA (name)]];
1683     }
1684   else
1685     {
1686       CHECK_STRING (value);
1687       [[NSUserDefaults standardUserDefaults] setObject:
1688                 [NSString stringWithUTF8String: SSDATA (value)]
1689                                         forKey: [NSString stringWithUTF8String:
1690                                                          SSDATA (name)]];
1691     }
1693   return Qnil;
1697 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
1698        Sx_server_max_request_size,
1699        0, 1, 0,
1700        doc: /* SKIP: real doc in xfns.c.  */)
1701      (Lisp_Object terminal)
1703   check_ns_display_info (terminal);
1704   /* This function has no real equivalent under Nextstep.  Return nil to
1705      indicate this.  */
1706   return Qnil;
1710 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
1711        doc: /* SKIP: real doc in xfns.c.  */)
1712   (Lisp_Object terminal)
1714   check_ns_display_info (terminal);
1715 #ifdef NS_IMPL_GNUSTEP
1716   return build_string ("GNU");
1717 #else
1718   return build_string ("Apple");
1719 #endif
1723 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
1724        doc: /* SKIP: real doc in xfns.c.  */)
1725   (Lisp_Object terminal)
1727   check_ns_display_info (terminal);
1728   /* NOTE: it is unclear what would best correspond with "protocol";
1729            we return 10.3, meaning Panther, since this is roughly the
1730            level that GNUstep's APIs correspond to.  The last number
1731            is where we distinguish between the Apple and GNUstep
1732            implementations ("distributor-specific release number") and
1733            give int'ized versions of major.minor.  */
1734   return list3i (10, 3, ns_appkit_version_int ());
1738 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
1739        doc: /* SKIP: real doc in xfns.c.  */)
1740   (Lisp_Object terminal)
1742   check_ns_display_info (terminal);
1743   return make_number (1);
1747 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
1748        doc: /* SKIP: real doc in xfns.c.  */)
1749   (Lisp_Object terminal)
1751   struct ns_display_info *dpyinfo = check_ns_display_info (terminal);
1753   return make_number (x_display_pixel_height (dpyinfo) / (92.0/25.4));
1757 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
1758        doc: /* SKIP: real doc in xfns.c.  */)
1759   (Lisp_Object terminal)
1761   struct ns_display_info *dpyinfo = check_ns_display_info (terminal);
1763   return make_number (x_display_pixel_width (dpyinfo) / (92.0/25.4));
1767 DEFUN ("x-display-backing-store", Fx_display_backing_store,
1768        Sx_display_backing_store, 0, 1, 0,
1769        doc: /* SKIP: real doc in xfns.c.  */)
1770   (Lisp_Object terminal)
1772   check_ns_display_info (terminal);
1773   /* Note that the xfns.c version has different return values.  */
1774   switch ([ns_get_window (terminal) backingType])
1775     {
1776     case NSBackingStoreBuffered:
1777       return intern ("buffered");
1778 #if defined (NS_IMPL_GNUSTEP) || MAC_OS_X_VERSION_MIN_REQUIRED < 101300
1779     case NSBackingStoreRetained:
1780       return intern ("retained");
1781     case NSBackingStoreNonretained:
1782       return intern ("non-retained");
1783 #endif
1784     default:
1785       error ("Strange value for backingType parameter of frame");
1786     }
1787   return Qnil;  /* not reached, shut compiler up */
1791 DEFUN ("x-display-visual-class", Fx_display_visual_class,
1792        Sx_display_visual_class, 0, 1, 0,
1793        doc: /* SKIP: real doc in xfns.c.  */)
1794   (Lisp_Object terminal)
1796   NSWindowDepth depth;
1798   check_ns_display_info (terminal);
1799   depth = [[[NSScreen screens] objectAtIndex:0] depth];
1801   if ( depth == NSBestDepth (NSCalibratedWhiteColorSpace, 2, 2, YES, NULL))
1802     return intern ("static-gray");
1803   else if (depth == NSBestDepth (NSCalibratedWhiteColorSpace, 8, 8, YES, NULL))
1804     return intern ("gray-scale");
1805   else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 8, 8, YES, NULL))
1806     return intern ("pseudo-color");
1807   else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 4, 12, NO, NULL))
1808     return intern ("true-color");
1809   else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 8, 24, NO, NULL))
1810     return intern ("direct-color");
1811   else
1812     /* Color management as far as we do it is really handled by
1813        Nextstep itself anyway.  */
1814     return intern ("direct-color");
1818 DEFUN ("x-display-save-under", Fx_display_save_under,
1819        Sx_display_save_under, 0, 1, 0,
1820        doc: /* SKIP: real doc in xfns.c.  */)
1821   (Lisp_Object terminal)
1823   check_ns_display_info (terminal);
1824   switch ([ns_get_window (terminal) backingType])
1825     {
1826     case NSBackingStoreBuffered:
1827       return Qt;
1829 #if defined (NS_IMPL_GNUSTEP) || MAC_OS_X_VERSION_MIN_REQUIRED < 101300
1830     case NSBackingStoreRetained:
1831     case NSBackingStoreNonretained:
1832       return Qnil;
1833 #endif
1835     default:
1836       error ("Strange value for backingType parameter of frame");
1837     }
1838   return Qnil;  /* not reached, shut compiler up */
1842 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
1843        1, 3, 0,
1844        doc: /* SKIP: real doc in xfns.c.  */)
1845      (Lisp_Object display, Lisp_Object resource_string, Lisp_Object must_succeed)
1847   struct ns_display_info *dpyinfo;
1849   CHECK_STRING (display);
1851   nxatoms_of_nsselect ();
1852   dpyinfo = ns_term_init (display);
1853   if (dpyinfo == 0)
1854     {
1855       if (!NILP (must_succeed))
1856         fatal ("Display on %s not responding.\n",
1857                SSDATA (display));
1858       else
1859         error ("Display on %s not responding.\n",
1860                SSDATA (display));
1861     }
1863   return Qnil;
1867 DEFUN ("x-close-connection", Fx_close_connection, Sx_close_connection,
1868        1, 1, 0,
1869        doc: /* SKIP: real doc in xfns.c.  */)
1870      (Lisp_Object terminal)
1872   check_ns_display_info (terminal);
1873   [NSApp terminate: NSApp];
1874   return Qnil;
1878 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
1879        doc: /* SKIP: real doc in xfns.c.  */)
1880      (void)
1882   Lisp_Object result = Qnil;
1883   struct ns_display_info *ndi;
1885   for (ndi = x_display_list; ndi; ndi = ndi->next)
1886     result = Fcons (XCAR (ndi->name_list_element), result);
1888   return result;
1892 DEFUN ("ns-hide-others", Fns_hide_others, Sns_hide_others,
1893        0, 0, 0,
1894        doc: /* Hides all applications other than Emacs.  */)
1895      (void)
1897   check_window_system (NULL);
1898   [NSApp hideOtherApplications: NSApp];
1899   return Qnil;
1902 DEFUN ("ns-hide-emacs", Fns_hide_emacs, Sns_hide_emacs,
1903        1, 1, 0,
1904        doc: /* If ON is non-nil, the entire Emacs application is hidden.
1905 Otherwise if Emacs is hidden, it is unhidden.
1906 If ON is equal to `activate', Emacs is unhidden and becomes
1907 the active application.  */)
1908      (Lisp_Object on)
1910   check_window_system (NULL);
1911   if (EQ (on, intern ("activate")))
1912     {
1913       [NSApp unhide: NSApp];
1914       [NSApp activateIgnoringOtherApps: YES];
1915     }
1916   else if (NILP (on))
1917     [NSApp unhide: NSApp];
1918   else
1919     [NSApp hide: NSApp];
1920   return Qnil;
1924 DEFUN ("ns-emacs-info-panel", Fns_emacs_info_panel, Sns_emacs_info_panel,
1925        0, 0, 0,
1926        doc: /* Shows the 'Info' or 'About' panel for Emacs.  */)
1927      (void)
1929   check_window_system (NULL);
1930   [NSApp orderFrontStandardAboutPanel: nil];
1931   return Qnil;
1935 DEFUN ("ns-font-name", Fns_font_name, Sns_font_name, 1, 1, 0,
1936        doc: /* Determine font PostScript or family name for font NAME.
1937 NAME should be a string containing either the font name or an XLFD
1938 font descriptor.  If string contains `fontset' and not
1939 `fontset-startup', it is left alone.  */)
1940      (Lisp_Object name)
1942   char *nm;
1943   CHECK_STRING (name);
1944   nm = SSDATA (name);
1946   if (nm[0] != '-')
1947     return name;
1948   if (strstr (nm, "fontset") && !strstr (nm, "fontset-startup"))
1949     return name;
1951   return build_string (ns_xlfd_to_fontname (SSDATA (name)));
1955 DEFUN ("ns-list-colors", Fns_list_colors, Sns_list_colors, 0, 1, 0,
1956        doc: /* Return a list of all available colors.
1957 The optional argument FRAME is currently ignored.  */)
1958      (Lisp_Object frame)
1960   Lisp_Object list = Qnil;
1961   NSEnumerator *colorlists;
1962   NSColorList *clist;
1964   if (!NILP (frame))
1965     {
1966       CHECK_FRAME (frame);
1967       if (! FRAME_NS_P (XFRAME (frame)))
1968         error ("non-Nextstep frame used in `ns-list-colors'");
1969     }
1971   block_input ();
1973   colorlists = [[NSColorList availableColorLists] objectEnumerator];
1974   while ((clist = [colorlists nextObject]))
1975     {
1976       if ([[clist name] length] < 7 ||
1977           [[clist name] rangeOfString: @"PANTONE"].location == 0)
1978         {
1979           NSEnumerator *cnames = [[clist allKeys] reverseObjectEnumerator];
1980           NSString *cname;
1981           while ((cname = [cnames nextObject]))
1982             list = Fcons (build_string ([cname UTF8String]), list);
1983 /*           for (i = [[clist allKeys] count] - 1; i >= 0; i--)
1984                list = Fcons (build_string ([[[clist allKeys] objectAtIndex: i]
1985                                              UTF8String]), list); */
1986         }
1987     }
1989   unblock_input ();
1991   return list;
1995 DEFUN ("ns-list-services", Fns_list_services, Sns_list_services, 0, 0, 0,
1996        doc: /* List available Nextstep services by querying NSApp.  */)
1997      (void)
1999 #ifdef NS_IMPL_COCOA
2000   /* You can't get services like this in 10.6+.  */
2001   return Qnil;
2002 #else
2003   Lisp_Object ret = Qnil;
2004   NSMenu *svcs;
2006   check_window_system (NULL);
2007   svcs = [[NSMenu alloc] initWithTitle: @"Services"];
2008   [NSApp setServicesMenu: svcs];
2009   [NSApp registerServicesMenuSendTypes: ns_send_types
2010                            returnTypes: ns_return_types];
2012   [svcs setAutoenablesItems: NO];
2014   ret = interpret_services_menu (svcs, Qnil, ret);
2015   return ret;
2016 #endif
2020 DEFUN ("ns-perform-service", Fns_perform_service, Sns_perform_service,
2021        2, 2, 0,
2022        doc: /* Perform Nextstep SERVICE on SEND.
2023 SEND should be either a string or nil.
2024 The return value is the result of the service, as string, or nil if
2025 there was no result.  */)
2026      (Lisp_Object service, Lisp_Object send)
2028   id pb;
2029   NSString *svcName;
2030   char *utfStr;
2032   CHECK_STRING (service);
2033   check_window_system (NULL);
2035   utfStr = SSDATA (service);
2036   svcName = [NSString stringWithUTF8String: utfStr];
2038   pb =[NSPasteboard pasteboardWithUniqueName];
2039   ns_string_to_pasteboard (pb, send);
2041   if (NSPerformService (svcName, pb) == NO)
2042     Fsignal (Qquit, list1 (build_string ("service not available")));
2044   if ([[pb types] count] == 0)
2045     return build_string ("");
2046   return ns_string_from_pasteboard (pb);
2050 #ifdef NS_IMPL_COCOA
2052 /* Compile and execute the AppleScript SCRIPT and return the error
2053    status as function value.  A zero is returned if compilation and
2054    execution is successful, in which case *RESULT is set to a Lisp
2055    string or a number containing the resulting script value.  Otherwise,
2056    1 is returned.  */
2057 static int
2058 ns_do_applescript (Lisp_Object script, Lisp_Object *result)
2060   NSAppleEventDescriptor *desc;
2061   NSDictionary *errorDict;
2062   NSAppleEventDescriptor *returnDescriptor = NULL;
2064   NSAppleScript *scriptObject =
2065     [[NSAppleScript alloc] initWithSource:
2066                              [NSString stringWithUTF8String: SSDATA (script)]];
2068   returnDescriptor = [scriptObject executeAndReturnError: &errorDict];
2069   [scriptObject release];
2070   *result = Qnil;
2072   if (returnDescriptor != NULL)
2073     {
2074       // successful execution
2075       if (kAENullEvent != [returnDescriptor descriptorType])
2076         {
2077           *result = Qt;
2078           // script returned an AppleScript result
2079           if ((typeUnicodeText == [returnDescriptor descriptorType]) ||
2080 #if defined (NS_IMPL_COCOA)
2081               (typeUTF16ExternalRepresentation
2082                == [returnDescriptor descriptorType]) ||
2083 #endif
2084               (typeUTF8Text == [returnDescriptor descriptorType]) ||
2085               (typeCString == [returnDescriptor descriptorType]))
2086             {
2087               desc = [returnDescriptor coerceToDescriptorType: typeUTF8Text];
2088               if (desc)
2089                 *result = build_string([[desc stringValue] UTF8String]);
2090             }
2091           else
2092             {
2093               /* use typeUTF16ExternalRepresentation? */
2094               // coerce the result to the appropriate ObjC type
2095               desc = [returnDescriptor coerceToDescriptorType: typeUTF8Text];
2096               if (desc)
2097                 *result = make_number([desc int32Value]);
2098             }
2099         }
2100     }
2101   else
2102     {
2103       // no script result, return error
2104       return 1;
2105     }
2106   return 0;
2109 /* Helper function called from sendEvent to run AppleScript
2110    from within the main event loop.  */
2112 void
2113 ns_run_ascript (void)
2115   if (! NILP (as_script))
2116     as_status = ns_do_applescript (as_script, as_result);
2117   as_script = Qnil;
2120 DEFUN ("ns-do-applescript", Fns_do_applescript, Sns_do_applescript, 1, 1, 0,
2121        doc: /* Execute AppleScript SCRIPT and return the result.
2122 If compilation and execution are successful, the resulting script value
2123 is returned as a string, a number or, in the case of other constructs, t.
2124 In case the execution fails, an error is signaled.  */)
2125      (Lisp_Object script)
2127   Lisp_Object result;
2128   int status;
2129   NSEvent *nxev;
2130   struct input_event ev;
2132   CHECK_STRING (script);
2133   check_window_system (NULL);
2135   block_input ();
2137   as_script = script;
2138   as_result = &result;
2140   /* Executing AppleScript requires the event loop to run, otherwise
2141      errors aren't returned and executeAndReturnError hangs forever.
2142      Post an event that runs AppleScript and then start the event
2143      loop.  The event loop is exited when the script is done.  */
2144   nxev = [NSEvent otherEventWithType: NSEventTypeApplicationDefined
2145                             location: NSMakePoint (0, 0)
2146                        modifierFlags: 0
2147                            timestamp: 0
2148                         windowNumber: [[NSApp mainWindow] windowNumber]
2149                              context: [NSApp context]
2150                              subtype: 0
2151                                data1: 0
2152                                data2: NSAPP_DATA2_RUNASSCRIPT];
2154   [NSApp postEvent: nxev atStart: NO];
2156   /* If there are other events, the event loop may exit.  Keep running
2157      until the script has been handled.  */
2158   ns_init_events (&ev);
2159   while (! NILP (as_script))
2160     [NSApp run];
2161   ns_finish_events ();
2163   status = as_status;
2164   as_status = 0;
2165   as_result = 0;
2166   unblock_input ();
2167   if (status == 0)
2168     return result;
2169   else if (!STRINGP (result))
2170     error ("AppleScript error %d", status);
2171   else
2172     error ("%s", SSDATA (result));
2174 #endif
2178 /* ==========================================================================
2180     Miscellaneous functions not called through hooks
2182    ========================================================================== */
2184 /* called from frame.c */
2185 struct ns_display_info *
2186 check_x_display_info (Lisp_Object frame)
2188   return check_ns_display_info (frame);
2192 void
2193 x_set_scroll_bar_default_width (struct frame *f)
2195   int wid = FRAME_COLUMN_WIDTH (f);
2196   FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = NS_SCROLL_BAR_WIDTH_DEFAULT;
2197   FRAME_CONFIG_SCROLL_BAR_COLS (f) = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) +
2198                                       wid - 1) / wid;
2201 void
2202 x_set_scroll_bar_default_height (struct frame *f)
2204   int height = FRAME_LINE_HEIGHT (f);
2205   FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = NS_SCROLL_BAR_WIDTH_DEFAULT;
2206   FRAME_CONFIG_SCROLL_BAR_LINES (f) = (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) +
2207                                        height - 1) / height;
2210 /* Terms implement this instead of x-get-resource directly.  */
2211 char *
2212 x_get_string_resource (XrmDatabase rdb, const char *name, const char *class)
2214   /* remove appname prefix; TODO: allow for !="Emacs" */
2215   const char *res, *toCheck = class + (!strncmp (class, "Emacs.", 6) ? 6 : 0);
2217   check_window_system (NULL);
2219   if (inhibit_x_resources)
2220     /* --quick was passed, so this is a no-op.  */
2221     return NULL;
2223   res = ns_get_defaults_value (toCheck);
2224   return (char *) (!res ? NULL
2225                    : !c_strncasecmp (res, "YES", 3) ? "true"
2226                    : !c_strncasecmp (res, "NO", 2) ? "false"
2227                    : res);
2231 Lisp_Object
2232 x_get_focus_frame (struct frame *frame)
2234   struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame);
2235   Lisp_Object nsfocus;
2237   if (!dpyinfo->x_focus_frame)
2238     return Qnil;
2240   XSETFRAME (nsfocus, dpyinfo->x_focus_frame);
2241   return nsfocus;
2244 /* ==========================================================================
2246     Lisp definitions that, for whatever reason, we can't alias as 'ns-XXX'.
2248    ========================================================================== */
2251 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
2252        doc: /* SKIP: real doc in xfns.c.  */)
2253      (Lisp_Object color, Lisp_Object frame)
2255   NSColor * col;
2256   check_window_system (NULL);
2257   return ns_lisp_to_color (color, &col) ? Qnil : Qt;
2261 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
2262        doc: /* SKIP: real doc in xfns.c.  */)
2263      (Lisp_Object color, Lisp_Object frame)
2265   NSColor * col;
2266   EmacsCGFloat red, green, blue, alpha;
2268   check_window_system (NULL);
2269   CHECK_STRING (color);
2271   block_input ();
2272   if (ns_lisp_to_color (color, &col))
2273     {
2274       unblock_input ();
2275       return Qnil;
2276     }
2278   [[col colorUsingDefaultColorSpace]
2279         getRed: &red green: &green blue: &blue alpha: &alpha];
2280   unblock_input ();
2281   return list3i (lrint (red * 65280), lrint (green * 65280),
2282                  lrint (blue * 65280));
2286 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
2287        doc: /* SKIP: real doc in xfns.c.  */)
2288      (Lisp_Object terminal)
2290   NSWindowDepth depth;
2291   NSString *colorSpace;
2293   check_ns_display_info (terminal);
2294   depth = [[[NSScreen screens] objectAtIndex:0] depth];
2295   colorSpace = NSColorSpaceFromDepth (depth);
2297   return    [colorSpace isEqualToString: NSDeviceWhiteColorSpace]
2298          || [colorSpace isEqualToString: NSCalibratedWhiteColorSpace]
2299       ? Qnil : Qt;
2303 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
2304        0, 1, 0,
2305        doc: /* SKIP: real doc in xfns.c.  */)
2306   (Lisp_Object terminal)
2308   NSWindowDepth depth;
2310   check_ns_display_info (terminal);
2311   depth = [[[NSScreen screens] objectAtIndex:0] depth];
2313   return NSBitsPerPixelFromDepth (depth) > 1 ? Qt : Qnil;
2317 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
2318        0, 1, 0,
2319        doc: /* SKIP: real doc in xfns.c.  */)
2320   (Lisp_Object terminal)
2322   struct ns_display_info *dpyinfo = check_ns_display_info (terminal);
2324   return make_number (x_display_pixel_width (dpyinfo));
2328 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
2329        Sx_display_pixel_height, 0, 1, 0,
2330        doc: /* SKIP: real doc in xfns.c.  */)
2331   (Lisp_Object terminal)
2333   struct ns_display_info *dpyinfo = check_ns_display_info (terminal);
2335   return make_number (x_display_pixel_height (dpyinfo));
2338 #ifdef NS_IMPL_COCOA
2340 /* Returns the name for the screen that OBJ represents, or NULL.
2341    Caller must free return value.
2344 static char *
2345 ns_get_name_from_ioreg (io_object_t obj)
2347   char *name = NULL;
2349   NSDictionary *info = (NSDictionary *)
2350     IODisplayCreateInfoDictionary (obj, kIODisplayOnlyPreferredName);
2351   NSDictionary *names = [info objectForKey:
2352                                 [NSString stringWithUTF8String:
2353                                             kDisplayProductName]];
2355   if ([names count] > 0)
2356     {
2357       NSString *n = [names objectForKey: [[names allKeys]
2358                                                  objectAtIndex:0]];
2359       if (n != nil) name = xstrdup ([n UTF8String]);
2360     }
2362   [info release];
2364   return name;
2367 /* Returns the name for the screen that DID came from, or NULL.
2368    Caller must free return value.
2371 static char *
2372 ns_screen_name (CGDirectDisplayID did)
2374   char *name = NULL;
2376 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1090
2377 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1090
2378   if (CGDisplayIOServicePort == NULL)
2379 #endif
2380     {
2381       mach_port_t masterPort;
2382       io_iterator_t it;
2383       io_object_t obj;
2385       /* CGDisplayIOServicePort is deprecated.  Do it another (harder) way.
2387          Is this code OK for macOS < 10.9, and GNUstep?  I suspect it is,
2388          in which case is it worth keeping the other method in here?  */
2390       if (IOMasterPort (MACH_PORT_NULL, &masterPort) != kIOReturnSuccess
2391           || IOServiceGetMatchingServices (masterPort,
2392                                            IOServiceMatching ("IONDRVDevice"),
2393                                            &it) != kIOReturnSuccess)
2394         return name;
2396       /* Must loop until we find a name.  Many devices can have the same unit
2397          number (represents different GPU parts), but only one has a name.  */
2398       while (! name && (obj = IOIteratorNext (it)))
2399         {
2400           CFMutableDictionaryRef props;
2401           const void *val;
2403           if (IORegistryEntryCreateCFProperties (obj,
2404                                                  &props,
2405                                                  kCFAllocatorDefault,
2406                                                  kNilOptions) == kIOReturnSuccess
2407               && props != nil
2408               && (val = CFDictionaryGetValue(props, @"IOFBDependentIndex")))
2409             {
2410               unsigned nr = [(NSNumber *)val unsignedIntegerValue];
2411               if (nr == CGDisplayUnitNumber (did))
2412                 name = ns_get_name_from_ioreg (obj);
2413             }
2415           CFRelease (props);
2416           IOObjectRelease (obj);
2417         }
2419       IOObjectRelease (it);
2420     }
2421 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1090
2422   else
2423 #endif
2424 #endif /* #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1090 */
2425 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1090
2426     name = ns_get_name_from_ioreg (CGDisplayIOServicePort (did));
2427 #endif
2428   return name;
2430 #endif /* NS_IMPL_COCOA */
2432 static Lisp_Object
2433 ns_make_monitor_attribute_list (struct MonitorInfo *monitors,
2434                                 int n_monitors,
2435                                 int primary_monitor,
2436                                 const char *source)
2438   Lisp_Object monitor_frames = Fmake_vector (make_number (n_monitors), Qnil);
2439   Lisp_Object frame, rest;
2440   NSArray *screens = [NSScreen screens];
2441   int i;
2443   FOR_EACH_FRAME (rest, frame)
2444     {
2445       struct frame *f = XFRAME (frame);
2447       if (FRAME_NS_P (f))
2448         {
2449           NSView *view = FRAME_NS_VIEW (f);
2450           NSScreen *screen = [[view window] screen];
2451           NSUInteger k;
2453           i = -1;
2454           for (k = 0; i == -1 && k < [screens count]; ++k)
2455             {
2456               if ([screens objectAtIndex: k] == screen)
2457                 i = (int)k;
2458             }
2460           if (i > -1)
2461             ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i)));
2462         }
2463     }
2465   return make_monitor_attribute_list (monitors, n_monitors, primary_monitor,
2466                                       monitor_frames, source);
2469 DEFUN ("ns-display-monitor-attributes-list",
2470        Fns_display_monitor_attributes_list,
2471        Sns_display_monitor_attributes_list,
2472        0, 1, 0,
2473        doc: /* Return a list of physical monitor attributes on the X display TERMINAL.
2475 The optional argument TERMINAL specifies which display to ask about.
2476 TERMINAL should be a terminal object, a frame or a display name (a string).
2477 If omitted or nil, that stands for the selected frame's display.
2479 In addition to the standard attribute keys listed in
2480 `display-monitor-attributes-list', the following keys are contained in
2481 the attributes:
2483  source -- String describing the source from which multi-monitor
2484            information is obtained, \"NS\" is always the source."
2486 Internal use only, use `display-monitor-attributes-list' instead.  */)
2487   (Lisp_Object terminal)
2489   struct terminal *term = decode_live_terminal (terminal);
2490   NSArray *screens;
2491   NSUInteger i, n_monitors;
2492   struct MonitorInfo *monitors;
2493   Lisp_Object attributes_list = Qnil;
2494   CGFloat primary_display_height = 0;
2496   if (term->type != output_ns)
2497     return Qnil;
2499   screens = [NSScreen screens];
2500   n_monitors = [screens count];
2501   if (n_monitors == 0)
2502     return Qnil;
2504   monitors = xzalloc (n_monitors * sizeof *monitors);
2506   for (i = 0; i < [screens count]; ++i)
2507     {
2508       NSScreen *s = [screens objectAtIndex:i];
2509       struct MonitorInfo *m = &monitors[i];
2510       NSRect fr = [s frame];
2511       NSRect vfr = [s visibleFrame];
2512       short y, vy;
2514 #ifdef NS_IMPL_COCOA
2515       NSDictionary *dict = [s deviceDescription];
2516       NSNumber *nid = [dict objectForKey:@"NSScreenNumber"];
2517       CGDirectDisplayID did = [nid unsignedIntValue];
2518 #endif
2519       if (i == 0)
2520         {
2521           primary_display_height = fr.size.height;
2522           y = (short) fr.origin.y;
2523           vy = (short) vfr.origin.y;
2524         }
2525       else
2526         {
2527           // Flip y coordinate as NS has y starting from the bottom.
2528           y = (short) (primary_display_height - fr.size.height - fr.origin.y);
2529           vy = (short) (primary_display_height -
2530                         vfr.size.height - vfr.origin.y);
2531         }
2533       m->geom.x = (short) fr.origin.x;
2534       m->geom.y = y;
2535       m->geom.width = (unsigned short) fr.size.width;
2536       m->geom.height = (unsigned short) fr.size.height;
2538       m->work.x = (short) vfr.origin.x;
2539       // y is flipped on NS, so vy - y are pixels missing at the bottom,
2540       // and fr.size.height - vfr.size.height are pixels missing in total.
2541       // Pixels missing at top are
2542       // fr.size.height - vfr.size.height - vy + y.
2543       // work.y is then pixels missing at top + y.
2544       m->work.y = (short) (fr.size.height - vfr.size.height) - vy + y + y;
2545       m->work.width = (unsigned short) vfr.size.width;
2546       m->work.height = (unsigned short) vfr.size.height;
2548 #ifdef NS_IMPL_COCOA
2549       m->name = ns_screen_name (did);
2551       {
2552         CGSize mms = CGDisplayScreenSize (did);
2553         m->mm_width = (int) mms.width;
2554         m->mm_height = (int) mms.height;
2555       }
2557 #else
2558       // Assume 92 dpi as x-display-mm-height/x-display-mm-width does.
2559       m->mm_width = (int) (25.4 * fr.size.width / 92.0);
2560       m->mm_height = (int) (25.4 * fr.size.height / 92.0);
2561 #endif
2562     }
2564   // Primary monitor is always first for NS.
2565   attributes_list = ns_make_monitor_attribute_list (monitors, n_monitors,
2566                                                     0, "NS");
2568   free_monitors (monitors, n_monitors);
2569   return attributes_list;
2573 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
2574        0, 1, 0,
2575        doc: /* SKIP: real doc in xfns.c.  */)
2576   (Lisp_Object terminal)
2578   check_ns_display_info (terminal);
2579   return make_number
2580     (NSBitsPerPixelFromDepth ([[[NSScreen screens] objectAtIndex:0] depth]));
2584 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
2585        0, 1, 0,
2586        doc: /* SKIP: real doc in xfns.c.  */)
2587   (Lisp_Object terminal)
2589   struct ns_display_info *dpyinfo = check_ns_display_info (terminal);
2590   /* We force 24+ bit depths to 24-bit to prevent an overflow.  */
2591   return make_number (1 << min (dpyinfo->n_planes, 24));
2594 /* TODO: move to xdisp or similar */
2595 static void
2596 compute_tip_xy (struct frame *f,
2597                 Lisp_Object parms,
2598                 Lisp_Object dx,
2599                 Lisp_Object dy,
2600                 int width,
2601                 int height,
2602                 int *root_x,
2603                 int *root_y)
2605   Lisp_Object left, top, right, bottom;
2606   NSPoint pt;
2607   NSScreen *screen;
2609   /* Start with user-specified or mouse position.  */
2610   left = Fcdr (Fassq (Qleft, parms));
2611   top = Fcdr (Fassq (Qtop, parms));
2612   right = Fcdr (Fassq (Qright, parms));
2613   bottom = Fcdr (Fassq (Qbottom, parms));
2615   if ((!INTEGERP (left) && !INTEGERP (right))
2616       || (!INTEGERP (top) && !INTEGERP (bottom)))
2617     pt = [NSEvent mouseLocation];
2618   else
2619     {
2620       /* Absolute coordinates.  */
2621       pt.x = INTEGERP (left) ? XINT (left) : XINT (right);
2622       pt.y = (x_display_pixel_height (FRAME_DISPLAY_INFO (f))
2623               - (INTEGERP (top) ? XINT (top) : XINT (bottom))
2624               - height);
2625     }
2627   /* Find the screen that pt is on.  */
2628   for (screen in [NSScreen screens])
2629     if (pt.x >= screen.frame.origin.x
2630         && pt.x < screen.frame.origin.x + screen.frame.size.width
2631         && pt.y >= screen.frame.origin.y
2632         && pt.y < screen.frame.origin.y + screen.frame.size.height)
2633       break;
2635   /* We could use this instead of the if above:
2637          if (CGRectContainsPoint ([screen frame], pt))
2639      which would be neater, but it causes problems building on old
2640      versions of macOS and in GNUstep.  */
2642   /* Ensure in bounds.  (Note, screen origin = lower left.) */
2643   if (INTEGERP (left) || INTEGERP (right))
2644     *root_x = pt.x;
2645   else if (pt.x + XINT (dx) <= screen.frame.origin.x)
2646     *root_x = screen.frame.origin.x;
2647   else if (pt.x + XINT (dx) + width
2648            <= screen.frame.origin.x + screen.frame.size.width)
2649     /* It fits to the right of the pointer.  */
2650     *root_x = pt.x + XINT (dx);
2651   else if (width + XINT (dx) <= pt.x)
2652     /* It fits to the left of the pointer.  */
2653     *root_x = pt.x - width - XINT (dx);
2654   else
2655     /* Put it left justified on the screen -- it ought to fit that way.  */
2656     *root_x = screen.frame.origin.x;
2658   if (INTEGERP (top) || INTEGERP (bottom))
2659     *root_y = pt.y;
2660   else if (pt.y - XINT (dy) - height >= screen.frame.origin.y)
2661     /* It fits below the pointer.  */
2662     *root_y = pt.y - height - XINT (dy);
2663   else if (pt.y + XINT (dy) + height
2664            <= screen.frame.origin.y + screen.frame.size.height)
2665     /* It fits above the pointer.  */
2666       *root_y = pt.y + XINT (dy);
2667   else
2668     /* Put it on the top.  */
2669     *root_y = screen.frame.origin.y + screen.frame.size.height - height;
2673 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
2674        doc: /* SKIP: real doc in xfns.c.  */)
2675      (Lisp_Object string, Lisp_Object frame, Lisp_Object parms, Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy)
2677   int root_x, root_y;
2678   ptrdiff_t count = SPECPDL_INDEX ();
2679   struct frame *f;
2680   char *str;
2681   NSSize size;
2682   NSColor *color;
2683   Lisp_Object t;
2685   specbind (Qinhibit_redisplay, Qt);
2687   CHECK_STRING (string);
2688   str = SSDATA (string);
2689   f = decode_window_system_frame (frame);
2690   if (NILP (timeout))
2691     timeout = make_number (5);
2692   else
2693     CHECK_NATNUM (timeout);
2695   if (NILP (dx))
2696     dx = make_number (5);
2697   else
2698     CHECK_NUMBER (dx);
2700   if (NILP (dy))
2701     dy = make_number (-10);
2702   else
2703     CHECK_NUMBER (dy);
2705   block_input ();
2706   if (ns_tooltip == nil)
2707     ns_tooltip = [[EmacsTooltip alloc] init];
2708   else
2709     Fx_hide_tip ();
2711   t = x_get_arg (NULL, parms, Qbackground_color, NULL, NULL, RES_TYPE_STRING);
2712   if (ns_lisp_to_color (t, &color) == 0)
2713     [ns_tooltip setBackgroundColor: color];
2715   t = x_get_arg (NULL, parms, Qforeground_color, NULL, NULL, RES_TYPE_STRING);
2716   if (ns_lisp_to_color (t, &color) == 0)
2717     [ns_tooltip setForegroundColor: color];
2719   [ns_tooltip setText: str];
2720   size = [ns_tooltip frame].size;
2722   /* Move the tooltip window where the mouse pointer is.  Resize and
2723      show it.  */
2724   compute_tip_xy (f, parms, dx, dy, (int)size.width, (int)size.height,
2725                   &root_x, &root_y);
2727   [ns_tooltip showAtX: root_x Y: root_y for: XINT (timeout)];
2728   unblock_input ();
2730   return unbind_to (count, Qnil);
2734 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
2735        doc: /* SKIP: real doc in xfns.c.  */)
2736      (void)
2738   if (ns_tooltip == nil || ![ns_tooltip isActive])
2739     return Qnil;
2740   [ns_tooltip hide];
2741   return Qt;
2744 /* Return geometric attributes of FRAME.  According to the value of
2745    ATTRIBUTES return the outer edges of FRAME (Qouter_edges), the inner
2746    edges of FRAME, the root window edges of frame (Qroot_edges).  Any
2747    other value means to return the geometry as returned by
2748    Fx_frame_geometry.  */
2749 static Lisp_Object
2750 frame_geometry (Lisp_Object frame, Lisp_Object attribute)
2752   struct frame *f = decode_live_frame (frame);
2753   Lisp_Object fullscreen_symbol = Fframe_parameter (frame, Qfullscreen);
2754   bool fullscreen = (EQ (fullscreen_symbol, Qfullboth)
2755                      || EQ (fullscreen_symbol, Qfullscreen));
2756   int border = fullscreen ? 0 : f->border_width;
2757   int title_height = fullscreen ? 0 : FRAME_NS_TITLEBAR_HEIGHT (f);
2758   int native_width = FRAME_PIXEL_WIDTH (f);
2759   int native_height = FRAME_PIXEL_HEIGHT (f);
2760   int outer_width = native_width + 2 * border;
2761   int outer_height = native_height + 2 * border + title_height;
2762   int native_left = f->left_pos + border;
2763   int native_top = f->top_pos + border + title_height;
2764   int native_right = f->left_pos + outer_width - border;
2765   int native_bottom = f->top_pos + outer_height - border;
2766   int internal_border_width = FRAME_INTERNAL_BORDER_WIDTH (f);
2767   int tool_bar_height = FRAME_TOOLBAR_HEIGHT (f);
2768   int tool_bar_width = (tool_bar_height
2769                         ? outer_width - 2 * internal_border_width
2770                         : 0);
2772   /* Construct list.  */
2773   if (EQ (attribute, Qouter_edges))
2774     return list4 (make_number (f->left_pos), make_number (f->top_pos),
2775                   make_number (f->left_pos + outer_width),
2776                   make_number (f->top_pos + outer_height));
2777   else if (EQ (attribute, Qnative_edges))
2778     return list4 (make_number (native_left), make_number (native_top),
2779                   make_number (native_right), make_number (native_bottom));
2780   else if (EQ (attribute, Qinner_edges))
2781     return list4 (make_number (native_left + internal_border_width),
2782                   make_number (native_top
2783                                + tool_bar_height
2784                                + internal_border_width),
2785                   make_number (native_right - internal_border_width),
2786                   make_number (native_bottom - internal_border_width));
2787   else
2788     return
2789       listn (CONSTYPE_HEAP, 10,
2790              Fcons (Qouter_position,
2791                     Fcons (make_number (f->left_pos),
2792                            make_number (f->top_pos))),
2793              Fcons (Qouter_size,
2794                     Fcons (make_number (outer_width),
2795                            make_number (outer_height))),
2796              Fcons (Qexternal_border_size,
2797                     (fullscreen
2798                      ? Fcons (make_number (0), make_number (0))
2799                      : Fcons (make_number (border), make_number (border)))),
2800              Fcons (Qtitle_bar_size,
2801                     Fcons (make_number (0), make_number (title_height))),
2802              Fcons (Qmenu_bar_external, Qnil),
2803              Fcons (Qmenu_bar_size, Fcons (make_number (0), make_number (0))),
2804              Fcons (Qtool_bar_external,
2805                     FRAME_EXTERNAL_TOOL_BAR (f) ? Qt : Qnil),
2806              Fcons (Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f)),
2807              Fcons (Qtool_bar_size,
2808                     Fcons (make_number (tool_bar_width),
2809                            make_number (tool_bar_height))),
2810              Fcons (Qinternal_border_width,
2811                     make_number (internal_border_width)));
2814 DEFUN ("ns-frame-geometry", Fns_frame_geometry, Sns_frame_geometry, 0, 1, 0,
2815        doc: /* Return geometric attributes of FRAME.
2816 FRAME must be a live frame and defaults to the selected one.  The return
2817 value is an association list of the attributes listed below.  All height
2818 and width values are in pixels.
2820 `outer-position' is a cons of the outer left and top edges of FRAME
2821   relative to the origin - the position (0, 0) - of FRAME's display.
2823 `outer-size' is a cons of the outer width and height of FRAME.  The
2824   outer size includes the title bar and the external borders as well as
2825   any menu and/or tool bar of frame.
2827 `external-border-size' is a cons of the horizontal and vertical width of
2828   FRAME's external borders as supplied by the window manager.
2830 `title-bar-size' is a cons of the width and height of the title bar of
2831   FRAME as supplied by the window manager.  If both of them are zero,
2832   FRAME has no title bar.  If only the width is zero, Emacs was not
2833   able to retrieve the width information.
2835 `menu-bar-external', if non-nil, means the menu bar is external (never
2836   included in the inner edges of FRAME).
2838 `menu-bar-size' is a cons of the width and height of the menu bar of
2839   FRAME.
2841 `tool-bar-external', if non-nil, means the tool bar is external (never
2842   included in the inner edges of FRAME).
2844 `tool-bar-position' tells on which side the tool bar on FRAME is and can
2845   be one of `left', `top', `right' or `bottom'.  If this is nil, FRAME
2846   has no tool bar.
2848 `tool-bar-size' is a cons of the width and height of the tool bar of
2849   FRAME.
2851 `internal-border-width' is the width of the internal border of
2852   FRAME.  */)
2853   (Lisp_Object frame)
2855   return frame_geometry (frame, Qnil);
2858 DEFUN ("ns-frame-edges", Fns_frame_edges, Sns_frame_edges, 0, 2, 0,
2859        doc: /* Return edge coordinates of FRAME.
2860 FRAME must be a live frame and defaults to the selected one.  The return
2861 value is a list of the form (LEFT, TOP, RIGHT, BOTTOM).  All values are
2862 in pixels relative to the origin - the position (0, 0) - of FRAME's
2863 display.
2865 If optional argument TYPE is the symbol `outer-edges', return the outer
2866 edges of FRAME.  The outer edges comprise the decorations of the window
2867 manager (like the title bar or external borders) as well as any external
2868 menu or tool bar of FRAME.  If optional argument TYPE is the symbol
2869 `native-edges' or nil, return the native edges of FRAME.  The native
2870 edges exclude the decorations of the window manager and any external
2871 menu or tool bar of FRAME.  If TYPE is the symbol `inner-edges', return
2872 the inner edges of FRAME.  These edges exclude title bar, any borders,
2873 menu bar or tool bar of FRAME.  */)
2874   (Lisp_Object frame, Lisp_Object type)
2876   return frame_geometry (frame, ((EQ (type, Qouter_edges)
2877                                   || EQ (type, Qinner_edges))
2878                                  ? type
2879                                  : Qnative_edges));
2882 DEFUN ("ns-set-mouse-absolute-pixel-position",
2883        Fns_set_mouse_absolute_pixel_position,
2884        Sns_set_mouse_absolute_pixel_position, 2, 2, 0,
2885        doc: /* Move mouse pointer to absolute pixel position (X, Y).
2886 The coordinates X and Y are interpreted in pixels relative to a position
2887 \(0, 0) of the selected frame's display.  */)
2888        (Lisp_Object x, Lisp_Object y)
2890 #ifdef NS_IMPL_COCOA
2891   /* GNUstep doesn't support CGWarpMouseCursorPosition, so none of
2892      this will work.  */
2893   struct frame *f = SELECTED_FRAME ();
2894   EmacsView *view = FRAME_NS_VIEW (f);
2895   NSScreen *screen = [[view window] screen];
2896   NSRect screen_frame = [screen frame];
2897   int mouse_x, mouse_y;
2899   NSScreen *primary_screen = [[NSScreen screens] objectAtIndex:0];
2900   NSRect primary_screen_frame = [primary_screen frame];
2901   CGFloat primary_screen_height = primary_screen_frame.size.height;
2903   if (FRAME_INITIAL_P (f) || !FRAME_NS_P (f))
2904     return Qnil;
2906   CHECK_TYPE_RANGED_INTEGER (int, x);
2907   CHECK_TYPE_RANGED_INTEGER (int, y);
2909   mouse_x = screen_frame.origin.x + XINT (x);
2911   if (screen == primary_screen)
2912     mouse_y = screen_frame.origin.y + XINT (y);
2913   else
2914     mouse_y = (primary_screen_height - screen_frame.size.height
2915                - screen_frame.origin.y) + XINT (y);
2917   CGPoint mouse_pos = CGPointMake(mouse_x, mouse_y);
2918   CGWarpMouseCursorPosition (mouse_pos);
2919 #endif /* NS_IMPL_COCOA */
2921   return Qnil;
2924 DEFUN ("ns-mouse-absolute-pixel-position",
2925        Fns_mouse_absolute_pixel_position,
2926        Sns_mouse_absolute_pixel_position, 0, 0, 0,
2927        doc: /* Return absolute position of mouse cursor in pixels.
2928 The position is returned as a cons cell (X . Y) of the
2929 coordinates of the mouse cursor position in pixels relative to a
2930 position (0, 0) of the selected frame's terminal.  */)
2931      (void)
2933   struct frame *f = SELECTED_FRAME ();
2934   EmacsView *view = FRAME_NS_VIEW (f);
2935   NSScreen *screen = [[view window] screen];
2936   NSPoint pt = [NSEvent mouseLocation];
2938   return Fcons(make_number(pt.x - screen.frame.origin.x),
2939                make_number(screen.frame.size.height -
2940                            (pt.y - screen.frame.origin.y)));
2943 DEFUN ("ns-show-character-palette",
2944        Fns_show_character_palette,
2945        Sns_show_character_palette, 0, 0, 0,
2946        doc: /* Show the macOS character palette.  */)
2947        (void)
2949   struct frame *f = SELECTED_FRAME ();
2950   EmacsView *view = FRAME_NS_VIEW (f);
2951   [NSApp orderFrontCharacterPalette:view];
2953   return Qnil;
2956 /* ==========================================================================
2958     Class implementations
2960    ========================================================================== */
2963   Handle arrow/function/control keys and copy/paste/cut in file dialogs.
2964   Return YES if handled, NO if not.
2965  */
2966 static BOOL
2967 handlePanelKeys (NSSavePanel *panel, NSEvent *theEvent)
2969   NSString *s;
2970   int i;
2971   BOOL ret = NO;
2973   if ([theEvent type] != NSEventTypeKeyDown) return NO;
2974   s = [theEvent characters];
2976   for (i = 0; i < [s length]; ++i)
2977     {
2978       int ch = (int) [s characterAtIndex: i];
2979       switch (ch)
2980         {
2981         case NSHomeFunctionKey:
2982         case NSDownArrowFunctionKey:
2983         case NSUpArrowFunctionKey:
2984         case NSLeftArrowFunctionKey:
2985         case NSRightArrowFunctionKey:
2986         case NSPageUpFunctionKey:
2987         case NSPageDownFunctionKey:
2988         case NSEndFunctionKey:
2989           /* Don't send command modified keys, as those are handled in the
2990              performKeyEquivalent method of the super class.  */
2991           if (! ([theEvent modifierFlags] & NSEventModifierFlagCommand))
2992             {
2993               [panel sendEvent: theEvent];
2994               ret = YES;
2995             }
2996           break;
2997           /* As we don't have the standard key commands for
2998              copy/paste/cut/select-all in our edit menu, we must handle
2999              them here.  TODO: handle Emacs key bindings for copy/cut/select-all
3000              here, paste works, because we have that in our Edit menu.
3001              I.e. refactor out code in nsterm.m, keyDown: to figure out the
3002              correct modifier.  */
3003         case 'x': // Cut
3004         case 'c': // Copy
3005         case 'v': // Paste
3006         case 'a': // Select all
3007           if ([theEvent modifierFlags] & NSEventModifierFlagCommand)
3008             {
3009               [NSApp sendAction:
3010                        (ch == 'x'
3011                         ? @selector(cut:)
3012                         : (ch == 'c'
3013                            ? @selector(copy:)
3014                            : (ch == 'v'
3015                               ? @selector(paste:)
3016                               : @selector(selectAll:))))
3017                              to:nil from:panel];
3018               ret = YES;
3019             }
3020         default:
3021           // Send all control keys, as the text field supports C-a, C-f, C-e
3022           // C-b and more.
3023           if ([theEvent modifierFlags] & NSEventModifierFlagControl)
3024             {
3025               [panel sendEvent: theEvent];
3026               ret = YES;
3027             }
3028           break;
3029         }
3030     }
3033   return ret;
3036 @implementation EmacsSavePanel
3037 - (BOOL)performKeyEquivalent:(NSEvent *)theEvent
3039   BOOL ret = handlePanelKeys (self, theEvent);
3040   if (! ret)
3041     ret = [super performKeyEquivalent:theEvent];
3042   return ret;
3044 @end
3047 @implementation EmacsOpenPanel
3048 - (BOOL)performKeyEquivalent:(NSEvent *)theEvent
3050   // NSOpenPanel inherits NSSavePanel, so passing self is OK.
3051   BOOL ret = handlePanelKeys (self, theEvent);
3052   if (! ret)
3053     ret = [super performKeyEquivalent:theEvent];
3054   return ret;
3056 @end
3059 @implementation EmacsFileDelegate
3060 /* --------------------------------------------------------------------------
3061    Delegate methods for Open/Save panels
3062    -------------------------------------------------------------------------- */
3063 - (BOOL)panel: (id)sender isValidFilename: (NSString *)filename
3065   return YES;
3067 - (BOOL)panel: (id)sender shouldShowFilename: (NSString *)filename
3069   return YES;
3071 - (NSString *)panel: (id)sender userEnteredFilename: (NSString *)filename
3072           confirmed: (BOOL)okFlag
3074   return filename;
3076 @end
3078 #endif
3081 /* ==========================================================================
3083     Lisp interface declaration
3085    ========================================================================== */
3088 void
3089 syms_of_nsfns (void)
3091   DEFSYM (Qfontsize, "fontsize");
3092   DEFSYM (Qframe_title_format, "frame-title-format");
3093   DEFSYM (Qicon_title_format, "icon-title-format");
3094   DEFSYM (Qdark, "dark");
3096   DEFVAR_LISP ("ns-icon-type-alist", Vns_icon_type_alist,
3097                doc: /* Alist of elements (REGEXP . IMAGE) for images of icons associated to frames.
3098 If the title of a frame matches REGEXP, then IMAGE.tiff is
3099 selected as the image of the icon representing the frame when it's
3100 miniaturized.  If an element is t, then Emacs tries to select an icon
3101 based on the filetype of the visited file.
3103 The images have to be installed in a folder called English.lproj in the
3104 Emacs folder.  You have to restart Emacs after installing new icons.
3106 Example: Install an icon Gnus.tiff and execute the following code
3108   (setq ns-icon-type-alist
3109         (append ns-icon-type-alist
3110                 \\='((\"^\\\\*\\\\(Group\\\\*$\\\\|Summary \\\\|Article\\\\*$\\\\)\"
3111                    . \"Gnus\"))))
3113 When you miniaturize a Group, Summary or Article frame, Gnus.tiff will
3114 be used as the image of the icon representing the frame.  */);
3115   Vns_icon_type_alist = list1 (Qt);
3117   DEFVAR_LISP ("ns-version-string", Vns_version_string,
3118                doc: /* Toolkit version for NS Windowing.  */);
3119   Vns_version_string = ns_appkit_version_str ();
3121   DEFVAR_BOOL ("ns-use-proxy-icon", ns_use_proxy_icon,
3122                doc: /* When non-nil display a proxy icon in the titlebar.
3123 Default is t.  */);
3124   ns_use_proxy_icon = true;
3126   defsubr (&Sns_read_file_name);
3127   defsubr (&Sns_get_resource);
3128   defsubr (&Sns_set_resource);
3129   defsubr (&Sxw_display_color_p); /* this and next called directly by C code */
3130   defsubr (&Sx_display_grayscale_p);
3131   defsubr (&Sns_font_name);
3132   defsubr (&Sns_list_colors);
3133 #ifdef NS_IMPL_COCOA
3134   defsubr (&Sns_do_applescript);
3135 #endif
3136   defsubr (&Sxw_color_defined_p);
3137   defsubr (&Sxw_color_values);
3138   defsubr (&Sx_server_max_request_size);
3139   defsubr (&Sx_server_vendor);
3140   defsubr (&Sx_server_version);
3141   defsubr (&Sx_display_pixel_width);
3142   defsubr (&Sx_display_pixel_height);
3143   defsubr (&Sns_display_monitor_attributes_list);
3144   defsubr (&Sns_frame_geometry);
3145   defsubr (&Sns_frame_edges);
3146   defsubr (&Sns_frame_list_z_order);
3147   defsubr (&Sns_frame_restack);
3148   defsubr (&Sns_set_mouse_absolute_pixel_position);
3149   defsubr (&Sns_mouse_absolute_pixel_position);
3150   defsubr (&Sns_show_character_palette);
3151   defsubr (&Sx_display_mm_width);
3152   defsubr (&Sx_display_mm_height);
3153   defsubr (&Sx_display_screens);
3154   defsubr (&Sx_display_planes);
3155   defsubr (&Sx_display_color_cells);
3156   defsubr (&Sx_display_visual_class);
3157   defsubr (&Sx_display_backing_store);
3158   defsubr (&Sx_display_save_under);
3159   defsubr (&Sx_create_frame);
3160   defsubr (&Sx_open_connection);
3161   defsubr (&Sx_close_connection);
3162   defsubr (&Sx_display_list);
3164   defsubr (&Sns_hide_others);
3165   defsubr (&Sns_hide_emacs);
3166   defsubr (&Sns_emacs_info_panel);
3167   defsubr (&Sns_list_services);
3168   defsubr (&Sns_perform_service);
3169   defsubr (&Sns_popup_font_panel);
3170   defsubr (&Sns_popup_color_panel);
3172   defsubr (&Sx_show_tip);
3173   defsubr (&Sx_hide_tip);
3175   as_status = 0;
3176   as_script = Qnil;
3177   as_result = 0;