From 34b6e22a06adccb7580782a848c0ff8e0bbae2c6 Mon Sep 17 00:00:00 2001
From: Sergey Fedorov <barracuda@macos-powerpc.org>
Date: Fri, 17 Jul 2026 19:41:33 +0000
Subject: [PATCH 5/6] 0005-leopard

---
 src/gui/macOS/QMPlay2MacExtensions.mm         | 129 +++++++++++-------
 src/gui/macOS/ScreenSaver.cpp                 |   5 +
 .../3rdparty/CoreAudio/AudioDevice.mm         |   4 +
 .../3rdparty/CoreAudio/AudioDeviceList.cpp    |   4 +
 src/qmplay2/opengl/OpenGLCommon.cpp           |   3 +
 5 files changed, 95 insertions(+), 50 deletions(-)

diff --git a/src/gui/macOS/QMPlay2MacExtensions.mm b/src/gui/macOS/QMPlay2MacExtensions.mm
index edeb8c94..54d924b9 100644
--- a/src/gui/macOS/QMPlay2MacExtensions.mm
+++ b/src/gui/macOS/QMPlay2MacExtensions.mm
@@ -4,48 +4,56 @@
 #include <QApplication>
 #include <QWidget>
 
-// For media keys on macOS 10.6.8 with gcc (no blocks)
 #include <Carbon/Carbon.h>
 #include <IOKit/hidsystem/ev_keymap.h>
 #include <AppKit/NSApplication.h>
 #include <AppKit/NSScreen.h>
 #include <AppKit/NSEvent.h>
 
-// Qt4 doesn't have QAbstractNativeEventFilter (Qt5.2+)
-// For macOS 10.6.8 with gcc (no blocks support), we use a polling-based approach
-// or carbon event handlers instead of Cocoa blocks
-
-// Forward declaration for the carbon event handler
-static OSStatus MediaKeysEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData);
-
+// Media keys handling for 10.5
+// We need to tap into system events, not keyboard events
 class MediaKeysFilter : public QObject
 {
 public:
     MediaKeysFilter(const QMPlay2MacExtensions::MediaKeysCallback &cb) :
         m_mediaKeysCallback(cb),
-        m_eventHandlerRef(NULL)
+        m_eventTap(NULL)
     {
-        // Use Carbon Event Manager for media keys support on 10.6.8 with gcc
-        // This doesn't require Apple blocks
-        EventTypeSpec eventTypes[1];
-        eventTypes[0].eventClass = kEventClassKeyboard;
-        eventTypes[0].eventKind = kEventHotKeyPressed;
-
-        InstallApplicationEventHandler(
-            NewEventHandlerUPP(MediaKeysEventHandler),
-            1,
-            eventTypes,
-            this,
-            &m_eventHandlerRef
+        // Create an event tap for system-defined events
+        // This works on 10.5+ and doesn't require blocks
+        CGEventMask eventMask = CGEventMaskBit(kCGEventTapDisabledByTimeout) | 
+                                CGEventMaskBit(kCGEventTapDisabledByUserInput) |
+                                CGEventMaskBit(NX_SYSDEFINED);
+
+        m_eventTap = CGEventTapCreate(
+            kCGSessionEventTap,
+            kCGHeadInsertEventTap,
+            kCGEventTapOptionDefault,
+            eventMask,
+            MediaKeysEventTapCallback,
+            this
         );
+        
+        if (m_eventTap)
+        {
+            m_runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, m_eventTap, 0);
+            CFRunLoopAddSource(CFRunLoopGetCurrent(), m_runLoopSource, kCFRunLoopCommonModes);
+            CGEventTapEnable(m_eventTap, true);
+        }
     }
 
     ~MediaKeysFilter()
     {
-        if (m_eventHandlerRef != NULL)
+        if (m_eventTap)
         {
-            RemoveEventHandler(m_eventHandlerRef);
-            m_eventHandlerRef = NULL;
+            CGEventTapEnable(m_eventTap, false);
+            if (m_runLoopSource)
+            {
+                CFRunLoopRemoveSource(CFRunLoopGetCurrent(), m_runLoopSource, kCFRunLoopCommonModes);
+                CFRelease(m_runLoopSource);
+            }
+            CFRelease(m_eventTap);
+            m_eventTap = NULL;
         }
     }
 
@@ -67,34 +75,41 @@ public:
         }
     }
 
