5.13.2 уходит

This commit is contained in:
kleuter 2021-05-01 14:01:35 +02:00
parent 4d982edc93
commit 4e79ef8198
23 changed files with 0 additions and 12608 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,23 +0,0 @@
#!/bin/bash
export PATH=$PATH:/usr/local/Qt-5.13.2/bin
cd qtbase
./configure -opensource -confirm-license -nomake examples -nomake tests -no-openssl -securetransport
make -j 12
echo maki | sudo -S sudo make install
cd ../qttools
qmake
make -j 12
echo maki | sudo -S sudo make install
cd ../qtmacextras
qmake
make -j 12
echo maki | sudo -S sudo make install
cd /usr/local
zip -r ~/Desktop/qt5.13.2_mac.zip Qt-5.13.2/*

View File

@ -1,23 +0,0 @@
#!/bin/bash
export PATH=$PATH:/usr/local/Qt-5.13.2/bin
cd qtbase
./configure $OPTIONS QMAKE_APPLE_DEVICE_ARCHS=arm64 -opensource -confirm-license -nomake examples -nomake tests -no-openssl -securetransport
make -j 8
echo maki | sudo -S sudo make install
cd ../qttools
qmake
make -j 8
echo maki | sudo -S sudo make install
cd ../qtmacextras
qmake
make -j 8
echo maki | sudo -S sudo make install
cd /usr/local
zip -r ~/Desktop/qt5.13.2_mac_arm.zip Qt-5.13.2/*

View File

@ -1,17 +0,0 @@
#!/bin/bash
export PATH=$PATH:/usr/local/Qt-5.13.2/bin
cd qtbase
./configure -developer-build -opensource -confirm-license -nomake examples -nomake tests -no-openssl -securetransport
make -j 12
cd ../qttools
qmake
make -j 12
cd ../qtmacextras
qmake
make -j 12

View File

@ -1,86 +0,0 @@
use strict;
die "Cannot proceed without the 'bin' folder'" if (!-e "bin");
my $arch = $ARGV[0];
my $openssl_v_major = "1.1.1"; # The 1.1.1 series is Long Term Support (LTS) release, supported until 11th September 2023
my $openssl_v_minor = "a";
my $openssl_version = "$openssl_v_major$openssl_v_minor";
my $openssl_dir = "openssl-$openssl_version";
my $openssl_download = "https://www.openssl.org/source/openssl-$openssl_version.tar.gz";
my $openssl_arch = $arch eq "amd64" ? "WIN64A" : "WIN32";
$arch = "x86" if ($arch eq ''); # specify x86 is nothing is specified
die "Please specify architecture (x86 or amd64)" if ($arch ne "x86" && $arch ne "amd64"); # die if user specified anything except x86 or amd64
# will create a batch file
my $batfile = 'compile_win.bat';
open BAT, '>', $batfile;
printLineToBat ("SET PATH=%PATH%;%cd%\\bin"); # add bin folder to the path for 7z and wget
printLineToBat ("CALL \"C:\\Program Files (x86)\\Microsoft Visual Studio\\2017\\Community\\VC\\Auxiliary\\Build\\vcvarsall.bat\" $arch");
printLineToBat ("SET _ROOT=%cd%");
printLineToBat ("SET PATH=%_ROOT%\\qtbase\\bin;%_ROOT%\\gnuwin32\\bin;%PATH%"); # http://doc.qt.io/qt-5/windows-building.html
printLineToBat ("cd qtbase");
printLineToBat ("if \"%~1\"==\"step2\" goto step2");
# step1: compile openssl and do configure. For some reason, can't continue script execution after configure, have to make step2
printLineToBat ("IF EXIST $openssl_dir\\build GOTO OPENSSL_ALREAD_COMPILED");
printLineToBat ("wget --no-check-certificate $openssl_download");
printLineToBat ("7z x openssl-$openssl_version.tar.gz");
printLineToBat ("7z x openssl-$openssl_version.tar");
printLineToBat ("rm openssl-$openssl_version.tar.gz");
printLineToBat ("rm openssl-$openssl_version.tar");
printLineToBat ("cd $openssl_dir");
printLineToBat ("perl Configure VC-$openssl_arch no-asm no-shared no-tests --prefix=%cd%\\build --openssldir=%cd%\\build");
printLineToBat ("nmake");
printLineToBat ("nmake install");
# do little clean up
printLineToBat ("rm test\\*.exe");
printLineToBat ("rm test\\*.pdb");
printLineToBat ("rm test\\*.obj");
printLineToBat (":OPENSSL_ALREAD_COMPILED");
# go back to qtbase
printLineToBat ("cd ..");
# -developer-build creates an in-source build for developer usage.
# openssl: see https://bugreports.qt.io/browse/QTBUG-65501
printLineToBat ("configure -opensource -developer-build -confirm-license -opengl desktop -mp -nomake tests -nomake examples -I \"%cd%\\$openssl_dir\\build\\include\" -openssl-linked OPENSSL_LIBS=\"%cd%\\$openssl_dir\\build\\lib\\libssl.lib %cd%\\$openssl_dir\\build\\lib\\libcrypto.lib -lcrypt32 -lws2_32 -lAdvapi32 -luser32\"");
printLineToBat ("goto :EOF");
# step 2:
printLineToBat (":step2");
printLineToBat ("nmake");
printLineToBat ("cd ..\\qttools");
printLineToBat ("..\\qtbase\\bin\\qmake");
printLineToBat ("nmake");
printLineToBat ("cd ..\\qtbase");
printLineToBat ("cd .."); # go up to qt dir
# openssl clean up
printLineToBat ("cd qtbase");
printLineToBat ("cd $openssl_dir");
printLineToBat ("del /s /f /q out32");
printLineToBat ("del /s /f /q out32.dbg");
printLineToBat ("cd ..");
printLineToBat ("cd ..");
# the rest
printLineToBat ("del *.obj /s /f");
printLineToBat ("del *.ilk /s /f");
printLineToBat ("del *.pch /s /f");
printLineToBat ("del Makefile* /s /f");
close BAT;
system ($batfile);
system ("$batfile step2");
system ("pause");
sub printLineToBat
{
print BAT "$_[0]\n";
}

View File

@ -1,119 +0,0 @@
#
# This file is used as a basis for the following compilers:
#
# - Microsoft C/C++ Optimizing Compiler (all desktop versions)
# - Intel C++ Compiler on Windows
# - Clang-cl
#
# Baseline:
#
# - Visual Studio 2005 (8.0), VC++ 14.0
#
# Version-specific settings go in msvc-version.conf (loaded by default_pre)
#
MAKEFILE_GENERATOR = MSVC.NET
QMAKE_PLATFORM = win32
QMAKE_COMPILER = msvc
CONFIG += flat debug_and_release debug_and_release_target precompile_header autogen_precompile_source embed_manifest_dll embed_manifest_exe
# MSVC 2017 15.8+ fixed std::aligned_storage but compilation fails without
# _ENABLE_EXTENDED_ALIGNED_STORAGE flag since the fix breaks binary compatibility.
DEFINES += UNICODE _UNICODE WIN32 _ENABLE_EXTENDED_ALIGNED_STORAGE
QMAKE_COMPILER_DEFINES += _WIN32
contains(QMAKE_TARGET.arch, x86_64) {
DEFINES += WIN64
QMAKE_COMPILER_DEFINES += _WIN64
}
QMAKE_CFLAGS_OPTIMIZE_DEBUG = -Od
QMAKE_CFLAGS_OPTIMIZE = -O2
QMAKE_CFLAGS_OPTIMIZE_SIZE = -O1
QMAKE_CC = cl
QMAKE_LEX = flex
QMAKE_LEXFLAGS =
QMAKE_YACC = bison -y
QMAKE_YACCFLAGS = -d
QMAKE_CFLAGS = -nologo -Zc:wchar_t
QMAKE_CFLAGS_WARN_ON = -W3
QMAKE_CFLAGS_WARN_OFF = -W0
QMAKE_CFLAGS_RELEASE = $$QMAKE_CFLAGS_OPTIMIZE -MD -Zi
QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += $$QMAKE_CFLAGS_OPTIMIZE -Zi -MD
QMAKE_CFLAGS_DEBUG = -Zi -MDd
QMAKE_CFLAGS_YACC =
QMAKE_CFLAGS_LTCG = -GL
contains(QMAKE_TARGET.arch, x86_64) {
# SSE2 is mandatory on 64-bit mode, so skip the option. It triggers:
# cl : Command line warning D9002 : ignoring unknown option '-arch:SSE2'
QMAKE_CFLAGS_SSE2 =
} else {
QMAKE_CFLAGS_SSE2 = -arch:SSE2
}
QMAKE_CFLAGS_SSE3 = $$QMAKE_CFLAGS_SSE2
QMAKE_CFLAGS_SSSE3 = $$QMAKE_CFLAGS_SSE2
QMAKE_CFLAGS_SSE4_1 = $$QMAKE_CFLAGS_SSE2
QMAKE_CFLAGS_SSE4_2 = $$QMAKE_CFLAGS_SSE2
QMAKE_CFLAGS_AESNI = $$QMAKE_CFLAGS_SSE2
QMAKE_CFLAGS_SHANI = $$QMAKE_CFLAGS_SSE2
QMAKE_CXX = $$QMAKE_CC
QMAKE_CXXFLAGS = $$QMAKE_CFLAGS
QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON -w34100 -w34189 -w44996
QMAKE_CXXFLAGS_WARN_OFF = $$QMAKE_CFLAGS_WARN_OFF
QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE
QMAKE_CXXFLAGS_RELEASE_WITH_DEBUGINFO += $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO
QMAKE_CXXFLAGS_DEBUG = $$QMAKE_CFLAGS_DEBUG
QMAKE_CXXFLAGS_YACC = $$QMAKE_CFLAGS_YACC
QMAKE_CXXFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG
QMAKE_CXXFLAGS_STL_ON = -EHsc
QMAKE_CXXFLAGS_STL_OFF =
QMAKE_CXXFLAGS_RTTI_ON = -GR
QMAKE_CXXFLAGS_RTTI_OFF =
QMAKE_CXXFLAGS_EXCEPTIONS_ON = -EHsc
QMAKE_CXXFLAGS_EXCEPTIONS_OFF =
QMAKE_INCDIR =
QMAKE_RUN_CC = $(CC) -c $(CFLAGS) $(INCPATH) -Fo$obj $src
QMAKE_RUN_CC_IMP = $(CC) -c $(CFLAGS) $(INCPATH) -Fo$@ $<
QMAKE_RUN_CC_IMP_BATCH = $(CC) -c $(CFLAGS) $(INCPATH) -Fo$@ @<<
QMAKE_RUN_CXX = $(CXX) -c $(CXXFLAGS) $(INCPATH) -Fo$obj $src
QMAKE_RUN_CXX_IMP = $(CXX) -c $(CXXFLAGS) $(INCPATH) -Fo$@ $<
QMAKE_RUN_CXX_IMP_BATCH = $(CXX) -c $(CXXFLAGS) $(INCPATH) -Fo$@ @<<
QMAKE_LINK = link
QMAKE_LFLAGS = /NOLOGO /DYNAMICBASE /NXCOMPAT
QMAKE_LFLAGS_RELEASE = /INCREMENTAL:NO
QMAKE_LFLAGS_RELEASE_WITH_DEBUGINFO = /DEBUG /OPT:REF /INCREMENTAL:NO
QMAKE_LFLAGS_DEBUG = /DEBUG
QMAKE_LFLAGS_CONSOLE = /SUBSYSTEM:CONSOLE
QMAKE_LFLAGS_WINDOWS = /SUBSYSTEM:WINDOWS
QMAKE_LFLAGS_EXE = \"/MANIFESTDEPENDENCY:type=\'win32\' name=\'Microsoft.Windows.Common-Controls\' version=\'6.0.0.0\' publicKeyToken=\'6595b64144ccf1df\' language=\'*\' processorArchitecture=\'*\'\"
QMAKE_LFLAGS_DLL = /DLL
QMAKE_LFLAGS_LTCG = /LTCG
QMAKE_PREFIX_SHLIB =
QMAKE_EXTENSION_SHLIB = dll
QMAKE_PREFIX_STATICLIB =
QMAKE_EXTENSION_STATICLIB = lib
QMAKE_LIBS =
QMAKE_LIBS_GUI = gdi32.lib comdlg32.lib oleaut32.lib imm32.lib winmm.lib ws2_32.lib ole32.lib uuid.lib user32.lib advapi32.lib
QMAKE_LIBS_NETWORK = ws2_32.lib user32.lib gdi32.lib
QMAKE_LIBS_OPENGL = glu32.lib opengl32.lib gdi32.lib user32.lib
QMAKE_LIBS_OPENGL_ES2 = gdi32.lib user32.lib
QMAKE_LIBS_OPENGL_ES2_DEBUG = gdi32.lib user32.lib
QMAKE_LIBS_COMPAT = advapi32.lib shell32.lib comdlg32.lib user32.lib gdi32.lib ws2_32.lib
QMAKE_LIBS_QT_ENTRY = -lqtmain
QMAKE_IDL = midl
QMAKE_LIB = lib /NOLOGO
QMAKE_RC = rc /NOLOGO
VCPROJ_EXTENSION = .vcproj
VCSOLUTION_EXTENSION = .sln
VCPROJ_KEYWORD = Qt4VSv1.0
include(angle.conf)
include(windows-desktop.conf)
include(windows-vulkan.conf)

View File

@ -1,56 +0,0 @@
TARGET = qtpcre2
CONFIG += \
static \
hide_symbols \
exceptions_off rtti_off warn_off
MODULE_DEFINES += PCRE2_CODE_UNIT_WIDTH=16
win32: MODULE_DEFINES += PCRE2_STATIC
MODULE_INCLUDEPATH += $$PWD/src
load(qt_helper_lib)
DEFINES += HAVE_CONFIG_H
# platform/compiler specific definitions
uikit|qnx|winrt: DEFINES += PCRE2_DISABLE_JIT
win32:contains(QT_ARCH, "arm"): DEFINES += PCRE2_DISABLE_JIT
win32:contains(QT_ARCH, "arm64"): DEFINES += PCRE2_DISABLE_JIT
macos:contains(QT_ARCH, "arm64"): DEFINES += PCRE2_DISABLE_JIT
SOURCES += \
$$PWD/src/pcre2_auto_possess.c \
$$PWD/src/pcre2_chartables.c \
$$PWD/src/pcre2_compile.c \
$$PWD/src/pcre2_config.c \
$$PWD/src/pcre2_context.c \
$$PWD/src/pcre2_dfa_match.c \
$$PWD/src/pcre2_error.c \
$$PWD/src/pcre2_extuni.c \
$$PWD/src/pcre2_find_bracket.c \
$$PWD/src/pcre2_jit_compile.c \
$$PWD/src/pcre2_maketables.c \
$$PWD/src/pcre2_match.c \
$$PWD/src/pcre2_match_data.c \
$$PWD/src/pcre2_newline.c \
$$PWD/src/pcre2_ord2utf.c \
$$PWD/src/pcre2_pattern_info.c \
$$PWD/src/pcre2_script_run.c \
$$PWD/src/pcre2_serialize.c \
$$PWD/src/pcre2_string_utils.c \
$$PWD/src/pcre2_study.c \
$$PWD/src/pcre2_substitute.c \
$$PWD/src/pcre2_substring.c \
$$PWD/src/pcre2_tables.c \
$$PWD/src/pcre2_ucd.c \
$$PWD/src/pcre2_valid_utf.c \
$$PWD/src/pcre2_xclass.c
HEADERS += \
$$PWD/src/config.h \
$$PWD/src/pcre2.h \
$$PWD/src/pcre2_internal.h \
$$PWD/src/pcre2_intmodedep.h \
$$PWD/src/pcre2_ucp.h

File diff suppressed because it is too large Load Diff

View File

@ -1,569 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qoperatingsystemversion.h"
#if !defined(Q_OS_DARWIN) && !defined(Q_OS_WIN)
#include "qoperatingsystemversion_p.h"
#endif
#if defined(Q_OS_DARWIN)
#include <QtCore/private/qcore_mac_p.h>
#endif
#include <qversionnumber.h>
#include <qdebug.h>
#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
#include <private/qjni_p.h>
#endif
QT_BEGIN_NAMESPACE
/*!
\class QOperatingSystemVersion
\inmodule QtCore
\since 5.9
\brief The QOperatingSystemVersion class provides information about the
operating system version.
Unlike other version functions in QSysInfo, QOperatingSystemVersion provides
access to the full version number that \a developers typically use to vary
behavior or determine whether to enable APIs or features based on the
operating system version (as opposed to the kernel version number or
marketing version).
This class is also a complete replacement for QSysInfo::macVersion and
QSysInfo::windowsVersion, additionally providing access to the third (micro)
version number component.
Presently, Android, Apple Platforms (iOS, macOS, tvOS, and watchOS),
and Windows are supported.
The \a majorVersion(), \a minorVersion(), and \a microVersion() functions
return the parts of the operating system version number based on:
\table
\header
\li Platforms
\li Value
\row
\li Android
\li result of parsing
\l{https://developer.android.com/reference/android/os/Build.VERSION.html#RELEASE}{android.os.Build.VERSION.RELEASE}
using QVersionNumber, with a fallback to
\l{https://developer.android.com/reference/android/os/Build.VERSION.html#SDK_INT}{android.os.Build.VERSION.SDK_INT}
to determine the major and minor version component if the former
fails
\row
\li Apple Platforms
\li majorVersion, minorVersion, and patchVersion from
\l{https://developer.apple.com/reference/foundation/nsprocessinfo/1410906-operatingsystemversion?language=objc}{NSProcessInfo.operatingSystemVersion}
\row
\li Windows
\li dwMajorVersion, dwMinorVersion, and dwBuildNumber from
\l{https://msdn.microsoft.com/en-us/library/mt723418.aspx}{RtlGetVersion} -
note that this function ALWAYS return the version number of the
underlying operating system, as opposed to the shim underneath
GetVersionEx that hides the real version number if the
application is not manifested for that version of the OS
\endtable
Because QOperatingSystemVersion stores both a version number and an OS type, the OS type
can be taken into account when performing comparisons. For example, on a macOS system running
macOS Sierra (v10.12), the following expression will return \c false even though the
major version number component of the object on the left hand side of the expression (10) is
greater than that of the object on the right (9):
\snippet code/src_corelib_global_qoperatingsystemversion.cpp 0
This allows expressions for multiple operating systems to be joined with a logical OR operator
and still work as expected. For example:
\snippet code/src_corelib_global_qoperatingsystemversion.cpp 1
A more naive comparison algorithm might incorrectly return true on all versions of macOS,
including Mac OS 9. This behavior is achieved by overloading the comparison operators to return
\c false whenever the OS types of the QOperatingSystemVersion instances being compared do not
match. Be aware that due to this it can be the case \c x >= y and \c x < y are BOTH \c false
for the same instances of \c x and \c y.
*/
/*!
\enum QOperatingSystemVersion::OSType
This enum provides symbolic names for the various operating
system families supported by QOperatingSystemVersion.
\value Android The Google Android operating system.
\value IOS The Apple iOS operating system.
\value MacOS The Apple macOS operating system.
\value TvOS The Apple tvOS operating system.
\value WatchOS The Apple watchOS operating system.
\value Windows The Microsoft Windows operating system.
\value Unknown An unknown or unsupported operating system.
*/
/*!
\fn QOperatingSystemVersion::QOperatingSystemVersion(OSType osType, int vmajor, int vminor = -1, int vmicro = -1)
Constructs a QOperatingSystemVersion consisting of the OS type \a osType, and
major, minor, and micro version numbers \a vmajor, \a vminor and \a vmicro, respectively.
*/
/*!
\fn QOperatingSystemVersion QOperatingSystemVersion::current()
Returns a QOperatingSystemVersion indicating the current OS and its version number.
\sa currentType()
*/
#if !defined(Q_OS_DARWIN) && !defined(Q_OS_WIN)
QOperatingSystemVersion QOperatingSystemVersion::current()
{
QOperatingSystemVersion version;
version.m_os = currentType();
#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED)
#ifndef QT_BOOTSTRAPPED
const QVersionNumber v = QVersionNumber::fromString(QJNIObjectPrivate::getStaticObjectField(
"android/os/Build$VERSION", "RELEASE", "Ljava/lang/String;").toString());
if (!v.isNull()) {
version.m_major = v.majorVersion();
version.m_minor = v.minorVersion();
version.m_micro = v.microVersion();
return version;
}
#endif
version.m_major = -1;
version.m_minor = -1;
static const struct {
uint major : 4;
uint minor : 4;
} versions[] = {
{ 1, 0 }, // API level 1
{ 1, 1 }, // API level 2
{ 1, 5 }, // API level 3
{ 1, 6 }, // API level 4
{ 2, 0 }, // API level 5
{ 2, 0 }, // API level 6
{ 2, 1 }, // API level 7
{ 2, 2 }, // API level 8
{ 2, 3 }, // API level 9
{ 2, 3 }, // API level 10
{ 3, 0 }, // API level 11
{ 3, 1 }, // API level 12
{ 3, 2 }, // API level 13
{ 4, 0 }, // API level 14
{ 4, 0 }, // API level 15
{ 4, 1 }, // API level 16
{ 4, 2 }, // API level 17
{ 4, 3 }, // API level 18
{ 4, 4 }, // API level 19
{ 4, 4 }, // API level 20
{ 5, 0 }, // API level 21
{ 5, 1 }, // API level 22
{ 6, 0 }, // API level 23
{ 7, 0 }, // API level 24
{ 7, 1 }, // API level 25
{ 8, 0 }, // API level 26
};
// This will give us at least the first 2 version components
const size_t versionIdx = size_t(QJNIObjectPrivate::getStaticField<jint>(
"android/os/Build$VERSION", "SDK_INT")) - 1;
if (versionIdx < sizeof(versions) / sizeof(versions[0])) {
version.m_major = versions[versionIdx].major;
version.m_minor = versions[versionIdx].minor;
}
// API level 6 was exactly version 2.0.1
version.m_micro = versionIdx == 5 ? 1 : -1;
#else
version.m_major = -1;
version.m_minor = -1;
version.m_micro = -1;
#endif
return version;
}
#endif
static inline int compareVersionComponents(int lhs, int rhs)
{
return lhs >= 0 && rhs >= 0 ? lhs - rhs : 0;
}
int QOperatingSystemVersion::compare(const QOperatingSystemVersion &v1,
const QOperatingSystemVersion &v2)
{
if (v1.m_major == v2.m_major) {
if (v1.m_minor == v2.m_minor) {
return compareVersionComponents(v1.m_micro, v2.m_micro);
}
return compareVersionComponents(v1.m_minor, v2.m_minor);
}
return compareVersionComponents(v1.m_major, v2.m_major);
}
/*!
\fn int QOperatingSystemVersion::majorVersion() const
Returns the major version number, that is, the first segment of the
operating system's version number.
See the main class documentation for what the major version number is on a given
operating system.
-1 indicates an unknown or absent version number component.
\sa minorVersion(), microVersion()
*/
/*!
\fn int QOperatingSystemVersion::minorVersion() const
Returns the minor version number, that is, the second segment of the
operating system's version number.
See the main class documentation for what the minor version number is on a given
operating system.
-1 indicates an unknown or absent version number component.
\sa majorVersion(), microVersion()
*/
/*!
\fn int QOperatingSystemVersion::microVersion() const
Returns the micro version number, that is, the third segment of the
operating system's version number.
See the main class documentation for what the micro version number is on a given
operating system.
-1 indicates an unknown or absent version number component.
\sa majorVersion(), minorVersion()
*/
/*!
\fn int QOperatingSystemVersion::segmentCount() const
Returns the number of integers stored in the version number.
*/
/*!
\fn QOperatingSystemVersion::OSType QOperatingSystemVersion::type() const
Returns the OS type identified by the QOperatingSystemVersion.
\sa name()
*/
/*!
\fn QOperatingSystemVersion::OSType QOperatingSystemVersion::currentType()
Returns the current OS type without constructing a QOperatingSystemVersion instance.
\sa current()
*/
/*!
\fn QString QOperatingSystemVersion::name() const
Returns a string representation of the OS type identified by the QOperatingSystemVersion.
\sa type()
*/
QString QOperatingSystemVersion::name() const
{
switch (type()) {
case QOperatingSystemVersion::Windows:
return QStringLiteral("Windows");
case QOperatingSystemVersion::MacOS: {
if (majorVersion() < 10)
return QStringLiteral("Mac OS");
if (majorVersion() == 10 && minorVersion() < 8)
return QStringLiteral("Mac OS X");
if (majorVersion() == 10 && minorVersion() < 12)
return QStringLiteral("OS X");
return QStringLiteral("macOS");
}
case QOperatingSystemVersion::IOS: {
if (majorVersion() < 4)
return QStringLiteral("iPhone OS");
return QStringLiteral("iOS");
}
case QOperatingSystemVersion::TvOS:
return QStringLiteral("tvOS");
case QOperatingSystemVersion::WatchOS:
return QStringLiteral("watchOS");
case QOperatingSystemVersion::Android:
return QStringLiteral("Android");
case QOperatingSystemVersion::Unknown:
default:
return QString();
}
}
#ifdef Q_COMPILER_INITIALIZER_LISTS
/*!
\fn bool QOperatingSystemVersion::isAnyOfType(std::initializer_list<OSType> types) const
Returns whether the OS type identified by the QOperatingSystemVersion
matches any of the OS types in \a types.
*/
bool QOperatingSystemVersion::isAnyOfType(std::initializer_list<OSType> types) const
{
for (const auto &t : qAsConst(types)) {
if (type() == t)
return true;
}
return false;
}
#endif
/*!
\variable QOperatingSystemVersion::Windows7
\brief a version corresponding to Windows 7 (version 6.1).
\since 5.9
*/
const QOperatingSystemVersion QOperatingSystemVersion::Windows7 =
QOperatingSystemVersion(QOperatingSystemVersion::Windows, 6, 1);
/*!
\variable QOperatingSystemVersion::Windows8
\brief a version corresponding to Windows 8 (version 6.2).
\since 5.9
*/
const QOperatingSystemVersion QOperatingSystemVersion::Windows8 =
QOperatingSystemVersion(QOperatingSystemVersion::Windows, 6, 2);
/*!
\variable QOperatingSystemVersion::Windows8_1
\brief a version corresponding to Windows 8.1 (version 6.3).
\since 5.9
*/
const QOperatingSystemVersion QOperatingSystemVersion::Windows8_1 =
QOperatingSystemVersion(QOperatingSystemVersion::Windows, 6, 3);
/*!
\variable QOperatingSystemVersion::Windows10
\brief a version corresponding to Windows 10 (version 10.0).
\since 5.9
*/
const QOperatingSystemVersion QOperatingSystemVersion::Windows10 =
QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10);
/*!
\variable QOperatingSystemVersion::OSXMavericks
\brief a version corresponding to OS X Mavericks (version 10.9).
\since 5.9
*/
const QOperatingSystemVersion QOperatingSystemVersion::OSXMavericks =
QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 9);
/*!
\variable QOperatingSystemVersion::OSXYosemite
\brief a version corresponding to OS X Yosemite (version 10.10).
\since 5.9
*/
const QOperatingSystemVersion QOperatingSystemVersion::OSXYosemite =
QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 10);
/*!
\variable QOperatingSystemVersion::OSXElCapitan
\brief a version corresponding to OS X El Capitan (version 10.11).
\since 5.9
*/
const QOperatingSystemVersion QOperatingSystemVersion::OSXElCapitan =
QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 11);
/*!
\variable QOperatingSystemVersion::MacOSSierra
\brief a version corresponding to macOS Sierra (version 10.12).
\since 5.9
*/
const QOperatingSystemVersion QOperatingSystemVersion::MacOSSierra =
QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 12);
/*!
\variable QOperatingSystemVersion::MacOSHighSierra
\brief a version corresponding to macOS High Sierra (version 10.13).
\since 5.9.1
*/
const QOperatingSystemVersion QOperatingSystemVersion::MacOSHighSierra =
QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 13);
/*!
\variable QOperatingSystemVersion::MacOSMojave
\brief a version corresponding to macOS Mojave (version 10.14).
\since 5.11.2
*/
const QOperatingSystemVersion QOperatingSystemVersion::MacOSMojave =
QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 14);
/*!
\variable QOperatingSystemVersion::MacOSCatalina
\brief a version corresponding to macOS Catalina (version 10.15).
\since 5.12.5
*/
const QOperatingSystemVersion QOperatingSystemVersion::MacOSCatalina =
QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 15);
/*!
\variable QOperatingSystemVersion::MacOSBigSur
\brief a version corresponding to macOS Big Sur
The actual version number depends on whether the application was built
using the Xcode 12 SDK. If it was, the version number corresponds
to macOS 11.0. If not it will correspond to macOS 10.16.
By comparing QOperatingSystemVersion::current() to this constant
you will always end up comparing to the right version number.
\since 6.0
*/
const QOperatingSystemVersion QOperatingSystemVersion::MacOSBigSur = [] {
#if defined(Q_OS_DARWIN)
if (QMacVersion::buildSDK(QMacVersion::ApplicationBinary) >= QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 16))
return QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 11, 0);
else
#endif
return QOperatingSystemVersion(QOperatingSystemVersion::MacOS, 10, 16);
}();
/*!
\variable QOperatingSystemVersion::AndroidJellyBean
\brief a version corresponding to Android Jelly Bean (version 4.1, API level 16).
\since 5.9
*/
const QOperatingSystemVersion QOperatingSystemVersion::AndroidJellyBean =
QOperatingSystemVersion(QOperatingSystemVersion::Android, 4, 1);
/*!
\variable QOperatingSystemVersion::AndroidJellyBean_MR1
\brief a version corresponding to Android Jelly Bean, maintenance release 1
(version 4.2, API level 17).
\since 5.9
*/
const QOperatingSystemVersion QOperatingSystemVersion::AndroidJellyBean_MR1 =
QOperatingSystemVersion(QOperatingSystemVersion::Android, 4, 2);
/*!
\variable QOperatingSystemVersion::AndroidJellyBean_MR2
\brief a version corresponding to Android Jelly Bean, maintenance release 2
(version 4.3, API level 18).
\since 5.9
*/
const QOperatingSystemVersion QOperatingSystemVersion::AndroidJellyBean_MR2 =
QOperatingSystemVersion(QOperatingSystemVersion::Android, 4, 3);
/*!
\variable QOperatingSystemVersion::AndroidKitKat
\brief a version corresponding to Android KitKat (versions 4.4 & 4.4W, API levels 19 & 20).
\since 5.9
*/
const QOperatingSystemVersion QOperatingSystemVersion::AndroidKitKat =
QOperatingSystemVersion(QOperatingSystemVersion::Android, 4, 4);
/*!
\variable QOperatingSystemVersion::AndroidLollipop
\brief a version corresponding to Android Lollipop (version 5.0, API level 21).
\since 5.9
*/
const QOperatingSystemVersion QOperatingSystemVersion::AndroidLollipop =
QOperatingSystemVersion(QOperatingSystemVersion::Android, 5, 0);
/*!
\variable QOperatingSystemVersion::AndroidLollipop_MR1
\brief a version corresponding to Android Lollipop, maintenance release 1
(version 5.1, API level 22).
\since 5.9
*/
const QOperatingSystemVersion QOperatingSystemVersion::AndroidLollipop_MR1 =
QOperatingSystemVersion(QOperatingSystemVersion::Android, 5, 1);
/*!
\variable QOperatingSystemVersion::AndroidMarshmallow
\brief a version corresponding to Android Marshmallow (version 6.0, API level 23).
\since 5.9
*/
const QOperatingSystemVersion QOperatingSystemVersion::AndroidMarshmallow =
QOperatingSystemVersion(QOperatingSystemVersion::Android, 6, 0);
/*!
\variable QOperatingSystemVersion::AndroidNougat
\brief a version corresponding to Android Nougat (version 7.0, API level 24).
\since 5.9
*/
const QOperatingSystemVersion QOperatingSystemVersion::AndroidNougat =
QOperatingSystemVersion(QOperatingSystemVersion::Android, 7, 0);
/*!
\variable QOperatingSystemVersion::AndroidNougat_MR1
\brief a version corresponding to Android Nougat, maintenance release 1
(version 7.0, API level 25).
\since 5.9
*/
const QOperatingSystemVersion QOperatingSystemVersion::AndroidNougat_MR1 =
QOperatingSystemVersion(QOperatingSystemVersion::Android, 7, 1);
/*!
\variable QOperatingSystemVersion::AndroidOreo
\brief a version corresponding to Android Oreo (version 8.0, API level 26).
\since 5.9.2
*/
const QOperatingSystemVersion QOperatingSystemVersion::AndroidOreo =
QOperatingSystemVersion(QOperatingSystemVersion::Android, 8, 0);
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug debug, const QOperatingSystemVersion &ov)
{
QDebugStateSaver saver(debug);
debug.nospace();
debug << "QOperatingSystemVersion(" << ov.name()
<< ", " << ov.majorVersion() << '.' << ov.minorVersion()
<< '.' << ov.microVersion() << ')';
return debug;
}
#endif // !QT_NO_DEBUG_STREAM
QT_END_NAMESPACE

