unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
From: Alan Third <alan@idiocy.org>
To: "Charles A. Roelli" <charles@aurox.ch>
Cc: Anders Lindgren <andlind@gmail.com>, 27810@debbugs.gnu.org
Subject: bug#27810: NS runtime feature detection
Date: Mon, 24 Jul 2017 21:44:04 +0100	[thread overview]
Message-ID: <20170724204404.GA20189@breton.holly.idiocy.org> (raw)
In-Reply-To: <508a4930-feab-588b-0ab9-f55a10ea85ec@aurox.ch>

[-- Attachment #1: Type: text/plain, Size: 1410 bytes --]

I wrote a big reply to this but seem to have lost it.

On Mon, Jul 24, 2017 at 09:02:57PM +0200, Charles A. Roelli wrote:
> nsterm.m: In function ‘-[EmacsView windowDidEnterFullScreen]’:
> nsterm.m:7395: error: ‘NSApplicationPresentationFullScreen’ undeclared
> (first use in this function)
> nsterm.m:7395: error: (Each undeclared identifier is reported only once
> nsterm.m:7395: error: for each function it appears in.)
> nsterm.m:7396: error: ‘NSApplicationPresentationAutoHideToolbar’ undeclared
> (first use in this function)

I think perhaps we need to just test ‘< 10.7’. I’ve attached a new
patch that deals with that and some other bits and pieces.

> I'm confused why the macro call you wrote doesn't prevent this. But
> when I change it to #if MAC_OS_X_VERSION_MIN_ALLOWED <=
> MAC_OS_X_VERSION_10_6, then it compiles.  This min/max stuff always
> confuses me...

I’m unclear where we should be using MIN_REQUIRED vs MAX_ALLOWED, but
I think we’re OK with MAX everywhere for what we’re doing. I’ve just
used MAX in both my new macros.

We need a proper runtime OS version check in a few places. I think
there are two ways of doing this depending on which OS version you’re
building on. It’s getting very close to circular. ;)

macfont.m looks like it could be a small nightmare as it has a LOT of
version dependent code.

Thanks for testing this patch.
-- 
Alan Third

[-- Attachment #2: 0001-Use-a-run-time-check-for-macOS-Sierra-tabbing-suppor.patch --]
[-- Type: text/plain, Size: 12355 bytes --]

From b26a3594f62544f3942e2eaceb4a1b1b92a2166d Mon Sep 17 00:00:00 2001
From: Alan Third <alan@idiocy.org>
Date: Thu, 6 Jul 2017 23:10:49 +0100
Subject: [PATCH] Use a run-time check for macOS Sierra tabbing support

* configure.ac: Add --enable-macos-runtime-feature-detection flag.
* src/nsterm.h (NSWindowTabbingMode): Define in pre-Sierra macOS.
(MACOS_MIN_VERSION, MACOS_MAX_VERSION): Add new defines for version
detection.
* src/nsterm.m (colorForEmacsRed):
(colorUsingDefaultColorSpace):
(runAlertPanel):
(firstRectForCharacterRange):
(initFrameFromEmacs):
(windowDidEnterFullScreen):
(toggleFullScreen):
(constrainFrameRect):
(scrollerWidth): Allow run-time checks.
* src/nsfns.m (ns_screen_name): Allow run-time checks.
---
 configure.ac |   6 ++++
 src/nsfns.m  |   7 ++--
 src/nsterm.h |  16 ++++++++-
 src/nsterm.m | 113 ++++++++++++++++++++++++++++++++++++-----------------------
 4 files changed, 96 insertions(+), 46 deletions(-)

diff --git a/configure.ac b/configure.ac
index 5e6dbda2b6..09ce9a851a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -426,6 +426,12 @@ AC_DEFUN
    EN_NS_SELF_CONTAINED=$enableval,
    EN_NS_SELF_CONTAINED=yes)
 
