FR: Add macOS 14.x (Sonoma) to SystemStats

See title.

Can this function also be updated so it doesn’t break every time a new OS comes out.

Let’s say I do something like:

if (juce::SystemStats::getOperatingSystemType () >= juce::SystemStats::OperatingSystemType::MacOS_11))

This doSomethingCool() will not be called for macOS 14.

I think it should be implemented like this:

SystemStats::OperatingSystemType SystemStats::getOperatingSystemType()
   #if JUCE_IOS
    return iOS;
    StringArray parts;
    parts.addTokens (getOSXVersion(), ".", StringRef());

    const auto major = parts[0].getIntValue();
    const auto minor = parts[1].getIntValue();

    switch (major)
        case 10:
            jassert (minor > 2);
            return (OperatingSystemType) (minor + MacOSX_10_7 - 7);

        case 11: return MacOS_11;
        case 12: return MacOS_12;
        case 13: return MacOS_13;
    if (major >= 14)
        return MacOS_Future;

    return MacOSX;

Alternatively, what about exposing:

int getOperatingSystemMajorVersion();

So that your code is:

if (SystemStats::getOperatingSystemMajorVersion() > 13)

An enum for version numbers sounds a bit strange to me.


This function already returns MacOSX for unknown macOS versions, so you can check for that value to see whether the current OS is a ‘future’ version.

We’ll add an explicit 14 version to the enum shortly.

True, but the value for Unknown is less than the value for all the known versions. So the logic to check correctly is quite awkward. It’s also not obvious the second check is required, leading to bugs that don’t show up in testing until a new OS is released.

if (juce::SystemStats::getOperatingSystemType() >= juce::SystemStats::OperatingSystemType::MacOS_11 || juce::SystemStats::getOperatingSystemType() == juce::SystemStats::OperatingSystemType::MacOS)

For example, there are numerous places in the juce codebase that don’t check for MacOSX or Windows for a future version of macOS or if Windows ever changes the major version number > 10. These checks all break when a new macOS comes out.

        if (SystemStats::getOperatingSystemType() >= SystemStats::WinVista
            && customComponent == nullptr)
            return openDialogVistaAndUp();

        return openDialogPreVista (async);
static bool isPre10_11 = SystemStats::getOperatingSystemType() <= SystemStats::MacOSX_10_10;
            if (SystemStats::getOperatingSystemType() <= SystemStats::MacOSX_10_9)
                if (SystemStats::getOperatingSystemType() < SystemStats::WinVista)
                    return nullptr;
        if (! component.isCurrentlyModal() && (styleFlags & windowHasDropShadow) != 0
            && ((! hasTitleBar()) || SystemStats::getOperatingSystemType() < SystemStats::WinVista))
            shadower = component.getLookAndFeel().createDropShadowerForComponent (component);

            if (shadower != nullptr)
                shadower->setOwner (&component);
       #if JUCE_DIRECT2D
        if (SystemStats::getOperatingSystemType() >= SystemStats::Windows7)
            s.add ("Direct2D");
        if (SystemStats::getOperatingSystemType() >= SystemStats::WinVista)
            return 0;