View File

@ -1,160 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtCore/qglobal.h>
#ifndef QOPERATINGSYSTEMVERSION_H
#define QOPERATINGSYSTEMVERSION_H
QT_BEGIN_NAMESPACE
class QString;
class QVersionNumber;
class Q_CORE_EXPORT QOperatingSystemVersion
{
public:
enum OSType {
Unknown = 0,
Windows,
MacOS,
IOS,
TvOS,
WatchOS,
Android
};
static const QOperatingSystemVersion Windows7;
static const QOperatingSystemVersion Windows8;
static const QOperatingSystemVersion Windows8_1;
static const QOperatingSystemVersion Windows10;
static const QOperatingSystemVersion OSXMavericks;
static const QOperatingSystemVersion OSXYosemite;
static const QOperatingSystemVersion OSXElCapitan;
static const QOperatingSystemVersion MacOSSierra;
static const QOperatingSystemVersion MacOSHighSierra;
static const QOperatingSystemVersion MacOSMojave;
static const QOperatingSystemVersion MacOSCatalina;
static const QOperatingSystemVersion MacOSBigSur;
static const QOperatingSystemVersion AndroidJellyBean;
static const QOperatingSystemVersion AndroidJellyBean_MR1;
static const QOperatingSystemVersion AndroidJellyBean_MR2;
static const QOperatingSystemVersion AndroidKitKat;
static const QOperatingSystemVersion AndroidLollipop;
static const QOperatingSystemVersion AndroidLollipop_MR1;
static const QOperatingSystemVersion AndroidMarshmallow;
static const QOperatingSystemVersion AndroidNougat;
static const QOperatingSystemVersion AndroidNougat_MR1;
static const QOperatingSystemVersion AndroidOreo;
Q_DECL_CONSTEXPR QOperatingSystemVersion(OSType osType,
int vmajor, int vminor = -1, int vmicro = -1)
: m_os(osType),
m_major(qMax(-1, vmajor)),
m_minor(vmajor < 0 ? -1 : qMax(-1, vminor)),
m_micro(vmajor < 0 || vminor < 0 ? -1 : qMax(-1, vmicro))
{ }
static QOperatingSystemVersion current();
static Q_DECL_CONSTEXPR OSType currentType()
{
#if defined(Q_OS_WIN)
return Windows;
#elif defined(Q_OS_MACOS)
return MacOS;
#elif defined(Q_OS_IOS)
return IOS;
#elif defined(Q_OS_TVOS)
return TvOS;
#elif defined(Q_OS_WATCHOS)
return WatchOS;
#elif defined(Q_OS_ANDROID)
return Android;
#else
return Unknown;
#endif
}
Q_DECL_CONSTEXPR int majorVersion() const { return m_major; }
Q_DECL_CONSTEXPR int minorVersion() const { return m_minor; }
Q_DECL_CONSTEXPR int microVersion() const { return m_micro; }
Q_DECL_CONSTEXPR int segmentCount() const
{ return m_micro >= 0 ? 3 : m_minor >= 0 ? 2 : m_major >= 0 ? 1 : 0; }
#ifdef Q_COMPILER_INITIALIZER_LISTS
bool isAnyOfType(std::initializer_list<OSType> types) const;
#endif
Q_DECL_CONSTEXPR OSType type() const { return m_os; }
QString name() const;
friend bool operator>(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs)
{ return lhs.type() == rhs.type() && QOperatingSystemVersion::compare(lhs, rhs) > 0; }
friend bool operator>=(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs)
{ return lhs.type() == rhs.type() && QOperatingSystemVersion::compare(lhs, rhs) >= 0; }
friend bool operator<(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs)
{ return lhs.type() == rhs.type() && QOperatingSystemVersion::compare(lhs, rhs) < 0; }
friend bool operator<=(const QOperatingSystemVersion &lhs, const QOperatingSystemVersion &rhs)
{ return lhs.type() == rhs.type() && QOperatingSystemVersion::compare(lhs, rhs) <= 0; }
private:
QOperatingSystemVersion() = default;
OSType m_os;
int m_major;
int m_minor;
int m_micro;
static int compare(const QOperatingSystemVersion &v1, const QOperatingSystemVersion &v2);
};
Q_DECLARE_TYPEINFO(QOperatingSystemVersion, QT_VERSION < QT_VERSION_CHECK(6, 0, 0) ? Q_RELOCATABLE_TYPE : Q_PRIMITIVE_TYPE);
#ifndef QT_NO_DEBUG_STREAM
class QDebug;
Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QOperatingSystemVersion &ov);
#endif
QT_END_NAMESPACE
#endif // QOPERATINGSYSTEMVERSION_H

View File

