--- utils/viewer-cocoa.m 2026-03-23 09:54:26.000000000 +0800 +++ utils/viewer-cocoa.m 2026-05-06 21:55:28.000000000 +0800 @@ -18,7 +18,9 @@ * Boston, MA 02111-1307, USA. */ #include "config.h" -#import + +#include /* bzero */ +#include #include #include @@ -28,33 +30,91 @@ #include "viewer-cocoa.h" #include "viewer-cocoa-resources.h" +/* Compatibility shims for renamed constants (macOS 10.12+) */ +#ifndef NSWindowStyleMaskTitled +# define NSWindowStyleMaskTitled NSTitledWindowMask +# define NSWindowStyleMaskClosable NSClosableWindowMask +#endif +#ifndef NSEventMaskAny +# define NSEventMaskAny NSAnyEventMask +#endif +#ifndef NSEventTypeKeyDown +# define NSEventTypeKeyDown NSKeyDown +#endif + +/* Forward-declare methods that were added after the 10.6 SDK so that + * GCC (which does not auto-import newer SDK declarations) knows their + * return types when we call them behind a -respondsToSelector: guard. + * Under clang with a modern SDK these categories are harmless no-ops. */ +#if MAC_OS_X_VERSION_MAX_ALLOWED < 101000 +@interface NSGraphicsContext (PangoCGContextAccessor) +- (CGContextRef)CGContext; +@end +#endif + +#if MAC_OS_X_VERSION_MAX_ALLOWED < 1070 +@interface NSWindow (PangoBackingScaleFactor) +- (CGFloat)backingScaleFactor; +@end +#endif + struct _CocoaViewer { NSApplication *app; }; @interface PangoView : NSView +{ + cairo_surface_t *_surface; /* explicit ivar required by GCC */ +} -@property (nonatomic, assign, nullable) cairo_surface_t *surface; +/* 'nullable' is a clang nullability annotation added in Xcode 7 (clang 6.1). + * Omit it so the code compiles with older toolchains. */ +@property (nonatomic, assign) cairo_surface_t *surface; @end @implementation PangoView +/* GCC does not auto-synthesize @property; clang does. + * This directive is a no-op on clang with a modern runtime. */ +@synthesize surface = _surface; + - (void)drawRect:(NSRect)dirtyRect { if ([self surface]) { NSGraphicsContext *context = [NSGraphicsContext currentContext]; - CGContextRef cgContext = [context CGContext]; - CGFloat scaleFactor = [[self window] backingScaleFactor]; + CGContextRef cgContext; + + /* -[NSGraphicsContext CGContext] is macOS 10.10+. + * Fall back to the deprecated -graphicsPort on older systems. */ + if ([context respondsToSelector:@selector(CGContext)]) + cgContext = [context CGContext]; + else + { +#ifdef __clang__ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wdeprecated-declarations" +#endif + cgContext = (CGContextRef)[context graphicsPort]; +#ifdef __clang__ +# pragma clang diagnostic pop +#endif + } + + /* -[NSWindow backingScaleFactor] is macOS 10.7+. + * On 10.6 there is no HiDPI so 1.0 is correct. */ + CGFloat scaleFactor = 1.0; + if ([[self window] respondsToSelector:@selector(backingScaleFactor)]) + scaleFactor = [[self window] backingScaleFactor]; CGContextTranslateCTM (cgContext, 0.0, [self bounds].size.height); CGContextScaleCTM (cgContext, 1/scaleFactor, -1/scaleFactor); cairo_surface_t *viewSurface = cairo_quartz_surface_create_for_cg_context (cgContext, - [self bounds].size.width * scaleFactor, - [self bounds].size.height * scaleFactor); + [self bounds].size.width * scaleFactor, + [self bounds].size.height * scaleFactor); cairo_surface_set_device_scale (viewSurface, scaleFactor, scaleFactor); cairo_t *cr = cairo_create (viewSurface);