From 873c70693362f24ccfa99861a758e3d9536b0b7c Mon Sep 17 00:00:00 2001 From: Sergey Fedorov Date: Sun, 3 May 2026 18:00:13 +0800 Subject: [PATCH 2/2] UI patch --- Rendering/UI/vtkCocoaMacOSXSDKCompatibility.h | 231 +++++++++++++++++- .../UI/vtkCocoaRenderWindowInteractor.mm | 5 +- 2 files changed, 226 insertions(+), 10 deletions(-) diff --git a/Rendering/UI/vtkCocoaMacOSXSDKCompatibility.h b/Rendering/UI/vtkCocoaMacOSXSDKCompatibility.h index 4153d7f704..a2c922868c 100644 --- a/Rendering/UI/vtkCocoaMacOSXSDKCompatibility.h +++ b/Rendering/UI/vtkCocoaMacOSXSDKCompatibility.h @@ -4,7 +4,7 @@ * @class vtkCocoaMacOSXSDKCompatibility * @brief Compatibility header * - * VTK requires the Mac OS X 10.7 SDK or later. + * VTK requires the Mac OS X 10.5 SDK or later. * However, this file is meant to allow us to use features from newer * SDKs by adding workarounds to still support the minimum SDK. * It is safe to include this header multiple times. @@ -12,12 +12,46 @@ #include -#if MAC_OS_X_VERSION_MAX_ALLOWED < 1070 -#error VTK requires the Mac OS X 10.7 SDK or later +#if MAC_OS_X_VERSION_MAX_ALLOWED < 1050 +#error VTK requires the Mac OS X 10.5 SDK or later +#endif + +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1050 +#error VTK requires a deployment target of Mac OS X 10.5 or later #endif -#if MAC_OS_X_VERSION_MIN_REQUIRED < 1070 -#error VTK requires a deployment target of Mac OS X 10.7 or later +// Provide __has_feature for compilers that don't support it (e.g. gcc) +#ifndef __has_feature +#define __has_feature(x) 0 +#endif + +// Portable diagnostic push/pop/ignore macros for gcc and clang +#ifdef __clang__ +#define VTK_DIAG_STR(s) #s +#define VTK_DIAG_JOINSTR(x,y) VTK_DIAG_STR(x ## y) +#define VTK_DIAG_DO_PRAGMA(x) _Pragma(#x) +#define VTK_DIAG_PRAGMA(x) VTK_DIAG_DO_PRAGMA(clang diagnostic x) +#define VTK_DIAG_OFF(x) \ + VTK_DIAG_PRAGMA(push) \ + VTK_DIAG_PRAGMA(ignored VTK_DIAG_JOINSTR(-W,x)) +#define VTK_DIAG_ON(x) VTK_DIAG_PRAGMA(pop) +#elif defined(__GNUC__) +#define VTK_DIAG_STR(s) #s +#define VTK_DIAG_JOINSTR(x,y) VTK_DIAG_STR(x ## y) +#define VTK_DIAG_DO_PRAGMA(x) _Pragma(#x) +#define VTK_DIAG_PRAGMA(x) VTK_DIAG_DO_PRAGMA(GCC diagnostic x) +#if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) +#define VTK_DIAG_OFF(x) \ + VTK_DIAG_PRAGMA(push) \ + VTK_DIAG_PRAGMA(ignored VTK_DIAG_JOINSTR(-W,x)) +#define VTK_DIAG_ON(x) VTK_DIAG_PRAGMA(pop) +#else +#define VTK_DIAG_OFF(x) VTK_DIAG_PRAGMA(ignored VTK_DIAG_JOINSTR(-W,x)) +#define VTK_DIAG_ON(x) VTK_DIAG_PRAGMA(warning VTK_DIAG_JOINSTR(-W,x)) +#endif +#else +#define VTK_DIAG_OFF(x) +#define VTK_DIAG_ON(x) #endif // Stop AssertMacros.h from defining its macros without underscore prefixes, @@ -50,6 +84,233 @@ #define NSEventMaskAny NSAnyEventMask #endif +// 10.7+ OpenGL profile constants - define for older SDKs +// These will be ignored at runtime on systems that don't support them +#if MAC_OS_X_VERSION_MAX_ALLOWED < 1070 +#define NSOpenGLPFAOpenGLProfile 99 +#define NSOpenGLProfileVersion3_2Core 0x3200 +#define NSOpenGLProfileVersionLegacy 0x1000 +#endif + +// 10.10+ OpenGL 4.1 profile constant +#if MAC_OS_X_VERSION_MAX_ALLOWED < 101000 +#define NSOpenGLProfileVersion4_1Core 0x4100 +#endif + +// Helper functions for 10.7+ backing APIs that work on older systems +// These provide runtime checks for the backing coordinate methods +#ifdef __OBJC__ +#import +#import + +// On SDKs < 10.7, the backing coordinate methods don't exist in headers, +// so we must use objc_msgSend to call them dynamically at runtime. +// We define typed function pointer casts to maintain type safety. + +// Convert point from view coordinates to backing (pixel) coordinates +// Falls back to identity transform on pre-10.7 systems +static inline NSPoint vtkCocoaConvertPointToBacking(NSView* view, NSPoint point) +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 + if ([view respondsToSelector:@selector(convertPointToBacking:)]) + { + return [view convertPointToBacking:point]; + } +#else + SEL sel = @selector(convertPointToBacking:); + if ([view respondsToSelector:sel]) + { + typedef NSPoint (*MsgSendPointPoint)(id, SEL, NSPoint); + MsgSendPointPoint msgSend = (MsgSendPointPoint)objc_msgSend; + return msgSend(view, sel, point); + } +#endif + return point; +} + +// Convert rect from view coordinates to backing (pixel) coordinates +static inline NSRect vtkCocoaConvertRectToBacking(id viewOrScreen, NSRect rect) +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 + if ([viewOrScreen respondsToSelector:@selector(convertRectToBacking:)]) + { + return [viewOrScreen convertRectToBacking:rect]; + } +#else + SEL sel = @selector(convertRectToBacking:); + if ([viewOrScreen respondsToSelector:sel]) + { + typedef NSRect (*MsgSendRectRect)(id, SEL, NSRect); + // For structs larger than register size, some ABIs use objc_msgSend_stret +#if defined(__i386__) || defined(__x86_64__) || defined(__arm64__) + MsgSendRectRect msgSend = (MsgSendRectRect)objc_msgSend; +#else + MsgSendRectRect msgSend = (MsgSendRectRect)objc_msgSend_stret; +#endif + return msgSend(viewOrScreen, sel, rect); + } +#endif + return rect; +} + +// Convert size from backing (pixel) coordinates to view coordinates +static inline NSSize vtkCocoaConvertSizeFromBacking(NSView* view, NSSize size) +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 + if ([view respondsToSelector:@selector(convertSizeFromBacking:)]) + { + return [view convertSizeFromBacking:size]; + } +#else + SEL sel = @selector(convertSizeFromBacking:); + if ([view respondsToSelector:sel]) + { + typedef NSSize (*MsgSendSizeSize)(id, SEL, NSSize); + MsgSendSizeSize msgSend = (MsgSendSizeSize)objc_msgSend; + return msgSend(view, sel, size); + } +#endif + return size; +} + +// Convert point from backing (pixel) coordinates to view coordinates +static inline NSPoint vtkCocoaConvertPointFromBacking(NSView* view, NSPoint point) +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 + if ([view respondsToSelector:@selector(convertPointFromBacking:)]) + { + return [view convertPointFromBacking:point]; + } +#else + SEL sel = @selector(convertPointFromBacking:); + if ([view respondsToSelector:sel]) + { + typedef NSPoint (*MsgSendPointPoint)(id, SEL, NSPoint); + MsgSendPointPoint msgSend = (MsgSendPointPoint)objc_msgSend; + return msgSend(view, sel, point); + } +#endif + return point; +} + +// Set whether the view wants best resolution OpenGL surface (10.7+) +// Does nothing on pre-10.7 systems +static inline void vtkCocoaSetWantsBestResolutionOpenGLSurface(NSView* view, BOOL wantsBest) +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 + if ([view respondsToSelector:@selector(setWantsBestResolutionOpenGLSurface:)]) + { + [view setWantsBestResolutionOpenGLSurface:wantsBest]; + } +#else + SEL sel = @selector(setWantsBestResolutionOpenGLSurface:); + if ([view respondsToSelector:sel]) + { + typedef void (*MsgSendVoidBool)(id, SEL, BOOL); + MsgSendVoidBool msgSend = (MsgSendVoidBool)objc_msgSend; + msgSend(view, sel, wantsBest); + } +#endif +} + +// Get backing scale factor from window (10.7+) +// Returns 1.0 on pre-10.7 systems +static inline CGFloat vtkCocoaGetBackingScaleFactor(NSWindow* window) +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 + if ([window respondsToSelector:@selector(backingScaleFactor)]) + { + return [window backingScaleFactor]; + } +#else + SEL sel = @selector(backingScaleFactor); + if ([window respondsToSelector:sel]) + { + typedef CGFloat (*MsgSendCGFloat)(id, SEL); + MsgSendCGFloat msgSend = (MsgSendCGFloat)objc_msgSend; + return msgSend(window, sel); + } +#endif + return 1.0; +} + +// Convert rect from backing coordinates on NSWindow (10.7+) +// Falls back to identity transform on pre-10.7 systems +static inline NSRect vtkCocoaWindowConvertRectFromBacking(NSWindow* window, NSRect rect) +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 + if ([window respondsToSelector:@selector(convertRectFromBacking:)]) + { + return [window convertRectFromBacking:rect]; + } +#else + SEL sel = @selector(convertRectFromBacking:); + if ([window respondsToSelector:sel]) + { + typedef NSRect (*MsgSendRectRect)(id, SEL, NSRect); +#if defined(__i386__) || defined(__x86_64__) || defined(__arm64__) + MsgSendRectRect msgSend = (MsgSendRectRect)objc_msgSend; +#else + MsgSendRectRect msgSend = (MsgSendRectRect)objc_msgSend_stret; +#endif + return msgSend(window, sel, rect); + } +#endif + return rect; +} + +// Convert rect to backing coordinates on NSWindow (10.7+) +// Falls back to identity transform on pre-10.7 systems +static inline NSRect vtkCocoaWindowConvertRectToBacking(NSWindow* window, NSRect rect) +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 + if ([window respondsToSelector:@selector(convertRectToBacking:)]) + { + return [window convertRectToBacking:rect]; + } +#else + SEL sel = @selector(convertRectToBacking:); + if ([window respondsToSelector:sel]) + { + typedef NSRect (*MsgSendRectRect)(id, SEL, NSRect); +#if defined(__i386__) || defined(__x86_64__) || defined(__arm64__) + MsgSendRectRect msgSend = (MsgSendRectRect)objc_msgSend; +#else + MsgSendRectRect msgSend = (MsgSendRectRect)objc_msgSend_stret; +#endif + return msgSend(window, sel, rect); + } +#endif + return rect; +} + +// Convert rect from backing coordinates on NSScreen (10.7+) +// Falls back to identity transform on pre-10.7 systems +static inline NSRect vtkCocoaScreenConvertRectFromBacking(NSScreen* screen, NSRect rect) +{ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 + if ([screen respondsToSelector:@selector(convertRectFromBacking:)]) + { + return [screen convertRectFromBacking:rect]; + } +#else + SEL sel = @selector(convertRectFromBacking:); + if ([screen respondsToSelector:sel]) + { + typedef NSRect (*MsgSendRectRect)(id, SEL, NSRect); +#if defined(__i386__) || defined(__x86_64__) || defined(__arm64__) + MsgSendRectRect msgSend = (MsgSendRectRect)objc_msgSend; +#else + MsgSendRectRect msgSend = (MsgSendRectRect)objc_msgSend_stret; +#endif + return msgSend(screen, sel, rect); + } +#endif + return rect; +} + +#endif // __OBJC__ + // Create handy #defines that indicate the Objective-C memory management model. // Manual Retain Release, Automatic Reference Counting, or Garbage Collection. #if defined(__OBJC_GC__) diff --git a/Rendering/UI/vtkCocoaRenderWindowInteractor.mm b/Rendering/UI/vtkCocoaRenderWindowInteractor.mm index af99efa8b6..1919032857 100644 --- a/Rendering/UI/vtkCocoaRenderWindowInteractor.mm +++ b/Rendering/UI/vtkCocoaRenderWindowInteractor.mm @@ -203,7 +203,10 @@ vtkCocoaRenderWindowInteractor::vtkCocoaRenderWindowInteractor() vtkCocoaRenderWindowInteractor::~vtkCocoaRenderWindowInteractor() { NSMutableDictionary* timerDict = (NSMutableDictionary*)(this->GetTimerDictionary()); - for (NSString* key in timerDict) + // Use NSEnumerator instead of fast enumeration for gcc compatibility + NSEnumerator* keyEnumerator = [timerDict keyEnumerator]; + NSString* key; + while ((key = [keyEnumerator nextObject]) != nil) { vtkCocoaTimer* cocoaTimer = [timerDict objectForKey:key]; [cocoaTimer stopTimer];