@ -1,288 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QGLOBAL_H
# include <QtCore/qglobal.h>
#endif
#ifndef QSYSTEMDETECTION_H
#define QSYSTEMDETECTION_H
/*
The operating system, must be one of: (Q_OS_x)
DARWIN - Any Darwin system (macOS, iOS, watchOS, tvOS)
MACOS - macOS
IOS - iOS
WATCHOS - watchOS
TVOS - tvOS
WIN32 - Win32 (Windows 2000/XP/Vista/7 and Windows Server 2003/2008)
WINRT - WinRT (Windows Runtime)
CYGWIN - Cygwin
SOLARIS - Sun Solaris
HPUX - HP-UX
LINUX - Linux [has variants]
FREEBSD - FreeBSD [has variants]
NETBSD - NetBSD
OPENBSD - OpenBSD
INTERIX - Interix
AIX - AIX
HURD - GNU Hurd
QNX - QNX [has variants]
QNX6 - QNX RTP 6.1
LYNX - LynxOS
BSD4 - Any BSD 4.4 system
UNIX - Any UNIX BSD/SYSV system
ANDROID - Android platform
HAIKU - Haiku
The following operating systems have variants:
LINUX - both Q_OS_LINUX and Q_OS_ANDROID are defined when building for Android
- only Q_OS_LINUX is defined if building for other Linux systems
FREEBSD - Q_OS_FREEBSD is defined only when building for FreeBSD with a BSD userland
- Q_OS_FREEBSD_KERNEL is always defined on FreeBSD, even if the userland is from GNU
*/
#if defined(__APPLE__) && (defined(__GNUC__) || defined(__xlC__) || defined(__xlc__))
# include <TargetConditionals.h>
# if defined(TARGET_OS_MAC) && TARGET_OS_MAC
# define Q_OS_DARWIN
# define Q_OS_BSD4
# ifdef __LP64__
# define Q_OS_DARWIN64
# else
# define Q_OS_DARWIN32
# endif
# if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
# define QT_PLATFORM_UIKIT
# if defined(TARGET_OS_WATCH) && TARGET_OS_WATCH
# define Q_OS_WATCHOS
# elif defined(TARGET_OS_TV) && TARGET_OS_TV
# define Q_OS_TVOS
# else
# // TARGET_OS_IOS is only available in newer SDKs,
# // so assume any other iOS-based platform is iOS for now
# define Q_OS_IOS
# endif
# else
# // TARGET_OS_OSX is only available in newer SDKs,
# // so assume any non iOS-based platform is macOS for now
# define Q_OS_MACOS
# endif
# else
# error "Qt has not been ported to this Apple platform - see http://www.qt.io/developers"
# endif
#elif defined(__ANDROID__) || defined(ANDROID)
# define Q_OS_ANDROID
# define Q_OS_LINUX
#elif defined(__CYGWIN__)
# define Q_OS_CYGWIN
#elif !defined(SAG_COM) && (!defined(WINAPI_FAMILY) || WINAPI_FAMILY==WINAPI_FAMILY_DESKTOP_APP) && (defined(WIN64) || defined(_WIN64) || defined(__WIN64__))
# define Q_OS_WIN32
# define Q_OS_WIN64
#elif !defined(SAG_COM) && (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__))
# if defined(WINAPI_FAMILY)
# ifndef WINAPI_FAMILY_PC_APP
# define WINAPI_FAMILY_PC_APP WINAPI_FAMILY_APP
# endif
# if defined(WINAPI_FAMILY_PHONE_APP) && WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
# define Q_OS_WINRT
# elif WINAPI_FAMILY==WINAPI_FAMILY_PC_APP
# define Q_OS_WINRT
# else
# define Q_OS_WIN32
# endif
# else
# define Q_OS_WIN32
# endif
#elif defined(__sun) || defined(sun)
# define Q_OS_SOLARIS
#elif defined(hpux) || defined(__hpux)
# define Q_OS_HPUX
#elif defined(__native_client__)
# define Q_OS_NACL
#elif defined(__EMSCRIPTEN__)
# define Q_OS_WASM
#elif defined(__linux__) || defined(__linux)
# define Q_OS_LINUX
#elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
# ifndef __FreeBSD_kernel__
# define Q_OS_FREEBSD
# endif
# define Q_OS_FREEBSD_KERNEL
# define Q_OS_BSD4
#elif defined(__NetBSD__)
# define Q_OS_NETBSD
# define Q_OS_BSD4
#elif defined(__OpenBSD__)
# define Q_OS_OPENBSD
# define Q_OS_BSD4
#elif defined(__INTERIX)
# define Q_OS_INTERIX
# define Q_OS_BSD4
#elif defined(_AIX)
# define Q_OS_AIX
#elif defined(__Lynx__)
# define Q_OS_LYNX
#elif defined(__GNU__)
# define Q_OS_HURD
#elif defined(__QNXNTO__)
# define Q_OS_QNX
#elif defined(__INTEGRITY)
# define Q_OS_INTEGRITY
#elif defined(VXWORKS) /* there is no "real" VxWorks define - this has to be set in the mkspec! */
# define Q_OS_VXWORKS
#elif defined(__HAIKU__)
# define Q_OS_HAIKU
#elif defined(__MAKEDEPEND__)
#else
# error "Qt has not been ported to this OS - see http://www.qt-project.org/"
#endif
#if defined(Q_OS_WIN32) || defined(Q_OS_WIN64) || defined(Q_OS_WINRT)
# define Q_OS_WINDOWS
# define Q_OS_WIN
#endif
#if defined(Q_OS_WIN)
# undef Q_OS_UNIX
#elif !defined(Q_OS_UNIX)
# define Q_OS_UNIX
#endif
// Compatibility synonyms
#ifdef Q_OS_DARWIN
#define Q_OS_MAC
#endif
#ifdef Q_OS_DARWIN32
#define Q_OS_MAC32
#endif
#ifdef Q_OS_DARWIN64
#define Q_OS_MAC64
#endif
#ifdef Q_OS_MACOS
#define Q_OS_MACX
#define Q_OS_OSX
#endif
#ifdef Q_OS_DARWIN
# include <Availability.h>
# include <AvailabilityMacros.h>
#
# ifdef Q_OS_MACOS
# if !defined(__MAC_OS_X_VERSION_MIN_REQUIRED) || __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_6
# undef __MAC_OS_X_VERSION_MIN_REQUIRED
# define __MAC_OS_X_VERSION_MIN_REQUIRED __MAC_10_6
# endif
# if !defined(MAC_OS_X_VERSION_MIN_REQUIRED) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6
# undef MAC_OS_X_VERSION_MIN_REQUIRED
# define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_6
# endif
# endif
#
# // Numerical checks are preferred to named checks, but to be safe
# // we define the missing version names in case Qt uses them.
#
# if !defined(__MAC_10_11)
# define __MAC_10_11 101100
# endif
# if !defined(__MAC_10_12)
# define __MAC_10_12 101200
# endif
# if !defined(__MAC_10_13)
# define __MAC_10_13 101300
# endif
# if !defined(__MAC_10_14)
# define __MAC_10_14 101400
# endif
# if !defined(__MAC_10_15)
# define __MAC_10_15 101500
# endif
# if !defined(__MAC_10_16)
# define __MAC_10_16 101600
# endif
# if !defined(MAC_OS_X_VERSION_10_11)
# define MAC_OS_X_VERSION_10_11 __MAC_10_11
# endif
# if !defined(MAC_OS_X_VERSION_10_12)
# define MAC_OS_X_VERSION_10_12 __MAC_10_12
# endif
# if !defined(MAC_OS_X_VERSION_10_13)
# define MAC_OS_X_VERSION_10_13 __MAC_10_13
# endif
# if !defined(MAC_OS_X_VERSION_10_14)
# define MAC_OS_X_VERSION_10_14 __MAC_10_14
# endif
# if !defined(MAC_OS_X_VERSION_10_15)
# define MAC_OS_X_VERSION_10_15 __MAC_10_15
# endif
# if !defined(MAC_OS_X_VERSION_10_16)
# define MAC_OS_X_VERSION_10_16 __MAC_10_16
# endif
#
# if !defined(__IPHONE_10_0)
# define __IPHONE_10_0 100000
# endif
# if !defined(__IPHONE_10_1)
# define __IPHONE_10_1 100100
# endif
# if !defined(__IPHONE_10_2)
# define __IPHONE_10_2 100200
# endif
# if !defined(__IPHONE_10_3)
# define __IPHONE_10_3 100300
# endif
# if !defined(__IPHONE_11_0)
# define __IPHONE_11_0 110000
# endif
# if !defined(__IPHONE_12_0)
# define __IPHONE_12_0 120000
# endif
#endif
#ifdef __LSB_VERSION__
# if __LSB_VERSION__ < 40
# error "This version of the Linux Standard Base is unsupported"
# endif
#ifndef QT_LINUXBASE
# define QT_LINUXBASE
#endif
#endif
#endif // QSYSTEMDETECTION_H

View File

@ -1,289 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <private/qcore_mac_p.h>
#include <new>
#include "qhash.h"
#include "qpair.h"
#include "qmutex.h"
#include "qvarlengtharray.h"
#include <dlfcn.h>
#include <mach-o/dyld.h>
QT_BEGIN_NAMESPACE
QCFString::operator QString() const
{
if (string.isEmpty() && value)
const_cast<QCFString*>(this)->string = QString::fromCFString(value);
return string;
}
QCFString::operator CFStringRef() const
{
if (!value)
const_cast<QCFString*>(this)->value = string.toCFString();
return value;
}
// --------------------------------------------------------------------------
#if defined(QT_USE_APPLE_UNIFIED_LOGGING)
bool AppleUnifiedLogger::willMirrorToStderr()
{
// When running under Xcode or LLDB, one or more of these variables will
// be set, which triggers libsystem_trace.dyld to log messages to stderr
// as well, via_os_log_impl_mirror_to_stderr. Un-setting these variables
// is not an option, as that would silence normal NSLog or os_log calls,
// so instead we skip our own stderr output. See rdar://36919139.
static bool willMirror = qEnvironmentVariableIsSet("OS_ACTIVITY_DT_MODE")
|| qEnvironmentVariableIsSet("ACTIVITY_LOG_STDERR")
|| qEnvironmentVariableIsSet("CFLOG_FORCE_STDERR");
return willMirror;
}
QT_MAC_WEAK_IMPORT(_os_log_default);
bool AppleUnifiedLogger::messageHandler(QtMsgType msgType, const QMessageLogContext &context,
const QString &message, const QString &optionalSubsystem)
{
QString subsystem = optionalSubsystem;
if (subsystem.isNull()) {
static QString bundleIdentifier = []() {
if (CFBundleRef bundle = CFBundleGetMainBundle()) {
if (CFStringRef identifier = CFBundleGetIdentifier(bundle))
return QString::fromCFString(identifier);
}
return QString();
}();
subsystem = bundleIdentifier;
}
const bool isDefault = !context.category || !strcmp(context.category, "default");
os_log_t log = isDefault ? OS_LOG_DEFAULT :
cachedLog(subsystem, QString::fromLatin1(context.category));
os_log_type_t logType = logTypeForMessageType(msgType);
if (!os_log_type_enabled(log, logType))
return false;
// Logging best practices says we should not include symbolication
// information or source file line numbers in messages, as the system
// will automatically captures this information. In our case, what
// the system captures is the call to os_log_with_type below, which
// isn't really useful, but we still don't want to include the context's
// info, as that would clutter the logging output. See rdar://35958308.
// The format must be a string constant, so we can't pass on the
// message. This means we won't be able to take advantage of the
// unified logging's custom format specifiers such as %{BOOL}d.
// We use the 'public' format specifier to prevent the logging
// system from redacting our log message.
os_log_with_type(log, logType, "%{public}s", qPrintable(message));
return willMirrorToStderr();
}
os_log_type_t AppleUnifiedLogger::logTypeForMessageType(QtMsgType msgType)
{
switch (msgType) {
case QtDebugMsg: return OS_LOG_TYPE_DEBUG;
case QtInfoMsg: return OS_LOG_TYPE_INFO;
case QtWarningMsg: return OS_LOG_TYPE_DEFAULT;
case QtCriticalMsg: return OS_LOG_TYPE_ERROR;
case QtFatalMsg: return OS_LOG_TYPE_FAULT;
}
return OS_LOG_TYPE_DEFAULT;
}
os_log_t AppleUnifiedLogger::cachedLog(const QString &subsystem, const QString &category)
{
static QBasicMutex mutex;
QMutexLocker locker(&mutex);
static QHash<QPair<QString, QString>, os_log_t> logs;
const auto cacheKey = qMakePair(subsystem, category);
os_log_t log = logs.value(cacheKey);
if (!log) {
log = os_log_create(subsystem.toLatin1().constData(),
category.toLatin1().constData());
logs.insert(cacheKey, log);
// Technically we should release the os_log_t resource when done
// with it, but since we don't know when a category is disabled
// we keep all cached os_log_t instances until shutdown, where
// the OS will clean them up for us.
}
return log;
}
#endif // QT_USE_APPLE_UNIFIED_LOGGING
// --------------------------------------------------------------------------
QOperatingSystemVersion QMacVersion::buildSDK(VersionTarget target)
{
switch (target) {
case ApplicationBinary: return applicationVersion().second;
case QtLibraries: return libraryVersion().second;
}
Q_UNREACHABLE();
}
QOperatingSystemVersion QMacVersion::deploymentTarget(VersionTarget target)
{
switch (target) {
case ApplicationBinary: return applicationVersion().first;
case QtLibraries: return libraryVersion().first;
}
Q_UNREACHABLE();
}
QOperatingSystemVersion QMacVersion::currentRuntime()
{
return QOperatingSystemVersion::current();
}
// Mach-O platforms
enum Platform {
macOS = 1,
iOS = 2,
tvOS = 3,
watchOS = 4,
bridgeOS = 5,
macCatalyst = 6,
iOSSimulator = 7,
tvOSSimulator = 8,
watchOSSimulator = 9
};
QMacVersion::VersionTuple QMacVersion::versionsForImage(const mach_header *machHeader)
{
static auto osForLoadCommand = [](uint32_t cmd) {
switch (cmd) {
case LC_VERSION_MIN_MACOSX: return QOperatingSystemVersion::MacOS;
case LC_VERSION_MIN_IPHONEOS: return QOperatingSystemVersion::IOS;
case LC_VERSION_MIN_TVOS: return QOperatingSystemVersion::TvOS;
case LC_VERSION_MIN_WATCHOS: return QOperatingSystemVersion::WatchOS;
default: return QOperatingSystemVersion::Unknown;
}
};
static auto osForPlatform = [](uint32_t platform) {
switch (platform) {
case Platform::macOS:
return QOperatingSystemVersion::MacOS;
case Platform::iOS:
case Platform::iOSSimulator:
return QOperatingSystemVersion::IOS;
case Platform::tvOS:
case Platform::tvOSSimulator:
return QOperatingSystemVersion::TvOS;
case Platform::watchOS:
case Platform::watchOSSimulator:
return QOperatingSystemVersion::WatchOS;
default:
return QOperatingSystemVersion::Unknown;
}
};
static auto makeVersionTuple = [](uint32_t dt, uint32_t sdk, QOperatingSystemVersion::OSType osType) {
return qMakePair(
QOperatingSystemVersion(osType, dt >> 16 & 0xffff, dt >> 8 & 0xff, dt & 0xff),
QOperatingSystemVersion(osType, sdk >> 16 & 0xffff, sdk >> 8 & 0xff, sdk & 0xff)
);
};
const bool is64Bit = machHeader->magic == MH_MAGIC_64 || machHeader->magic == MH_CIGAM_64;
auto commandCursor = uintptr_t(machHeader) + (is64Bit ? sizeof(mach_header_64) : sizeof(mach_header));
for (uint32_t i = 0; i < machHeader->ncmds; ++i) {
load_command *loadCommand = reinterpret_cast<load_command *>(commandCursor);
if (loadCommand->cmd == LC_VERSION_MIN_MACOSX || loadCommand->cmd == LC_VERSION_MIN_IPHONEOS
|| loadCommand->cmd == LC_VERSION_MIN_TVOS || loadCommand->cmd == LC_VERSION_MIN_WATCHOS) {
auto versionCommand = reinterpret_cast<version_min_command *>(loadCommand);
return makeVersionTuple(versionCommand->version, versionCommand->sdk, osForLoadCommand(loadCommand->cmd));
#if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_13, __IPHONE_11_0, __TVOS_11_0, __WATCHOS_4_0)
} else if (loadCommand->cmd == LC_BUILD_VERSION) {
auto versionCommand = reinterpret_cast<build_version_command *>(loadCommand);
return makeVersionTuple(versionCommand->minos, versionCommand->sdk, osForPlatform(versionCommand->platform));
#endif
}
commandCursor += loadCommand->cmdsize;
}
Q_ASSERT_X(false, "QMacVersion", "Could not find any version load command");
Q_UNREACHABLE();
}
QMacVersion::VersionTuple QMacVersion::applicationVersion()
{
static VersionTuple version = []() {
const mach_header *executableHeader = nullptr;
for (uint32_t i = 0; i < _dyld_image_count(); ++i) {
auto header = _dyld_get_image_header(i);
if (header->filetype == MH_EXECUTE) {
executableHeader = header;
break;
}
}
Q_ASSERT_X(executableHeader, "QMacVersion", "Failed to resolve Mach-O header of executable");
return versionsForImage(executableHeader);
}();
return version;
}
QMacVersion::VersionTuple QMacVersion::libraryVersion()
{
static VersionTuple version = []() {
Dl_info qtCoreImage;
dladdr((const void *)&QMacVersion::libraryVersion, &qtCoreImage);
Q_ASSERT_X(qtCoreImage.dli_fbase, "QMacVersion", "Failed to resolve Mach-O header of QtCore");
return versionsForImage(static_cast<mach_header*>(qtCoreImage.dli_fbase));
}();
return version;
}
// -------------------------------------------------------------------------
QT_END_NAMESPACE

View File