+AC_ARG_ENABLE(macos-runtime-feature-detection,
+[AS_HELP_STRING([--enable-macos-runtime-feature-detection],
+                [bypass compiler checks of macOS versions])],
+   AC_DEFINE(NS_RUNTIME_CHECKS, 1,
+             [Perform runtime checks of macOS features.]))
+
 locallisppathset=no
 AC_ARG_ENABLE(locallisppath,
 [AS_HELP_STRING([--enable-locallisppath=PATH],
diff --git a/src/nsfns.m b/src/nsfns.m
index 36748cebb8..c5ff65806a 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -2512,12 +2512,15 @@ and GNUstep implementations ("distributor-specific release
 {
   char *name = NULL;
 
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
+#if MACOS_MIN_VERSION (MAC_OS_X_VERSION_10_9)
   mach_port_t masterPort;
   io_iterator_t it;
   io_object_t obj;
 
-  // CGDisplayIOServicePort is deprecated.  Do it another (harder) way.
+  /* CGDisplayIOServicePort is deprecated.  Do it another (harder) way.
+
+     Is this code OK for macOS < 10.9, and GNUstep?  I suspect it is,
+     in which case is it worth keeping the other method in here? */
 
   if (IOMasterPort (MACH_PORT_NULL, &masterPort) != kIOReturnSuccess
       || IOServiceGetMatchingServices (masterPort,
diff --git a/src/nsterm.h b/src/nsterm.h
index 0f1b36db7b..9578591d9d 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -49,6 +49,13 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #endif /* NS_IMPL_COCOA */
 
+#define MACOS_MIN_VERSION(min) (defined (NS_IMPL_COCOA)                 \
+                                && (MAC_OS_X_VERSION_MAX_ALLOWED >= min \
+                                    || defined (NS_RUNTIME_CHECKS)))
+#define MACOS_MAX_VERSION(max) (defined (NS_IMPL_COCOA)                 \
+                                && (MAC_OS_X_VERSION_MAX_ALLOWED <= max \
+                                    || defined (NS_RUNTIME_CHECKS)))
+
 #ifdef __OBJC__
 
 /* CGFloat on GNUstep may be 4 or 8 byte, but functions expect float* for some
@@ -1317,6 +1324,13 @@ extern char gnustep_base_version[];  /* version tracking */
 #ifdef __OBJC__
 typedef NSUInteger NSWindowStyleMask;
 #endif
-#endif
 
+/* Window tabbing mode enums are new too. */
+enum NSWindowTabbingMode
+  {
+    NSWindowTabbingModeAutomatic,
+    NSWindowTabbingModePreferred,
+    NSWindowTabbingModeDisallowed
+  };
+#endif
 #endif	/* HAVE_NS */
diff --git a/src/nsterm.m b/src/nsterm.m
index a3c7031331..07ec899583 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -136,15 +136,15 @@ @implementation NSColor (EmacsColor)
 + (NSColor *)colorForEmacsRed:(CGFloat)red green:(CGFloat)green
                          blue:(CGFloat)blue alpha:(CGFloat)alpha
 {
-#ifdef NS_IMPL_COCOA
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
-  if (ns_use_srgb_colorspace)
+#if MACOS_MIN_VERSION (MAC_OS_X_VERSION_10_7)
+  if (ns_use_srgb_colorspace
+      && [NSColor respondsToSelector:
+                    @selector(colorWithSRGBRed:green:blue:alpha:)])
       return [NSColor colorWithSRGBRed: red
                                  green: green
                                   blue: blue
                                  alpha: alpha];
 #endif
-#endif
   return [NSColor colorWithCalibratedRed: red
                                    green: green
                                     blue: blue
@@ -153,12 +153,15 @@ + (NSColor *)colorForEmacsRed:(CGFloat)red green:(CGFloat)green
 
 - (NSColor *)colorUsingDefaultColorSpace
 {
-#ifdef NS_IMPL_COCOA
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
-  if (ns_use_srgb_colorspace)
+#if MACOS_MIN_VERSION (MAC_OS_X_VERSION_10_7)
+  /* FIXMES: We're checking for colorWithSRGBRed here so this will
+     only work in the same place as in the method above.  It should
+     really be a check whether we're on macOS 10.7 or above. */
+  if (ns_use_srgb_colorspace
+      && [NSColor respondsToSelector:
+                    @selector(colorWithSRGBRed:green:blue:alpha:)])
     return [self colorUsingColorSpace: [NSColorSpace sRGBColorSpace]];
 #endif
-#endif
   return [self colorUsingColorSpaceName: NSCalibratedRGBColorSpace];
 }
 
@@ -5550,8 +5553,7 @@ - (void) terminate: (id)sender
               NSString *defaultButton,
               NSString *alternateButton)
 {
-#if !defined (NS_IMPL_COCOA) || \
-  MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_9
+#ifdef NS_IMPL_GNUSTEP
   return NSRunAlertPanel(title, msgFormat, defaultButton, alternateButton, nil)
     == NSAlertDefaultReturn;
 #else
@@ -6312,14 +6314,28 @@ - (NSRect)firstRectForCharacterRange: (NSRange)theRange
                                        +FRAME_LINE_HEIGHT (emacsframe));
 
   pt = [self convertPoint: pt toView: nil];
-#if !defined (NS_IMPL_COCOA) || \
-  MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
-  pt = [[self window] convertBaseToScreen: pt];
-  rect.origin = pt;
-#else
-  rect.origin = pt;
-  rect = [[self window] convertRectToScreen: rect];
+
+#ifdef NS_RUNTIME_CHECKS
+  if ([[self window] respondsToSelector: @selector(convertRectToScreen:)])
+    {
+#endif
+#if MACOS_MIN_VERSION (MAC_OS_X_VERSION_10_7)
+      rect.origin = pt;
+      rect = [[self window] convertRectToScreen: rect];
+#endif
+#ifdef NS_RUNTIME_CHECKS
+    }
+  else
+    {
+#endif
+#if MACOS_MAX_VERSION (MAC_OS_X_VERSION_10_6) || defined (NS_IMPL_GNUSTEP)
+      pt = [[self window] convertBaseToScreen: pt];
+      rect.origin = pt;
+#endif
+#ifdef NS_RUNTIME_CHECKS
+    }
 #endif
+
   return rect;
 }
 
@@ -7019,9 +7035,9 @@ - (instancetype) initFrameFromEmacs: (struct frame *)f
 
   [win setAcceptsMouseMovedEvents: YES];
   [win setDelegate: self];
-#if !defined (NS_IMPL_COCOA) || \
-  MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_9
-  [win useOptimizedDrawing: YES];
+#if !defined (NS_IMPL_COCOA) || MACOS_MAX_VERSION (MAC_OS_X_VERSION_10_9)
+  if ([win respondsToSelector: @selector(useOptimizedDrawing:)])
+    [win useOptimizedDrawing: YES];
 #endif
 
   [[win contentView] addSubview: self];
@@ -7081,19 +7097,19 @@ - (instancetype) initFrameFromEmacs: (struct frame *)f
   if ([col alphaComponent] != (EmacsCGFloat) 1.0)
     [win setOpaque: NO];
 
-#if !defined (NS_IMPL_COCOA) || \
-  MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_9
-  [self allocateGState];
+#if !defined (NS_IMPL_COCOA) || MACOS_MAX_VERSION (MAC_OS_X_VERSION_10_9)
+  if ([self respondsToSelector: @selector(allocateGState)])
+    [self allocateGState];
 #endif
   [NSApp registerServicesMenuSendTypes: ns_send_types
                            returnTypes: [NSArray array]];
 
+#if MACOS_MIN_VERSION (MAC_OS_X_VERSION_10_12)
   /* macOS Sierra automatically enables tabbed windows.  We can't
      allow this to be enabled until it's available on a Free system.
      Currently it only happens by accident and is buggy anyway. */
-#if defined (NS_IMPL_COCOA) && \
-  MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_12
-  [win setTabbingMode: NSWindowTabbingModeDisallowed];
+  if ([win respondsToSelector: @selector(setTabbingMode:)])
+    [win setTabbingMode: NSWindowTabbingModeDisallowed];
 #endif
 
   ns_window_num++;
@@ -7349,7 +7365,11 @@ - (void)windowDidEnterFullScreen /* provided for direct calls */
     {
       BOOL tbar_visible = FRAME_EXTERNAL_TOOL_BAR (emacsframe) ? YES : NO;
 #ifdef NS_IMPL_COCOA
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
+#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
+      /* These two values are only defined in 10.7 and above. */
+      int NSApplicationPresentationFullScreen = (1 << 10);
+      int NSApplicationPresentationAutoHideToolbar = (1 << 11);
+#endif
       unsigned val = (unsigned)[NSApp presentationOptions];
 
       // Mac OS X 10.7 bug fix, the menu won't appear without this.
@@ -7365,7 +7385,6 @@ - (void)windowDidEnterFullScreen /* provided for direct calls */
           [NSApp setPresentationOptions: options];
         }
 #endif
-#endif
       [toolbar setVisible:tbar_visible];
     }
 }
@@ -7499,10 +7518,10 @@ - (void)toggleFullScreen: (id)sender
     {
       NSScreen *screen = [w screen];
 
-#if defined (NS_IMPL_COCOA) && \
-  MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
+#if MACOS_MIN_VERSION (MAC_OS_X_VERSION_10_9)
       /* Hide ghost menu bar on secondary monitor? */
-      if (! onFirstScreen)
+      if (! onFirstScreen
+          && [NSScreen respondsToSelector: @selector(screensHaveSeparateSpaces)])
         onFirstScreen = [NSScreen screensHaveSeparateSpaces];
 #endif
       /* Hide dock and menubar if we are on the primary screen.  */
@@ -7530,9 +7549,9 @@ - (void)toggleFullScreen: (id)sender
       [fw setTitle:[w title]];
       [fw setDelegate:self];
       [fw setAcceptsMouseMovedEvents: YES];
-#if !defined (NS_IMPL_COCOA) || \
-  MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_9
-      [fw useOptimizedDrawing: YES];
+#if !defined (NS_IMPL_COCOA) || MACOS_MAX_VERSION (MAC_OS_X_VERSION_10_9)
+      if ([fw respondsToSelector: @selector(useOptimizedDrawing:)])
+        [fw useOptimizedDrawing: YES];
 #endif
       [fw setBackgroundColor: col];
       if ([col alphaComponent] != (EmacsCGFloat) 1.0)
@@ -8093,10 +8112,11 @@ - (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen
              NSTRACE_ARG_RECT (frameRect));
 
 #ifdef NS_IMPL_COCOA
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
+#if MACOS_MIN_VERSION (MAC_OS_X_VERSION_10_9)
   // If separate spaces is on, it is like each screen is independent.  There is
   // no spanning of frames across screens.
-  if ([NSScreen screensHaveSeparateSpaces])
+  if ([NSScreen respondsToSelector: @selector(screensHaveSeparateSpaces)]
+      && [NSScreen screensHaveSeparateSpaces])
     {
       NSTRACE_MSG ("Screens have separate spaces");
       frameRect = [super constrainFrameRect:frameRect toScreen:screen];
@@ -8104,7 +8124,7 @@ - (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen
       return frameRect;
     }
   else
-#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9 */
+#endif /* MACOS_MIN_VERSION (MAC_OS_X_VERSION_10_9) */
     // Check that the proposed frameRect is visible in at least one
     // screen.  If it is not, ask the system to reposition it (only
     // for non-child windows).
@@ -8310,12 +8330,19 @@ + (CGFloat) scrollerWidth
   /* TODO: if we want to allow variable widths, this is the place to do it,
            however neither GNUstep nor Cocoa support it very well */
   CGFloat r;
-#if !defined (NS_IMPL_COCOA) || \
-  MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
-  r = [NSScroller scrollerWidth];
-#else
-  r = [NSScroller scrollerWidthForControlSize: NSControlSizeRegular
-                                scrollerStyle: NSScrollerStyleLegacy];
+#ifdef NS_RUNTIME_CHECKS
+  if ([NSScroller respondsToSelector:
+                    @selector(scrollerWidthForControlSize:scrollerStyle:)])
+#endif
+#if MACOS_MIN_VERSION (MAC_OS_X_VERSION_10_7)
+    r = [NSScroller scrollerWidthForControlSize: NSControlSizeRegular
+                                  scrollerStyle: NSScrollerStyleLegacy];
+#endif
+#ifdef NS_RUNTIME_CHECKS
+  else
+#endif
+#if MACOS_MAX_VERSION (MAC_OS_X_VERSION_10_6)
+    r = [NSScroller scrollerWidth];
 #endif
   return r;
 }
-- 
2.12.0


       reply	other threads:[~2017-07-24 20:44 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20170716230109.GA54914@breton.holly.idiocy.org>
     [not found] ` <1ce59431-ff6b-dc89-31a6-8fc5bd4e3926@aurox.ch>
     [not found]   ` <CABr8ebb788TSgj=GgP26_nOK6O2SznZaDx9bTQOgxmYfkz321g@mail.gmail.com>
     [not found]     ` <e6be1e89-14a9-da0a-7d15-3f29dd37e91f@aurox.ch>
     [not found]       ` <20170718221629.GA55506@breton.holly.idiocy.org>
     [not found]         ` <bdf95a23-8ea2-73c4-35c9-2943e23a36dd@aurox.ch>
     [not found]           ` <CABr8ebYtZqNAa5t=QYhBWebcsdFvhXGsuO4t2d2P-UeKQ8hPTQ@mail.gmail.com>
     [not found]             ` <20170722112230.GA58424@breton.holly.idiocy.org>
     [not found]               ` <20170723121701.GA3730@breton.holly.idiocy.org>
     [not found]                 ` <508a4930-feab-588b-0ab9-f55a10ea85ec@aurox.ch>
2017-07-24 20:44                   ` Alan Third [this message]
2017-07-24 20:53                     ` bug#27810: NS runtime feature detection Glenn Morris
2017-07-25 17:56                       ` Alan Third
2017-07-25 18:22                         ` Charles A. Roelli
2017-07-25 20:08                           ` Anders Lindgren
2017-07-26 21:57                     ` Alan Third
2017-07-31 19:05                       ` Charles A. Roelli
2017-08-01 15:38                         ` Anders Lindgren
2017-08-01 22:03                           ` Alan Third
2017-08-06 20:29                             ` Charles A. Roelli
2017-08-06 21:29                               ` Alan Third
2017-08-07 19:23                                 ` Charles A. Roelli
2017-08-10 21:04                                   ` Alan Third
2017-08-12 11:13                                     ` Charles A. Roelli
2017-08-12 13:02                                       ` Charles A. Roelli
2017-08-16 20:31                                         ` Alan Third
2017-08-12 15:51                                       ` Alan Third
2017-09-12 20:01                                         ` David Caldwell
2017-09-12 20:06                                           ` David Reitter
2017-09-12 20:34                                             ` Alan Third
2017-09-12 20:29                                           ` Alan Third
2017-09-13 19:03                                             ` Charles A. Roelli
2017-07-24 20:22 bug#27810: macOS " Alan Third
2017-07-26  2:59 ` Richard Stallman
2017-07-26 16:06   ` Alan Third
2017-07-27  1:43     ` Richard Stallman
2017-07-27 17:31       ` Eli Zaretskii
2017-07-28 17:14         ` Richard Stallman
2017-07-28 17:36           ` Eli Zaretskii
2017-07-29 19:04             ` Richard Stallman
2017-07-31  0:45               ` Richard Stallman
2017-07-29 19:07     ` Richard Stallman
2017-07-30 12:12       ` Alan Third
2017-07-30 14:15         ` Eli Zaretskii
2017-07-31  0:47         ` Richard Stallman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170724204404.GA20189@breton.holly.idiocy.org \
    --to=alan@idiocy.org \
    --cc=27810@debbugs.gnu.org \
    --cc=andlind@gmail.com \
    --cc=charles@aurox.ch \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).