-    QMPlay2MacExtensions::MediaKeysCallback m_mediaKeysCallback;
-    EventHandlerRef m_eventHandlerRef;
-} static *g_mediaKeysFilter;
-
-// Carbon event handler callback (no blocks needed)
-static OSStatus MediaKeysEventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData)
-{
-    Q_UNUSED(nextHandler)
+    static CGEventRef MediaKeysEventTapCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon)
+    {
+        Q_UNUSED(proxy)
 
-    MediaKeysFilter *filter = static_cast<MediaKeysFilter*>(userData);
-    if (!filter)
-        return eventNotHandledErr;
+        MediaKeysFilter *filter = static_cast<MediaKeysFilter*>(refcon);
 
-    UInt32 eventClass = GetEventClass(event);
-    UInt32 eventKind = GetEventKind(event);
+        if (type == kCGEventTapDisabledByTimeout)
+        {
+            CGEventTapEnable(filter->m_eventTap, true);
+            return event;
+        }
 
-    if (eventClass == kEventClassKeyboard && eventKind == kEventHotKeyPressed)
-    {
-        EventHotKeyID hotKeyID;
-        GetEventParameter(event, kEventParamDirectObject, typeEventHotKeyID, NULL, sizeof(hotKeyID), NULL, &hotKeyID);
+        if (type == NX_SYSDEFINED)
+        {
+            NSEvent *nsEvent = [NSEvent eventWithCGEvent:event];
+            if ([nsEvent type] == NSSystemDefined && [nsEvent subtype] == 8)
+            {
+                int keyCode = (([nsEvent data1] & 0xFFFF0000) >> 16);
+                int keyFlags = ([nsEvent data1] & 0x0000FFFF);
+                int keyState = (((keyFlags & 0xFF00) >> 8) == 0xA);
+
+                if (keyState == 1)
+                {
+                    filter->handleMediaKey(keyCode);
+                }
+            }
+        }
 
-        // Handle media key based on hotKeyID
-        filter->handleMediaKey(hotKeyID.id);
-        return noErr;
+        return event;
     }
 
-    return eventNotHandledErr;
-}
+    QMPlay2MacExtensions::MediaKeysCallback m_mediaKeysCallback;
+    CFMachPortRef m_eventTap;
+    CFRunLoopSourceRef m_runLoopSource;
+} static *g_mediaKeysFilter = NULL;
 
 /**/
 
@@ -112,27 +127,41 @@ void QMPlay2MacExtensions::registerMacOSMediaKeys(const MediaKeysCallback &cb)
     if (!g_mediaKeysFilter)
     {
         g_mediaKeysFilter = new MediaKeysFilter(cb);
-        // Qt4 doesn't need installNativeEventFilter - Carbon events are handled directly
     }
 }
+
 void QMPlay2MacExtensions::unregisterMacOSMediaKeys()
 {
     if (g_mediaKeysFilter)
     {
         delete g_mediaKeysFilter;
-        g_mediaKeysFilter = nullptr;
+        g_mediaKeysFilter = NULL;
     }
 }
 
 void QMPlay2MacExtensions::showSystemUi(QWidget *mainWindow, bool visible)
 {
     Q_UNUSED(mainWindow)
-    // macOS 10.6.8 doesn't have screensHaveSeparateSpaces (10.9+)
-    // Simplified for older macOS version
+    Q_UNUSED(visible)
+
+    // NSApplicationPresentationOptions and setPresentationOptions: are 10.6+
+    // On 10.5, we need to use the older SetSystemUIMode API from Carbon
+
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
+    if (visible)
+    {
+        SetSystemUIMode(kUIModeNormal, 0);
+    }
+    else
+    {
+        SetSystemUIMode(kUIModeAllHidden, kUIOptionAutoShowMenuBar);
+    }
+#else
     NSApplicationPresentationOptions flags;
     if (visible)
         flags = NSApplicationPresentationDefault;
     else
         flags = (NSApplicationPresentationOptions)(NSApplicationPresentationHideDock | NSApplicationPresentationAutoHideMenuBar);
     [NSApp setPresentationOptions:flags];
+#endif
 }