@ -1,428 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QCORE_MAC_P_H
#define QCORE_MAC_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of other Qt classes. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "private/qglobal_p.h"
#include <QtCore/qoperatingsystemversion.h>
struct mach_header;
#ifndef __IMAGECAPTURE__
# define __IMAGECAPTURE__
#endif
// --------------------------------------------------------------------------
#if defined(QT_BOOTSTRAPPED)
#include <ApplicationServices/ApplicationServices.h>
#else
#include <CoreFoundation/CoreFoundation.h>
#endif
#ifdef __OBJC__
#include <Foundation/Foundation.h>
#include <functional>
#endif
#include "qstring.h"
#include "qscopedpointer.h"
#include "qpair.h"
#if defined( __OBJC__) && defined(QT_NAMESPACE)
#define QT_NAMESPACE_ALIAS_OBJC_CLASS(__KLASS__) @compatibility_alias __KLASS__ QT_MANGLE_NAMESPACE(__KLASS__)
#else
#define QT_NAMESPACE_ALIAS_OBJC_CLASS(__KLASS__)
#endif
#define QT_MAC_WEAK_IMPORT(symbol) extern "C" decltype(symbol) symbol __attribute__((weak_import));
QT_BEGIN_NAMESPACE
template <typename T, typename U, U (*RetainFunction)(U), void (*ReleaseFunction)(U)>
class QAppleRefCounted
{
public:
QAppleRefCounted(const T &t = T()) : value(t) {}
QAppleRefCounted(QAppleRefCounted &&other) : value(other.value) { other.value = T(); }
QAppleRefCounted(const QAppleRefCounted &other) : value(other.value) { if (value) RetainFunction(value); }
~QAppleRefCounted() { if (value) ReleaseFunction(value); }
operator T() const { return value; }
void swap(QAppleRefCounted &other) Q_DECL_NOEXCEPT_EXPR(noexcept(qSwap(value, other.value)))
{ qSwap(value, other.value); }
QAppleRefCounted &operator=(const QAppleRefCounted &other)
{ QAppleRefCounted copy(other); swap(copy); return *this; }
QAppleRefCounted &operator=(QAppleRefCounted &&other)
{ QAppleRefCounted moved(std::move(other)); swap(moved); return *this; }
T *operator&() { return &value; }
protected:
T value;
};
#ifdef Q_OS_MACOS
class QMacRootLevelAutoReleasePool
{
public:
QMacRootLevelAutoReleasePool();
~QMacRootLevelAutoReleasePool();
private:
QScopedPointer<QMacAutoReleasePool> pool;
};
#endif
/*
Helper class that automates refernce counting for CFtypes.
After constructing the QCFType object, it can be copied like a
value-based type.
Note that you must own the object you are wrapping.
This is typically the case if you get the object from a Core
Foundation function with the word "Create" or "Copy" in it. If
you got the object from a "Get" function, either retain it or use
constructFromGet(). One exception to this rule is the
HIThemeGet*Shape functions, which in reality are "Copy" functions.
*/
template <typename T>
class QCFType : public QAppleRefCounted<T, CFTypeRef, CFRetain, CFRelease>
{
public:
using QAppleRefCounted<T, CFTypeRef, CFRetain, CFRelease>::QAppleRefCounted;
template <typename X> X as() const { return reinterpret_cast<X>(this->value); }
static QCFType constructFromGet(const T &t)
{
if (t)
CFRetain(t);
return QCFType<T>(t);
}
};
class Q_CORE_EXPORT QCFString : public QCFType<CFStringRef>
{
public:
inline QCFString(const QString &str) : QCFType<CFStringRef>(0), string(str) {}
inline QCFString(const CFStringRef cfstr = 0) : QCFType<CFStringRef>(cfstr) {}
inline QCFString(const QCFType<CFStringRef> &other) : QCFType<CFStringRef>(other) {}
operator QString() const;
operator CFStringRef() const;
private:
QString string;
};
#ifdef Q_OS_MACOS
Q_CORE_EXPORT QChar qt_mac_qtKey2CocoaKey(Qt::Key key);
Q_CORE_EXPORT Qt::Key qt_mac_cocoaKey2QtKey(QChar keyCode);
Q_CORE_EXPORT bool qt_mac_applicationIsInDarkMode();
#endif
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug debug, const QMacAutoReleasePool *pool);
#endif
Q_CORE_EXPORT bool qt_apple_isApplicationExtension();
#if defined(Q_OS_MACOS) && !defined(QT_BOOTSTRAPPED)
Q_CORE_EXPORT bool qt_apple_isSandboxed();
# ifdef __OBJC__
QT_END_NAMESPACE
@interface NSObject (QtSandboxHelpers)
- (id)qt_valueForPrivateKey:(NSString *)key;
@end
QT_BEGIN_NAMESPACE
# endif
#endif
#if !defined(QT_BOOTSTRAPPED) && !defined(Q_OS_WATCHOS)
QT_END_NAMESPACE
# if defined(Q_OS_MACOS)
Q_FORWARD_DECLARE_OBJC_CLASS(NSApplication);
using AppleApplication = NSApplication;
# else
Q_FORWARD_DECLARE_OBJC_CLASS(UIApplication);
using AppleApplication = UIApplication;
# endif
QT_BEGIN_NAMESPACE
Q_CORE_EXPORT AppleApplication *qt_apple_sharedApplication();
#endif
// --------------------------------------------------------------------------
#if !defined(QT_BOOTSTRAPPED)
#define QT_USE_APPLE_UNIFIED_LOGGING
QT_END_NAMESPACE
#include <os/log.h>
QT_BEGIN_NAMESPACE
class Q_CORE_EXPORT AppleUnifiedLogger
{
public:
static bool messageHandler(QtMsgType msgType, const QMessageLogContext &context, const QString &message,
const QString &subsystem = QString());
static bool willMirrorToStderr();
private:
static os_log_type_t logTypeForMessageType(QtMsgType msgType);
static os_log_t cachedLog(const QString &subsystem, const QString &category);
};
#endif
// --------------------------------------------------------------------------
#if !defined(QT_BOOTSTRAPPED)
QT_END_NAMESPACE
#include <os/activity.h>
QT_BEGIN_NAMESPACE
template <typename T> using QAppleOsType = QAppleRefCounted<T, void *, os_retain, os_release>;
class Q_CORE_EXPORT QAppleLogActivity
{
public:
QAppleLogActivity() : activity(nullptr) {}
QAppleLogActivity(os_activity_t activity) : activity(activity) {}
~QAppleLogActivity() { if (activity) leave(); }
QAppleLogActivity(const QAppleLogActivity &) = delete;
QAppleLogActivity& operator=(const QAppleLogActivity &) = delete;
QAppleLogActivity(QAppleLogActivity&& other)
: activity(other.activity), state(other.state) { other.activity = nullptr; }
QAppleLogActivity& operator=(QAppleLogActivity &&other)
{
if (this != &other) {
activity = other.activity;
state = other.state;
other.activity = nullptr;
}
return *this;
}
QAppleLogActivity&& enter()
{
if (activity)
os_activity_scope_enter(static_cast<os_activity_t>(*this), &state);
return std::move(*this);
}
void leave() {
if (activity)
os_activity_scope_leave(&state);
}
operator os_activity_t()
{
return reinterpret_cast<os_activity_t>(static_cast<void *>(activity));
}
private:
// Work around API_AVAILABLE not working for templates by using void*
QAppleOsType<void *> activity;
os_activity_scope_state_s state;
};
#define QT_APPLE_LOG_ACTIVITY_CREATE(condition, description, parent) []() { \
if (!(condition)) \
return QAppleLogActivity(); \
return QAppleLogActivity(os_activity_create(description, parent, OS_ACTIVITY_FLAG_DEFAULT)); \
}()
#define QT_VA_ARGS_CHOOSE(_1, _2, _3, _4, _5, _6, _7, _8, _9, N, ...) N
#define QT_VA_ARGS_COUNT(...) QT_VA_ARGS_CHOOSE(__VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1)
#define QT_OVERLOADED_MACRO(MACRO, ...) _QT_OVERLOADED_MACRO(MACRO, QT_VA_ARGS_COUNT(__VA_ARGS__))(__VA_ARGS__)
#define _QT_OVERLOADED_MACRO(MACRO, ARGC) _QT_OVERLOADED_MACRO_EXPAND(MACRO, ARGC)
#define _QT_OVERLOADED_MACRO_EXPAND(MACRO, ARGC) MACRO##ARGC
#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT3(condition, description, parent) QT_APPLE_LOG_ACTIVITY_CREATE(condition, description, parent)
#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT2(description, parent) QT_APPLE_LOG_ACTIVITY_WITH_PARENT3(true, description, parent)
#define QT_APPLE_LOG_ACTIVITY_WITH_PARENT(...) QT_OVERLOADED_MACRO(QT_APPLE_LOG_ACTIVITY_WITH_PARENT, __VA_ARGS__)
QT_MAC_WEAK_IMPORT(_os_activity_current);
#define QT_APPLE_LOG_ACTIVITY2(condition, description) QT_APPLE_LOG_ACTIVITY_CREATE(condition, description, OS_ACTIVITY_CURRENT)
#define QT_APPLE_LOG_ACTIVITY1(description) QT_APPLE_LOG_ACTIVITY2(true, description)
#define QT_APPLE_LOG_ACTIVITY(...) QT_OVERLOADED_MACRO(QT_APPLE_LOG_ACTIVITY, __VA_ARGS__)
#define QT_APPLE_SCOPED_LOG_ACTIVITY(...) QAppleLogActivity scopedLogActivity = QT_APPLE_LOG_ACTIVITY(__VA_ARGS__).enter();
#endif // !defined(QT_BOOTSTRAPPED)
// -------------------------------------------------------------------------
#if defined( __OBJC__)
class QMacNotificationObserver
{
public:
QMacNotificationObserver() {}
template<typename Functor>
QMacNotificationObserver(id object, NSNotificationName name, Functor callback) {
observer = [[NSNotificationCenter defaultCenter] addObserverForName:name
object:object queue:nil usingBlock:^(NSNotification *) {
callback();
}
];
}
QMacNotificationObserver(const QMacNotificationObserver& other) = delete;
QMacNotificationObserver(QMacNotificationObserver&& other) : observer(other.observer) {
other.observer = nil;
}
QMacNotificationObserver &operator=(const QMacNotificationObserver& other) = delete;
QMacNotificationObserver &operator=(QMacNotificationObserver&& other) {
if (this != &other) {
remove();
observer = other.observer;
other.observer = nil;
}
return *this;
}
void remove() {
if (observer)
[[NSNotificationCenter defaultCenter] removeObserver:observer];
observer = nil;
}
~QMacNotificationObserver() { remove(); }
private:
id observer = nil;
};
QT_END_NAMESPACE
@interface QT_MANGLE_NAMESPACE(KeyValueObserver) : NSObject
@end
QT_NAMESPACE_ALIAS_OBJC_CLASS(KeyValueObserver);
QT_BEGIN_NAMESPACE
class Q_CORE_EXPORT QMacKeyValueObserver
{
public:
using Callback = std::function<void()>;
QMacKeyValueObserver() {}
// Note: QMacKeyValueObserver must not outlive the object observed!
QMacKeyValueObserver(id object, NSString *keyPath, Callback callback,
NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew)
: object(object), keyPath(keyPath), callback(new Callback(callback))
{
addObserver(options);
}
QMacKeyValueObserver(const QMacKeyValueObserver &other)
: QMacKeyValueObserver(other.object, other.keyPath, *other.callback.get()) {}
QMacKeyValueObserver(QMacKeyValueObserver &&other) { swap(other, *this); }
~QMacKeyValueObserver() { removeObserver(); }
QMacKeyValueObserver &operator=(const QMacKeyValueObserver &other) {
QMacKeyValueObserver tmp(other);
swap(tmp, *this);
return *this;
}
QMacKeyValueObserver &operator=(QMacKeyValueObserver &&other) {
QMacKeyValueObserver tmp(std::move(other));
swap(tmp, *this);
return *this;
}
void removeObserver();
private:
void swap(QMacKeyValueObserver &first, QMacKeyValueObserver &second) {
std::swap(first.object, second.object);
std::swap(first.keyPath, second.keyPath);
std::swap(first.callback, second.callback);
}
void addObserver(NSKeyValueObservingOptions options);
id object = nil;
NSString *keyPath = nullptr;
std::unique_ptr<Callback> callback;
static KeyValueObserver *observer;
};
#endif
// -------------------------------------------------------------------------
class Q_CORE_EXPORT QMacVersion
{
public:
enum VersionTarget {
ApplicationBinary,
QtLibraries
};
static QOperatingSystemVersion buildSDK(VersionTarget target = ApplicationBinary);
static QOperatingSystemVersion deploymentTarget(VersionTarget target = ApplicationBinary);
static QOperatingSystemVersion currentRuntime();
private:
QMacVersion() = default;
using VersionTuple = QPair<QOperatingSystemVersion, QOperatingSystemVersion>;
static VersionTuple versionsForImage(const mach_header *machHeader);
static VersionTuple applicationVersion();
static VersionTuple libraryVersion();
};
// -------------------------------------------------------------------------
QT_END_NAMESPACE
#endif // QCORE_MAC_P_H

View File

@ -1,421 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
/****************************************************************************
**
** Copyright (c) 2007-2008, Apple, Inc.
**
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
**
** * Redistributions of source code must retain the above copyright notice,
** this list of conditions and the following disclaimer.
**
** * Redistributions in binary form must reproduce the above copyright notice,
** this list of conditions and the following disclaimer in the documentation
** and/or other materials provided with the distribution.
**
** * Neither the name of Apple, Inc. nor the names of its contributors
** may be used to endorse or promote products derived from this software
** without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
** PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
** LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
****************************************************************************/
#import "qcocoaapplicationdelegate.h"
#include "qcocoaintegration.h"
#include "qcocoamenu.h"
#include "qcocoamenuloader.h"
#include "qcocoamenuitem.h"
#include "qcocoansmenu.h"
#include <qevent.h>
#include <qurl.h>
#include <qdebug.h>
#include <qguiapplication.h>
#include <private/qguiapplication_p.h>
#include "qt_mac_p.h"
#include <qpa/qwindowsysteminterface.h>
#include <qwindowdefs.h>
QT_USE_NAMESPACE
@implementation QCocoaApplicationDelegate {
bool startedQuit;
NSObject <NSApplicationDelegate> *reflectionDelegate;
bool inLaunch;
}
+ (instancetype)sharedDelegate
{
static QCocoaApplicationDelegate *shared = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
shared = [[self alloc] init];
atexit_b(^{
[shared release];
shared = nil;
});
});
return shared;
}
- (instancetype)init
{
self = [super init];
if (self) {
inLaunch = true;
}
return self;
}
- (void)dealloc
{
[_dockMenu release];
if (reflectionDelegate) {
[[NSApplication sharedApplication] setDelegate:reflectionDelegate];
[reflectionDelegate release];
}
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super dealloc];
}
- (NSMenu *)applicationDockMenu:(NSApplication *)sender
{
Q_UNUSED(sender);
// Manually invoke the delegate's -menuWillOpen: method.
// See QTBUG-39604 (and its fix) for details.
[self.dockMenu.delegate menuWillOpen:self.dockMenu];
return [[self.dockMenu retain] autorelease];
}
- (BOOL)canQuit
{
[[NSApp mainMenu] cancelTracking];
bool handle_quit = true;
NSMenuItem *quitMenuItem = [[QT_MANGLE_NAMESPACE(QCocoaMenuLoader) sharedMenuLoader] quitMenuItem];
if (!QGuiApplicationPrivate::instance()->modalWindowList.isEmpty()
&& [quitMenuItem isEnabled]) {
int visible = 0;
const QWindowList tlws = QGuiApplication::topLevelWindows();
for (int i = 0; i < tlws.size(); ++i) {
if (tlws.at(i)->isVisible())
++visible;
}
handle_quit = (visible <= 1);
}
if (handle_quit) {
QCloseEvent ev;
QGuiApplication::sendEvent(qGuiApp, &ev);
if (ev.isAccepted()) {
return YES;
}
}
return NO;
}
// This function will only be called when NSApp is actually running.
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
{
// The reflection delegate gets precedence
if (reflectionDelegate) {
if ([reflectionDelegate respondsToSelector:@selector(applicationShouldTerminate:)])
return [reflectionDelegate applicationShouldTerminate:sender];
return NSTerminateNow;
}
if ([self canQuit]) {
if (!startedQuit) {
startedQuit = true;
// Close open windows. This is done in order to deliver de-expose
// events while the event loop is still running.
const QWindowList topLevels = QGuiApplication::topLevelWindows();
for (int i = 0; i < topLevels.size(); ++i) {
QWindow *topLevelWindow = topLevels.at(i);
// Already closed windows will not have a platform window, skip those
if (topLevelWindow->handle())
QWindowSystemInterface::handleCloseEvent(topLevelWindow);
}
QWindowSystemInterface::flushWindowSystemEvents();
QGuiApplication::exit(0);
startedQuit = false;
}
}
if (QGuiApplicationPrivate::instance()->threadData->eventLoops.isEmpty()) {
// INVARIANT: No event loop is executing. This probably
// means that Qt is used as a plugin, or as a part of a native
// Cocoa application. In any case it should be fine to
// terminate now:
return NSTerminateNow;
}
return NSTerminateCancel;
}
- (void)applicationWillFinishLaunching:(NSNotification *)notification
{
Q_UNUSED(notification);
/*
From the Cocoa documentation: "A good place to install event handlers
is in the applicationWillFinishLaunching: method of the application
delegate. At that point, the Application Kit has installed its default
event handlers, so if you install a handler for one of the same events,
it will replace the Application Kit version."
*/
/*
If Qt is used as a plugin, we let the 3rd party application handle
events like quit and open file events. Otherwise, if we install our own
handlers, we easily end up breaking functionality the 3rd party
application depends on.
*/
NSAppleEventManager *eventManager = [NSAppleEventManager sharedAppleEventManager];
[eventManager setEventHandler:self
andSelector:@selector(getUrl:withReplyEvent:)
forEventClass:kInternetEventClass
andEventID:kAEGetURL];
}
// called by QCocoaIntegration's destructor before resetting the application delegate to nil
- (void)removeAppleEventHandlers
{
NSAppleEventManager *eventManager = [NSAppleEventManager sharedAppleEventManager];
[eventManager removeEventHandlerForEventClass:kInternetEventClass andEventID:kAEGetURL];
}
- (bool)inLaunch
{
return inLaunch;
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
Q_UNUSED(aNotification);
inLaunch = false;
if (qEnvironmentVariableIsEmpty("QT_MAC_DISABLE_FOREGROUND_APPLICATION_TRANSFORM")) {
// Move the application window to front to avoid launching behind the terminal.
// Ignoring other apps is necessary (we must ignore the terminal), but makes
// Qt apps play slightly less nice with other apps when lanching from Finder
// (See the activateIgnoringOtherApps docs.)
[[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
}
}
- (void)application:(NSApplication *)sender openFiles:(NSArray *)filenames
{
Q_UNUSED(filenames);
Q_UNUSED(sender);
for (NSString *fileName in filenames) {
QString qtFileName = QString::fromNSString(fileName);
if (inLaunch) {
// We need to be careful because Cocoa will be nice enough to take
// command line arguments and send them to us as events. Given the history
// of Qt Applications, this will result in behavior people don't want, as
// they might be doing the opening themselves with the command line parsing.
if (qApp->arguments().contains(qtFileName))
continue;
}
QWindowSystemInterface::handleFileOpenEvent(qtFileName);
}
if (reflectionDelegate &&
[reflectionDelegate respondsToSelector:@selector(application:openFiles:)])
[reflectionDelegate application:sender openFiles:filenames];
}
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
{
// If we have a reflection delegate, that will get to call the shots.
if (reflectionDelegate
&& [reflectionDelegate respondsToSelector:
@selector(applicationShouldTerminateAfterLastWindowClosed:)])
return [reflectionDelegate applicationShouldTerminateAfterLastWindowClosed:sender];
return NO; // Someday qApp->quitOnLastWindowClosed(); when QApp and NSApp work closer together.
}
- (void)applicationDidBecomeActive:(NSNotification *)notification
{
if (reflectionDelegate
&& [reflectionDelegate respondsToSelector:@selector(applicationDidBecomeActive:)])
[reflectionDelegate applicationDidBecomeActive:notification];
QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive);
}
- (void)applicationDidResignActive:(NSNotification *)notification
{
if (reflectionDelegate
&& [reflectionDelegate respondsToSelector:@selector(applicationDidResignActive:)])
[reflectionDelegate applicationDidResignActive:notification];
QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationInactive);
}
- (BOOL)applicationShouldHandleReopen:(NSApplication *)theApplication hasVisibleWindows:(BOOL)flag
{
Q_UNUSED(theApplication);
Q_UNUSED(flag);
if (reflectionDelegate
&& [reflectionDelegate respondsToSelector:@selector(applicationShouldHandleReopen:hasVisibleWindows:)])
return [reflectionDelegate applicationShouldHandleReopen:theApplication hasVisibleWindows:flag];
/*
true to force delivery of the event even if the application state is already active,
because rapp (handle reopen) events are sent each time the dock icon is clicked regardless
of the active state of the application or number of visible windows. For example, a browser
app that has no windows opened would need the event be to delivered even if it was already
active in order to create a new window as per OS X conventions.
*/
QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive, true /*forcePropagate*/);
return YES;
}
- (void)setReflectionDelegate:(NSObject <NSApplicationDelegate> *)oldDelegate
{
[oldDelegate retain];
[reflectionDelegate release];
reflectionDelegate = oldDelegate;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
NSMethodSignature *result = [super methodSignatureForSelector:aSelector];
if (!result && reflectionDelegate) {
result = [reflectionDelegate methodSignatureForSelector:aSelector];
}
return result;
}
- (BOOL)respondsToSelector:(SEL)aSelector
{
BOOL result = [super respondsToSelector:aSelector];
if (!result && reflectionDelegate)
result = [reflectionDelegate respondsToSelector:aSelector];
return result;
}
- (void)forwardInvocation:(NSInvocation *)invocation
{
SEL invocationSelector = [invocation selector];
if (reflectionDelegate && [reflectionDelegate respondsToSelector:invocationSelector])
[invocation invokeWithTarget:reflectionDelegate];
else
[self doesNotRecognizeSelector:invocationSelector];
}
- (void)getUrl:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent
{
Q_UNUSED(replyEvent);
NSString *urlString = [[event paramDescriptorForKeyword:keyDirectObject] stringValue];
QWindowSystemInterface::handleFileOpenEvent(QUrl(QString::fromNSString(urlString)));
}
@end
@implementation QCocoaApplicationDelegate (Menus)
- (BOOL)validateMenuItem:(NSMenuItem*)item
{
auto *nativeItem = qt_objc_cast<QCocoaNSMenuItem *>(item);
if (!nativeItem)
return item.enabled; // FIXME Test with with Qt as plugin or embedded QWindow.
auto *platformItem = nativeItem.platformMenuItem;
if (!platformItem) // Try a bit harder with orphan menu itens
return item.hasSubmenu || (item.enabled && (item.action != @selector(qt_itemFired:)));
// Menu-holding items are always enabled, as it's conventional in Cocoa
if (platformItem->menu())
return YES;
return platformItem->isEnabled();
}
@end
@implementation QCocoaApplicationDelegate (MenuAPI)
- (void)qt_itemFired:(QCocoaNSMenuItem *)item
{
if (item.hasSubmenu)
return;
auto *nativeItem = qt_objc_cast<QCocoaNSMenuItem *>(item);
Q_ASSERT_X(nativeItem, qPrintable(__FUNCTION__), "Triggered menu item is not a QCocoaNSMenuItem.");
auto *platformItem = nativeItem.platformMenuItem;
// Menu-holding items also get a target to play nicely
// with NSMenuValidation but should not trigger.
if (!platformItem || platformItem->menu())
return;
QScopedScopeLevelCounter scopeLevelCounter(QGuiApplicationPrivate::instance()->threadData);
QGuiApplicationPrivate::modifier_buttons = [QNSView convertKeyModifiers:[NSEvent modifierFlags]];
static QMetaMethod activatedSignal = QMetaMethod::fromSignal(&QCocoaMenuItem::activated);
activatedSignal.invoke(platformItem, Qt::QueuedConnection);
}
@end

