>From 44d3d2d20789997505a93101d6d14e6c854dbd50 Mon Sep 17 00:00:00 2001 From: Alan Third Date: Thu, 6 Jul 2017 23:10:49 +0100 Subject: [PATCH] Allow use of run-time OS version checks on macOS (bug#27810) * src/nsterm.h (NSWindowTabbingMode): Define in pre-Sierra macOS. * src/nsterm.m (colorForEmacsRed): (colorUsingDefaultColorSpace): (runAlertPanel): (firstRectForCharacterRange): (initFrameFromEmacs): (windowDidEnterFullScreen): (toggleFullScreen): (constrainFrameRect): (scrollerWidth): Allow run-time checks. * src/nsfns.m (ns_screen_name): Use run-time OS version checks. * src/macfont.m (macfont_draw): Use run-time OS version checks. --- src/macfont.m | 16 +++++-- src/nsfns.m | 79 ++++++++++++++++++-------------- src/nsterm.h | 9 +++- src/nsterm.m | 144 ++++++++++++++++++++++++++++++++++++++++------------------ 4 files changed, 164 insertions(+), 84 deletions(-) diff --git a/src/macfont.m b/src/macfont.m index 4d310e47ae..d373e391f9 100644 --- a/src/macfont.m +++ b/src/macfont.m @@ -2870,10 +2870,18 @@ So we use CTFontDescriptorCreateMatchingFontDescriptor (no Apple says there are no plans to address this issue (rdar://11644870) currently. So we add a workaround. */ #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 - CGContextSetLineWidth (context, synthetic_bold_factor * font_size - * [[FRAME_NS_VIEW(f) window] backingScaleFactor]); -#else - CGContextSetLineWidth (context, synthetic_bold_factor * font_size); +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7 + if ([[FRAME_NS_VIEW(f) window] respondsToSelector: + @selector(backingScaleFactor)]) +#endif + CGContextSetLineWidth (context, synthetic_bold_factor * font_size + * [[FRAME_NS_VIEW(f) window] backingScaleFactor]); +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7 + else +#endif +#endif +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7 + CGContextSetLineWidth (context, synthetic_bold_factor * font_size); #endif CG_SET_STROKE_COLOR_WITH_FACE_FOREGROUND (context, face, f); } diff --git a/src/nsfns.m b/src/nsfns.m index 36748cebb8..62c25d5e87 100644 --- a/src/nsfns.m +++ b/src/nsfns.m @@ -2513,51 +2513,60 @@ and GNUstep implementations ("distributor-specific release char *name = NULL; #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9 - mach_port_t masterPort; - io_iterator_t it; - io_object_t obj; +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_9 + if (CGDisplayIOServicePort == NULL) +#endif + { + 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. - if (IOMasterPort (MACH_PORT_NULL, &masterPort) != kIOReturnSuccess - || IOServiceGetMatchingServices (masterPort, - IOServiceMatching ("IONDRVDevice"), - &it) != kIOReturnSuccess) - return name; + 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? */ - /* Must loop until we find a name. Many devices can have the same unit - number (represents different GPU parts), but only one has a name. */ - while (! name && (obj = IOIteratorNext (it))) - { - CFMutableDictionaryRef props; - const void *val; - - if (IORegistryEntryCreateCFProperties (obj, - &props, - kCFAllocatorDefault, - kNilOptions) == kIOReturnSuccess - && props != nil - && (val = CFDictionaryGetValue(props, @"IOFBDependentIndex"))) + if (IOMasterPort (MACH_PORT_NULL, &masterPort) != kIOReturnSuccess + || IOServiceGetMatchingServices (masterPort, + IOServiceMatching ("IONDRVDevice"), + &it) != kIOReturnSuccess) + return name; + + /* Must loop until we find a name. Many devices can have the same unit + number (represents different GPU parts), but only one has a name. */ + while (! name && (obj = IOIteratorNext (it))) { - unsigned nr = [(NSNumber *)val unsignedIntegerValue]; - if (nr == CGDisplayUnitNumber (did)) - name = ns_get_name_from_ioreg (obj); + CFMutableDictionaryRef props; + const void *val; + + if (IORegistryEntryCreateCFProperties (obj, + &props, + kCFAllocatorDefault, + kNilOptions) == kIOReturnSuccess + && props != nil + && (val = CFDictionaryGetValue(props, @"IOFBDependentIndex"))) + { + unsigned nr = [(NSNumber *)val unsignedIntegerValue]; + if (nr == CGDisplayUnitNumber (did)) + name = ns_get_name_from_ioreg (obj); + } + + CFRelease (props); + IOObjectRelease (obj); } - CFRelease (props); - IOObjectRelease (obj); + IOObjectRelease (it); } - - IOObjectRelease (it); - -#else - - name = ns_get_name_from_ioreg (CGDisplayIOServicePort (did)); - +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_9 + else +#endif +#endif /* #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9 */ +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_9 + name = ns_get_name_from_ioreg (CGDisplayIOServicePort (did)); #endif return name; } -#endif +#endif /* NS_IMPL_COCOA */ static Lisp_Object ns_make_monitor_attribute_list (struct MonitorInfo *monitors, diff --git a/src/nsterm.h b/src/nsterm.h index 0f1b36db7b..e1dae28111 100644 --- a/src/nsterm.h +++ b/src/nsterm.h @@ -1317,6 +1317,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 36d906a7ce..10f726be86 100644 --- a/src/nsterm.m +++ b/src/nsterm.m @@ -136,14 +136,18 @@ @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) - return [NSColor colorWithSRGBRed: red - green: green - blue: blue - alpha: alpha]; +#if defined (NS_IMPL_COCOA) \ + && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 + if (ns_use_srgb_colorspace +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7 + && [NSColor respondsToSelector: + @selector(colorWithSRGBRed:green:blue:alpha:)] #endif + ) + return [NSColor colorWithSRGBRed: red + green: green + blue: blue + alpha: alpha]; #endif return [NSColor colorWithCalibratedRed: red green: green @@ -153,11 +157,18 @@ + (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) - return [self colorUsingColorSpace: [NSColorSpace sRGBColorSpace]]; + /* 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 defined (NS_IMPL_COCOA) \ + && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 + if (ns_use_srgb_colorspace +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7 + && [NSColor respondsToSelector: + @selector(colorWithSRGBRed:green:blue:alpha:)] #endif + ) + return [self colorUsingColorSpace: [NSColorSpace sRGBColorSpace]]; #endif return [self colorUsingColorSpaceName: NSCalibratedRGBColorSpace]; } @@ -5563,8 +5574,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 @@ -6325,14 +6335,27 @@ - (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]; + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7 + if ([[self window] respondsToSelector: @selector(convertRectToScreen:)]) + { +#endif + rect.origin = pt; + rect = [[self window] convertRectToScreen: rect]; +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7 + } + else +#endif +#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 */ +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7 \ + || defined (NS_IMPL_GNUSTEP) + { + pt = [[self window] convertBaseToScreen: pt]; + rect.origin = pt; + } #endif + return rect; } @@ -7032,9 +7055,12 @@ - (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) \ + || MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_9 +#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_9 + if ([win respondsToSelector: @selector(useOptimizedDrawing:)]) +#endif + [win useOptimizedDrawing: YES]; #endif [[win contentView] addSubview: self]; @@ -7094,9 +7120,12 @@ - (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) \ + || MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_9 +#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_9 + if ([self respondsToSelector: @selector(allocateGState)]) +#endif + [self allocateGState]; #endif [NSApp registerServicesMenuSendTypes: ns_send_types returnTypes: [NSArray array]]; @@ -7104,9 +7133,12 @@ - (instancetype) initFrameFromEmacs: (struct frame *)f /* 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 defined (NS_IMPL_COCOA) \ + && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12 +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_12 + if ([win respondsToSelector: @selector(setTabbingMode:)]) +#endif + [win setTabbingMode: NSWindowTabbingModeDisallowed]; #endif ns_window_num++; @@ -7362,7 +7394,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. @@ -7378,7 +7414,6 @@ - (void)windowDidEnterFullScreen /* provided for direct calls */ [NSApp setPresentationOptions: options]; } #endif -#endif [toolbar setVisible:tbar_visible]; } } @@ -7512,10 +7547,14 @@ - (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 defined (NS_IMPL_COCOA) \ + && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9 /* Hide ghost menu bar on secondary monitor? */ - if (! onFirstScreen) + if (! onFirstScreen +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_9 + && [NSScreen respondsToSelector: @selector(screensHaveSeparateSpaces)] +#endif + ) onFirstScreen = [NSScreen screensHaveSeparateSpaces]; #endif /* Hide dock and menubar if we are on the primary screen. */ @@ -7543,9 +7582,12 @@ - (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) \ + || MAC_OS_X_VERSION_MIN_ALLOWED <= MAC_OS_X_VERSION_10_9 +#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_9 + if ([fw respondsToSelector: @selector(useOptimizedDrawing:)]) +#endif + [fw useOptimizedDrawing: YES]; #endif [fw setBackgroundColor: col]; if ([col alphaComponent] != (EmacsCGFloat) 1.0) @@ -8109,7 +8151,11 @@ - (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen #if MAC_OS_X_VERSION_MAX_ALLOWED >= 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 ( +#if MAC_OS_X_VERSION_MIN_ALLOWED < MAC_OS_X_VERSION_10_9 + [NSScreen respondsToSelector: @selector(screensHaveSeparateSpaces)] && +#endif + [NSScreen screensHaveSeparateSpaces]) { NSTRACE_MSG ("Screens have separate spaces"); frameRect = [super constrainFrameRect:frameRect toScreen:screen]; @@ -8118,6 +8164,7 @@ - (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen } else #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 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). @@ -8323,12 +8370,21 @@ + (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]; +#if defined (NS_IMPL_COCOA) \ + && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 +#if MAC_OS_X_VERSION_MIN_ALLOWED < MAC_OS_X_VERSION_10_7 + if ([NSScroller respondsToSelector: + @selector(scrollerWidthForControlSize:scrollerStyle:)]) +#endif + r = [NSScroller scrollerWidthForControlSize: NSControlSizeRegular + scrollerStyle: NSScrollerStyleLegacy]; +#if MAC_OS_X_VERSION_MIN_ALLOWED < MAC_OS_X_VERSION_10_7 + else +#endif +#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 */ +#if MAC_OS_X_VERSION_MIN_ALLOWED < MAC_OS_X_VERSION_10_7 \ + || defined (NS_IMPL_GNUSTEP) + r = [NSScroller scrollerWidth]; #endif return r; } -- 2.12.0