diff --git a/src/gui/macOS/ScreenSaver.cpp b/src/gui/macOS/ScreenSaver.cpp
index 36885a39..fa890a29 100644
--- a/src/gui/macOS/ScreenSaver.cpp
+++ b/src/gui/macOS/ScreenSaver.cpp
@@ -39,8 +39,13 @@ public:
 
     inline void inhibit()
     {
+#if MAC_OS_X_VERSION_MAX_ALLOWED < 1060
+		m_okDisp = (IOPMAssertionCreate(kIOPMAssertionTypeNoDisplaySleep, kIOPMAssertionLevelOn, &m_idDisp) == kIOReturnSuccess);
+		m_okSys  = (IOPMAssertionCreate(kIOPMAssertionTypeNoIdleSleep, kIOPMAssertionLevelOn, &m_idSys)  == kIOReturnSuccess);
+#else
         m_okDisp = (IOPMAssertionCreateWithName(kIOPMAssertPreventUserIdleDisplaySleep, kIOPMAssertionLevelOn, QMPLAY2_MEDIA_PLAYBACK, &m_idDisp) == kIOReturnSuccess);
         m_okSys  = (IOPMAssertionCreateWithName(kIOPMAssertPreventUserIdleSystemSleep,  kIOPMAssertionLevelOn, QMPLAY2_MEDIA_PLAYBACK, &m_idSys)  == kIOReturnSuccess);
+#endif
     }
     inline void unInhibit()
     {
diff --git a/src/modules/PortAudio/3rdparty/CoreAudio/AudioDevice.mm b/src/modules/PortAudio/3rdparty/CoreAudio/AudioDevice.mm
index d08a3ff6..9c3b9ef2 100644
--- a/src/modules/PortAudio/3rdparty/CoreAudio/AudioDevice.mm
+++ b/src/modules/PortAudio/3rdparty/CoreAudio/AudioDevice.mm
@@ -49,6 +49,10 @@
 #include "AudioDevice.h"
 #import <Cocoa/Cocoa.h>
 
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
+#define __Verify_noErr verify_noerr
+#endif
+
 char *OSTStr(OSType type)
 {
     static union OSTStr {
diff --git a/src/modules/PortAudio/3rdparty/CoreAudio/AudioDeviceList.cpp b/src/modules/PortAudio/3rdparty/CoreAudio/AudioDeviceList.cpp
index 1efb0bd2..749fce9f 100644
--- a/src/modules/PortAudio/3rdparty/CoreAudio/AudioDeviceList.cpp
+++ b/src/modules/PortAudio/3rdparty/CoreAudio/AudioDeviceList.cpp
@@ -48,6 +48,10 @@
 
 #include "AudioDeviceList.h"
 
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
+#define __Verify_noErr verify_noerr
+#endif
+
 AudioDeviceList::AudioDeviceList(bool forInput)
     : mForInput(forInput)
 {
diff --git a/src/qmplay2/opengl/OpenGLCommon.cpp b/src/qmplay2/opengl/OpenGLCommon.cpp
index c7fe3540..1f709308 100644
--- a/src/qmplay2/opengl/OpenGLCommon.cpp
+++ b/src/qmplay2/opengl/OpenGLCommon.cpp
@@ -52,6 +52,9 @@
 #ifndef GL_TEXTURE_RECTANGLE_ARB
     #define GL_TEXTURE_RECTANGLE_ARB 0x84F5
 #endif
+#ifndef GL_R16_EXT
+    #define GL_R16_EXT 0x822A
+#endif
 #ifndef GL_R16
     #define GL_R16 GL_R16_EXT
 #endif