View File

@ -1,357 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QCOCOAHELPERS_H
#define QCOCOAHELPERS_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It provides helper functions
// for the Cocoa lighthouse plugin. This header file may
// change from version to version without notice, or even be removed.
//
// We mean it.
//
#include "qt_mac_p.h"
#include <private/qguiapplication_p.h>
#include <QtCore/qoperatingsystemversion.h>
#include <QtGui/qpalette.h>
#include <QtGui/qscreen.h>
#include <objc/runtime.h>
#include <objc/message.h>
Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSView));
struct mach_header;
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(lcQpaWindow)
Q_DECLARE_LOGGING_CATEGORY(lcQpaDrawing)
Q_DECLARE_LOGGING_CATEGORY(lcQpaMouse)
Q_DECLARE_LOGGING_CATEGORY(lcQpaScreen)
class QPixmap;
class QString;
// Conversion functions
QStringList qt_mac_NSArrayToQStringList(NSArray<NSString *> *nsarray);
NSMutableArray<NSString *> *qt_mac_QStringListToNSMutableArray(const QStringList &list);
NSDragOperation qt_mac_mapDropAction(Qt::DropAction action);
NSDragOperation qt_mac_mapDropActions(Qt::DropActions actions);
Qt::DropAction qt_mac_mapNSDragOperation(NSDragOperation nsActions);
Qt::DropActions qt_mac_mapNSDragOperations(NSDragOperation nsActions);
template <typename T>
typename std::enable_if<std::is_pointer<T>::value, T>::type
qt_objc_cast(id object)
{
if ([object isKindOfClass:[typename std::remove_pointer<T>::type class]])
return static_cast<T>(object);
return nil;
}
QT_MANGLE_NAMESPACE(QNSView) *qnsview_cast(NSView *view);
// Misc
void qt_mac_transformProccessToForegroundApplication();
QString qt_mac_applicationName();
QPointF qt_mac_flip(const QPointF &pos, const QRectF &reference);
QRectF qt_mac_flip(const QRectF &rect, const QRectF &reference);
Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum);
Qt::MouseButton cocoaButton2QtButton(NSEvent *event);
QEvent::Type cocoaEvent2QtMouseEvent(NSEvent *event);
Qt::MouseButtons cocoaMouseButtons2QtMouseButtons(NSInteger pressedMouseButtons);
Qt::MouseButtons currentlyPressedMouseButtons();
// strip out '&' characters, and convert "&&" to a single '&', in menu
// text - since menu text is sometimes decorated with these for Windows
// accelerators.
QString qt_mac_removeAmpersandEscapes(QString s);
enum {
QtCocoaEventSubTypeWakeup = SHRT_MAX,
QtCocoaEventSubTypePostMessage = SHRT_MAX-1
};
class QCocoaPostMessageArgs {
public:
id target;
SEL selector;
int argCount;
id arg1;
id arg2;
QCocoaPostMessageArgs(id target, SEL selector, int argCount=0, id arg1=0, id arg2=0)
: target(target), selector(selector), argCount(argCount), arg1(arg1), arg2(arg2)
{
[target retain];
[arg1 retain];
[arg2 retain];
}
~QCocoaPostMessageArgs()
{
[arg2 release];
[arg1 release];
[target release];
}
};
template<typename T>
T qt_mac_resolveOption(const T &fallback, const QByteArray &environment)
{
// check for environment variable
if (!environment.isEmpty()) {
QByteArray env = qgetenv(environment);
if (!env.isEmpty())
return T(env.toInt()); // works when T is bool, int.
}
return fallback;
}
template<typename T>
T qt_mac_resolveOption(const T &fallback, QWindow *window, const QByteArray &property, const QByteArray &environment)
{
// check for environment variable
if (!environment.isEmpty()) {
QByteArray env = qgetenv(environment);
if (!env.isEmpty())
return T(env.toInt()); // works when T is bool, int.
}
// check for window property
if (window && !property.isNull()) {
QVariant windowProperty = window->property(property);
if (windowProperty.isValid())
return windowProperty.value<T>();
}
// return default value.
return fallback;
}
// https://stackoverflow.com/a/52722575/2761869
template<class R>
struct backwards_t {
R r;
constexpr auto begin() const { using std::rbegin; return rbegin(r); }
constexpr auto begin() { using std::rbegin; return rbegin(r); }
constexpr auto end() const { using std::rend; return rend(r); }
constexpr auto end() { using std::rend; return rend(r); }
};
template<class R>
constexpr backwards_t<R> backwards(R&& r) { return {std::forward<R>(r)}; }
QT_END_NAMESPACE
// @compatibility_alias doesn't work with protocols
#define QNSPanelDelegate QT_MANGLE_NAMESPACE(QNSPanelDelegate)
@protocol QNSPanelDelegate
@required
- (void)onOkClicked;
- (void)onCancelClicked;
@end
@interface QT_MANGLE_NAMESPACE(QNSPanelContentsWrapper) : NSView
@property (nonatomic, readonly) NSButton *okButton;
@property (nonatomic, readonly) NSButton *cancelButton;
@property (nonatomic, readonly) NSView *panelContents; // ARC: unretained, make it weak
@property (nonatomic, assign) NSEdgeInsets panelContentsMargins;
- (instancetype)initWithPanelDelegate:(id<QNSPanelDelegate>)panelDelegate;
- (void)dealloc;
- (NSButton *)createButtonWithTitle:(const char *)title;
- (void)layout;
@end
QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSPanelContentsWrapper);
// -------------------------------------------------------------------------
// QAppleRefCounted expects the retain function to return the object
io_object_t q_IOObjectRetain(io_object_t obj);
// QAppleRefCounted expects the release function to return void
void q_IOObjectRelease(io_object_t obj);
template <typename T>
class QIOType : public QAppleRefCounted<T, io_object_t, q_IOObjectRetain, q_IOObjectRelease>
{
using QAppleRefCounted<T, io_object_t, q_IOObjectRetain, q_IOObjectRelease>::QAppleRefCounted;
};
// -------------------------------------------------------------------------
// Depending on the ABI of the platform, we may need to use objc_msgSendSuper_stret:
// - http://www.sealiesoftware.com/blog/archive/2008/10/30/objc_explain_objc_msgSend_stret.html
// - https://lists.apple.com/archives/cocoa-dev/2008/Feb/msg02338.html
template <typename T>
struct objc_msgsend_requires_stret
{ static const bool value =
#if defined(Q_PROCESSOR_X86)
#define PLATFORM_USES_SEND_SUPER_STRET 1
// Any return value larger than two registers on i386/x86_64
sizeof(T) > sizeof(void*) * 2;
#elif defined(Q_PROCESSOR_ARM_32)
#define PLATFORM_USES_SEND_SUPER_STRET 1
// Any return value larger than a single register on arm
sizeof(T) > sizeof(void*);
#elif defined(Q_PROCESSOR_ARM_64)
#define PLATFORM_USES_SEND_SUPER_STRET 0
// Stret not used on arm64
false;
#endif
};
template <>
struct objc_msgsend_requires_stret<void>
{ static const bool value = false; };
template <typename ReturnType, typename... Args>
ReturnType qt_msgSendSuper(id receiver, SEL selector, Args... args)
{
static_assert(!objc_msgsend_requires_stret<ReturnType>::value,
"The given return type requires stret on this platform");
typedef ReturnType (*SuperFn)(objc_super *, SEL, Args...);
SuperFn superFn = reinterpret_cast<SuperFn>(objc_msgSendSuper);
objc_super sup = { receiver, [receiver superclass] };
return superFn(&sup, selector, args...);
}
#if PLATFORM_USES_SEND_SUPER_STRET
template <typename ReturnType, typename... Args>
ReturnType qt_msgSendSuper_stret(id receiver, SEL selector, Args... args)
{
static_assert(objc_msgsend_requires_stret<ReturnType>::value,
"The given return type does not use stret on this platform");
typedef void (*SuperStretFn)(ReturnType *, objc_super *, SEL, Args...);
SuperStretFn superStretFn = reinterpret_cast<SuperStretFn>(objc_msgSendSuper_stret);
objc_super sup = { receiver, [receiver superclass] };
ReturnType ret;
superStretFn(&ret, &sup, selector, args...);
return ret;
}
#endif
template<typename... Args>
class QSendSuperHelper {
public:
QSendSuperHelper(id receiver, SEL sel, Args... args)
: m_receiver(receiver), m_selector(sel), m_args(std::make_tuple(args...)), m_sent(false)
{
}
~QSendSuperHelper()
{
if (!m_sent)
msgSendSuper<void>(m_args);
}
template <typename ReturnType>
operator ReturnType()
{
#if defined(QT_DEBUG)
Method method = class_getInstanceMethod(object_getClass(m_receiver), m_selector);
char returnTypeEncoding[256];
method_getReturnType(method, returnTypeEncoding, sizeof(returnTypeEncoding));
NSUInteger alignedReturnTypeSize = 0;
NSGetSizeAndAlignment(returnTypeEncoding, nullptr, &alignedReturnTypeSize);
Q_ASSERT(alignedReturnTypeSize == sizeof(ReturnType));
#endif
m_sent = true;
return msgSendSuper<ReturnType>(m_args);
}
private:
template <typename ReturnType, bool V>
using if_requires_stret = typename std::enable_if<objc_msgsend_requires_stret<ReturnType>::value == V, ReturnType>::type;
template <typename ReturnType, int... Is>
if_requires_stret<ReturnType, false> msgSendSuper(std::tuple<Args...>& args, QtPrivate::IndexesList<Is...>)
{
return qt_msgSendSuper<ReturnType>(m_receiver, m_selector, std::get<Is>(args)...);
}
#if PLATFORM_USES_SEND_SUPER_STRET
template <typename ReturnType, int... Is>
if_requires_stret<ReturnType, true> msgSendSuper(std::tuple<Args...>& args, QtPrivate::IndexesList<Is...>)
{
return qt_msgSendSuper_stret<ReturnType>(m_receiver, m_selector, std::get<Is>(args)...);
}
#endif
template <typename ReturnType>
ReturnType msgSendSuper(std::tuple<Args...>& args)
{
return msgSendSuper<ReturnType>(args, QtPrivate::makeIndexSequence<sizeof...(Args)>{});
}
id m_receiver;
SEL m_selector;
std::tuple<Args...> m_args;
bool m_sent;
};
template<typename... Args>
QSendSuperHelper<Args...> qt_objcDynamicSuperHelper(id receiver, SEL selector, Args... args)
{
return QSendSuperHelper<Args...>(receiver, selector, args...);
}
// Same as calling super, but the super_class field resolved at runtime instead of compile time
#define qt_objcDynamicSuper(...) qt_objcDynamicSuperHelper(self, _cmd, ##__VA_ARGS__)
#endif //QCOCOAHELPERS_H

View File

@ -1,512 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <qpa/qplatformtheme.h>
#include "qcocoahelpers.h"
#include "qnsview.h"
#include <QtCore>
#include <QtGui>
#include <qpa/qplatformscreen.h>
#include <private/qguiapplication_p.h>
#include <private/qwindow_p.h>
#include <QtGui/private/qcoregraphics_p.h>
#ifndef QT_NO_WIDGETS
#include <QtWidgets/QWidget>
#endif
#include <algorithm>
QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcQpaWindow, "qt.qpa.window");
Q_LOGGING_CATEGORY(lcQpaDrawing, "qt.qpa.drawing");
Q_LOGGING_CATEGORY(lcQpaMouse, "qt.qpa.input.mouse", QtCriticalMsg);
Q_LOGGING_CATEGORY(lcQpaScreen, "qt.qpa.screen", QtCriticalMsg);
//
// Conversion Functions
//
QStringList qt_mac_NSArrayToQStringList(NSArray<NSString *> *array)
{
QStringList result;
for (NSString *string in array)
result << QString::fromNSString(string);
return result;
}
NSMutableArray<NSString *> *qt_mac_QStringListToNSMutableArray(const QStringList &list)
{
NSMutableArray<NSString *> *result = [NSMutableArray<NSString *> arrayWithCapacity:list.size()];
for (const QString &string : list)
[result addObject:string.toNSString()];
return result;
}
struct dndenum_mapper
{
NSDragOperation mac_code;
Qt::DropAction qt_code;
bool Qt2Mac;
};
static dndenum_mapper dnd_enums[] = {
{ NSDragOperationLink, Qt::LinkAction, true },
{ NSDragOperationMove, Qt::MoveAction, true },
{ NSDragOperationDelete, Qt::MoveAction, true },
{ NSDragOperationCopy, Qt::CopyAction, true },
{ NSDragOperationGeneric, Qt::CopyAction, false },
{ NSDragOperationEvery, Qt::ActionMask, false },
{ NSDragOperationNone, Qt::IgnoreAction, false }
};
NSDragOperation qt_mac_mapDropAction(Qt::DropAction action)
{
for (int i=0; dnd_enums[i].qt_code; i++) {
if (dnd_enums[i].Qt2Mac && (action & dnd_enums[i].qt_code)) {
return dnd_enums[i].mac_code;
}
}
return NSDragOperationNone;
}
NSDragOperation qt_mac_mapDropActions(Qt::DropActions actions)
{
NSDragOperation nsActions = NSDragOperationNone;
for (int i=0; dnd_enums[i].qt_code; i++) {
if (dnd_enums[i].Qt2Mac && (actions & dnd_enums[i].qt_code))
nsActions |= dnd_enums[i].mac_code;
}
return nsActions;
}
Qt::DropAction qt_mac_mapNSDragOperation(NSDragOperation nsActions)
{
Qt::DropAction action = Qt::IgnoreAction;
for (int i=0; dnd_enums[i].mac_code; i++) {
if (nsActions & dnd_enums[i].mac_code)
return dnd_enums[i].qt_code;
}
return action;
}
Qt::DropActions qt_mac_mapNSDragOperations(NSDragOperation nsActions)
{
Qt::DropActions actions = Qt::IgnoreAction;
for (int i=0; dnd_enums[i].mac_code; i++) {
if (dnd_enums[i].mac_code == NSDragOperationEvery)
continue;
if (nsActions & dnd_enums[i].mac_code)
actions |= dnd_enums[i].qt_code;
}
return actions;
}
/*!
Returns the view cast to a QNSview if possible.
If the view is not a QNSView, nil is returned, which is safe to
send messages to, effectivly making [qnsview_cast(view) message]
a no-op.
For extra verbosity and clearer code, please consider checking
that the platform window is not a foreign window before using
this cast, via QPlatformWindow::isForeignWindow().
Do not use this method soley to check for foreign windows, as
that will make the code harder to read for people not working
primarily on macOS, who do not know the difference between the
NSView and QNSView cases.
*/
QNSView *qnsview_cast(NSView *view)
{
return qt_objc_cast<QNSView *>(view);
}
//
// Misc
//
// Sets the activation policy for this process to NSApplicationActivationPolicyRegular,
// unless either LSUIElement or LSBackgroundOnly is set in the Info.plist.
void qt_mac_transformProccessToForegroundApplication()
{
bool forceTransform = true;
CFTypeRef value = CFBundleGetValueForInfoDictionaryKey(CFBundleGetMainBundle(),
CFSTR("LSUIElement"));
if (value) {
CFTypeID valueType = CFGetTypeID(value);
// Officially it's supposed to be a string, a boolean makes sense, so we'll check.
// A number less so, but OK.
if (valueType == CFStringGetTypeID())
forceTransform = !(QString::fromCFString(static_cast<CFStringRef>(value)).toInt());
else if (valueType == CFBooleanGetTypeID())
forceTransform = !CFBooleanGetValue(static_cast<CFBooleanRef>(value));
else if (valueType == CFNumberGetTypeID()) {
int valueAsInt;
CFNumberGetValue(static_cast<CFNumberRef>(value), kCFNumberIntType, &valueAsInt);
forceTransform = !valueAsInt;
}
}
if (forceTransform) {
value = CFBundleGetValueForInfoDictionaryKey(CFBundleGetMainBundle(),
CFSTR("LSBackgroundOnly"));
if (value) {
CFTypeID valueType = CFGetTypeID(value);
if (valueType == CFBooleanGetTypeID())
forceTransform = !CFBooleanGetValue(static_cast<CFBooleanRef>(value));
else if (valueType == CFStringGetTypeID())
forceTransform = !(QString::fromCFString(static_cast<CFStringRef>(value)).toInt());
else if (valueType == CFNumberGetTypeID()) {
int valueAsInt;
CFNumberGetValue(static_cast<CFNumberRef>(value), kCFNumberIntType, &valueAsInt);
forceTransform = !valueAsInt;
}
}
}
if (forceTransform) {
[[NSApplication sharedApplication] setActivationPolicy:NSApplicationActivationPolicyRegular];
}
}
QString qt_mac_applicationName()
{
QString appName;
CFTypeRef string = CFBundleGetValueForInfoDictionaryKey(CFBundleGetMainBundle(), CFSTR("CFBundleName"));
if (string)
appName = QString::fromCFString(static_cast<CFStringRef>(string));
if (appName.isEmpty()) {
QString arg0 = QGuiApplicationPrivate::instance()->appName();
if (arg0.contains("/")) {
QStringList parts = arg0.split(QLatin1Char('/'));
appName = parts.at(parts.count() - 1);
} else {
appName = arg0;
}
}
return appName;
}
// -------------------------------------------------------------------------
/*!
\fn QPointF qt_mac_flip(const QPointF &pos, const QRectF &reference)
\fn QRectF qt_mac_flip(const QRectF &rect, const QRectF &reference)
Flips the Y coordinate of the point/rect between quadrant I and IV.
The native coordinate system on macOS uses quadrant I, with origin
in bottom left, and Qt uses quadrant IV, with origin in top left.
By flipping the Y coordinate, we can map the point/rect between
the two coordinate systems.
The flip is always in relation to a reference rectangle, e.g.
the frame of the parent view, or the screen geometry. In the
latter case the specialized QCocoaScreen::mapFrom/To functions
should be used instead.
*/
QPointF qt_mac_flip(const QPointF &pos, const QRectF &reference)
{
return QPointF(pos.x(), reference.height() - pos.y());
}
QRectF qt_mac_flip(const QRectF &rect, const QRectF &reference)
{
return QRectF(qt_mac_flip(rect.bottomLeft(), reference), rect.size());
}
// -------------------------------------------------------------------------
/*!
\fn Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum)
Returns the Qt::Button that corresponds to an NSEvent.buttonNumber.
\note AppKit will use buttonNumber 0 to indicate both "left button"
and "no button". Only NSEvents that describes mouse press/release
events (e.g NSEventTypeOtherMouseDown) will contain a valid
button number.
*/
Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum)
{
if (buttonNum >= 0 && buttonNum <= 31)
return Qt::MouseButton(1 << buttonNum);
return Qt::NoButton;
}
/*!
\fn Qt::MouseButton cocoaButton2QtButton(NSEvent *event)
Returns the Qt::Button that corresponds to an NSEvent.buttonNumber.
\note AppKit will use buttonNumber 0 to indicate both "left button"
and "no button". Only NSEvents that describes mouse press/release/dragging
events (e.g NSEventTypeOtherMouseDown) will contain a valid
button number.
\note Wacom tablet might not return the correct button number for NSEvent buttonNumber
on right clicks. Decide here that the button is the "right" button.
*/
Qt::MouseButton cocoaButton2QtButton(NSEvent *event)
{
if (cocoaEvent2QtMouseEvent(event) == QEvent::MouseMove)
return Qt::NoButton;
switch (event.type) {
case NSEventTypeRightMouseUp:
case NSEventTypeRightMouseDown:
return Qt::RightButton;
default:
break;
}
return cocoaButton2QtButton(event.buttonNumber);
}
/*!
\fn QEvent::Type cocoaEvent2QtMouseEvent(NSEvent *event)
Returns the QEvent::Type that corresponds to an NSEvent.type.
*/
QEvent::Type cocoaEvent2QtMouseEvent(NSEvent *event)
{
switch (event.type) {
case NSEventTypeLeftMouseDown:
case NSEventTypeRightMouseDown:
case NSEventTypeOtherMouseDown:
return QEvent::MouseButtonPress;
case NSEventTypeLeftMouseUp:
case NSEventTypeRightMouseUp:
case NSEventTypeOtherMouseUp:
return QEvent::MouseButtonRelease;
case NSEventTypeLeftMouseDragged:
case NSEventTypeRightMouseDragged:
case NSEventTypeOtherMouseDragged:
return QEvent::MouseMove;
case NSEventTypeMouseMoved:
return QEvent::MouseMove;
default:
break;
}
return QEvent::None;
}
/*!
\fn Qt::MouseButtons cocoaMouseButtons2QtMouseButtons(NSInteger pressedMouseButtons)
Returns the Qt::MouseButtons that corresponds to an NSEvent.pressedMouseButtons.
*/
Qt::MouseButtons cocoaMouseButtons2QtMouseButtons(NSInteger pressedMouseButtons)
{
return static_cast<Qt::MouseButton>(pressedMouseButtons & Qt::MouseButtonMask);
}
/*!
\fn Qt::MouseButtons currentlyPressedMouseButtons()
Returns the Qt::MouseButtons that corresponds to an NSEvent.pressedMouseButtons.
*/
Qt::MouseButtons currentlyPressedMouseButtons()
{
return cocoaMouseButtons2QtMouseButtons(NSEvent.pressedMouseButtons);
}
QString qt_mac_removeAmpersandEscapes(QString s)
{
return QPlatformTheme::removeMnemonics(s).trimmed();
}
// -------------------------------------------------------------------------
QT_END_NAMESPACE
/*! \internal
This NSView derived class is used to add OK/Cancel
buttons to NSColorPanel and NSFontPanel. It replaces
the panel's content view, while reparenting the former
content view into itself. It also takes care of setting
the target-action for the OK/Cancel buttons and making
sure the layout is consistent.
*/
@implementation QNSPanelContentsWrapper {
NSButton *_okButton;
NSButton *_cancelButton;
NSView *_panelContents;
NSEdgeInsets _panelContentsMargins;
}
@synthesize okButton = _okButton;
@synthesize cancelButton = _cancelButton;
@synthesize panelContents = _panelContents;
@synthesize panelContentsMargins = _panelContentsMargins;
- (instancetype)initWithPanelDelegate:(id<QNSPanelDelegate>)panelDelegate
{
if ((self = [super initWithFrame:NSZeroRect])) {
// create OK and Cancel buttons and add these as subviews
_okButton = [self createButtonWithTitle:"&OK"];
_okButton.action = @selector(onOkClicked);
_okButton.target = panelDelegate;
_cancelButton = [self createButtonWithTitle:"Cancel"];
_cancelButton.action = @selector(onCancelClicked);
_cancelButton.target = panelDelegate;
_panelContents = nil;
_panelContentsMargins = NSEdgeInsetsMake(0, 0, 0, 0);
}
return self;
}
- (void)dealloc
{
[_okButton release];
_okButton = nil;
[_cancelButton release];
_cancelButton = nil;
_panelContents = nil;
[super dealloc];
}
- (NSButton *)createButtonWithTitle:(const char *)title
{
NSButton *button = [[NSButton alloc] initWithFrame:NSZeroRect];
button.buttonType = NSMomentaryLightButton;
button.bezelStyle = NSRoundedBezelStyle;
const QString &cleanTitle = QPlatformTheme::removeMnemonics(QCoreApplication::translate("QDialogButtonBox", title));
// FIXME: Not obvious, from Cocoa's documentation, that QString::toNSString() makes a deep copy
button.title = (NSString *)cleanTitle.toCFString();
((NSButtonCell *)button.cell).font =
[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSControlSizeRegular]];
[self addSubview:button];
return button;
}
- (void)layout
{
static const CGFloat ButtonMinWidth = 78.0; // 84.0 for Carbon
static const CGFloat ButtonMinHeight = 32.0;
static const CGFloat ButtonSpacing = 0.0;
static const CGFloat ButtonTopMargin = 0.0;
static const CGFloat ButtonBottomMargin = 7.0;
static const CGFloat ButtonSideMargin = 9.0;
NSSize frameSize = self.frame.size;
[self.okButton sizeToFit];
NSSize okSizeHint = self.okButton.frame.size;
[self.cancelButton sizeToFit];
NSSize cancelSizeHint = self.cancelButton.frame.size;
const CGFloat buttonWidth = qMin(qMax(ButtonMinWidth,
qMax(okSizeHint.width, cancelSizeHint.width)),
CGFloat((frameSize.width - 2.0 * ButtonSideMargin - ButtonSpacing) * 0.5));
const CGFloat buttonHeight = qMax(ButtonMinHeight,
qMax(okSizeHint.height, cancelSizeHint.height));
NSRect okRect = { { frameSize.width - ButtonSideMargin - buttonWidth,
ButtonBottomMargin },
{ buttonWidth, buttonHeight } };
self.okButton.frame = okRect;
self.okButton.needsDisplay = YES;
NSRect cancelRect = { { okRect.origin.x - ButtonSpacing - buttonWidth,
ButtonBottomMargin },
{ buttonWidth, buttonHeight } };
self.cancelButton.frame = cancelRect;
self.cancelButton.needsDisplay = YES;
// The third view should be the original panel contents. Cache it.
if (!self.panelContents)
for (NSView *view in self.subviews)
if (view != self.okButton && view != self.cancelButton) {
_panelContents = view;
break;
}
const CGFloat buttonBoxHeight = ButtonBottomMargin + buttonHeight + ButtonTopMargin;
const NSRect panelContentsFrame = NSMakeRect(
self.panelContentsMargins.left,
buttonBoxHeight + self.panelContentsMargins.bottom,
frameSize.width - (self.panelContentsMargins.left + self.panelContentsMargins.right),
frameSize.height - buttonBoxHeight - (self.panelContentsMargins.top + self.panelContentsMargins.bottom));
self.panelContents.frame = panelContentsFrame;
self.panelContents.needsDisplay = YES;
self.needsDisplay = YES;
[super layout];
}
// -------------------------------------------------------------------------
io_object_t q_IOObjectRetain(io_object_t obj)
{
kern_return_t ret = IOObjectRetain(obj);
Q_ASSERT(!ret);
return obj;
}
void q_IOObjectRelease(io_object_t obj)
{
kern_return_t ret = IOObjectRelease(obj);
Q_ASSERT(!ret);
}
@end

View File

@ -1,142 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QCOCOASCREEN_H
#define QCOCOASCREEN_H
#include <AppKit/AppKit.h>
#include "qcocoacursor.h"
#include <qpa/qplatformintegration.h>
QT_BEGIN_NAMESPACE
class QCocoaIntegration;
class QCocoaScreen : public QPlatformScreen
{
public:
~QCocoaScreen();
// ----------------------------------------------------
// Virtual methods overridden from QPlatformScreen
QPixmap grabWindow(WId window, int x, int y, int width, int height) const override;
QRect geometry() const override { return m_geometry; }
QRect availableGeometry() const override { return m_availableGeometry; }
int depth() const override { return m_depth; }
QImage::Format format() const override { return m_format; }
qreal devicePixelRatio() const override { return m_devicePixelRatio; }
QSizeF physicalSize() const override { return m_physicalSize; }
QDpi logicalDpi() const override { return m_logicalDpi; }
qreal refreshRate() const override { return m_refreshRate; }
QString name() const override { return m_name; }
QPlatformCursor *cursor() const override { return m_cursor; }
QWindow *topLevelAt(const QPoint &point) const override;
QList<QPlatformScreen *> virtualSiblings() const override;
QPlatformScreen::SubpixelAntialiasingType subpixelAntialiasingTypeHint() const override;
// ----------------------------------------------------
NSScreen *nativeScreen() const;
void requestUpdate();
void deliverUpdateRequests();
bool isRunningDisplayLink() const;
static QCocoaScreen *primaryScreen();
static QCocoaScreen *get(NSScreen *nsScreen);
static QCocoaScreen *get(CGDirectDisplayID displayId);
static QCocoaScreen *get(CFUUIDRef uuid);
static CGPoint mapToNative(const QPointF &pos, QCocoaScreen *screen = QCocoaScreen::primaryScreen());
static CGRect mapToNative(const QRectF &rect, QCocoaScreen *screen = QCocoaScreen::primaryScreen());
static QPointF mapFromNative(CGPoint pos, QCocoaScreen *screen = QCocoaScreen::primaryScreen());
static QRectF mapFromNative(CGRect rect, QCocoaScreen *screen = QCocoaScreen::primaryScreen());
private:
static void initializeScreens();
static void updateScreens();
static void cleanupScreens();
static bool updateScreensIfNeeded();
static NSArray *s_screenConfigurationBeforeUpdate;
static void add(CGDirectDisplayID displayId);
QCocoaScreen(CGDirectDisplayID displayId);
void update(CGDirectDisplayID displayId);
void remove();
bool isOnline() const;
bool isMirroring() const;
CGDirectDisplayID m_displayId = kCGNullDirectDisplay;
CGDirectDisplayID displayId() const { return m_displayId; }
QRect m_geometry;
QRect m_availableGeometry;
QDpi m_logicalDpi;
qreal m_refreshRate;
int m_depth;
QString m_name;
QImage::Format m_format;
QSizeF m_physicalSize;
QCocoaCursor *m_cursor;
qreal m_devicePixelRatio;
CVDisplayLinkRef m_displayLink = nullptr;
dispatch_source_t m_displayLinkSource = nullptr;
QAtomicInt m_pendingUpdates;
friend class QCocoaIntegration;
friend class QCocoaWindow;
friend QDebug operator<<(QDebug debug, const QCocoaScreen *screen);
};
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug debug, const QCocoaScreen *screen);
#endif
QT_END_NAMESPACE
@interface NSScreen (QtExtras)
@property(readonly) CGDirectDisplayID qt_displayId;
@end
#endif // QCOCOASCREEN_H

View File

@ -1,831 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qcocoascreen.h"
#include "qcocoawindow.h"
#include "qcocoahelpers.h"
#include "qcocoaintegration.h"
#include <QtCore/qcoreapplication.h>
#include <QtGui/private/qcoregraphics_p.h>
#include <IOKit/graphics/IOGraphicsLib.h>
#include <QtGui/private/qwindow_p.h>
#include <QtCore/private/qeventdispatcher_cf_p.h>
QT_BEGIN_NAMESPACE
namespace CoreGraphics {
Q_NAMESPACE
enum DisplayChange {
ReconfiguredWithFlagsMissing = 0,
Moved = kCGDisplayMovedFlag,
SetMain = kCGDisplaySetMainFlag,
SetMode = kCGDisplaySetModeFlag,
Added = kCGDisplayAddFlag,
Removed = kCGDisplayRemoveFlag,
Enabled = kCGDisplayEnabledFlag,
Disabled = kCGDisplayDisabledFlag,
Mirrored = kCGDisplayMirrorFlag,
UnMirrored = kCGDisplayUnMirrorFlag,
DesktopShapeChanged = kCGDisplayDesktopShapeChangedFlag
};
Q_ENUM_NS(DisplayChange)
}
NSArray *QCocoaScreen::s_screenConfigurationBeforeUpdate = nil;
void QCocoaScreen::initializeScreens()
{
updateScreens();
CGDisplayRegisterReconfigurationCallback([](CGDirectDisplayID displayId, CGDisplayChangeSummaryFlags flags, void *userInfo) {
Q_UNUSED(userInfo);
// Displays are reconfigured in batches, and we want to update our screens
// once a batch ends, so that all the states of the displays are up to date.
static int displayReconfigurationsInProgress = 0;
const bool beforeReconfigure = flags & kCGDisplayBeginConfigurationFlag;
qCDebug(lcQpaScreen).verbosity(0).nospace() << "Display " << displayId
<< (beforeReconfigure ? " about to reconfigure" : " was ")
<< QFlags<CoreGraphics::DisplayChange>(flags)
<< " with " << displayReconfigurationsInProgress
<< " display configuration(s) in progress";
if (!flags) {
// CGDisplayRegisterReconfigurationCallback has been observed to be called
// with flags unset. This seems like a bug. The callback is not paired with
// a matching "completion" callback either, so we don't know whether to treat
// it as a begin or end of reconfigure.
return;
}
if (beforeReconfigure) {
if (!displayReconfigurationsInProgress++) {
// There might have been a screen reconfigure before this that
// we didn't process yet, so do that now if that's the case.
updateScreensIfNeeded();
Q_ASSERT(!s_screenConfigurationBeforeUpdate);
s_screenConfigurationBeforeUpdate = NSScreen.screens;
qCDebug(lcQpaScreen, "Display reconfigure transaction started"
" with screen configuration %p", s_screenConfigurationBeforeUpdate);
static void (^tryScreenUpdate)();
tryScreenUpdate = ^void () {
qCDebug(lcQpaScreen) << "Attempting screen update from runloop block";
if (!updateScreensIfNeeded())
CFRunLoopPerformBlock(CFRunLoopGetMain(), kCFRunLoopCommonModes, tryScreenUpdate);
};
CFRunLoopPerformBlock(CFRunLoopGetMain(), kCFRunLoopCommonModes, tryScreenUpdate);
}
} else {
Q_ASSERT_X(displayReconfigurationsInProgress, "QCococaScreen",
"Display configuration transactions are expected to be balanced");
if (!--displayReconfigurationsInProgress) {
qCDebug(lcQpaScreen) << "Display reconfigure transaction completed";
// We optimistically update now, in case the NSScreens have changed
updateScreensIfNeeded();
}
}
}, nullptr);
static QMacNotificationObserver screenParameterObserver(NSApplication.sharedApplication,
NSApplicationDidChangeScreenParametersNotification, [&]() {
qCDebug(lcQpaScreen) << "Received screen parameter change notification";
updateScreensIfNeeded(); // As a last resort we update screens here
});
}
bool QCocoaScreen::updateScreensIfNeeded()
{
if (!s_screenConfigurationBeforeUpdate) {
qCDebug(lcQpaScreen) << "QScreens have already been updated, all good";
return true;
}
if (s_screenConfigurationBeforeUpdate == NSScreen.screens) {
qCDebug(lcQpaScreen) << "Still waiting for NSScreen configuration change";
return false;
}
qCDebug(lcQpaScreen, "NSScreen configuration changed to %p", NSScreen.screens);
updateScreens();
s_screenConfigurationBeforeUpdate = nil;
return true;
}
/*
Update the list of available QScreens, and the properties of existing screens.
At this point we rely on the NSScreen.screens to be up to date.
*/
void QCocoaScreen::updateScreens()
{
uint32_t displayCount = 0;
if (CGGetOnlineDisplayList(0, nullptr, &displayCount) != kCGErrorSuccess)
qFatal("Failed to get number of online displays");
QVector<CGDirectDisplayID> onlineDisplays(displayCount);
if (CGGetOnlineDisplayList(displayCount, onlineDisplays.data(), &displayCount) != kCGErrorSuccess)
qFatal("Failed to get online displays");
qCInfo(lcQpaScreen) << "Updating screens with" << displayCount
<< "online displays:" << onlineDisplays;
// TODO: Verify whether we can always assume the main display is first
int mainDisplayIndex = onlineDisplays.indexOf(CGMainDisplayID());
if (mainDisplayIndex < 0) {
qCWarning(lcQpaScreen) << "Main display not in list of online displays!";
} else if (mainDisplayIndex > 0) {
qCWarning(lcQpaScreen) << "Main display not first display, making sure it is";
onlineDisplays.move(mainDisplayIndex, 0);
}
for (CGDirectDisplayID displayId : onlineDisplays) {
Q_ASSERT(CGDisplayIsOnline(displayId));
if (CGDisplayMirrorsDisplay(displayId))
continue;
// A single physical screen can map to multiple displays IDs,
// depending on which GPU is in use or which physical port the
// screen is connected to. By mapping the display ID to a UUID,
// which are shared between displays that target the same screen,
// we can pick an existing QScreen to update instead of needlessly
// adding and removing QScreens.
QCFType<CFUUIDRef> uuid = CGDisplayCreateUUIDFromDisplayID(displayId);
Q_ASSERT(uuid);
if (QCocoaScreen *existingScreen = QCocoaScreen::get(uuid)) {
existingScreen->update(displayId);
qCInfo(lcQpaScreen) << "Updated" << existingScreen;
if (CGDisplayIsMain(displayId) && existingScreen != qGuiApp->primaryScreen()->handle()) {
qCInfo(lcQpaScreen) << "Primary screen changed to" << existingScreen;
QWindowSystemInterface::handlePrimaryScreenChanged(existingScreen);
}
} else {
QCocoaScreen::add(displayId);
}
}
for (QScreen *screen : QGuiApplication::screens()) {
QCocoaScreen *platformScreen = static_cast<QCocoaScreen*>(screen->handle());
if (!platformScreen->isOnline() || platformScreen->isMirroring())
platformScreen->remove();
}
}
void QCocoaScreen::add(CGDirectDisplayID displayId)
{
const bool isPrimary = CGDisplayIsMain(displayId);
QCocoaScreen *cocoaScreen = new QCocoaScreen(displayId);
qCInfo(lcQpaScreen) << "Adding" << cocoaScreen
<< (isPrimary ? "as new primary screen" : "");
QWindowSystemInterface::handleScreenAdded(cocoaScreen, isPrimary);
}
QCocoaScreen::QCocoaScreen(CGDirectDisplayID displayId)
: QPlatformScreen(), m_displayId(displayId)
{
update(m_displayId);
m_cursor = new QCocoaCursor;
}
void QCocoaScreen::cleanupScreens()
{
// Remove screens in reverse order to avoid crash in case of multiple screens
for (QScreen *screen : backwards(QGuiApplication::screens()))
static_cast<QCocoaScreen*>(screen->handle())->remove();
}
void QCocoaScreen::remove()
{
// This may result in the application responding to QGuiApplication::screenRemoved
// by moving the window to another screen, either by setGeometry, or by setScreen.
// If the window isn't moved by the application, Qt will as a fallback move it to
// the primary screen via setScreen. Due to the way setScreen works, this won't
// actually recreate the window on the new screen, it will just assign the new
// QScreen to the window. The associated NSWindow will have an NSScreen determined
// by AppKit. AppKit will then move the window to another screen by changing the
// geometry, and we will get a callback in QCocoaWindow::windowDidMove and then
// QCocoaWindow::windowDidChangeScreen. At that point the window will appear to have
// already changed its screen, but that's only true if comparing the Qt screens,
// not when comparing the NSScreens.
qCInfo(lcQpaScreen) << "Removing " << this;
QWindowSystemInterface::handleScreenRemoved(this);
}
QCocoaScreen::~QCocoaScreen()
{
Q_ASSERT_X(!screen(), "QCocoaScreen", "QScreen should be deleted first");
delete m_cursor;
CVDisplayLinkRelease(m_displayLink);
if (m_displayLinkSource)
dispatch_release(m_displayLinkSource);
}
static QString displayName(CGDirectDisplayID displayID)
{
QIOType<io_iterator_t> iterator;
if (IOServiceGetMatchingServices(kIOMasterPortDefault,
IOServiceMatching("IODisplayConnect"), &iterator))
return QString();
QIOType<io_service_t> display;
while ((display = IOIteratorNext(iterator)) != 0)
{
NSDictionary *info = [(__bridge NSDictionary*)IODisplayCreateInfoDictionary(
display, kIODisplayOnlyPreferredName) autorelease];
if ([[info objectForKey:@kDisplayVendorID] longValue] != CGDisplayVendorNumber(displayID))
continue;
if ([[info objectForKey:@kDisplayProductID] longValue] != CGDisplayModelNumber(displayID))
continue;
if ([[info objectForKey:@kDisplaySerialNumber] longValue] != CGDisplaySerialNumber(displayID))
continue;
NSDictionary *localizedNames = [info objectForKey:@kDisplayProductName];
if (![localizedNames count])
break; // Correct screen, but no name in dictionary
return QString::fromNSString([localizedNames objectForKey:[[localizedNames allKeys] objectAtIndex:0]]);
}
return QString();
}
void QCocoaScreen::update(CGDirectDisplayID displayId)
{
if (displayId != m_displayId) {
qCDebug(lcQpaScreen) << "Reconnecting" << this << "as display" << displayId;
m_displayId = displayId;
}
Q_ASSERT(isOnline());
const QRect previousGeometry = m_geometry;
const QRect previousAvailableGeometry = m_availableGeometry;
const QDpi previousLogicalDpi = m_logicalDpi;
const qreal previousRefreshRate = m_refreshRate;
// Some properties are only available via NSScreen
NSScreen *nsScreen = nativeScreen();
Q_ASSERT(nsScreen);
// The reference screen for the geometry is always the primary screen
QRectF primaryScreenGeometry = QRectF::fromCGRect(CGDisplayBounds(CGMainDisplayID()));
m_geometry = qt_mac_flip(QRectF::fromCGRect(nsScreen.frame), primaryScreenGeometry).toRect();
m_availableGeometry = qt_mac_flip(QRectF::fromCGRect(nsScreen.visibleFrame), primaryScreenGeometry).toRect();
m_devicePixelRatio = nsScreen.backingScaleFactor;
m_format = QImage::Format_RGB32;
m_depth = NSBitsPerPixelFromDepth(nsScreen.depth);
CGSize size = CGDisplayScreenSize(m_displayId);
m_physicalSize = QSizeF(size.width, size.height);
m_logicalDpi.first = 72;
m_logicalDpi.second = 72;
QCFType<CGDisplayModeRef> displayMode = CGDisplayCopyDisplayMode(m_displayId);
float refresh = CGDisplayModeGetRefreshRate(displayMode);
m_refreshRate = refresh > 0 ? refresh : 60.0;
m_name = displayName(m_displayId);
const bool didChangeGeometry = m_geometry != previousGeometry || m_availableGeometry != previousAvailableGeometry;
if (didChangeGeometry)
QWindowSystemInterface::handleScreenGeometryChange(screen(), geometry(), availableGeometry());
if (m_logicalDpi != previousLogicalDpi)
QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(screen(), m_logicalDpi.first, m_logicalDpi.second);
if (m_refreshRate != previousRefreshRate)
QWindowSystemInterface::handleScreenRefreshRateChange(screen(), m_refreshRate);
}
// ----------------------- Display link -----------------------
Q_LOGGING_CATEGORY(lcQpaScreenUpdates, "qt.qpa.screen.updates", QtCriticalMsg);
void QCocoaScreen::requestUpdate()
{
Q_ASSERT(m_displayId);
if (!m_displayLink) {
CVDisplayLinkCreateWithCGDisplay(m_displayId, &m_displayLink);
CVDisplayLinkSetOutputCallback(m_displayLink, [](CVDisplayLinkRef, const CVTimeStamp*,
const CVTimeStamp*, CVOptionFlags, CVOptionFlags*, void* displayLinkContext) -> int {
// FIXME: It would be nice if update requests would include timing info
static_cast<QCocoaScreen*>(displayLinkContext)->deliverUpdateRequests();
return kCVReturnSuccess;
}, this);
qCDebug(lcQpaScreenUpdates) << "Display link created for" << this;
// During live window resizing -[NSWindow _resizeWithEvent:] will spin a local event loop
// in event-tracking mode, dequeuing only the mouse drag events needed to update the window's
// frame. It will repeatedly spin this loop until no longer receiving any mouse drag events,
// and will then update the frame (effectively coalescing/compressing the events). Unfortunately
// the events are pulled out using -[NSApplication nextEventMatchingEventMask:untilDate:inMode:dequeue:]
// which internally uses CFRunLoopRunSpecific, so the event loop will also process GCD queues and other
// runloop sources that have been added to the tracking mode. This includes the GCD display-link
// source that we use to marshal the display-link callback over to the main thread. If the
// subsequent delivery of the update-request on the main thread stalls due to inefficient
// user code, the NSEventThread will have had time to deliver additional mouse drag events,
// and the logic in -[NSWindow _resizeWithEvent:] will keep on compressing events and never
// get to the point of actually updating the window frame, making it seem like the window
// is stuck in its original size. Only when the user stops moving their mouse, and the event
// queue is completely drained of drag events, will the window frame be updated.
// By keeping an event tap listening for drag events, registered as a version 1 runloop source,
// we prevent the GCD source from being prioritized, giving the resize logic enough time
// to finish coalescing the events. This is incidental, but conveniently gives us the behavior
// we are looking for, interleaving display-link updates and resize events.
static CFMachPortRef eventTap = []() {
CFMachPortRef eventTap = CGEventTapCreateForPid(getpid(), kCGTailAppendEventTap,
kCGEventTapOptionListenOnly, NSEventMaskLeftMouseDragged,
[](CGEventTapProxy, CGEventType type, CGEventRef event, void *) -> CGEventRef {
if (type == kCGEventTapDisabledByTimeout)
qCWarning(lcQpaScreenUpdates) << "Event tap disabled due to timeout!";
return event; // Listen only tap, so what we return doesn't really matter
}, nullptr);
CGEventTapEnable(eventTap, false); // Event taps are normally enabled when created
static CFRunLoopSourceRef runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserverForName:NSWindowWillStartLiveResizeNotification object:nil queue:nil
usingBlock:^(NSNotification *notification) {
qCDebug(lcQpaScreenUpdates) << "Live resize of" << notification.object
<< "started. Enabling event tap";
CGEventTapEnable(eventTap, true);
}];
[center addObserverForName:NSWindowDidEndLiveResizeNotification object:nil queue:nil
usingBlock:^(NSNotification *notification) {
qCDebug(lcQpaScreenUpdates) << "Live resize of" << notification.object
<< "ended. Disabling event tap";
CGEventTapEnable(eventTap, false);
}];
return eventTap;
}();
Q_UNUSED(eventTap);
}
if (!CVDisplayLinkIsRunning(m_displayLink)) {
qCDebug(lcQpaScreenUpdates) << "Starting display link for" << this;
CVDisplayLinkStart(m_displayLink);
}
}
// Helper to allow building up debug output in multiple steps
struct DeferredDebugHelper
{
DeferredDebugHelper(const QLoggingCategory &cat) {
if (cat.isDebugEnabled())
debug = new QDebug(QMessageLogger().debug(cat).nospace());
}
~DeferredDebugHelper() {
flushOutput();
}
void flushOutput() {
if (debug) {
delete debug;
debug = nullptr;
}
}
QDebug *debug = nullptr;
};
#define qDeferredDebug(helper) if (Q_UNLIKELY(helper.debug)) *helper.debug
void QCocoaScreen::deliverUpdateRequests()
{
if (!isOnline())
return;
QMacAutoReleasePool pool;
// The CVDisplayLink callback is a notification that it's a good time to produce a new frame.
// Since the callback is delivered on a separate thread we have to marshal it over to the
// main thread, as Qt requires update requests to be delivered there. This needs to happen
// asynchronously, as otherwise we may end up deadlocking if the main thread calls back
// into any of the CVDisplayLink APIs.
if (!NSThread.isMainThread) {
// We're explicitly not using the data of the GCD source to track the pending updates,
// as the data isn't reset to 0 until after the event handler, and also doesn't update
// during the event handler, both of which we need to track late frames.
const int pendingUpdates = ++m_pendingUpdates;
DeferredDebugHelper screenUpdates(lcQpaScreenUpdates());
qDeferredDebug(screenUpdates) << "display link callback for screen " << m_displayId;
if (const int framesAheadOfDelivery = pendingUpdates - 1) {
// If we have more than one update pending it means that a previous display link callback
// has not been fully processed on the main thread, either because GCD hasn't delivered
// it on the main thread yet, because the processing of the update request is taking
// too long, or because the update request was deferred due to window live resizing.
qDeferredDebug(screenUpdates) << ", " << framesAheadOfDelivery << " frame(s) ahead";
// We skip the frame completely if we're live-resizing, to not put any extra
// strain on the main thread runloop. Otherwise we assume we should push frames
// as fast as possible, and hopefully the callback will be delivered on the
// main thread just when the previous finished.
if (qt_apple_sharedApplication().keyWindow.inLiveResize) {
qDeferredDebug(screenUpdates) << "; waiting for main thread to catch up";
return;
}
}
qDeferredDebug(screenUpdates) << "; signaling dispatch source";
if (!m_displayLinkSource) {
m_displayLinkSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, dispatch_get_main_queue());
dispatch_source_set_event_handler(m_displayLinkSource, ^{
deliverUpdateRequests();
});
dispatch_resume(m_displayLinkSource);
}
dispatch_source_merge_data(m_displayLinkSource, 1);
} else {
DeferredDebugHelper screenUpdates(lcQpaScreenUpdates());
qDeferredDebug(screenUpdates) << "gcd event handler on main thread";
const int pendingUpdates = m_pendingUpdates;
if (pendingUpdates > 1)
qDeferredDebug(screenUpdates) << ", " << (pendingUpdates - 1) << " frame(s) behind display link";
screenUpdates.flushOutput();
bool pauseUpdates = true;
auto windows = QGuiApplication::allWindows();
for (int i = 0; i < windows.size(); ++i) {
QWindow *window = windows.at(i);
auto *platformWindow = static_cast<QCocoaWindow*>(window->handle());
if (!platformWindow)
continue;
if (!platformWindow->hasPendingUpdateRequest())
continue;
if (window->screen() != screen())
continue;
// Skip windows that are not doing update requests via display link
if (!platformWindow->updatesWithDisplayLink())
continue;
platformWindow->deliverUpdateRequest();
// Another update request was triggered, keep the display link running
if (platformWindow->hasPendingUpdateRequest())
pauseUpdates = false;
}
if (pauseUpdates) {
// Pause the display link if there are no pending update requests
qCDebug(lcQpaScreenUpdates) << "Stopping display link for" << this;
CVDisplayLinkStop(m_displayLink);
}
if (const int missedUpdates = m_pendingUpdates.fetchAndStoreRelaxed(0) - pendingUpdates) {
qCWarning(lcQpaScreenUpdates) << "main thread missed" << missedUpdates
<< "update(s) from display link during update request delivery";
}
}
}
bool QCocoaScreen::isRunningDisplayLink() const
{
return m_displayLink && CVDisplayLinkIsRunning(m_displayLink);
}
// -----------------------------------------------------------
QPlatformScreen::SubpixelAntialiasingType QCocoaScreen::subpixelAntialiasingTypeHint() const
{
QPlatformScreen::SubpixelAntialiasingType type = QPlatformScreen::subpixelAntialiasingTypeHint();
if (type == QPlatformScreen::Subpixel_None) {
// Every OSX machine has RGB pixels unless a peculiar or rotated non-Apple screen is attached
type = QPlatformScreen::Subpixel_RGB;
}
return type;
}
QWindow *QCocoaScreen::topLevelAt(const QPoint &point) const
{
NSPoint screenPoint = mapToNative(point);
// Search (hit test) for the top-level window. [NSWidow windowNumberAtPoint:
// belowWindowWithWindowNumber] may return windows that are not interesting
// to Qt. The search iterates until a suitable window or no window is found.
NSInteger topWindowNumber = 0;
QWindow *window = nullptr;
do {
// Get the top-most window, below any previously rejected window.
topWindowNumber = [NSWindow windowNumberAtPoint:screenPoint
belowWindowWithWindowNumber:topWindowNumber];
// Continue the search if the window does not belong to this process.
NSWindow *nsWindow = [NSApp windowWithWindowNumber:topWindowNumber];
if (!nsWindow)
continue;
// Continue the search if the window does not belong to Qt.
if (![nsWindow conformsToProtocol:@protocol(QNSWindowProtocol)])
continue;
QCocoaWindow *cocoaWindow = qnsview_cast(nsWindow.contentView).platformWindow;
if (!cocoaWindow)
continue;
window = cocoaWindow->window();
// Continue the search if the window is not a top-level window.
if (!window->isTopLevel())
continue;
// Stop searching. The current window is the correct window.
break;
} while (topWindowNumber > 0);
return window;
}
QPixmap QCocoaScreen::grabWindow(WId view, int x, int y, int width, int height) const
{
// Determine the grab rect. FIXME: The rect should be bounded by the view's
// geometry, but note that for the pixeltool use case that window will be the
// desktop widget's view, which currently gets resized to fit one screen
// only, since its NSWindow has the NSWindowStyleMaskTitled flag set.
Q_UNUSED(view);
QRect grabRect = QRect(x, y, width, height);
qCDebug(lcQpaScreen) << "input grab rect" << grabRect;
// Find which displays to grab from, or all of them if the grab size is unspecified
const int maxDisplays = 128;
CGDirectDisplayID displays[maxDisplays];
CGDisplayCount displayCount;
CGRect cgRect = (width < 0 || height < 0) ? CGRectInfinite : grabRect.toCGRect();
const CGDisplayErr err = CGGetDisplaysWithRect(cgRect, maxDisplays, displays, &displayCount);
if (err || displayCount == 0)
return QPixmap();
// If the grab size is not specified, set it to be the bounding box of all screens,
if (width < 0 || height < 0) {
QRect windowRect;
for (uint i = 0; i < displayCount; ++i) {
QRect displayBounds = QRectF::fromCGRect(CGDisplayBounds(displays[i])).toRect();
windowRect = windowRect.united(displayBounds);
}
if (grabRect.width() < 0)
grabRect.setWidth(windowRect.width());
if (grabRect.height() < 0)
grabRect.setHeight(windowRect.height());
}
qCDebug(lcQpaScreen) << "final grab rect" << grabRect << "from" << displayCount << "displays";
// Grab images from each display
QVector<QImage> images;
QVector<QRect> destinations;
for (uint i = 0; i < displayCount; ++i) {
auto display = displays[i];
QRect displayBounds = QRectF::fromCGRect(CGDisplayBounds(display)).toRect();
QRect grabBounds = displayBounds.intersected(grabRect);
QRect displayLocalGrabBounds = QRect(QPoint(grabBounds.topLeft() - displayBounds.topLeft()), grabBounds.size());
QImage displayImage = qt_mac_toQImage(QCFType<CGImageRef>(CGDisplayCreateImageForRect(display, displayLocalGrabBounds.toCGRect())));
displayImage.setDevicePixelRatio(displayImage.size().width() / displayLocalGrabBounds.size().width());
images.append(displayImage);
QRect destBounds = QRect(QPoint(grabBounds.topLeft() - grabRect.topLeft()), grabBounds.size());
destinations.append(destBounds);
qCDebug(lcQpaScreen) << "grab display" << i << "global" << grabBounds << "local" << displayLocalGrabBounds
<< "grab image size" << displayImage.size() << "devicePixelRatio" << displayImage.devicePixelRatio();
}
// Determine the highest dpr, which becomes the dpr for the returned pixmap.
qreal dpr = 1.0;
for (uint i = 0; i < displayCount; ++i)
dpr = qMax(dpr, images.at(i).devicePixelRatio());
// Allocate target pixmap and draw each screen's content
qCDebug(lcQpaScreen) << "Create grap pixmap" << grabRect.size() << "at devicePixelRatio" << dpr;
QPixmap windowPixmap(grabRect.size() * dpr);
windowPixmap.setDevicePixelRatio(dpr);
windowPixmap.fill(Qt::transparent);
QPainter painter(&windowPixmap);
for (uint i = 0; i < displayCount; ++i)
painter.drawImage(destinations.at(i), images.at(i));
return windowPixmap;
}
bool QCocoaScreen::isOnline() const
{
// When a display is disconnected CGDisplayIsOnline and other CGDisplay
// functions that take a displayId will not return false, but will start
// returning -1 to signal that the displayId is invalid. Some functions
// will also assert or even crash in this case, so it's important that
// we double check if a display is online before calling other functions.
auto isOnline = CGDisplayIsOnline(m_displayId);
static const uint32_t kCGDisplayIsDisconnected = int32_t(-1);
return isOnline != kCGDisplayIsDisconnected && isOnline;
}
/*
Returns true if a screen is mirroring another screen
*/
bool QCocoaScreen::isMirroring() const
{
if (!isOnline())
return false;
return CGDisplayMirrorsDisplay(m_displayId);
}
/*!
The screen used as a reference for global window geometry
*/
QCocoaScreen *QCocoaScreen::primaryScreen()
{
// Note: The primary screen that Qt knows about may not match the current CGMainDisplayID()
// if macOS has not yet been able to inform us that the main display has changed, but we
// will update the primary screen accordingly once the reconfiguration callback comes in.
return static_cast<QCocoaScreen *>(QGuiApplication::primaryScreen()->handle());
}
QList<QPlatformScreen*> QCocoaScreen::virtualSiblings() const
{
QList<QPlatformScreen*> siblings;
// Screens on macOS are always part of the same virtual desktop
for (QScreen *screen : QGuiApplication::screens())
siblings << screen->handle();
return siblings;
}
QCocoaScreen *QCocoaScreen::get(NSScreen *nsScreen)
{
if (s_screenConfigurationBeforeUpdate) {
qCWarning(lcQpaScreen) << "Trying to resolve screen while waiting for screen reconfigure!";
if (!updateScreensIfNeeded())
qCWarning(lcQpaScreen) << "Failed to do last minute screen update. Expect crashes.";
}
return get(nsScreen.qt_displayId);
}
QCocoaScreen *QCocoaScreen::get(CGDirectDisplayID displayId)
{
for (QScreen *screen : QGuiApplication::screens()) {
QCocoaScreen *cocoaScreen = static_cast<QCocoaScreen*>(screen->handle());
if (cocoaScreen->m_displayId == displayId)
return cocoaScreen;
}
return nullptr;
}
QCocoaScreen *QCocoaScreen::get(CFUUIDRef uuid)
{
for (QScreen *screen : QGuiApplication::screens()) {
auto *platformScreen = static_cast<QCocoaScreen*>(screen->handle());
if (!platformScreen->isOnline())
continue;
auto displayId = platformScreen->displayId();
QCFType<CFUUIDRef> candidateUuid(CGDisplayCreateUUIDFromDisplayID(displayId));
Q_ASSERT(candidateUuid);
if (candidateUuid == uuid)
return platformScreen;
}
return nullptr;
}
NSScreen *QCocoaScreen::nativeScreen() const
{
if (!m_displayId)
return nil; // The display has been disconnected
for (NSScreen *screen in NSScreen.screens) {
if (screen.qt_displayId == m_displayId)
return screen;
}
return nil;
}
CGPoint QCocoaScreen::mapToNative(const QPointF &pos, QCocoaScreen *screen)
{
Q_ASSERT(screen);
return qt_mac_flip(pos, screen->geometry()).toCGPoint();
}
CGRect QCocoaScreen::mapToNative(const QRectF &rect, QCocoaScreen *screen)
{
Q_ASSERT(screen);
return qt_mac_flip(rect, screen->geometry()).toCGRect();
}
QPointF QCocoaScreen::mapFromNative(CGPoint pos, QCocoaScreen *screen)
{
Q_ASSERT(screen);
return qt_mac_flip(QPointF::fromCGPoint(pos), screen->geometry());
}
QRectF QCocoaScreen::mapFromNative(CGRect rect, QCocoaScreen *screen)
{
Q_ASSERT(screen);
return qt_mac_flip(QRectF::fromCGRect(rect), screen->geometry());
}
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug debug, const QCocoaScreen *screen)
{
QDebugStateSaver saver(debug);
debug.nospace();
debug << "QCocoaScreen(" << (const void *)screen;
if (screen) {
debug << ", " << screen->name();
if (screen->isOnline()) {
if (CGDisplayIsAsleep(screen->displayId()))
debug << ", Sleeping";
if (auto mirroring = CGDisplayMirrorsDisplay(screen->displayId()))
debug << ", mirroring=" << mirroring;
} else {
debug << ", Offline";
}
debug << ", " << screen->geometry();
debug << ", dpr=" << screen->devicePixelRatio();
debug << ", displayId=" << screen->displayId();
if (auto nativeScreen = screen->nativeScreen())
debug << ", " << nativeScreen;
}
debug << ')';
return debug;
}
#endif // !QT_NO_DEBUG_STREAM
#include "qcocoascreen.moc"
QT_END_NAMESPACE
@implementation NSScreen (QtExtras)
- (CGDirectDisplayID)qt_displayId
{
return [self.deviceDescription[@"NSScreenNumber"] unsignedIntValue];
}
@end

View File

@ -1,246 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qcocoasystemsettings.h"
#include "qcocoahelpers.h"
#include <QtCore/private/qcore_mac_p.h>
#include <QtGui/qfont.h>
#include <QtGui/private/qcoregraphics_p.h>
#if !QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14)
@interface NSColor (MojaveForwardDeclarations)
@property (class, strong, readonly) NSColor *selectedContentBackgroundColor NS_AVAILABLE_MAC(10_14);
@property (class, strong, readonly) NSColor *unemphasizedSelectedTextBackgroundColor NS_AVAILABLE_MAC(10_14);
@property (class, strong, readonly) NSColor *unemphasizedSelectedTextColor NS_AVAILABLE_MAC(10_14);
@property (class, strong, readonly) NSColor *unemphasizedSelectedContentBackgroundColor NS_AVAILABLE_MAC(10_14);
@property (class, strong, readonly) NSArray<NSColor *> *alternatingContentBackgroundColors NS_AVAILABLE_MAC(10_14);
// Missing from non-Mojave SDKs, even if introduced in 10.10
@property (class, strong, readonly) NSColor *linkColor NS_AVAILABLE_MAC(10_10);
@end
#endif
QT_BEGIN_NAMESPACE
QPalette * qt_mac_createSystemPalette()
{
QColor qc;
// Standard palette initialization (copied from Qt 4 styles)
QBrush backgroundBrush = qt_mac_toQBrush([NSColor windowBackgroundColor]);
QColor background = backgroundBrush.color();
QColor light(background.lighter(110));
QColor dark(background.darker(160));
QColor mid(background.darker(140));
QPalette *palette = new QPalette(Qt::black, background, light, dark, mid, Qt::black, Qt::white);
palette->setBrush(QPalette::Window, backgroundBrush);
palette->setBrush(QPalette::Disabled, QPalette::WindowText, dark);
palette->setBrush(QPalette::Disabled, QPalette::Text, dark);
palette->setBrush(QPalette::Disabled, QPalette::ButtonText, dark);
palette->setBrush(QPalette::Disabled, QPalette::Base, backgroundBrush);
QBrush textBackgroundBrush = qt_mac_toQBrush([NSColor textBackgroundColor]);
palette->setBrush(QPalette::Active, QPalette::Base, textBackgroundBrush);
palette->setBrush(QPalette::Inactive, QPalette::Base, textBackgroundBrush);
palette->setColor(QPalette::Disabled, QPalette::Dark, QColor(191, 191, 191));
palette->setColor(QPalette::Active, QPalette::Dark, QColor(191, 191, 191));
palette->setColor(QPalette::Inactive, QPalette::Dark, QColor(191, 191, 191));
// System palette initialization:
QBrush br = qt_mac_toQBrush([NSColor selectedControlColor]);
palette->setBrush(QPalette::Active, QPalette::Highlight, br);
if (__builtin_available(macOS 10.14, *)) {
const auto inactiveHighlight = qt_mac_toQBrush([NSColor unemphasizedSelectedContentBackgroundColor]);
palette->setBrush(QPalette::Inactive, QPalette::Highlight, inactiveHighlight);
palette->setBrush(QPalette::Disabled, QPalette::Highlight, inactiveHighlight);
} else {
palette->setBrush(QPalette::Inactive, QPalette::Highlight, br);
palette->setBrush(QPalette::Disabled, QPalette::Highlight, br);
}
palette->setBrush(QPalette::Shadow, qt_mac_toQColor([NSColor shadowColor]));
qc = qt_mac_toQColor([NSColor controlTextColor]);
palette->setColor(QPalette::Active, QPalette::Text, qc);
palette->setColor(QPalette::Active, QPalette::WindowText, qc);
palette->setColor(QPalette::Active, QPalette::HighlightedText, qc);
palette->setColor(QPalette::Inactive, QPalette::Text, qc);
palette->setColor(QPalette::Inactive, QPalette::WindowText, qc);
palette->setColor(QPalette::Inactive, QPalette::HighlightedText, qc);
qc = qt_mac_toQColor([NSColor disabledControlTextColor]);
palette->setColor(QPalette::Disabled, QPalette::Text, qc);
palette->setColor(QPalette::Disabled, QPalette::WindowText, qc);
palette->setColor(QPalette::Disabled, QPalette::HighlightedText, qc);
palette->setBrush(QPalette::ToolTipBase, qt_mac_toQBrush([NSColor controlColor]));
// fix for https://bugreports.qt.io/browse/QTBUG-71740
palette->setColor(QPalette::Normal, QPalette::Link, qt_mac_toQColor([NSColor linkColor]));
return palette;
}
struct QMacPaletteMap {
inline QMacPaletteMap(QPlatformTheme::Palette p, NSColor *a, NSColor *i) :
active(a), inactive(i), paletteRole(p) { }
NSColor *active;
NSColor *inactive;
QPlatformTheme::Palette paletteRole;
};
#define MAC_PALETTE_ENTRY(pal, active, inactive) \
QMacPaletteMap(pal, [NSColor active], [NSColor inactive])
static QMacPaletteMap mac_widget_colors[] = {
MAC_PALETTE_ENTRY(QPlatformTheme::ToolButtonPalette, controlTextColor, disabledControlTextColor),
MAC_PALETTE_ENTRY(QPlatformTheme::ButtonPalette, controlTextColor, disabledControlTextColor),
MAC_PALETTE_ENTRY(QPlatformTheme::HeaderPalette, headerTextColor, disabledControlTextColor),
MAC_PALETTE_ENTRY(QPlatformTheme::ComboBoxPalette, controlTextColor, disabledControlTextColor),
MAC_PALETTE_ENTRY(QPlatformTheme::ItemViewPalette, textColor, disabledControlTextColor),
MAC_PALETTE_ENTRY(QPlatformTheme::MessageBoxLabelPalette, textColor, disabledControlTextColor),
MAC_PALETTE_ENTRY(QPlatformTheme::TabBarPalette, controlTextColor, disabledControlTextColor),
MAC_PALETTE_ENTRY(QPlatformTheme::LabelPalette, textColor, disabledControlTextColor),
MAC_PALETTE_ENTRY(QPlatformTheme::GroupBoxPalette, textColor, disabledControlTextColor),
MAC_PALETTE_ENTRY(QPlatformTheme::MenuPalette, controlTextColor, disabledControlTextColor),
MAC_PALETTE_ENTRY(QPlatformTheme::MenuBarPalette, controlTextColor, disabledControlTextColor),
MAC_PALETTE_ENTRY(QPlatformTheme::TextEditPalette, textColor, disabledControlTextColor),
MAC_PALETTE_ENTRY(QPlatformTheme::TextLineEditPalette, textColor, disabledControlTextColor)
};
#undef MAC_PALETTE_ENTRY
static const int mac_widget_colors_count = sizeof(mac_widget_colors) / sizeof(mac_widget_colors[0]);
QHash<QPlatformTheme::Palette, QPalette*> qt_mac_createRolePalettes()
{
QHash<QPlatformTheme::Palette, QPalette*> palettes;
QColor qc;
for (int i = 0; i < mac_widget_colors_count; i++) {
QPalette &pal = *qt_mac_createSystemPalette();
if (mac_widget_colors[i].active) {
qc = qt_mac_toQColor(mac_widget_colors[i].active);
pal.setColor(QPalette::Active, QPalette::Text, qc);
pal.setColor(QPalette::Inactive, QPalette::Text, qc);
pal.setColor(QPalette::Active, QPalette::WindowText, qc);
pal.setColor(QPalette::Inactive, QPalette::WindowText, qc);
pal.setColor(QPalette::Active, QPalette::HighlightedText, qc);
pal.setColor(QPalette::Inactive, QPalette::HighlightedText, qc);
pal.setColor(QPalette::Active, QPalette::ButtonText, qc);
pal.setColor(QPalette::Inactive, QPalette::ButtonText, qc);
qc = qt_mac_toQColor(mac_widget_colors[i].inactive);
pal.setColor(QPalette::Disabled, QPalette::Text, qc);
pal.setColor(QPalette::Disabled, QPalette::WindowText, qc);
pal.setColor(QPalette::Disabled, QPalette::HighlightedText, qc);
pal.setColor(QPalette::Disabled, QPalette::ButtonText, qc);
}
if (mac_widget_colors[i].paletteRole == QPlatformTheme::MenuPalette
|| mac_widget_colors[i].paletteRole == QPlatformTheme::MenuBarPalette) {
NSColor *selectedMenuItemColor = nil;
if (__builtin_available(macOS 10.14, *)) {
// Cheap approximation for NSVisualEffectView (see deprecation note for selectedMenuItemTextColor)
selectedMenuItemColor = [[NSColor selectedContentBackgroundColor] highlightWithLevel:0.4];
} else {
// selectedMenuItemColor would presumably be the correct color to use as the background
// for selected menu items. But that color is always blue, and doesn't follow the
// appearance color in system preferences. So we therefore deliberatly choose to use
// keyboardFocusIndicatorColor instead, which appears to have the same color value.
selectedMenuItemColor = [NSColor keyboardFocusIndicatorColor];
}
pal.setBrush(QPalette::Highlight, qt_mac_toQColor(selectedMenuItemColor));
qc = qt_mac_toQColor([NSColor labelColor]);
pal.setBrush(QPalette::ButtonText, qc);
pal.setBrush(QPalette::Text, qc);
qc = qt_mac_toQColor([NSColor selectedMenuItemTextColor]);
pal.setBrush(QPalette::HighlightedText, qc);
qc = qt_mac_toQColor([NSColor disabledControlTextColor]);
pal.setBrush(QPalette::Disabled, QPalette::Text, qc);
} else if ((mac_widget_colors[i].paletteRole == QPlatformTheme::ButtonPalette)
|| (mac_widget_colors[i].paletteRole == QPlatformTheme::HeaderPalette)
|| (mac_widget_colors[i].paletteRole == QPlatformTheme::TabBarPalette)) {
pal.setColor(QPalette::Disabled, QPalette::ButtonText,
pal.color(QPalette::Disabled, QPalette::Text));
pal.setColor(QPalette::Inactive, QPalette::ButtonText,
pal.color(QPalette::Inactive, QPalette::Text));
pal.setColor(QPalette::Active, QPalette::ButtonText,
pal.color(QPalette::Active, QPalette::Text));
} else if (mac_widget_colors[i].paletteRole == QPlatformTheme::ItemViewPalette) {
NSArray<NSColor *> *baseColors = nil;
NSColor *activeHighlightColor = nil;
if (__builtin_available(macOS 10.14, *)) {
baseColors = [NSColor alternatingContentBackgroundColors];
activeHighlightColor = [NSColor selectedContentBackgroundColor];
pal.setBrush(QPalette::Inactive, QPalette::HighlightedText,
qt_mac_toQBrush([NSColor unemphasizedSelectedTextColor]));
} else {
baseColors = [NSColor controlAlternatingRowBackgroundColors];
activeHighlightColor = [NSColor alternateSelectedControlColor];
pal.setBrush(QPalette::Inactive, QPalette::HighlightedText,
pal.brush(QPalette::Active, QPalette::Text));
}
pal.setBrush(QPalette::Base, qt_mac_toQBrush(baseColors[0]));
pal.setBrush(QPalette::AlternateBase, qt_mac_toQBrush(baseColors[1]));
pal.setBrush(QPalette::Active, QPalette::Highlight,
qt_mac_toQBrush(activeHighlightColor));
pal.setBrush(QPalette::Active, QPalette::HighlightedText,
qt_mac_toQBrush([NSColor alternateSelectedControlTextColor]));
pal.setBrush(QPalette::Inactive, QPalette::Text,
pal.brush(QPalette::Active, QPalette::Text));
} else if (mac_widget_colors[i].paletteRole == QPlatformTheme::TextEditPalette) {
pal.setBrush(QPalette::Active, QPalette::Base, qt_mac_toQColor([NSColor textBackgroundColor]));
pal.setBrush(QPalette::Inactive, QPalette::Text,
pal.brush(QPalette::Active, QPalette::Text));
pal.setBrush(QPalette::Inactive, QPalette::HighlightedText,
pal.brush(QPalette::Active, QPalette::Text));
} else if (mac_widget_colors[i].paletteRole == QPlatformTheme::TextLineEditPalette
|| mac_widget_colors[i].paletteRole == QPlatformTheme::ComboBoxPalette) {
pal.setBrush(QPalette::Active, QPalette::Base, qt_mac_toQColor([NSColor textBackgroundColor]));
pal.setBrush(QPalette::Disabled, QPalette::Base,
pal.brush(QPalette::Active, QPalette::Base));
} else if (mac_widget_colors[i].paletteRole == QPlatformTheme::LabelPalette) {
qc = qt_mac_toQColor([NSColor labelColor]);
pal.setBrush(QPalette::Inactive, QPalette::ToolTipText, qc);
}
palettes.insert(mac_widget_colors[i].paletteRole, &pal);
}
return palettes;
}
QT_END_NAMESPACE

View File

@ -1,234 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
// This file is included from qnsview.mm, and only used to organize the code
@implementation QT_MANGLE_NAMESPACE(QNSView) (Drawing)
- (void)initDrawing
{
self.wantsLayer = [self layerExplicitlyRequested]
|| [self shouldUseMetalLayer]
|| [self layerEnabledByMacOS];
// Enable high-DPI OpenGL for retina displays. Enabling has the side
// effect that Cocoa will start calling glViewport(0, 0, width, height),
// overriding any glViewport calls in application code. This is usually not a
// problem, except if the application wants to have a "custom" viewport.
// (like the hellogl example)
if (m_platformWindow->window()->supportsOpenGL()) {
self.wantsBestResolutionOpenGLSurface = qt_mac_resolveOption(YES, m_platformWindow->window(),
"_q_mac_wantsBestResolutionOpenGLSurface", "QT_MAC_WANTS_BEST_RESOLUTION_OPENGL_SURFACE");
// See also QCocoaGLContext::makeCurrent for software renderer workarounds.
}
}
- (BOOL)isOpaque
{
if (!m_platformWindow)
return true;
return m_platformWindow->isOpaque();
}
- (BOOL)isFlipped
{
return YES;
}
- (void)drawRect:(NSRect)dirtyRect
{
Q_UNUSED(dirtyRect);
if (!m_platformWindow)
return;
QRegion exposedRegion;
const NSRect *dirtyRects;
NSInteger numDirtyRects;
[self getRectsBeingDrawn:&dirtyRects count:&numDirtyRects];
for (int i = 0; i < numDirtyRects; ++i)
exposedRegion += QRectF::fromCGRect(dirtyRects[i]).toRect();
qCDebug(lcQpaDrawing) << "[QNSView drawRect:]" << m_platformWindow->window() << exposedRegion;
m_platformWindow->handleExposeEvent(exposedRegion);
}
- (BOOL)layerEnabledByMacOS
{
// AppKit has its own logic for this, but if we rely on that, our layers are created
// by AppKit at a point where we've already set up other parts of the platform plugin
// based on the presence of layers or not. Once we've rewritten these parts to support
// dynamically picking up layer enablement we can let AppKit do its thing.
if (QMacVersion::currentRuntime() >= QOperatingSystemVersion::MacOSBigSur)
return true; // Big Sur always enables layer-backing, regardless of SDK
if (QMacVersion::currentRuntime() >= QOperatingSystemVersion::MacOSMojave
&& QMacVersion::buildSDK() >= QOperatingSystemVersion::MacOSMojave)
return true; // Mojave and Catalina enable layers based on the app's SDK
return false; // Prior versions needed explicitly enabled layer backing
}
- (BOOL)layerExplicitlyRequested
{
static bool wantsLayer = [&]() {
int wantsLayer = qt_mac_resolveOption(-1, m_platformWindow->window(),
"_q_mac_wantsLayer", "QT_MAC_WANTS_LAYER");
if (wantsLayer != -1 && [self layerEnabledByMacOS]) {
qCWarning(lcQpaDrawing) << "Layer-backing can not be explicitly controlled on 10.14 when built against the 10.14 SDK";
return true;
}
return wantsLayer == 1;
}();
return wantsLayer;
}
- (BOOL)shouldUseMetalLayer
{
// MetalSurface needs a layer, and so does VulkanSurface (via MoltenVK)
QSurface::SurfaceType surfaceType = m_platformWindow->window()->surfaceType();
return surfaceType == QWindow::MetalSurface || surfaceType == QWindow::VulkanSurface;
}
- (CALayer *)makeBackingLayer
{
if ([self shouldUseMetalLayer]) {
// Check if Metal is supported. If it isn't then it's most likely
// too late at this point and the QWindow will be non-functional,
// but we can at least print a warning.
if (![MTLCreateSystemDefaultDevice() autorelease]) {
qWarning() << "QWindow initialization error: Metal is not supported";
return [super makeBackingLayer];
}
CAMetalLayer *layer = [CAMetalLayer layer];
// Set the contentsScale for the layer. This is normally done in
// viewDidChangeBackingProperties, however on startup that function
// is called before the layer is created here. The layer's drawableSize
// is updated from layoutSublayersOfLayer as usual.
layer.contentsScale = self.window.backingScaleFactor;
return layer;
}
return [super makeBackingLayer];
}
- (void)setLayer:(CALayer *)layer
{
qCDebug(lcQpaDrawing) << "Making" << self << "layer-backed with" << layer
<< "due to being" << ([self layerExplicitlyRequested] ? "explicitly requested"
: [self shouldUseMetalLayer] ? "needed by surface type" : "enabled by macOS");
[super setLayer:layer];
layer.delegate = self;
}
- (NSViewLayerContentsRedrawPolicy)layerContentsRedrawPolicy
{
// We need to set this explicitly since the super implementation
// returns LayerContentsRedrawNever for custom layers like CAMetalLayer.
return NSViewLayerContentsRedrawDuringViewResize;
}
#if 0 // Disabled until we enable lazy backingstore resizing
- (NSViewLayerContentsPlacement)layerContentsPlacement
{
// Always place the layer at top left without any automatic scaling,
// so that we can re-use larger layers when resizing a window down.
return NSViewLayerContentsPlacementTopLeft;
}
#endif
- (void)updateMetalLayerDrawableSize:(CAMetalLayer *)layer
{
CGSize drawableSize = layer.bounds.size;
drawableSize.width *= layer.contentsScale;
drawableSize.height *= layer.contentsScale;
layer.drawableSize = drawableSize;
}
- (void)layoutSublayersOfLayer:(CALayer *)layer
{
if ([layer isKindOfClass:CAMetalLayer.class])
[self updateMetalLayerDrawableSize:static_cast<CAMetalLayer* >(layer)];
}
- (void)displayLayer:(CALayer *)layer
{
if (!NSThread.isMainThread) {
// Qt is calling AppKit APIs such as -[NSOpenGLContext setView:] on secondary threads,
// which we shouldn't do. This may result in AppKit (wrongly) triggering a display on
// the thread where we made the call, so block it here and defer to the main thread.
qCWarning(lcQpaDrawing) << "Display non non-main thread! Deferring to main thread";
dispatch_async(dispatch_get_main_queue(), ^{ self.needsDisplay = YES; });
return;
}
Q_ASSERT(layer == self.layer);
if (!m_platformWindow)
return;
qCDebug(lcQpaDrawing) << "[QNSView displayLayer]" << m_platformWindow->window();
// FIXME: Find out if there's a way to resolve the dirty rect like in drawRect:
m_platformWindow->handleExposeEvent(QRectF::fromCGRect(self.bounds).toRect());
}
- (void)viewDidChangeBackingProperties
{
CALayer *layer = self.layer;
if (!layer)
return;
layer.contentsScale = self.window.backingScaleFactor;
// Metal layers must be manually updated on e.g. screen change
if ([layer isKindOfClass:CAMetalLayer.class]) {
[self updateMetalLayerDrawableSize:static_cast<CAMetalLayer* >(layer)];
[self setNeedsDisplay:YES];
}
}
@end

File diff suppressed because it is too large Load Diff