diff --git a/5.13.2/bin/7z.dll b/5.13.2/bin/7z.dll deleted file mode 100644 index 0ba2232..0000000 Binary files a/5.13.2/bin/7z.dll and /dev/null differ diff --git a/5.13.2/bin/7z.exe b/5.13.2/bin/7z.exe deleted file mode 100644 index d3fe532..0000000 Binary files a/5.13.2/bin/7z.exe and /dev/null differ diff --git a/5.13.2/bin/wget.exe b/5.13.2/bin/wget.exe deleted file mode 100644 index cda6b94..0000000 Binary files a/5.13.2/bin/wget.exe and /dev/null differ diff --git a/5.13.2/compile_mac.sh b/5.13.2/compile_mac.sh deleted file mode 100644 index 7c5839f..0000000 --- a/5.13.2/compile_mac.sh +++ /dev/null @@ -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/* \ No newline at end of file diff --git a/5.13.2/compile_mac_arm.sh b/5.13.2/compile_mac_arm.sh deleted file mode 100644 index 7554803..0000000 --- a/5.13.2/compile_mac_arm.sh +++ /dev/null @@ -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/* \ No newline at end of file diff --git a/5.13.2/compile_mac_dev.sh b/5.13.2/compile_mac_dev.sh deleted file mode 100644 index ec71047..0000000 --- a/5.13.2/compile_mac_dev.sh +++ /dev/null @@ -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 \ No newline at end of file diff --git a/5.13.2/compile_win.pl b/5.13.2/compile_win.pl deleted file mode 100644 index 04ad716..0000000 --- a/5.13.2/compile_win.pl +++ /dev/null @@ -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"; -} \ No newline at end of file diff --git a/5.13.2/qtbase/mkspecs/common/msvc-desktop.conf b/5.13.2/qtbase/mkspecs/common/msvc-desktop.conf deleted file mode 100644 index 24c2eb7..0000000 --- a/5.13.2/qtbase/mkspecs/common/msvc-desktop.conf +++ /dev/null @@ -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) diff --git a/5.13.2/qtbase/src/3rdparty/pcre2/pcre2.pro b/5.13.2/qtbase/src/3rdparty/pcre2/pcre2.pro deleted file mode 100644 index d89ebaa..0000000 --- a/5.13.2/qtbase/src/3rdparty/pcre2/pcre2.pro +++ /dev/null @@ -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 diff --git a/5.13.2/qtbase/src/corelib/configure.json b/5.13.2/qtbase/src/corelib/configure.json deleted file mode 100644 index d9d5954..0000000 --- a/5.13.2/qtbase/src/corelib/configure.json +++ /dev/null @@ -1,1079 +0,0 @@ -{ - "module": "core", - "testDir": "../../config.tests", - - "commandline": { - "options": { - "doubleconversion": { "type": "enum", "values": [ "no", "qt", "system" ] }, - "eventfd": "boolean", - "glib": "boolean", - "iconv": { "type": "enum", "values": [ "no", "yes", "posix", "sun", "gnu" ] }, - "icu": "boolean", - "inotify": "boolean", - "journald": "boolean", - "mimetype-database": "boolean", - "pcre": { "type": "enum", "values": [ "qt", "system" ] }, - "posix-ipc": { "type": "boolean", "name": "ipc_posix" }, - "pps": { "type": "boolean", "name": "qqnx_pps" }, - "slog2": "boolean", - "syslog": "boolean", - "trace": { "type": "optionalString", "values": [ "etw", "lttng", "no", "yes" ] } - } - }, - - "libraries": { - "doubleconversion": { - "label": "DoubleConversion", - "test": { - "main": "(void) double_conversion::StringToDoubleConverter::NO_FLAGS;" - }, - "headers": "double-conversion/double-conversion.h", - "sources": [ - "-ldouble-conversion" - ] - }, - "glib": { - "label": "GLib", - "test": { - "head": "typedef struct _GMainContext GMainContext;", - "main": [ - "g_thread_init(NULL);", - "(void) g_main_context_default();", - "(void) g_source_new(0, 0);", - "g_source_add_poll(NULL, NULL);" - ] - }, - "headers": "glib.h", - "sources": [ - { "type": "pkgConfig", "args": "glib-2.0 gthread-2.0" } - ] - }, - "posix_iconv": { - "label": "POSIX iconv", - "export": "iconv", - "test": { - "main": [ - "iconv_t x = iconv_open(\"\", \"\");", - "char *inp, *outp;", - "size_t inbytes, outbytes;", - "iconv(x, &inp, &inbytes, &outp, &outbytes);", - "iconv_close(x);" - ] - }, - "headers": "iconv.h", - "sources": [ - { "libs": "-liconv", "condition": "config.openbsd || config.haiku" }, - { "libs": "", "condition": "!(config.openbsd || config.haiku)" } - ] - }, - "gnu_iconv": { - "label": "GNU libiconv", - "export": "iconv", - "test": { - "main": [ - "iconv_t x = iconv_open(\"\", \"\");", - "const char *inp;", - "char *outp;", - "size_t inbytes, outbytes;", - "iconv(x, &inp, &inbytes, &outp, &outbytes);", - "iconv_close(x);" - ] - }, - "headers": "iconv.h", - "sources": [ - "-liconv" - ] - }, - "sun_iconv": { - "label": "SUN libiconv", - "export": "iconv", - "test": { - "inherit": "gnu_iconv" - }, - "sources": [ - "" - ] - }, - "icu": { - "label": "ICU", - "test": { - "main": [ - "UErrorCode status = U_ZERO_ERROR;", - "UCollator *collator = ucol_open(\"ru_RU\", &status);", - "if (!U_FAILURE(status))", - " ucol_close(collator);" - ] - }, - "headers": [ "unicode/utypes.h", "unicode/ucol.h", "unicode/ustring.h" ], - "sources": [ - { - "builds": { - "debug": "-lsicuind -lsicuucd -lsicudtd", - "release": "-lsicuin -lsicuuc -lsicudt" - }, - "condition": "config.win32 && !features.shared" - }, - { "libs": "-licuin -licuuc -licudt", "condition": "config.win32 && features.shared" }, - { "libs": "-licui18n -licuuc -licudata", "condition": "!config.win32" } - ], - "use": [ - { "lib": "libdl", "condition": "features.dlopen" } - ] - }, - "journald": { - "label": "journald", - "test": { - "main": "sd_journal_send(\"PRIORITY=%i\", LOG_INFO, NULL);" - }, - "headers": [ "systemd/sd-journal.h", "syslog.h" ], - "sources": [ - { "type": "pkgConfig", "args": "libsystemd" }, - { "type": "pkgConfig", "args": "libsystemd-journal" } - ] - }, - "libatomic": { - "label": "64 bit atomics", - "test": { - "tail": [ - "void test(volatile std::atomic &a)", - "{", - " std::int64_t v = a.load(std::memory_order_acquire);", - " while (!a.compare_exchange_strong(v, v + 1,", - " std::memory_order_acq_rel,", - " std::memory_order_acquire)) {", - " v = a.exchange(v - 1);", - " }", - " a.store(v + 1, std::memory_order_release);", - "}" - ], - "main": [ - "void *ptr = (void*)0xffffffc0; // any random pointer", - "test(*reinterpret_cast *>(ptr));" - ], - "qmake": "CONFIG += c++11" - }, - "headers": [ "atomic", "cstdint" ], - "sources": [ - "", - "-latomic" - ] - }, - "libdl": { - "label": "dlopen()", - "test": { - "main": [ - "dlclose(dlopen(0, 0));", - "dlsym(RTLD_DEFAULT, 0);", - "dlerror();" - ] - }, - "headers": "dlfcn.h", - "sources": [ - "", - "-ldl" - ] - }, - "librt": { - "label": "clock_gettime()", - "test": { - "main": "timespec ts; clock_gettime(CLOCK_REALTIME, &ts);" - }, - "headers": [ "unistd.h", "time.h" ], - "sources": [ - "", - "-lrt" - ] - }, - "lttng-ust": { - "label": "lttng-ust", - "test": { - "main": "lttng_session_destroy(nullptr);" - }, - "headers": "lttng/ust-events.h", - "sources": [ - { "type": "pkgConfig", "args": "lttng-ust" }, - "-llttng-ust" - ], - "use": "libdl" - }, - "pcre2": { - "label": "PCRE2", - "test": { - "head": "#define PCRE2_CODE_UNIT_WIDTH 16", - "tail": [ - "#if (PCRE2_MAJOR < 10) || ((PCRE2_MAJOR == 10) && (PCRE2_MINOR < 20))", - "# error This PCRE version is not supported", - "#endif" - ] - }, - "headers": "pcre2.h", - "sources": [ - { "type": "pkgConfig", "args": "libpcre2-16" }, - "-lpcre2-16" - ] - }, - "pps": { - "label": "PPS", - "test": { - "main": [ - "pps_decoder_t decoder;", - "pps_decoder_initialize(&decoder, NULL);" - ] - }, - "headers": "sys/pps.h", - "sources": [ - "-lpps" - ] - }, - "slog2": { - "label": "slog2", - "test": { - "main": "slog2_set_default_buffer((slog2_buffer_t)-1);" - }, - "export": "", - "headers": "sys/slog2.h", - "sources": [ - "-lslog2" - ] - } - }, - - "tests": { - "atomicfptr": { - "label": "working std::atomic for function pointers", - "type": "compile", - "test": { - "include": "atomic", - "tail": [ - "typedef void (*fptr)(int);", - "typedef std::atomic atomicfptr;", - "void testfunction(int) { }", - "void test(volatile atomicfptr &a)", - "{", - " fptr v = a.load(std::memory_order_acquire);", - " while (!a.compare_exchange_strong(v, &testfunction,", - " std::memory_order_acq_rel,", - " std::memory_order_acquire)) {", - " v = a.exchange(&testfunction);", - " }", - " a.store(&testfunction, std::memory_order_release);", - "}" - ], - "main": [ - "atomicfptr fptr(testfunction);", - "test(fptr);" - ], - "qmake": "CONFIG += c++11" - } - }, - "clock-monotonic": { - "label": "POSIX monotonic clock", - "type": "compile", - "test": { - "include": [ "unistd.h", "time.h" ], - "main": [ - "#if defined(_POSIX_MONOTONIC_CLOCK) && (_POSIX_MONOTONIC_CLOCK-0 >= 0)", - "timespec ts;", - "clock_gettime(CLOCK_MONOTONIC, &ts);", - "#else", - "# error Feature _POSIX_MONOTONIC_CLOCK not available", - "#endif" - ] - }, - "use": "librt" - }, - "cloexec": { - "label": "O_CLOEXEC", - "type": "compile", - "test": { - "head": "#define _GNU_SOURCE 1", - "include": [ "sys/types.h", "sys/socket.h", "fcntl.h", "unistd.h" ], - "main": [ - "int pipes[2];", - "(void) pipe2(pipes, O_CLOEXEC | O_NONBLOCK);", - "(void) fcntl(0, F_DUPFD_CLOEXEC, 0);", - "(void) dup3(0, 3, O_CLOEXEC);", - "#if defined(__NetBSD__)", - "(void) paccept(0, 0, 0, NULL, SOCK_CLOEXEC | SOCK_NONBLOCK);", - "#else", - "(void) accept4(0, 0, 0, SOCK_CLOEXEC | SOCK_NONBLOCK);", - "#endif" - ] - } - }, - "cxx11_future": { - "label": "C++11 ", - "type": "compile", - "test": { - "include": "future", - "main": [ - "std::future f = std::async([]() { return 42; });", - "(void)f.get();" - ], - "qmake": "unix:LIBS += -lpthread" - } - }, - "cxx11_random": { - "label": "C++11 ", - "type": "compile", - "test": { - "include": "random", - "main": "std::mt19937 mt(0);" - } - }, - "eventfd": { - "label": "eventfd", - "type": "compile", - "test": { - "include": "sys/eventfd.h", - "main": [ - "eventfd_t value;", - "int fd = eventfd(0, EFD_CLOEXEC);", - "eventfd_read(fd, &value);", - "eventfd_write(fd, value);" - ] - } - }, - "futimens": { - "label": "futimens()", - "type": "compile", - "test": { - "include": "sys/stat.h", - "main": "futimens(-1, 0);", - "qmake": [ - "# Block futimens() on Apple platforms unless it's available on ALL", - "# deployment targets. This simplifies the logic at the call site", - "# dramatically, as it isn't strictly needed compared to futimes().", - "darwin: QMAKE_CXXFLAGS += -Werror=unguarded-availability -Werror=unguarded-availability-new", - "CONFIG += warn_on" - ] - } - }, - "futimes": { - "label": "futimes()", - "type": "compile", - "test": { - "include": "sys/time.h", - "main": "futimes(-1, 0);" - } - }, - "getauxval": { - "label": "getauxval()", - "type": "compile", - "test": { - "include": "sys/auxv.h", - "main": "(void) getauxval(AT_NULL);" - } - }, - "getentropy": { - "label": "getentropy()", - "type": "compile", - "test": { - "include": "unistd.h", - "main": [ - "char buf[32];", - "(void) getentropy(buf, sizeof(buf));" - ] - } - }, - "glibc": { - "label": "GNU libc", - "type": "compile", - "test": { - "include": "stdlib.h", - "main": [ - "return __GLIBC__;" - ] - } - }, - "inotify": { - "label": "inotify", - "type": "compile", - "test": { - "include": "sys/inotify.h", - "main": [ - "inotify_init();", - "inotify_add_watch(0, \"foobar\", IN_ACCESS);", - "inotify_rm_watch(0, 1);" - ] - } - }, - "ipc_sysv": { - "label": "SysV IPC", - "type": "compile", - "test": { - "include": [ "sys/types.h", "sys/ipc.h", "sys/sem.h", "sys/shm.h", "fcntl.h" ], - "main": [ - "key_t unix_key = ftok(\"test\", 'Q');", - "semctl(semget(unix_key, 1, 0666 | IPC_CREAT | IPC_EXCL), 0, IPC_RMID, 0);", - "shmget(unix_key, 0, 0666 | IPC_CREAT | IPC_EXCL);", - "shmctl(0, 0, (struct shmid_ds *)(0));" - ] - } - }, - "ipc_posix": { - "label": "POSIX IPC", - "type": "compile", - "test": { - "include": [ "sys/types.h", "sys/mman.h", "semaphore.h", "fcntl.h" ], - "main": [ - "sem_close(sem_open(\"test\", O_CREAT | O_EXCL, 0666, 0));", - "shm_open(\"test\", O_RDWR | O_CREAT | O_EXCL, 0666);", - "shm_unlink(\"test\");" - ], - "qmake": "linux: LIBS += -lpthread -lrt" - } - }, - "linkat": { - "label": "linkat()", - "type": "compile", - "test": { - "head": "#define _ATFILE_SOURCE 1", - "include": [ "fcntl.h", "unistd.h" ], - "main": "linkat(AT_FDCWD, \"foo\", AT_FDCWD, \"bar\", AT_SYMLINK_FOLLOW);" - } - }, - "ppoll": { - "label": "ppoll()", - "type": "compile", - "test": { - "include": [ "signal.h", "poll.h" ], - "main": [ - "struct pollfd pfd;", - "struct timespec ts;", - "sigset_t sig;", - "ppoll(&pfd, 1, &ts, &sig);" - ] - } - }, - "pollts": { - "label": "pollts()", - "type": "compile", - "test": { - "include": [ "poll.h", "signal.h", "time.h" ], - "main": [ - "struct pollfd pfd;", - "struct timespec ts;", - "sigset_t sig;", - "pollts(&pfd, 1, &ts, &sig);" - ] - } - }, - "poll": { - "label": "poll()", - "type": "compile", - "test": { - "include": "poll.h", - "main": [ - "struct pollfd pfd;", - "poll(&pfd, 1, 0);" - ] - } - }, - "renameat2": { - "label": "renameat2()", - "type": "compile", - "test": { - "head": "#define _ATFILE_SOURCE 1", - "include": [ "fcntl.h", "stdio.h" ], - "main": "renameat2(AT_FDCWD, argv[1], AT_FDCWD, argv[2], RENAME_NOREPLACE | RENAME_WHITEOUT);" - } - }, - "statx": { - "label": "statx() in libc", - "type": "compile", - "test": { - "head": "#define _ATFILE_SOURCE 1", - "include": [ "sys/types.h", "sys/stat.h", "unistd.h", "fcntl.h" ], - "main": [ - "struct statx statxbuf;", - "unsigned int mask = STATX_BASIC_STATS;", - "return statx(AT_FDCWD, \"\", AT_STATX_SYNC_AS_STAT, mask, &statxbuf);" - ] - } - }, - "syslog": { - "label": "syslog", - "type": "compile", - "test": { - "include": "syslog.h", - "main": [ - "openlog(\"qt\", 0, LOG_USER);", - "syslog(LOG_INFO, \"configure\");", - "closelog();" - ] - } - }, - "xlocalescanprint": { - "label": "xlocale.h (or equivalents)", - "type": "compile", - "test": { - "files": { - "qglobal.h": [ - "#ifndef QGLOBAL_H", - "#define QGLOBAL_H", - "#endif" - ] - }, - "tail": [ - "#define QT_BEGIN_NAMESPACE", - "#define QT_END_NAMESPACE", - "", - "#ifdef _MSVC_VER", - "#define Q_CC_MSVC _MSVC_VER", - "#endif", - "", - "#define QT_NO_DOUBLECONVERSION", - "", - "#include QDSP_P_H" - ], - "main": [ - "#ifdef _MSVC_VER", - "_locale_t invalidLocale = NULL;", - "#else", - "locale_t invalidLocale = NULL;", - "#endif", - "double a = 3.4;", - "qDoubleSnprintf(argv[0], 1, invalidLocale, \"invalid format\", a);", - "qDoubleSscanf(argv[0], invalidLocale, \"invalid format\", &a, &argc);" - ], - "qmake": "DEFINES += QDSP_P_H=$$shell_quote(\\\"@PWD@/tools/qdoublescanprint_p.h\\\")" - } - } - }, - - "features": { - "clock-gettime": { - "label": "clock_gettime()", - "condition": "config.unix && libs.librt", - "output": [ "privateFeature" ] - }, - "clock-monotonic": { - "label": "POSIX monotonic clock", - "condition": "features.clock-gettime && tests.clock-monotonic", - "output": [ "feature" ] - }, - "dlopen": { - "label": "dlopen()", - "condition": "config.unix && libs.libdl", - "output": [ "privateFeature" ] - }, - "doubleconversion": { - "label": "DoubleConversion", - "output": [ "privateFeature", "feature" ] - }, - "system-doubleconversion": { - "label": " Using system DoubleConversion", - "enable": "input.doubleconversion == 'system'", - "disable": "input.doubleconversion == 'qt'", - "condition": "features.doubleconversion && libs.doubleconversion", - "output": [ "privateFeature" ] - }, - "cxx11_future": { - "label": "C++11 ", - "condition": "tests.cxx11_future", - "output": [ "publicFeature" ] - }, - "eventfd": { - "label": "eventfd", - "condition": "!config.wasm && tests.eventfd", - "output": [ "feature" ] - }, - "futimens": { - "label": "futimens()", - "condition": "!config.win32 && tests.futimens", - "output": [ "privateFeature" ] - }, - "futimes": { - "label": "futimes()", - "condition": "!config.win32 && !features.futimens && tests.futimes", - "output": [ "privateFeature" ] - }, - "getauxval": { - "label": "getauxval()", - "condition": "config.linux && tests.getauxval", - "output": [ "privateFeature" ] - }, - "getentropy": { - "label": "getentropy()", - "condition": "config.unix && tests.getentropy", - "output": [ "privateFeature" ] - }, - "glib": { - "label": "GLib", - "autoDetect": "!config.win32", - "condition": "libs.glib", - "output": [ "privateFeature", "feature" ] - }, - "glibc": { - "label": "GNU libc", - "autoDetect": "config.linux", - "condition": "tests.glibc", - "output": [ "privateFeature" ] - }, - "iconv": { - "label": "iconv", - "purpose": "Provides internationalization on Unix.", - "section": "Internationalization", - "condition": "!features.icu && features.textcodec && (features.posix-libiconv || features.sun-libiconv || features.gnu-libiconv)", - "output": [ "privateFeature", "feature" ] - }, - "posix-libiconv": { - "label": "POSIX iconv", - "enable": "input.iconv == 'posix'", - "disable": "input.iconv == 'sun' || input.iconv == 'gnu' || input.iconv == 'no'", - "condition": "!config.win32 && !config.qnx && !config.android && !config.darwin && libs.posix_iconv", - "output": [ "privateFeature" ] - }, - "sun-libiconv": { - "label": "SUN iconv", - "enable": "input.iconv == 'sun'", - "disable": "input.iconv == 'posix' || input.iconv == 'gnu' || input.iconv == 'no'", - "condition": "!config.win32 && !config.qnx && !config.android && !config.darwin && !features.posix-libiconv && libs.sun_iconv" - }, - "gnu-libiconv": { - "label": "GNU iconv", - "enable": "input.iconv == 'gnu'", - "disable": "input.iconv == 'posix' || input.iconv == 'sun' || input.iconv == 'no'", - "condition": "!config.win32 && !config.qnx && !config.android && !config.darwin && !features.posix-libiconv && !features.sun-libiconv && libs.gnu_iconv", - "output": [ "privateFeature" ] - }, - "icu": { - "label": "ICU", - "autoDetect": "!config.win32", - "condition": "libs.icu", - "output": [ "privateFeature" ] - }, - "inotify": { - "label": "inotify", - "condition": "tests.inotify", - "output": [ "privateFeature", "feature" ] - }, - "ipc_posix": { - "label": "Using POSIX IPC", - "autoDetect": "!config.win32", - "condition": "!tests.ipc_sysv && tests.ipc_posix", - "output": [ { "type": "define", "name": "QT_POSIX_IPC" } ] - }, - "journald": { - "label": "journald", - "autoDetect": false, - "condition": "libs.journald", - "output": [ "privateFeature" ] - }, - "linkat": { - "label": "linkat()", - "comment": "Currently only used by QTemporaryFile; linkat() exists on Android, but hardlink creation fails due to security rules", - "autoDetect": "config.linux && !config.android", - "condition": "tests.linkat", - "output": [ "privateFeature" ] - }, - "std-atomic64": { - "label": "64 bit atomic operations", - "condition": "libs.libatomic", - "output": [ "publicFeature" ] - }, - "mimetype": { - "label": "Mimetype handling", - "purpose": "Provides MIME type handling.", - "section": "Utilities", - "condition": "features.textcodec", - "output": [ "publicFeature", "feature" ] - }, - "mimetype-database": { - "label": "Built-in copy of the MIME database", - "condition": "features.mimetype", - "output": [ "privateFeature" ] - }, - "system-pcre2": { - "label": "Using system PCRE2", - "disable": "input.pcre == 'qt'", - "enable": "input.pcre == 'system'", - "condition": "libs.pcre2", - "output": [ - "privateFeature", - { "type": "privateConfig", "negative": true, "name": "pcre2" } - ] - }, - "poll_ppoll": { - "label": "Native ppoll()", - "emitIf": "!config.win32", - "condition": "!config.wasm && tests.ppoll", - "output": [ "privateFeature" ] - }, - "poll_pollts": { - "label": "Native pollts()", - "emitIf": "!config.win32", - "condition": "!features.poll_ppoll && tests.pollts", - "output": [ "privateFeature" ] - }, - "poll_poll": { - "label": "Native poll()", - "emitIf": "!config.win32", - "condition": "!features.poll_ppoll && !features.poll_pollts && tests.poll", - "output": [ "privateFeature" ] - }, - "poll_select": { - "label": "Emulated poll()", - "emitIf": "!config.win32", - "condition": "!features.poll_ppoll && !features.poll_pollts && !features.poll_poll", - "output": [ - "privateFeature", - { "type": "define", "name": "QT_NO_NATIVE_POLL" } - ] - }, - "qqnx_pps": { - "label": "PPS", - "emitIf": "config.qnx", - "condition": "libs.pps", - "output": [ "privateFeature" ] - }, - "qeventtransition": { - "label": "QEventTransition class", - "condition": "features.statemachine", - "output": [ "publicFeature" ] - }, - "renameat2": { - "label": "renameat2()", - "condition": "config.linux && tests.renameat2", - "output": [ "privateFeature" ] - }, - "slog2": { - "label": "slog2", - "condition": "libs.slog2", - "output": [ "privateFeature" ] - }, - "statx": { - "label": "statx() in libc", - "condition": "config.linux && tests.statx", - "output": [ "privateFeature" ] - }, - "syslog": { - "label": "syslog", - "autoDetect": false, - "condition": "tests.syslog", - "output": [ "privateFeature" ] - }, - "threadsafe-cloexec": { - "label": "Threadsafe pipe creation", - "condition": "tests.cloexec", - "output": [ - "publicQtConfig", - { "type": "define", "name": "QT_THREADSAFE_CLOEXEC", "value": 1 } - ] - }, - "properties": { - "label": "Properties", - "purpose": "Supports scripting Qt-based applications.", - "section": "Kernel", - "output": [ "publicFeature", "feature" ] - }, - "regularexpression": { - "label": "QRegularExpression", - "purpose": "Provides an API to Perl-compatible regular expressions.", - "section": "Kernel", - "output": [ "publicFeature", "feature" ] - }, - "sharedmemory": { - "label": "QSharedMemory", - "purpose": "Provides access to a shared memory segment.", - "section": "Kernel", - "condition": [ - "config.android || config.win32 || (!config.vxworks && (tests.ipc_sysv || tests.ipc_posix))" - ], - "output": [ "publicFeature", "feature" ] - }, - "systemsemaphore": { - "label": "QSystemSemaphore", - "purpose": "Provides a general counting system semaphore.", - "section": "Kernel", - "condition": [ - "!config.integrity && !config.vxworks", - "config.android || config.win32 || tests.ipc_sysv || tests.ipc_posix" - ], - "output": [ "publicFeature", "feature" ] - }, - "xmlstream": { - "label": "XML Streaming APIs", - "purpose": "Provides a simple streaming API for XML.", - "section": "Kernel", - "output": [ "publicFeature", "feature" ] - }, - "xmlstreamreader": { - "label": "QXmlStreamReader", - "purpose": "Provides a well-formed XML parser with a simple streaming API.", - "section": "Kernel", - "condition": "features.xmlstream", - "output": [ "publicFeature", "feature" ] - }, - "xmlstreamwriter": { - "label": "QXmlStreamWriter", - "purpose": "Provides a XML writer with a simple streaming API.", - "section": "Kernel", - "condition": "features.xmlstream", - "output": [ "publicFeature", "feature" ] - }, - "textdate": { - "label": "Text Date", - "purpose": "Supports month and day names in dates.", - "section": "Data structures", - "output": [ "publicFeature", "feature" ] - }, - "datestring": { - "label": "QDate/QTime/QDateTime", - "purpose": "Provides conversion between dates and strings.", - "section": "Data structures", - "condition": "features.textdate", - "output": [ "publicFeature", "feature" ] - }, - "process": { - "label": "QProcess", - "purpose": "Supports external process invocation.", - "section": "File I/O", - "condition": "features.processenvironment && !config.winrt && !config.uikit && !config.integrity && !config.vxworks", - "output": [ "publicFeature", "feature" ] - }, - "processenvironment": { - "label": "QProcessEnvironment", - "purpose": "Provides a higher-level abstraction of environment variables.", - "section": "File I/O", - "condition": "!config.winrt && !config.integrity", - "output": [ "publicFeature" ] - }, - "temporaryfile": { - "label": "QTemporaryFile", - "purpose": "Provides an I/O device that operates on temporary files.", - "section": "File I/O", - "output": [ "publicFeature", "feature" ] - }, - "library": { - "label": "QLibrary", - "purpose": "Provides a wrapper for dynamically loaded libraries.", - "section": "File I/O", - "condition": "config.win32 || config.hpux || (!config.nacl && features.dlopen)", - "output": [ "publicFeature", "feature" ] - }, - "settings": { - "label": "QSettings", - "purpose": "Provides persistent application settings.", - "section": "File I/O", - "output": [ "publicFeature", "feature" ] - }, - "filesystemwatcher": { - "label": "QFileSystemWatcher", - "purpose": "Provides an interface for monitoring files and directories for modifications.", - "section": "File I/O", - "condition": "!config.winrt", - "output": [ "publicFeature", "feature" ] - }, - "filesystemiterator": { - "label": "QFileSystemIterator", - "purpose": "Provides fast file system iteration.", - "section": "File I/O", - "output": [ "publicFeature", "feature" ] - }, - "itemmodel": { - "label": "Qt Item Model", - "purpose": "Provides the item model for item views", - "section": "ItemViews", - "output": [ "publicFeature", "feature" ] - }, - "proxymodel": { - "label": "QAbstractProxyModel", - "purpose": "Supports processing of data passed between another model and a view.", - "section": "ItemViews", - "condition": "features.itemmodel", - "output": [ "publicFeature", "feature" ] - }, - "sortfilterproxymodel": { - "label": "QSortFilterProxyModel", - "purpose": "Supports sorting and filtering of data passed between another model and a view.", - "section": "ItemViews", - "condition": "features.proxymodel", - "output": [ "publicFeature", "feature" ] - }, - "identityproxymodel": { - "label": "QIdentityProxyModel", - "purpose": "Supports proxying a source model unmodified.", - "section": "ItemViews", - "condition": "features.proxymodel", - "output": [ "publicFeature", "feature" ] - }, - "transposeproxymodel": { - "label": "QTransposeProxyModel", - "purpose": "Provides a proxy to swap rows and columns of a model.", - "section": "ItemViews", - "condition": "features.proxymodel", - "output": [ "publicFeature", "feature" ] - }, - "concatenatetablesproxymodel": { - "label": "QConcatenateTablesProxyModel", - "purpose": "Supports concatenating source models.", - "section": "ItemViews", - "condition": "features.proxymodel", - "output": [ "publicFeature", "feature" ] - }, - "stringlistmodel": { - "label": "QStringListModel", - "purpose": "Provides a model that supplies strings to views.", - "section": "ItemViews", - "condition": "features.itemmodel", - "output": [ "publicFeature", "feature" ] - }, - "translation": { - "label": "Translation", - "purpose": "Supports translations using QObject::tr().", - "section": "Internationalization", - "output": [ "publicFeature", "feature" ] - }, - "textcodec": { - "label": "QTextCodec", - "purpose": "Supports conversions between text encodings.", - "section": "Internationalization", - "output": [ "publicFeature", "feature" ] - }, - "codecs": { - "label": "Codecs", - "purpose": "Supports non-unicode text conversions.", - "section": "Internationalization", - "condition": "features.textcodec", - "output": [ "publicFeature", "feature" ] - }, - "big_codecs": { - "label": "Big Codecs", - "purpose": "Supports big codecs, e.g. CJK.", - "section": "Internationalization", - "condition": "features.textcodec", - "output": [ "publicFeature", "feature" ] - }, - "animation": { - "label": "Animation", - "purpose": "Provides a framework for animations.", - "section": "Utilities", - "condition": "features.properties", - "output": [ "publicFeature", "feature" ] - }, - "statemachine": { - "label": "State machine", - "purpose": "Provides hierarchical finite state machines.", - "section": "Utilities", - "condition": "features.properties", - "output": [ "publicFeature", "feature" ] - }, - "gestures": { - "label": "Gesture", - "purpose": "Provides a framework for gestures.", - "section": "Utilities", - "output": [ "publicFeature", "feature" ] - }, - "sha3-fast": { - "label": "Speed optimized SHA3", - "purpose": "Optimizes SHA3 for speed instead of size.", - "section": "Utilities", - "output": [ "privateFeature" ] - }, - "timezone": { - "label": "QTimeZone", - "purpose": "Provides support for time-zone handling.", - "section": "Utilities", - "output": [ "publicFeature" ] - }, - "datetimeparser": { - "label": "QDateTimeParser", - "purpose": "Provides support for parsing date-time texts.", - "section": "Utilities", - "output": [ "privateFeature" ] - }, - "commandlineparser": { - "label": "QCommandlineParser", - "purpose": "Provides support for command line parsing.", - "section": "Utilities", - "output": [ "publicFeature" ] - }, - "lttng": { - "label": "LTTNG", - "autoDetect": false, - "enable": "input.trace == 'lttng' || (input.trace =='yes' && config.linux)", - "disable": "input.trace == 'etw' || input.trace =='no'", - "condition": "config.linux && libs.lttng-ust", - "output": [ "privateFeature" ] - }, - "etw": { - "label": "ETW", - "autoDetect": false, - "enable": "input.trace == 'etw' || (input.trace == 'yes' && config.win32)", - "disable": "input.trace == 'lttng' || input.trace == 'no'", - "condition": "config.win32", - "output": [ "privateFeature" ] - }, - "topleveldomain": { - "label": "QUrl::topLevelDomain()", - "purpose": "Provides support for extracting the top level domain from URLs. - -If enabled, a binary dump of the Public Suffix List (http://www.publicsuffix.org, -Mozilla License) is included. The data is then also used in QNetworkCookieJar::validateCookie.", - "section": "Utilities", - "output": [ "publicFeature" ] - } - }, - - "report": [ - { - "type": "note", - "condition": "features.journald || features.syslog || (config.qnx && features.slog2)", - "message": "journald, syslog or slog2 integration is enabled. -If your users intend to develop applications against this build, -ensure that the IDEs they use either set QT_FORCE_STDERR_LOGGING to 1 -or are able to read the logged output from journald, syslog or slog2." - }, - { - "type": "error", - "condition": "!tests.cxx11_random", - "message": "C++11 is required and is missing or failed to compile." - }, - { - "type": "error", - "condition": "input.doubleconversion == 'no' && !tests.xlocalescanprint", - "message": "Your C library does not provide sscanf_l or snprintf_l. -You need to use libdouble-conversion for double/string conversion." - }, - { - "type": "error", - "condition": "!tests.atomicfptr", - "message": "detected a std::atomic implementation that fails for function pointers. -Please apply the patch corresponding to your Standard Library vendor, found in - qtbase/config.tests/atomicfptr" - } - ], - - "summary": [ - { - "section": "Qt Core", - "entries": [ - "doubleconversion", - "system-doubleconversion", - "glib", - "iconv", - "icu", - "mimetype-database", - { - "message": "Tracing backend", - "type": "firstAvailableFeature", - "args": "etw lttng" - }, - { - "section": "Logging backends", - "entries": [ - "journald", "syslog", "slog2" - ] - }, - { - "type": "feature", - "args": "qqnx_pps", - "condition": "config.qnx" - }, - "system-pcre2" - ] - } - ] -} diff --git a/5.13.2/qtbase/src/corelib/global/qoperatingsystemversion.cpp b/5.13.2/qtbase/src/corelib/global/qoperatingsystemversion.cpp deleted file mode 100644 index a0ea801..0000000 --- a/5.13.2/qtbase/src/corelib/global/qoperatingsystemversion.cpp +++ /dev/null @@ -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 -#endif - -#include -#include - -#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) -#include -#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( - "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 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 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 diff --git a/5.13.2/qtbase/src/corelib/global/qoperatingsystemversion.h b/5.13.2/qtbase/src/corelib/global/qoperatingsystemversion.h deleted file mode 100644 index db4da1a..0000000 --- a/5.13.2/qtbase/src/corelib/global/qoperatingsystemversion.h +++ /dev/null @@ -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 - -#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 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 diff --git a/5.13.2/qtbase/src/corelib/global/qsystemdetection.h b/5.13.2/qtbase/src/corelib/global/qsystemdetection.h deleted file mode 100644 index d87e181..0000000 --- a/5.13.2/qtbase/src/corelib/global/qsystemdetection.h +++ /dev/null @@ -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 -#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 -# 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 -# include -# -# 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 diff --git a/5.13.2/qtbase/src/corelib/kernel/qcore_mac.cpp b/5.13.2/qtbase/src/corelib/kernel/qcore_mac.cpp deleted file mode 100644 index 22b5b54..0000000 --- a/5.13.2/qtbase/src/corelib/kernel/qcore_mac.cpp +++ /dev/null @@ -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 -#include - -#include "qhash.h" -#include "qpair.h" -#include "qmutex.h" -#include "qvarlengtharray.h" - -#include -#include - -QT_BEGIN_NAMESPACE - -QCFString::operator QString() const -{ - if (string.isEmpty() && value) - const_cast(this)->string = QString::fromCFString(value); - return string; -} - -QCFString::operator CFStringRef() const -{ - if (!value) - const_cast(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, 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(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(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(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(qtCoreImage.dli_fbase)); - }(); - return version; -} - -// ------------------------------------------------------------------------- - -QT_END_NAMESPACE diff --git a/5.13.2/qtbase/src/corelib/kernel/qcore_mac_p.h b/5.13.2/qtbase/src/corelib/kernel/qcore_mac_p.h deleted file mode 100644 index b78bc32..0000000 --- a/5.13.2/qtbase/src/corelib/kernel/qcore_mac_p.h +++ /dev/null @@ -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 -struct mach_header; - -#ifndef __IMAGECAPTURE__ -# define __IMAGECAPTURE__ -#endif - -// -------------------------------------------------------------------------- - -#if defined(QT_BOOTSTRAPPED) -#include -#else -#include -#endif - -#ifdef __OBJC__ -#include -#include -#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 -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 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 -class QCFType : public QAppleRefCounted -{ -public: - using QAppleRefCounted::QAppleRefCounted; - template X as() const { return reinterpret_cast(this->value); } - static QCFType constructFromGet(const T &t) - { - if (t) - CFRetain(t); - return QCFType(t); - } -}; - -class Q_CORE_EXPORT QCFString : public QCFType -{ -public: - inline QCFString(const QString &str) : QCFType(0), string(str) {} - inline QCFString(const CFStringRef cfstr = 0) : QCFType(cfstr) {} - inline QCFString(const QCFType &other) : QCFType(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 -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 -QT_BEGIN_NAMESPACE - -template using QAppleOsType = QAppleRefCounted; - -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(*this), &state); - return std::move(*this); - } - - void leave() { - if (activity) - os_activity_scope_leave(&state); - } - - operator os_activity_t() - { - return reinterpret_cast(static_cast(activity)); - } - -private: - // Work around API_AVAILABLE not working for templates by using void* - QAppleOsType 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 - 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; - - 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; - - 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; - static VersionTuple versionsForImage(const mach_header *machHeader); - static VersionTuple applicationVersion(); - static VersionTuple libraryVersion(); -}; - -// ------------------------------------------------------------------------- - -QT_END_NAMESPACE - -#endif // QCORE_MAC_P_H diff --git a/5.13.2/qtbase/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/5.13.2/qtbase/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm deleted file mode 100644 index b88c28a..0000000 --- a/5.13.2/qtbase/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm +++ /dev/null @@ -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 -#include -#include -#include -#include -#include "qt_mac_p.h" -#include -#include - -QT_USE_NAMESPACE - -@implementation QCocoaApplicationDelegate { - bool startedQuit; - NSObject *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 *)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(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(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 diff --git a/5.13.2/qtbase/src/plugins/platforms/cocoa/qcocoahelpers.h b/5.13.2/qtbase/src/plugins/platforms/cocoa/qcocoahelpers.h deleted file mode 100644 index e74c7c6..0000000 --- a/5.13.2/qtbase/src/plugins/platforms/cocoa/qcocoahelpers.h +++ /dev/null @@ -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 -#include -#include -#include - -#include -#include - -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 *nsarray); -NSMutableArray *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 std::enable_if::value, T>::type -qt_objc_cast(id object) -{ - if ([object isKindOfClass:[typename std::remove_pointer::type class]]) - return static_cast(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 -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 -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(); - } - - // return default value. - return fallback; -} - -// https://stackoverflow.com/a/52722575/2761869 -template -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 -constexpr backwards_t backwards(R&& r) { return {std::forward(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)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 -class QIOType : public QAppleRefCounted -{ - using QAppleRefCounted::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 -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 -{ static const bool value = false; }; - -template -ReturnType qt_msgSendSuper(id receiver, SEL selector, Args... args) -{ - static_assert(!objc_msgsend_requires_stret::value, - "The given return type requires stret on this platform"); - - typedef ReturnType (*SuperFn)(objc_super *, SEL, Args...); - SuperFn superFn = reinterpret_cast(objc_msgSendSuper); - objc_super sup = { receiver, [receiver superclass] }; - return superFn(&sup, selector, args...); -} - -#if PLATFORM_USES_SEND_SUPER_STRET -template -ReturnType qt_msgSendSuper_stret(id receiver, SEL selector, Args... args) -{ - static_assert(objc_msgsend_requires_stret::value, - "The given return type does not use stret on this platform"); - - typedef void (*SuperStretFn)(ReturnType *, objc_super *, SEL, Args...); - SuperStretFn superStretFn = reinterpret_cast(objc_msgSendSuper_stret); - - objc_super sup = { receiver, [receiver superclass] }; - ReturnType ret; - superStretFn(&ret, &sup, selector, args...); - return ret; -} -#endif - -template -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(m_args); - } - - template - 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(m_args); - } - -private: - template - using if_requires_stret = typename std::enable_if::value == V, ReturnType>::type; - - template - if_requires_stret msgSendSuper(std::tuple& args, QtPrivate::IndexesList) - { - return qt_msgSendSuper(m_receiver, m_selector, std::get(args)...); - } - -#if PLATFORM_USES_SEND_SUPER_STRET - template - if_requires_stret msgSendSuper(std::tuple& args, QtPrivate::IndexesList) - { - return qt_msgSendSuper_stret(m_receiver, m_selector, std::get(args)...); - } -#endif - - template - ReturnType msgSendSuper(std::tuple& args) - { - return msgSendSuper(args, QtPrivate::makeIndexSequence{}); - } - - id m_receiver; - SEL m_selector; - std::tuple m_args; - bool m_sent; -}; - -template -QSendSuperHelper qt_objcDynamicSuperHelper(id receiver, SEL selector, Args... args) -{ - return QSendSuperHelper(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 - diff --git a/5.13.2/qtbase/src/plugins/platforms/cocoa/qcocoahelpers.mm b/5.13.2/qtbase/src/plugins/platforms/cocoa/qcocoahelpers.mm deleted file mode 100644 index dfffe96..0000000 --- a/5.13.2/qtbase/src/plugins/platforms/cocoa/qcocoahelpers.mm +++ /dev/null @@ -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 - -#include "qcocoahelpers.h" -#include "qnsview.h" - -#include -#include -#include -#include -#include -#include - -#ifndef QT_NO_WIDGETS -#include -#endif - -#include - -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 *array) -{ - QStringList result; - for (NSString *string in array) - result << QString::fromNSString(string); - return result; -} - -NSMutableArray *qt_mac_QStringListToNSMutableArray(const QStringList &list) -{ - NSMutableArray *result = [NSMutableArray 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(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(value)).toInt()); - else if (valueType == CFBooleanGetTypeID()) - forceTransform = !CFBooleanGetValue(static_cast(value)); - else if (valueType == CFNumberGetTypeID()) { - int valueAsInt; - CFNumberGetValue(static_cast(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(value)); - else if (valueType == CFStringGetTypeID()) - forceTransform = !(QString::fromCFString(static_cast(value)).toInt()); - else if (valueType == CFNumberGetTypeID()) { - int valueAsInt; - CFNumberGetValue(static_cast(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(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(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)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 diff --git a/5.13.2/qtbase/src/plugins/platforms/cocoa/qcocoascreen.h b/5.13.2/qtbase/src/plugins/platforms/cocoa/qcocoascreen.h deleted file mode 100644 index 1c88447..0000000 --- a/5.13.2/qtbase/src/plugins/platforms/cocoa/qcocoascreen.h +++ /dev/null @@ -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 - -#include "qcocoacursor.h" - -#include - -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 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 diff --git a/5.13.2/qtbase/src/plugins/platforms/cocoa/qcocoascreen.mm b/5.13.2/qtbase/src/plugins/platforms/cocoa/qcocoascreen.mm deleted file mode 100644 index a66483c..0000000 --- a/5.13.2/qtbase/src/plugins/platforms/cocoa/qcocoascreen.mm +++ /dev/null @@ -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 -#include - -#include - -#include - -#include - -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(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 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 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(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(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 iterator; - if (IOServiceGetMatchingServices(kIOMasterPortDefault, - IOServiceMatching("IODisplayConnect"), &iterator)) - return QString(); - - QIOType 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 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(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(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 images; - QVector 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(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(QGuiApplication::primaryScreen()->handle()); -} - -QList QCocoaScreen::virtualSiblings() const -{ - QList 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(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(screen->handle()); - if (!platformScreen->isOnline()) - continue; - - auto displayId = platformScreen->displayId(); - QCFType 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 diff --git a/5.13.2/qtbase/src/plugins/platforms/cocoa/qcocoasystemsettings.mm b/5.13.2/qtbase/src/plugins/platforms/cocoa/qcocoasystemsettings.mm deleted file mode 100644 index b58aed0..0000000 --- a/5.13.2/qtbase/src/plugins/platforms/cocoa/qcocoasystemsettings.mm +++ /dev/null @@ -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 -#include -#include - -#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 *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 qt_mac_createRolePalettes() -{ - QHash 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 *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 diff --git a/5.13.2/qtbase/src/plugins/platforms/cocoa/qnsview_drawing.mm b/5.13.2/qtbase/src/plugins/platforms/cocoa/qnsview_drawing.mm deleted file mode 100644 index 14e45a0..0000000 --- a/5.13.2/qtbase/src/plugins/platforms/cocoa/qnsview_drawing.mm +++ /dev/null @@ -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(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(layer)]; - [self setNeedsDisplay:YES]; - } -} - -@end diff --git a/5.13.2/qtbase/src/plugins/styles/mac/qmacstyle_mac.mm b/5.13.2/qtbase/src/plugins/styles/mac/qmacstyle_mac.mm deleted file mode 100644 index 3f8ad50..0000000 --- a/5.13.2/qtbase/src/plugins/styles/mac/qmacstyle_mac.mm +++ /dev/null @@ -1,6728 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtWidgets 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$ -** -****************************************************************************/ - -/* - Note: The qdoc comments for QMacStyle are contained in - .../doc/src/qstyles.qdoc. -*/ - -#include - -#include "qmacstyle_mac_p.h" -#include "qmacstyle_mac_p_p.h" - -#define QMAC_QAQUASTYLE_SIZE_CONSTRAIN -//#define DEBUG_SIZE_CONSTRAINT - -#include -#if QT_CONFIG(tabbar) -#include -#endif -#include -#include -#include -#if QT_CONFIG(combobox) -#include -#include -#endif -#if QT_CONFIG(dialogbuttonbox) -#include -#endif -#if QT_CONFIG(dockwidget) -#include -#endif -#include -#include -#include -#include -#include -#include -#if QT_CONFIG(lineedit) -#include -#endif -#if QT_CONFIG(mainwindow) -#include -#endif -#if QT_CONFIG(mdiarea) -#include -#endif -#if QT_CONFIG(menubar) -#include -#endif -#include -#include -#include -#include -#if QT_CONFIG(progressbar) -#include -#endif -#if QT_CONFIG(pushbutton) -#include -#endif -#include -#if QT_CONFIG(rubberband) -#include -#endif -#if QT_CONFIG(scrollbar) -#include -#endif -#if QT_CONFIG(sizegrip) -#include -#endif -#include -#include -#if QT_CONFIG(toolbutton) -#include -#endif -#if QT_CONFIG(treeview) -#include -#endif -#if QT_CONFIG(tableview) -#include -#endif -#include -#if QT_CONFIG(wizard) -#include -#endif -#include -#if QT_CONFIG(datetimeedit) -#include -#endif -#include -#include -#if QT_CONFIG(graphicsview) -#include -#endif -#include -#include -#include -#include -#include -#include -#include - -#include - -QT_USE_NAMESPACE - -static QWindow *qt_getWindow(const QWidget *widget) -{ - return widget ? widget->window()->windowHandle() : 0; -} - -@interface QT_MANGLE_NAMESPACE(QIndeterminateProgressIndicator) : NSProgressIndicator - -@property (readonly, nonatomic) NSInteger animators; - -- (instancetype)init; - -- (void)startAnimation; -- (void)stopAnimation; - -- (void)drawWithFrame:(CGRect)rect inView:(NSView *)view; - -@end - -QT_NAMESPACE_ALIAS_OBJC_CLASS(QIndeterminateProgressIndicator); - -@implementation QIndeterminateProgressIndicator - -- (instancetype)init -{ - if ((self = [super init])) { - _animators = 0; - self.indeterminate = YES; - self.usesThreadedAnimation = NO; - self.alphaValue = 0.0; - } - - return self; -} - -- (void)startAnimation -{ - if (_animators == 0) { - self.hidden = NO; - [super startAnimation:self]; - } - ++_animators; -} - -- (void)stopAnimation -{ - --_animators; - if (_animators == 0) { - [super stopAnimation:self]; - self.hidden = YES; - [self removeFromSuperviewWithoutNeedingDisplay]; - } -} - -- (void)drawWithFrame:(CGRect)rect inView:(NSView *)view -{ - // The alphaValue change is not strictly necessary, but feels safer. - self.alphaValue = 1.0; - if (self.superview != view) - [view addSubview:self]; - if (!CGRectEqualToRect(self.frame, rect)) - self.frame = rect; - [self drawRect:rect]; - self.alphaValue = 0.0; -} - -@end - -@interface QT_MANGLE_NAMESPACE(QVerticalSplitView) : NSSplitView -- (BOOL)isVertical; -@end - -QT_NAMESPACE_ALIAS_OBJC_CLASS(QVerticalSplitView); - -@implementation QVerticalSplitView -- (BOOL)isVertical -{ - return YES; -} -@end - -// See render code in drawPrimitive(PE_FrameTabWidget) -@interface QT_MANGLE_NAMESPACE(QDarkNSBox) : NSBox -@end - -QT_NAMESPACE_ALIAS_OBJC_CLASS(QDarkNSBox); - -@implementation QDarkNSBox -- (instancetype)init -{ - if ((self = [super init])) { - self.title = @""; - self.titlePosition = NSNoTitle; - self.boxType = NSBoxCustom; - self.cornerRadius = 3; - self.borderColor = [NSColor.controlColor colorWithAlphaComponent:0.1]; - self.fillColor = [NSColor.darkGrayColor colorWithAlphaComponent:0.2]; - } - - return self; -} - -- (void)drawRect:(NSRect)rect -{ - [super drawRect:rect]; -} -@end - -QT_BEGIN_NAMESPACE - -// The following constants are used for adjusting the size -// of push buttons so that they are drawn inside their bounds. -const int QMacStylePrivate::PushButtonLeftOffset = 6; -const int QMacStylePrivate::PushButtonRightOffset = 12; -const int QMacStylePrivate::PushButtonContentPadding = 6; - -QVector > QMacStylePrivate::scrollBars; - -// Title bar gradient colors for Lion were determined by inspecting PSDs exported -// using CoreUI's CoreThemeDocument; there is no public API to retrieve them - -static QLinearGradient titlebarGradientActive() -{ - static QLinearGradient darkGradient = [](){ - QLinearGradient gradient; - // FIXME: colors are chosen somewhat arbitrarily and could be fine-tuned, - // or ideally determined by calling a native API. - gradient.setColorAt(0, QColor(47, 47, 47)); - return gradient; - }(); - static QLinearGradient lightGradient = [](){ - QLinearGradient gradient; - gradient.setColorAt(0, QColor(235, 235, 235)); - gradient.setColorAt(0.5, QColor(210, 210, 210)); - gradient.setColorAt(0.75, QColor(195, 195, 195)); - gradient.setColorAt(1, QColor(180, 180, 180)); - return gradient; - }(); - return qt_mac_applicationIsInDarkMode() ? darkGradient : lightGradient; -} - -static QLinearGradient titlebarGradientInactive() -{ - static QLinearGradient darkGradient = [](){ - QLinearGradient gradient; - gradient.setColorAt(1, QColor(42, 42, 42)); - return gradient; - }(); - static QLinearGradient lightGradient = [](){ - QLinearGradient gradient; - gradient.setColorAt(0, QColor(250, 250, 250)); - gradient.setColorAt(1, QColor(225, 225, 225)); - return gradient; - }(); - return qt_mac_applicationIsInDarkMode() ? darkGradient : lightGradient; -} - -#if QT_CONFIG(tabwidget) -/* - Since macOS 10.14 AppKit is using transparency more extensively, especially for the - dark theme. Inactive buttons, for example, are semi-transparent. And we use them to - draw tab widget's tab bar. The combination of NSBox (also a part of tab widget) - and these transparent buttons gives us an undesired side-effect: an outline of - NSBox is visible through transparent buttons. To avoid this, we have this hack below: - we clip the area where the line would be visible through the buttons. The area we - want to clip away can be described as an intersection of the option's rect and - the tab widget's tab bar rect. But some adjustments are required, since those rects - are anyway adjusted during the rendering and they are not exactly what you'll see on - the screen. Thus this switch-statement inside. -*/ -static void clipTabBarFrame(const QStyleOption *option, const QMacStyle *style, CGContextRef ctx) -{ - Q_ASSERT(option); - Q_ASSERT(style); - Q_ASSERT(ctx); - - if (qt_mac_applicationIsInDarkMode()) { - QTabWidget *tabWidget = qobject_cast(option->styleObject); - Q_ASSERT(tabWidget); - - QRect tabBarRect = style->subElementRect(QStyle::SE_TabWidgetTabBar, option, tabWidget).adjusted(2, 0, -3, 0); - switch (tabWidget->tabPosition()) { - case QTabWidget::South: - tabBarRect.setY(tabBarRect.y() + tabBarRect.height() / 2); - break; - case QTabWidget::North: - case QTabWidget::West: - tabBarRect = tabBarRect.adjusted(0, 2, 0, -2); - break; - case QTabWidget::East: - tabBarRect = tabBarRect.adjusted(tabBarRect.width() / 2, 2, tabBarRect.width() / 2, -2); - } - - const QRegion clipPath = QRegion(option->rect) - tabBarRect; - QVarLengthArray cgRects; - for (const QRect &qtRect : clipPath) - cgRects.push_back(qtRect.toCGRect()); - if (cgRects.size()) - CGContextClipToRects(ctx, &cgRects[0], size_t(cgRects.size())); - } -} -#endif // QT_CONFIG(tabwidget) - -static const QColor titlebarSeparatorLineActive(111, 111, 111); -static const QColor titlebarSeparatorLineInactive(131, 131, 131); -static const QColor darkModeSeparatorLine(88, 88, 88); - -// Gradient colors used for the dock widget title bar and -// non-unifed tool bar bacground. -static const QColor lightMainWindowGradientBegin(240, 240, 240); -static const QColor lightMainWindowGradientEnd(200, 200, 200); -static const QColor darkMainWindowGradientBegin(47, 47, 47); -static const QColor darkMainWindowGradientEnd(47, 47, 47); - -static const int DisclosureOffset = 4; - -static const qreal titleBarIconTitleSpacing = 5; -static const qreal titleBarTitleRightMargin = 12; -static const qreal titleBarButtonSpacing = 8; - -// Tab bar colors -// active: window is active -// selected: tab is selected -// hovered: tab is hovered -bool isDarkMode() { return qt_mac_applicationIsInDarkMode(); } - -static const QColor lightTabBarTabBackgroundActive(190, 190, 190); -static const QColor darkTabBarTabBackgroundActive(38, 38, 38); -static const QColor tabBarTabBackgroundActive() { return isDarkMode() ? darkTabBarTabBackgroundActive : lightTabBarTabBackgroundActive; } - -static const QColor lightTabBarTabBackgroundActiveHovered(178, 178, 178); -static const QColor darkTabBarTabBackgroundActiveHovered(32, 32, 32); -static const QColor tabBarTabBackgroundActiveHovered() { return isDarkMode() ? darkTabBarTabBackgroundActiveHovered : lightTabBarTabBackgroundActiveHovered; } - -static const QColor lightTabBarTabBackgroundActiveSelected(211, 211, 211); -static const QColor darkTabBarTabBackgroundActiveSelected(52, 52, 52); -static const QColor tabBarTabBackgroundActiveSelected() { return isDarkMode() ? darkTabBarTabBackgroundActiveSelected : lightTabBarTabBackgroundActiveSelected; } - -static const QColor lightTabBarTabBackground(227, 227, 227); -static const QColor darkTabBarTabBackground(38, 38, 38); -static const QColor tabBarTabBackground() { return isDarkMode() ? darkTabBarTabBackground : lightTabBarTabBackground; } - -static const QColor lightTabBarTabBackgroundSelected(246, 246, 246); -static const QColor darkTabBarTabBackgroundSelected(52, 52, 52); -static const QColor tabBarTabBackgroundSelected() { return isDarkMode() ? darkTabBarTabBackgroundSelected : lightTabBarTabBackgroundSelected; } - -static const QColor lightTabBarTabLineActive(160, 160, 160); -static const QColor darkTabBarTabLineActive(90, 90, 90); -static const QColor tabBarTabLineActive() { return isDarkMode() ? darkTabBarTabLineActive : lightTabBarTabLineActive; } - -static const QColor lightTabBarTabLineActiveHovered(150, 150, 150); -static const QColor darkTabBarTabLineActiveHovered(90, 90, 90); -static const QColor tabBarTabLineActiveHovered() { return isDarkMode() ? darkTabBarTabLineActiveHovered : lightTabBarTabLineActiveHovered; } - -static const QColor lightTabBarTabLine(210, 210, 210); -static const QColor darkTabBarTabLine(90, 90, 90); -static const QColor tabBarTabLine() { return isDarkMode() ? darkTabBarTabLine : lightTabBarTabLine; } - -static const QColor lightTabBarTabLineSelected(189, 189, 189); -static const QColor darkTabBarTabLineSelected(90, 90, 90); -static const QColor tabBarTabLineSelected() { return isDarkMode() ? darkTabBarTabLineSelected : lightTabBarTabLineSelected; } - -static const QColor tabBarCloseButtonBackgroundHovered(162, 162, 162); -static const QColor tabBarCloseButtonBackgroundPressed(153, 153, 153); -static const QColor tabBarCloseButtonBackgroundSelectedHovered(192, 192, 192); -static const QColor tabBarCloseButtonBackgroundSelectedPressed(181, 181, 181); -static const QColor tabBarCloseButtonCross(100, 100, 100); -static const QColor tabBarCloseButtonCrossSelected(115, 115, 115); - -static const int closeButtonSize = 14; -static const qreal closeButtonCornerRadius = 2.0; - -static const int headerSectionArrowHeight = 6; -static const int headerSectionSeparatorInset = 2; - -// One for each of QStyleHelper::WidgetSizePolicy -static const QMarginsF comboBoxFocusRingMargins[3] = { - { 0.5, 2, 3.5, 4 }, - { 0.5, 1, 2.5, 4 }, - { 0.5, 1.5, 2.5, 3.5 } -}; - -static const QMarginsF pullDownButtonShadowMargins[3] = { - { 0.5, -1, 0.5, 2 }, - { 0.5, -1.5, 0.5, 2.5 }, - { 0.5, 0, 0.5, 1 } -}; - -static const QMarginsF pushButtonShadowMargins[3] = { - { 1.5, -1.5, 1.5, 4.5 }, - { 1.5, -1, 1.5, 4 }, - { 1.5, 0.5, 1.5, 2.5 } -}; - -// These are frame heights as reported by Xcode 9's Interface Builder. -// Alignemnet rectangle's heights match for push and popup buttons -// with respective values 21, 18 and 15. - -static const qreal comboBoxDefaultHeight[3] = { - 26, 22, 19 -}; - -static const qreal pushButtonDefaultHeight[3] = { - 32, 28, 16 -}; - -static const qreal popupButtonDefaultHeight[3] = { - 26, 22, 15 -}; - -static const int toolButtonArrowSize = 7; -static const int toolButtonArrowMargin = 2; - -static const qreal focusRingWidth = 3.5; - -// An application can force 'Aqua' theme while the system theme is one of -// the 'Dark' variants. Since in Qt we sometimes use NSControls and even -// NSCells directly without attaching them to any view hierarchy, we have -// to set NSAppearance.currentAppearance to 'Aqua' manually, to make sure -// the correct rendering path is triggered. Apple recommends us to un-set -// the current appearance back after we finished with drawing. This is what -// AppearanceSync is for. - -class AppearanceSync { -public: - AppearanceSync() - { -#if QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14) - if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave - && !qt_mac_applicationIsInDarkMode()) { - auto requiredAppearanceName = NSApplication.sharedApplication.effectiveAppearance.name; - if (![NSAppearance.currentAppearance.name isEqualToString:requiredAppearanceName]) { - previous = NSAppearance.currentAppearance; - NSAppearance.currentAppearance = [NSAppearance appearanceNamed:requiredAppearanceName]; - } - } -#endif // QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14) - } - - ~AppearanceSync() - { - if (previous) - NSAppearance.currentAppearance = previous; - } - -private: - NSAppearance *previous = nil; - - Q_DISABLE_COPY(AppearanceSync) -}; - -static bool setupScroller(NSScroller *scroller, const QStyleOptionSlider *sb) -{ - const qreal length = sb->maximum - sb->minimum + sb->pageStep; - if (qFuzzyIsNull(length)) - return false; - const qreal proportion = sb->pageStep / length; - const qreal range = qreal(sb->maximum - sb->minimum); - qreal value = range ? qreal(sb->sliderValue - sb->minimum) / range : 0; - if (sb->orientation == Qt::Horizontal && sb->direction == Qt::RightToLeft) - value = 1.0 - value; - - scroller.frame = sb->rect.toCGRect(); - scroller.floatValue = value; - scroller.knobProportion = proportion; - return true; -} - -static bool setupSlider(NSSlider *slider, const QStyleOptionSlider *sl) -{ - if (sl->minimum >= sl->maximum) - return false; - - slider.frame = sl->rect.toCGRect(); - slider.minValue = sl->minimum; - slider.maxValue = sl->maximum; - slider.intValue = sl->sliderPosition; - slider.enabled = sl->state & QStyle::State_Enabled; - if (sl->tickPosition != QSlider::NoTicks) { - // Set numberOfTickMarks, but TicksBothSides will be treated differently - int interval = sl->tickInterval; - if (interval == 0) { - interval = sl->pageStep; - if (interval == 0) - interval = sl->singleStep; - if (interval == 0) - interval = 1; // return false? - } - slider.numberOfTickMarks = 1 + ((sl->maximum - sl->minimum) / interval); - - const bool ticksAbove = sl->tickPosition == QSlider::TicksAbove; - if (sl->orientation == Qt::Horizontal) - slider.tickMarkPosition = ticksAbove ? NSTickMarkPositionAbove : NSTickMarkPositionBelow; - else - slider.tickMarkPosition = ticksAbove ? NSTickMarkPositionLeading : NSTickMarkPositionTrailing; - } else { - slider.numberOfTickMarks = 0; - } - - return true; -} - -static void fixStaleGeometry(NSSlider *slider) -{ - // If it's later fixed in AppKit, this function is not needed. - // On macOS Mojave we suddenly have NSSliderCell with a cached - // (and stale) geometry, thus its -drawKnob, -drawBarInside:flipped:, - // -drawTickMarks fail to render the slider properly. Setting the number - // of tickmarks triggers an update in geometry. - - Q_ASSERT(slider); - - if (QOperatingSystemVersion::current() < QOperatingSystemVersion::MacOSMojave) - return; - - NSSliderCell *cell = slider.cell; - const NSRect barRect = [cell barRectFlipped:NO]; - const NSSize sliderSize = slider.frame.size; - CGFloat difference = 0.; - if (slider.vertical) - difference = std::abs(sliderSize.height - barRect.size.height); - else - difference = std::abs(sliderSize.width - barRect.size.width); - - if (difference > 6.) { - // Stale ... - const auto nOfTicks = slider.numberOfTickMarks; - // Non-zero, different from nOfTicks to force update - slider.numberOfTickMarks = nOfTicks + 10; - slider.numberOfTickMarks = nOfTicks; - } -} - -static bool isInMacUnifiedToolbarArea(QWindow *window, int windowY) -{ - QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface(); - QPlatformNativeInterface::NativeResourceForIntegrationFunction function = - nativeInterface->nativeResourceFunctionForIntegration("testContentBorderPosition"); - if (!function) - return false; // Not Cocoa platform plugin. - - typedef bool (*TestContentBorderPositionFunction)(QWindow *, int); - return (reinterpret_cast(function))(window, windowY); -} - - -static void drawTabCloseButton(QPainter *p, bool hover, bool selected, bool pressed, bool documentMode) -{ - p->setRenderHints(QPainter::Antialiasing); - QRect rect(0, 0, closeButtonSize, closeButtonSize); - const int width = rect.width(); - const int height = rect.height(); - - if (hover) { - // draw background circle - QColor background; - if (selected) { - if (documentMode) - background = pressed ? tabBarCloseButtonBackgroundSelectedPressed : tabBarCloseButtonBackgroundSelectedHovered; - else - background = QColor(255, 255, 255, pressed ? 150 : 100); // Translucent white - } else { - background = pressed ? tabBarCloseButtonBackgroundPressed : tabBarCloseButtonBackgroundHovered; - if (!documentMode) - background = background.lighter(pressed ? 135 : 140); // Lighter tab background, lighter color - } - - p->setPen(Qt::transparent); - p->setBrush(background); - p->drawRoundedRect(rect, closeButtonCornerRadius, closeButtonCornerRadius); - } - - // draw cross - const int margin = 3; - QPen crossPen; - crossPen.setColor(selected ? (documentMode ? tabBarCloseButtonCrossSelected : Qt::white) : tabBarCloseButtonCross); - crossPen.setWidthF(1.1); - crossPen.setCapStyle(Qt::FlatCap); - p->setPen(crossPen); - p->drawLine(margin, margin, width - margin, height - margin); - p->drawLine(margin, height - margin, width - margin, margin); -} - -#if QT_CONFIG(tabbar) -QRect rotateTabPainter(QPainter *p, QTabBar::Shape shape, QRect tabRect) -{ - const auto tabDirection = QMacStylePrivate::tabDirection(shape); - if (QMacStylePrivate::verticalTabs(tabDirection)) { - int newX, newY, newRot; - if (tabDirection == QMacStylePrivate::East) { - newX = tabRect.width(); - newY = tabRect.y(); - newRot = 90; - } else { - newX = 0; - newY = tabRect.y() + tabRect.height(); - newRot = -90; - } - tabRect.setRect(0, 0, tabRect.height(), tabRect.width()); - QMatrix m; - m.translate(newX, newY); - m.rotate(newRot); - p->setMatrix(m, true); - } - return tabRect; -} - -void drawTabShape(QPainter *p, const QStyleOptionTab *tabOpt, bool isUnified, int tabOverlap) -{ - QRect rect = tabOpt->rect; - if (QMacStylePrivate::verticalTabs(QMacStylePrivate::tabDirection(tabOpt->shape))) - rect = rect.adjusted(-tabOverlap, 0, 0, 0); - else - rect = rect.adjusted(0, -tabOverlap, 0, 0); - - p->translate(rect.x(), rect.y()); - rect.moveLeft(0); - rect.moveTop(0); - const QRect tabRect = rotateTabPainter(p, tabOpt->shape, rect); - - const int width = tabRect.width(); - const int height = tabRect.height(); - const bool active = (tabOpt->state & QStyle::State_Active); - const bool selected = (tabOpt->state & QStyle::State_Selected); - - const QRect bodyRect(1, 2, width - 2, height - 3); - const QRect topLineRect(1, 0, width - 2, 1); - const QRect bottomLineRect(1, height - 1, width - 2, 1); - if (selected) { - // fill body - if (tabOpt->documentMode && isUnified) { - p->save(); - p->setCompositionMode(QPainter::CompositionMode_Source); - p->fillRect(tabRect, QColor(Qt::transparent)); - p->restore(); - } else if (active) { - p->fillRect(bodyRect, tabBarTabBackgroundActiveSelected()); - // top line - p->fillRect(topLineRect, tabBarTabLineSelected()); - } else { - p->fillRect(bodyRect, tabBarTabBackgroundSelected()); - } - } else { - // when the mouse is over non selected tabs they get a new color - const bool hover = (tabOpt->state & QStyle::State_MouseOver); - if (hover) { - // fill body - p->fillRect(bodyRect, tabBarTabBackgroundActiveHovered()); - // bottom line - p->fillRect(bottomLineRect, isDarkMode() ? QColor(Qt::black) : tabBarTabLineActiveHovered()); - } - } - - // separator lines between tabs - const QRect leftLineRect(0, 1, 1, height - 2); - const QRect rightLineRect(width - 1, 1, 1, height - 2); - const QColor separatorLineColor = active ? tabBarTabLineActive() : tabBarTabLine(); - p->fillRect(leftLineRect, separatorLineColor); - p->fillRect(rightLineRect, separatorLineColor); -} - -void drawTabBase(QPainter *p, const QStyleOptionTabBarBase *tbb, const QWidget *w) -{ - QRect r = tbb->rect; - if (QMacStylePrivate::verticalTabs(QMacStylePrivate::tabDirection(tbb->shape))) - r.setWidth(w->width()); - else - r.setHeight(w->height()); - - const QRect tabRect = rotateTabPainter(p, tbb->shape, r); - const int width = tabRect.width(); - const int height = tabRect.height(); - const bool active = (tbb->state & QStyle::State_Active); - - // fill body - const QRect bodyRect(0, 1, width, height - 1); - const QColor bodyColor = active ? tabBarTabBackgroundActive() : tabBarTabBackground(); - p->fillRect(bodyRect, bodyColor); - - // top line - const QRect topLineRect(0, 0, width, 1); - const QColor topLineColor = active ? tabBarTabLineActive() : tabBarTabLine(); - p->fillRect(topLineRect, topLineColor); - - // bottom line - const QRect bottomLineRect(0, height - 1, width, 1); - bool isDocument = false; - if (const QTabBar *tabBar = qobject_cast(w)) - isDocument = tabBar->documentMode(); - const QColor bottomLineColor = isDocument && isDarkMode() ? QColor(Qt::black) : active ? tabBarTabLineActive() : tabBarTabLine(); - p->fillRect(bottomLineRect, bottomLineColor); -} -#endif - -static QStyleHelper::WidgetSizePolicy getControlSize(const QStyleOption *option, const QWidget *widget) -{ - const auto wsp = QStyleHelper::widgetSizePolicy(widget, option); - if (wsp == QStyleHelper::SizeDefault) - return QStyleHelper::SizeLarge; - - return wsp; -} - -#if QT_CONFIG(treeview) -static inline bool isTreeView(const QWidget *widget) -{ - return (widget && widget->parentWidget() && - qobject_cast(widget->parentWidget())); -} -#endif - -static QString qt_mac_removeMnemonics(const QString &original) -{ - QString returnText(original.size(), 0); - int finalDest = 0; - int currPos = 0; - int l = original.length(); - while (l) { - if (original.at(currPos) == QLatin1Char('&')) { - ++currPos; - --l; - if (l == 0) - break; - } else if (original.at(currPos) == QLatin1Char('(') && l >= 4 && - original.at(currPos + 1) == QLatin1Char('&') && - original.at(currPos + 2) != QLatin1Char('&') && - original.at(currPos + 3) == QLatin1Char(')')) { - /* remove mnemonics its format is "\s*(&X)" */ - int n = 0; - while (finalDest > n && returnText.at(finalDest - n - 1).isSpace()) - ++n; - finalDest -= n; - currPos += 4; - l -= 4; - continue; - } - returnText[finalDest] = original.at(currPos); - ++currPos; - ++finalDest; - --l; - } - returnText.truncate(finalDest); - return returnText; -} - -static bool qt_macWindowMainWindow(const QWidget *window) -{ - if (QWindow *w = window->windowHandle()) { - if (w->handle()) { - if (NSWindow *nswindow = static_cast(QGuiApplication::platformNativeInterface()->nativeResourceForWindow(QByteArrayLiteral("nswindow"), w))) { - return [nswindow isMainWindow]; - } - } - } - return false; -} - -/***************************************************************************** - QMacCGStyle globals - *****************************************************************************/ -const int macItemFrame = 2; // menu item frame width -const int macItemHMargin = 3; // menu item hor text margin -const int macRightBorder = 12; // right border on mac - -/***************************************************************************** - QMacCGStyle utility functions - *****************************************************************************/ - -enum QAquaMetric { - // Prepend kThemeMetric to get the HIToolBox constant. - // Represents the values already used in QMacStyle. - CheckBoxHeight = 0, - CheckBoxWidth, - EditTextFrameOutset, - FocusRectOutset, - HSliderHeight, - HSliderTickHeight, - LargeProgressBarThickness, - ListHeaderHeight, - MenuSeparatorHeight, // GetThemeMenuSeparatorHeight - MiniCheckBoxHeight, - MiniCheckBoxWidth, - MiniHSliderHeight, - MiniHSliderTickHeight, - MiniPopupButtonHeight, - MiniPushButtonHeight, - MiniRadioButtonHeight, - MiniRadioButtonWidth, - MiniVSliderTickWidth, - MiniVSliderWidth, - NormalProgressBarThickness, - PopupButtonHeight, - ProgressBarShadowOutset, - PushButtonHeight, - RadioButtonHeight, - RadioButtonWidth, - SeparatorSize, - SmallCheckBoxHeight, - SmallCheckBoxWidth, - SmallHSliderHeight, - SmallHSliderTickHeight, - SmallPopupButtonHeight, - SmallProgressBarShadowOutset, - SmallPushButtonHeight, - SmallRadioButtonHeight, - SmallRadioButtonWidth, - SmallVSliderTickWidth, - SmallVSliderWidth, - VSliderTickWidth, - VSliderWidth -}; - -static const int qt_mac_aqua_metrics[] = { - // Values as of macOS 10.12.4 and Xcode 8.3.1 - 18 /* CheckBoxHeight */, - 18 /* CheckBoxWidth */, - 1 /* EditTextFrameOutset */, - 4 /* FocusRectOutset */, - 22 /* HSliderHeight */, - 5 /* HSliderTickHeight */, - 16 /* LargeProgressBarThickness */, - 17 /* ListHeaderHeight */, - 12 /* MenuSeparatorHeight, aka GetThemeMenuSeparatorHeight */, - 11 /* MiniCheckBoxHeight */, - 10 /* MiniCheckBoxWidth */, - 12 /* MiniHSliderHeight */, - 4 /* MiniHSliderTickHeight */, - 15 /* MiniPopupButtonHeight */, - 16 /* MiniPushButtonHeight */, - 11 /* MiniRadioButtonHeight */, - 10 /* MiniRadioButtonWidth */, - 4 /* MiniVSliderTickWidth */, - 12 /* MiniVSliderWidth */, - 12 /* NormalProgressBarThickness */, - 20 /* PopupButtonHeight */, - 4 /* ProgressBarShadowOutset */, - 20 /* PushButtonHeight */, - 18 /* RadioButtonHeight */, - 18 /* RadioButtonWidth */, - 1 /* SeparatorSize */, - 16 /* SmallCheckBoxHeight */, - 14 /* SmallCheckBoxWidth */, - 15 /* SmallHSliderHeight */, - 4 /* SmallHSliderTickHeight */, - 17 /* SmallPopupButtonHeight */, - 2 /* SmallProgressBarShadowOutset */, - 17 /* SmallPushButtonHeight */, - 15 /* SmallRadioButtonHeight */, - 14 /* SmallRadioButtonWidth */, - 4 /* SmallVSliderTickWidth */, - 15 /* SmallVSliderWidth */, - 5 /* VSliderTickWidth */, - 22 /* VSliderWidth */ -}; - -static inline int qt_mac_aqua_get_metric(QAquaMetric m) -{ - return qt_mac_aqua_metrics[m]; -} - -static QSize qt_aqua_get_known_size(QStyle::ContentsType ct, const QWidget *widg, QSize szHint, - QStyleHelper::WidgetSizePolicy sz) -{ - QSize ret(-1, -1); - if (sz != QStyleHelper::SizeSmall && sz != QStyleHelper::SizeLarge && sz != QStyleHelper::SizeMini) { - qDebug("Not sure how to return this..."); - return ret; - } - if ((widg && widg->testAttribute(Qt::WA_SetFont)) || !QApplication::desktopSettingsAware()) { - // If you're using a custom font and it's bigger than the default font, - // then no constraints for you. If you are smaller, we can try to help you out - QFont font = qt_app_fonts_hash()->value(widg->metaObject()->className(), QFont()); - if (widg->font().pointSize() > font.pointSize()) - return ret; - } - - if (ct == QStyle::CT_CustomBase && widg) { -#if QT_CONFIG(pushbutton) - if (qobject_cast(widg)) - ct = QStyle::CT_PushButton; -#endif - else if (qobject_cast(widg)) - ct = QStyle::CT_RadioButton; -#if QT_CONFIG(checkbox) - else if (qobject_cast(widg)) - ct = QStyle::CT_CheckBox; -#endif -#if QT_CONFIG(combobox) - else if (qobject_cast(widg)) - ct = QStyle::CT_ComboBox; -#endif -#if QT_CONFIG(toolbutton) - else if (qobject_cast(widg)) - ct = QStyle::CT_ToolButton; -#endif - else if (qobject_cast(widg)) - ct = QStyle::CT_Slider; -#if QT_CONFIG(progressbar) - else if (qobject_cast(widg)) - ct = QStyle::CT_ProgressBar; -#endif -#if QT_CONFIG(lineedit) - else if (qobject_cast(widg)) - ct = QStyle::CT_LineEdit; -#endif - else if (qobject_cast(widg)) - ct = QStyle::CT_HeaderSection; -#if QT_CONFIG(menubar) - else if (qobject_cast(widg)) - ct = QStyle::CT_MenuBar; -#endif -#if QT_CONFIG(sizegrip) - else if (qobject_cast(widg)) - ct = QStyle::CT_SizeGrip; -#endif - else - return ret; - } - - switch (ct) { -#if QT_CONFIG(pushbutton) - case QStyle::CT_PushButton: { - const QPushButton *psh = qobject_cast(widg); - // If this comparison is false, then the widget was not a push button. - // This is bad and there's very little we can do since we were requested to find a - // sensible size for a widget that pretends to be a QPushButton but is not. - if(psh) { - QString buttonText = qt_mac_removeMnemonics(psh->text()); - if (buttonText.contains(QLatin1Char('\n'))) - ret = QSize(-1, -1); - else if (sz == QStyleHelper::SizeLarge) - ret = QSize(-1, qt_mac_aqua_get_metric(PushButtonHeight)); - else if (sz == QStyleHelper::SizeSmall) - ret = QSize(-1, qt_mac_aqua_get_metric(SmallPushButtonHeight)); - else if (sz == QStyleHelper::SizeMini) - ret = QSize(-1, qt_mac_aqua_get_metric(MiniPushButtonHeight)); - - if (!psh->icon().isNull()){ - // If the button got an icon, and the icon is larger than the - // button, we can't decide on a default size - ret.setWidth(-1); - if (ret.height() < psh->iconSize().height()) - ret.setHeight(-1); - } - else if (buttonText == QLatin1String("OK") || buttonText == QLatin1String("Cancel")){ - // Aqua Style guidelines restrict the size of OK and Cancel buttons to 68 pixels. - // However, this doesn't work for German, therefore only do it for English, - // I suppose it would be better to do some sort of lookups for languages - // that like to have really long words. - // FIXME This is not exactly true. Out of context, OK buttons have their - // implicit size calculated the same way as any other button. Inside a - // QDialogButtonBox, their size should be calculated such that the action - // or accept button (i.e., rightmost) and cancel button have the same width. - ret.setWidth(69); - } - } else { - // The only sensible thing to do is to return whatever the style suggests... - if (sz == QStyleHelper::SizeLarge) - ret = QSize(-1, qt_mac_aqua_get_metric(PushButtonHeight)); - else if (sz == QStyleHelper::SizeSmall) - ret = QSize(-1, qt_mac_aqua_get_metric(SmallPushButtonHeight)); - else if (sz == QStyleHelper::SizeMini) - ret = QSize(-1, qt_mac_aqua_get_metric(MiniPushButtonHeight)); - else - // Since there's no default size we return the large size... - ret = QSize(-1, qt_mac_aqua_get_metric(PushButtonHeight)); - } -#endif -#if 0 //Not sure we are applying the rules correctly for RadioButtons/CheckBoxes --Sam - } else if (ct == QStyle::CT_RadioButton) { - QRadioButton *rdo = static_cast(widg); - // Exception for case where multiline radio button text requires no size constrainment - if (rdo->text().find('\n') != -1) - return ret; - if (sz == QStyleHelper::SizeLarge) - ret = QSize(-1, qt_mac_aqua_get_metric(RadioButtonHeight)); - else if (sz == QStyleHelper::SizeSmall) - ret = QSize(-1, qt_mac_aqua_get_metric(SmallRadioButtonHeight)); - else if (sz == QStyleHelper::SizeMini) - ret = QSize(-1, qt_mac_aqua_get_metric(MiniRadioButtonHeight)); - } else if (ct == QStyle::CT_CheckBox) { - if (sz == QStyleHelper::SizeLarge) - ret = QSize(-1, qt_mac_aqua_get_metric(CheckBoxHeight)); - else if (sz == QStyleHelper::SizeSmall) - ret = QSize(-1, qt_mac_aqua_get_metric(SmallCheckBoxHeight)); - else if (sz == QStyleHelper::SizeMini) - ret = QSize(-1, qt_mac_aqua_get_metric(MiniCheckBoxHeight)); -#endif - break; - } - case QStyle::CT_SizeGrip: - // Not HIG kosher: mimic what we were doing earlier until we support 4-edge resizing in MDI subwindows - if (sz == QStyleHelper::SizeLarge || sz == QStyleHelper::SizeSmall) { - int s = sz == QStyleHelper::SizeSmall ? 16 : 22; // large: pixel measured from HITheme, small: from my hat - int width = 0; -#if QT_CONFIG(mdiarea) - if (widg && qobject_cast(widg->parentWidget())) - width = s; -#endif - ret = QSize(width, s); - } - break; - case QStyle::CT_ComboBox: - switch (sz) { - case QStyleHelper::SizeLarge: - ret = QSize(-1, qt_mac_aqua_get_metric(PopupButtonHeight)); - break; - case QStyleHelper::SizeSmall: - ret = QSize(-1, qt_mac_aqua_get_metric(SmallPopupButtonHeight)); - break; - case QStyleHelper::SizeMini: - ret = QSize(-1, qt_mac_aqua_get_metric(MiniPopupButtonHeight)); - break; - default: - break; - } - break; - case QStyle::CT_ToolButton: - if (sz == QStyleHelper::SizeSmall) { - int width = 0, height = 0; - if (szHint == QSize(-1, -1)) { //just 'guess'.. -#if QT_CONFIG(toolbutton) - const QToolButton *bt = qobject_cast(widg); - // If this conversion fails then the widget was not what it claimed to be. - if(bt) { - if (!bt->icon().isNull()) { - QSize iconSize = bt->iconSize(); - QSize pmSize = bt->icon().actualSize(QSize(32, 32), QIcon::Normal); - width = qMax(width, qMax(iconSize.width(), pmSize.width())); - height = qMax(height, qMax(iconSize.height(), pmSize.height())); - } - if (!bt->text().isNull() && bt->toolButtonStyle() != Qt::ToolButtonIconOnly) { - int text_width = bt->fontMetrics().horizontalAdvance(bt->text()), - text_height = bt->fontMetrics().height(); - if (bt->toolButtonStyle() == Qt::ToolButtonTextUnderIcon) { - width = qMax(width, text_width); - height += text_height; - } else { - width += text_width; - width = qMax(height, text_height); - } - } - } else -#endif - { - // Let's return the size hint... - width = szHint.width(); - height = szHint.height(); - } - } else { - width = szHint.width(); - height = szHint.height(); - } - width = qMax(20, width + 5); //border - height = qMax(20, height + 5); //border - ret = QSize(width, height); - } - break; - case QStyle::CT_Slider: { - int w = -1; - const QSlider *sld = qobject_cast(widg); - // If this conversion fails then the widget was not what it claimed to be. - if(sld) { - if (sz == QStyleHelper::SizeLarge) { - if (sld->orientation() == Qt::Horizontal) { - w = qt_mac_aqua_get_metric(HSliderHeight); - if (sld->tickPosition() != QSlider::NoTicks) - w += qt_mac_aqua_get_metric(HSliderTickHeight); - } else { - w = qt_mac_aqua_get_metric(VSliderWidth); - if (sld->tickPosition() != QSlider::NoTicks) - w += qt_mac_aqua_get_metric(VSliderTickWidth); - } - } else if (sz == QStyleHelper::SizeSmall) { - if (sld->orientation() == Qt::Horizontal) { - w = qt_mac_aqua_get_metric(SmallHSliderHeight); - if (sld->tickPosition() != QSlider::NoTicks) - w += qt_mac_aqua_get_metric(SmallHSliderTickHeight); - } else { - w = qt_mac_aqua_get_metric(SmallVSliderWidth); - if (sld->tickPosition() != QSlider::NoTicks) - w += qt_mac_aqua_get_metric(SmallVSliderTickWidth); - } - } else if (sz == QStyleHelper::SizeMini) { - if (sld->orientation() == Qt::Horizontal) { - w = qt_mac_aqua_get_metric(MiniHSliderHeight); - if (sld->tickPosition() != QSlider::NoTicks) - w += qt_mac_aqua_get_metric(MiniHSliderTickHeight); - } else { - w = qt_mac_aqua_get_metric(MiniVSliderWidth); - if (sld->tickPosition() != QSlider::NoTicks) - w += qt_mac_aqua_get_metric(MiniVSliderTickWidth); - } - } - } else { - // This is tricky, we were requested to find a size for a slider which is not - // a slider. We don't know if this is vertical or horizontal or if we need to - // have tick marks or not. - // For this case we will return an horizontal slider without tick marks. - w = qt_mac_aqua_get_metric(HSliderHeight); - w += qt_mac_aqua_get_metric(HSliderTickHeight); - } - if (sld->orientation() == Qt::Horizontal) - ret.setHeight(w); - else - ret.setWidth(w); - break; - } -#if QT_CONFIG(progressbar) - case QStyle::CT_ProgressBar: { - int finalValue = -1; - Qt::Orientation orient = Qt::Horizontal; - if (const QProgressBar *pb = qobject_cast(widg)) - orient = pb->orientation(); - - if (sz == QStyleHelper::SizeLarge) - finalValue = qt_mac_aqua_get_metric(LargeProgressBarThickness) - + qt_mac_aqua_get_metric(ProgressBarShadowOutset); - else - finalValue = qt_mac_aqua_get_metric(NormalProgressBarThickness) - + qt_mac_aqua_get_metric(SmallProgressBarShadowOutset); - if (orient == Qt::Horizontal) - ret.setHeight(finalValue); - else - ret.setWidth(finalValue); - break; - } -#endif -#if QT_CONFIG(combobox) - case QStyle::CT_LineEdit: - if (!widg || !qobject_cast(widg->parentWidget())) { - //should I take into account the font dimentions of the lineedit? -Sam - if (sz == QStyleHelper::SizeLarge) - ret = QSize(-1, 21); - else - ret = QSize(-1, 19); - } - break; -#endif - case QStyle::CT_HeaderSection: -#if QT_CONFIG(treeview) - if (isTreeView(widg)) - ret = QSize(-1, qt_mac_aqua_get_metric(ListHeaderHeight)); -#endif - break; - case QStyle::CT_MenuBar: - if (sz == QStyleHelper::SizeLarge) { - ret = QSize(-1, [[NSApp mainMenu] menuBarHeight]); - // In the qt_mac_set_native_menubar(false) case, - // we come it here with a zero-height main menu, - // preventing the in-window menu from displaying. - // Use 22 pixels for the height, by observation. - if (ret.height() <= 0) - ret.setHeight(22); - } - break; - default: - break; - } - return ret; -} - - -#if defined(QMAC_QAQUASTYLE_SIZE_CONSTRAIN) || defined(DEBUG_SIZE_CONSTRAINT) -static QStyleHelper::WidgetSizePolicy qt_aqua_guess_size(const QWidget *widg, QSize large, QSize small, QSize mini) -{ - Q_UNUSED(widg); - - if (large == QSize(-1, -1)) { - if (small != QSize(-1, -1)) - return QStyleHelper::SizeSmall; - if (mini != QSize(-1, -1)) - return QStyleHelper::SizeMini; - return QStyleHelper::SizeDefault; - } else if (small == QSize(-1, -1)) { - if (mini != QSize(-1, -1)) - return QStyleHelper::SizeMini; - return QStyleHelper::SizeLarge; - } else if (mini == QSize(-1, -1)) { - return QStyleHelper::SizeLarge; - } - - if (qEnvironmentVariableIsSet("QWIDGET_ALL_SMALL")) - return QStyleHelper::SizeSmall; - else if (qEnvironmentVariableIsSet("QWIDGET_ALL_MINI")) - return QStyleHelper::SizeMini; - - return QStyleHelper::SizeLarge; -} -#endif - -void QMacStylePrivate::drawFocusRing(QPainter *p, const QRectF &targetRect, int hMargin, int vMargin, const CocoaControl &cw) const -{ - QPainterPath focusRingPath; - focusRingPath.setFillRule(Qt::OddEvenFill); - - qreal hOffset = 0.0; - qreal vOffset = 0.0; - switch (cw.type) { - case Box: - case Button_SquareButton: - case SegmentedControl_Middle: - case TextField: { - auto innerRect = targetRect; - if (cw.type == TextField) - innerRect = innerRect.adjusted(hMargin, vMargin, -hMargin, -vMargin).adjusted(0.5, 0.5, -0.5, -0.5); - const auto outerRect = innerRect.adjusted(-focusRingWidth, -focusRingWidth, focusRingWidth, focusRingWidth); - const auto outerRadius = focusRingWidth; - focusRingPath.addRect(innerRect); - focusRingPath.addRoundedRect(outerRect, outerRadius, outerRadius); - break; - } - case Button_CheckBox: { - const auto cbInnerRadius = (cw.size == QStyleHelper::SizeMini ? 2.0 : 3.0); - const auto cbSize = cw.size == QStyleHelper::SizeLarge ? 13 : - cw.size == QStyleHelper::SizeSmall ? 11 : 9; // As measured - hOffset = hMargin + (cw.size == QStyleHelper::SizeLarge ? 2.5 : - cw.size == QStyleHelper::SizeSmall ? 2.0 : 1.0); // As measured - vOffset = 0.5 * qreal(targetRect.height() - cbSize); - const auto cbInnerRect = QRectF(0, 0, cbSize, cbSize); - const auto cbOuterRadius = cbInnerRadius + focusRingWidth; - const auto cbOuterRect = cbInnerRect.adjusted(-focusRingWidth, -focusRingWidth, focusRingWidth, focusRingWidth); - focusRingPath.addRoundedRect(cbOuterRect, cbOuterRadius, cbOuterRadius); - focusRingPath.addRoundedRect(cbInnerRect, cbInnerRadius, cbInnerRadius); - break; - } - case Button_RadioButton: { - const auto rbSize = cw.size == QStyleHelper::SizeLarge ? 15 : - cw.size == QStyleHelper::SizeSmall ? 13 : 9; // As measured - hOffset = hMargin + (cw.size == QStyleHelper::SizeLarge ? 1.5 : - cw.size == QStyleHelper::SizeSmall ? 1.0 : 1.0); // As measured - vOffset = 0.5 * qreal(targetRect.height() - rbSize); - const auto rbInnerRect = QRectF(0, 0, rbSize, rbSize); - const auto rbOuterRect = rbInnerRect.adjusted(-focusRingWidth, -focusRingWidth, focusRingWidth, focusRingWidth); - focusRingPath.addEllipse(rbInnerRect); - focusRingPath.addEllipse(rbOuterRect); - break; - } - case Button_PopupButton: - case Button_PullDown: - case Button_PushButton: - case SegmentedControl_Single: { - const qreal innerRadius = cw.type == Button_PushButton ? 3 : 4; - const qreal outerRadius = innerRadius + focusRingWidth; - hOffset = targetRect.left(); - vOffset = targetRect.top(); - const auto innerRect = targetRect.translated(-targetRect.topLeft()); - const auto outerRect = innerRect.adjusted(-hMargin, -vMargin, hMargin, vMargin); - focusRingPath.addRoundedRect(innerRect, innerRadius, innerRadius); - focusRingPath.addRoundedRect(outerRect, outerRadius, outerRadius); - break; - } - case ComboBox: - case SegmentedControl_First: - case SegmentedControl_Last: { - hOffset = targetRect.left(); - vOffset = targetRect.top(); - const qreal innerRadius = 8; - const qreal outerRadius = innerRadius + focusRingWidth; - const auto innerRect = targetRect.translated(-targetRect.topLeft()); - const auto outerRect = innerRect.adjusted(-hMargin, -vMargin, hMargin, vMargin); - - const auto cbFocusFramePath = [](const QRectF &rect, qreal tRadius, qreal bRadius) { - QPainterPath path; - - if (tRadius > 0) { - const auto topLeftCorner = QRectF(rect.topLeft(), QSizeF(tRadius, tRadius)); - path.arcMoveTo(topLeftCorner, 180); - path.arcTo(topLeftCorner, 180, -90); - } else { - path.moveTo(rect.topLeft()); - } - const auto rightEdge = rect.right() - bRadius; - path.arcTo(rightEdge, rect.top(), bRadius, bRadius, 90, -90); - path.arcTo(rightEdge, rect.bottom() - bRadius, bRadius, bRadius, 0, -90); - if (tRadius > 0) - path.arcTo(rect.left(), rect.bottom() - tRadius, tRadius, tRadius, 270, -90); - else - path.lineTo(rect.bottomLeft()); - path.closeSubpath(); - - return path; - }; - - const auto innerPath = cbFocusFramePath(innerRect, 0, innerRadius); - focusRingPath.addPath(innerPath); - const auto outerPath = cbFocusFramePath(outerRect, 2 * focusRingWidth, outerRadius); - focusRingPath.addPath(outerPath); - break; - } - default: - Q_UNREACHABLE(); - } - - auto focusRingColor = qt_mac_toQColor(NSColor.keyboardFocusIndicatorColor.CGColor); - if (!qt_mac_applicationIsInDarkMode()) { - // This color already has alpha ~ 0.25, this value is too small - the ring is - // very pale and nothing like the native one. 0.39 makes it better (not ideal - // anyway). The color seems to be correct in dark more without any modification. - focusRingColor.setAlphaF(0.39); - } - - p->save(); - p->setRenderHint(QPainter::Antialiasing); - - if (cw.type == SegmentedControl_First) { - // TODO Flip left-right - } - p->translate(hOffset, vOffset); - p->fillPath(focusRingPath, focusRingColor); - p->restore(); -} - -QPainterPath QMacStylePrivate::windowPanelPath(const QRectF &r) const -{ - static const qreal CornerPointOffset = 5.5; - static const qreal CornerControlOffset = 2.1; - - QPainterPath path; - // Top-left corner - path.moveTo(r.left(), r.top() + CornerPointOffset); - path.cubicTo(r.left(), r.top() + CornerControlOffset, - r.left() + CornerControlOffset, r.top(), - r.left() + CornerPointOffset, r.top()); - // Top-right corner - path.lineTo(r.right() - CornerPointOffset, r.top()); - path.cubicTo(r.right() - CornerControlOffset, r.top(), - r.right(), r.top() + CornerControlOffset, - r.right(), r.top() + CornerPointOffset); - // Bottom-right corner - path.lineTo(r.right(), r.bottom() - CornerPointOffset); - path.cubicTo(r.right(), r.bottom() - CornerControlOffset, - r.right() - CornerControlOffset, r.bottom(), - r.right() - CornerPointOffset, r.bottom()); - // Bottom-right corner - path.lineTo(r.left() + CornerPointOffset, r.bottom()); - path.cubicTo(r.left() + CornerControlOffset, r.bottom(), - r.left(), r.bottom() - CornerControlOffset, - r.left(), r.bottom() - CornerPointOffset); - path.lineTo(r.left(), r.top() + CornerPointOffset); - - return path; -} - -QMacStylePrivate::CocoaControlType QMacStylePrivate::windowButtonCocoaControl(QStyle::SubControl sc) const -{ - struct WindowButtons { - QStyle::SubControl sc; - QMacStylePrivate::CocoaControlType ct; - }; - - static const WindowButtons buttons[] = { - { QStyle::SC_TitleBarCloseButton, QMacStylePrivate::Button_WindowClose }, - { QStyle::SC_TitleBarMinButton, QMacStylePrivate::Button_WindowMiniaturize }, - { QStyle::SC_TitleBarMaxButton, QMacStylePrivate::Button_WindowZoom } - }; - - for (const auto &wb : buttons) - if (wb.sc == sc) - return wb.ct; - - return NoControl; -} - - -#if QT_CONFIG(tabbar) -void QMacStylePrivate::tabLayout(const QStyleOptionTab *opt, const QWidget *widget, QRect *textRect, QRect *iconRect) const -{ - Q_ASSERT(textRect); - Q_ASSERT(iconRect); - QRect tr = opt->rect; - const bool verticalTabs = opt->shape == QTabBar::RoundedEast - || opt->shape == QTabBar::RoundedWest - || opt->shape == QTabBar::TriangularEast - || opt->shape == QTabBar::TriangularWest; - if (verticalTabs) - tr.setRect(0, 0, tr.height(), tr.width()); // 0, 0 as we will have a translate transform - - int verticalShift = proxyStyle->pixelMetric(QStyle::PM_TabBarTabShiftVertical, opt, widget); - int horizontalShift = proxyStyle->pixelMetric(QStyle::PM_TabBarTabShiftHorizontal, opt, widget); - const int hpadding = 4; - const int vpadding = proxyStyle->pixelMetric(QStyle::PM_TabBarTabVSpace, opt, widget) / 2; - if (opt->shape == QTabBar::RoundedSouth || opt->shape == QTabBar::TriangularSouth) - verticalShift = -verticalShift; - tr.adjust(hpadding, verticalShift - vpadding, horizontalShift - hpadding, vpadding); - - // left widget - if (!opt->leftButtonSize.isEmpty()) { - const int buttonSize = verticalTabs ? opt->leftButtonSize.height() : opt->leftButtonSize.width(); - tr.setLeft(tr.left() + 4 + buttonSize); - // make text aligned to center - if (opt->rightButtonSize.isEmpty()) - tr.setRight(tr.right() - 4 - buttonSize); - } - // right widget - if (!opt->rightButtonSize.isEmpty()) { - const int buttonSize = verticalTabs ? opt->rightButtonSize.height() : opt->rightButtonSize.width(); - tr.setRight(tr.right() - 4 - buttonSize); - // make text aligned to center - if (opt->leftButtonSize.isEmpty()) - tr.setLeft(tr.left() + 4 + buttonSize); - } - - // icon - if (!opt->icon.isNull()) { - QSize iconSize = opt->iconSize; - if (!iconSize.isValid()) { - int iconExtent = proxyStyle->pixelMetric(QStyle::PM_SmallIconSize); - iconSize = QSize(iconExtent, iconExtent); - } - QSize tabIconSize = opt->icon.actualSize(iconSize, - (opt->state & QStyle::State_Enabled) ? QIcon::Normal : QIcon::Disabled, - (opt->state & QStyle::State_Selected) ? QIcon::On : QIcon::Off); - // High-dpi icons do not need adjustment; make sure tabIconSize is not larger than iconSize - tabIconSize = QSize(qMin(tabIconSize.width(), iconSize.width()), qMin(tabIconSize.height(), iconSize.height())); - - *iconRect = QRect(tr.left(), tr.center().y() - tabIconSize.height() / 2, - tabIconSize.width(), tabIconSize.height()); - if (!verticalTabs) - *iconRect = proxyStyle->visualRect(opt->direction, opt->rect, *iconRect); - - int stylePadding = proxyStyle->pixelMetric(QStyle::PM_TabBarTabHSpace, opt, widget) / 2; - stylePadding -= hpadding; - - tr.setLeft(tr.left() + stylePadding + tabIconSize.width() + 4); - tr.setRight(tr.right() - stylePadding - tabIconSize.width() - 4); - } - - if (!verticalTabs) - tr = proxyStyle->visualRect(opt->direction, opt->rect, tr); - - *textRect = tr; -} - -QMacStylePrivate::Direction QMacStylePrivate::tabDirection(QTabBar::Shape shape) -{ - switch (shape) { - case QTabBar::RoundedSouth: - case QTabBar::TriangularSouth: - return South; - case QTabBar::RoundedNorth: - case QTabBar::TriangularNorth: - return North; - case QTabBar::RoundedWest: - case QTabBar::TriangularWest: - return West; - case QTabBar::RoundedEast: - case QTabBar::TriangularEast: - return East; - } -} - -bool QMacStylePrivate::verticalTabs(QMacStylePrivate::Direction direction) -{ - return (direction == QMacStylePrivate::East - || direction == QMacStylePrivate::West); -} - -#endif // QT_CONFIG(tabbar) - -QStyleHelper::WidgetSizePolicy QMacStylePrivate::effectiveAquaSizeConstrain(const QStyleOption *option, - const QWidget *widg, - QStyle::ContentsType ct, - QSize szHint, QSize *insz) const -{ - QStyleHelper::WidgetSizePolicy sz = aquaSizeConstrain(option, widg, ct, szHint, insz); - if (sz == QStyleHelper::SizeDefault) - return QStyleHelper::SizeLarge; - return sz; -} - -QStyleHelper::WidgetSizePolicy QMacStylePrivate::aquaSizeConstrain(const QStyleOption *option, const QWidget *widg, - QStyle::ContentsType ct, QSize szHint, QSize *insz) const -{ -#if defined(QMAC_QAQUASTYLE_SIZE_CONSTRAIN) || defined(DEBUG_SIZE_CONSTRAINT) - if (option) { - if (option->state & QStyle::State_Small) - return QStyleHelper::SizeSmall; - if (option->state & QStyle::State_Mini) - return QStyleHelper::SizeMini; - } - - if (!widg) { - if (insz) - *insz = QSize(); - if (qEnvironmentVariableIsSet("QWIDGET_ALL_SMALL")) - return QStyleHelper::SizeSmall; - if (qEnvironmentVariableIsSet("QWIDGET_ALL_MINI")) - return QStyleHelper::SizeMini; - return QStyleHelper::SizeDefault; - } - - QSize large = qt_aqua_get_known_size(ct, widg, szHint, QStyleHelper::SizeLarge), - small = qt_aqua_get_known_size(ct, widg, szHint, QStyleHelper::SizeSmall), - mini = qt_aqua_get_known_size(ct, widg, szHint, QStyleHelper::SizeMini); - bool guess_size = false; - QStyleHelper::WidgetSizePolicy ret = QStyleHelper::SizeDefault; - QStyleHelper::WidgetSizePolicy wsp = QStyleHelper::widgetSizePolicy(widg); - if (wsp == QStyleHelper::SizeDefault) - guess_size = true; - else if (wsp == QStyleHelper::SizeMini) - ret = QStyleHelper::SizeMini; - else if (wsp == QStyleHelper::SizeSmall) - ret = QStyleHelper::SizeSmall; - else if (wsp == QStyleHelper::SizeLarge) - ret = QStyleHelper::SizeLarge; - if (guess_size) - ret = qt_aqua_guess_size(widg, large, small, mini); - - QSize *sz = 0; - if (ret == QStyleHelper::SizeSmall) - sz = &small; - else if (ret == QStyleHelper::SizeLarge) - sz = &large; - else if (ret == QStyleHelper::SizeMini) - sz = &mini; - if (insz) - *insz = sz ? *sz : QSize(-1, -1); -#ifdef DEBUG_SIZE_CONSTRAINT - if (sz) { - const char *size_desc = "Unknown"; - if (sz == &small) - size_desc = "Small"; - else if (sz == &large) - size_desc = "Large"; - else if (sz == &mini) - size_desc = "Mini"; - qDebug("%s - %s: %s taken (%d, %d) [%d, %d]", - widg ? widg->objectName().toLatin1().constData() : "*Unknown*", - widg ? widg->metaObject()->className() : "*Unknown*", size_desc, widg->width(), widg->height(), - sz->width(), sz->height()); - } -#endif - return ret; -#else - if (insz) - *insz = QSize(); - Q_UNUSED(widg); - Q_UNUSED(ct); - Q_UNUSED(szHint); - return QStyleHelper::SizeDefault; -#endif -} - -uint qHash(const QMacStylePrivate::CocoaControl &cw, uint seed = 0) -{ - return ((cw.type << 2) | cw.size) ^ seed; -} - -QMacStylePrivate::CocoaControl::CocoaControl() - : type(NoControl), size(QStyleHelper::SizeDefault) -{ -} - -QMacStylePrivate::CocoaControl::CocoaControl(CocoaControlType t, QStyleHelper::WidgetSizePolicy s) - : type(t), size(s) -{ -} - -bool QMacStylePrivate::CocoaControl::operator==(const CocoaControl &other) const -{ - return other.type == type && other.size == size; -} - -QSizeF QMacStylePrivate::CocoaControl::defaultFrameSize() const -{ - // We need this because things like NSView.alignmentRectInsets - // or -[NSCell titleRectForBounds:] won't work unless the control - // has a reasonable frame set. IOW, it's a chicken and egg problem. - // These values are as observed in Xcode 9's Interface Builder. - - if (type == Button_PushButton) - return QSizeF(-1, pushButtonDefaultHeight[size]); - - if (type == Button_PopupButton - || type == Button_PullDown) - return QSizeF(-1, popupButtonDefaultHeight[size]); - - if (type == ComboBox) - return QSizeF(-1, comboBoxDefaultHeight[size]); - - return QSizeF(); -} - -QRectF QMacStylePrivate::CocoaControl::adjustedControlFrame(const QRectF &rect) const -{ - QRectF frameRect; - const auto frameSize = defaultFrameSize(); - if (type == QMacStylePrivate::Button_SquareButton) { - frameRect = rect.adjusted(3, 1, -3, -1) - .adjusted(focusRingWidth, focusRingWidth, -focusRingWidth, -focusRingWidth); - } else if (type == QMacStylePrivate::Button_PushButton) { - // Start from the style option's top-left corner. - frameRect = QRectF(rect.topLeft(), - QSizeF(rect.width(), frameSize.height())); - if (size == QStyleHelper::SizeSmall) - frameRect = frameRect.translated(0, 1.5); - else if (size == QStyleHelper::SizeMini) - frameRect = frameRect.adjusted(0, 0, -8, 0).translated(4, 4); - } else { - // Center in the style option's rect. - frameRect = QRectF(QPointF(0, (rect.height() - frameSize.height()) / 2.0), - QSizeF(rect.width(), frameSize.height())); - frameRect = frameRect.translated(rect.topLeft()); - if (type == QMacStylePrivate::Button_PullDown || type == QMacStylePrivate::Button_PopupButton) { - if (size == QStyleHelper::SizeLarge) - frameRect = frameRect.adjusted(0, 0, -6, 0).translated(3, 0); - else if (size == QStyleHelper::SizeSmall) - frameRect = frameRect.adjusted(0, 0, -4, 0).translated(2, 1); - else if (size == QStyleHelper::SizeMini) - frameRect = frameRect.adjusted(0, 0, -9, 0).translated(5, 0); - } else if (type == QMacStylePrivate::ComboBox) { - frameRect = frameRect.adjusted(0, 0, -6, 0).translated(4, 0); - } - } - - return frameRect; -} - -QMarginsF QMacStylePrivate::CocoaControl::titleMargins() const -{ - if (type == QMacStylePrivate::Button_PushButton) { - if (size == QStyleHelper::SizeLarge) - return QMarginsF(12, 5, 12, 9); - if (size == QStyleHelper::SizeSmall) - return QMarginsF(12, 4, 12, 9); - if (size == QStyleHelper::SizeMini) - return QMarginsF(10, 1, 10, 2); - } - - if (type == QMacStylePrivate::Button_PullDown) { - if (size == QStyleHelper::SizeLarge) - return QMarginsF(7.5, 2.5, 22.5, 5.5); - if (size == QStyleHelper::SizeSmall) - return QMarginsF(7.5, 2, 20.5, 4); - if (size == QStyleHelper::SizeMini) - return QMarginsF(4.5, 0, 16.5, 2); - } - - if (type == QMacStylePrivate::Button_SquareButton) - return QMarginsF(6, 1, 6, 2); - - return QMarginsF(); -} - -bool QMacStylePrivate::CocoaControl::getCocoaButtonTypeAndBezelStyle(NSButtonType *buttonType, NSBezelStyle *bezelStyle) const -{ - switch (type) { - case Button_CheckBox: - *buttonType = NSSwitchButton; - *bezelStyle = NSRegularSquareBezelStyle; - break; - case Button_Disclosure: - *buttonType = NSOnOffButton; - *bezelStyle = NSDisclosureBezelStyle; - break; - case Button_RadioButton: - *buttonType = NSRadioButton; - *bezelStyle = NSRegularSquareBezelStyle; - break; - case Button_SquareButton: - *buttonType = NSPushOnPushOffButton; - *bezelStyle = NSShadowlessSquareBezelStyle; - break; - case Button_PushButton: - *buttonType = NSPushOnPushOffButton; - *bezelStyle = NSRoundedBezelStyle; - break; - default: - return false; - } - - return true; -} - -QMacStylePrivate::CocoaControlType cocoaControlType(const QStyleOption *opt, const QWidget *w) -{ - if (const auto *btn = qstyleoption_cast(opt)) { - const bool hasMenu = btn->features & QStyleOptionButton::HasMenu; - // When the contents won't fit in a large sized button, - // and WA_MacNormalSize is not set, make the button square. - // Threshold used to be at 34, not 32. - const auto maxNonSquareHeight = pushButtonDefaultHeight[QStyleHelper::SizeLarge]; - const bool isSquare = (btn->features & QStyleOptionButton::Flat) - || (btn->rect.height() > maxNonSquareHeight - && !(w && w->testAttribute(Qt::WA_MacNormalSize))); - return (isSquare? QMacStylePrivate::Button_SquareButton : - hasMenu ? QMacStylePrivate::Button_PullDown : - QMacStylePrivate::Button_PushButton); - } - - if (const auto *combo = qstyleoption_cast(opt)) { - if (combo->editable) - return QMacStylePrivate::ComboBox; - // TODO Me may support square, non-editable combo boxes, but not more than that - return QMacStylePrivate::Button_PopupButton; - } - - return QMacStylePrivate::NoControl; -} - -/** - Carbon draws comboboxes (and other views) outside the rect given as argument. Use this function to obtain - the corresponding inner rect for drawing the same combobox so that it stays inside the given outerBounds. -*/ -CGRect QMacStylePrivate::comboboxInnerBounds(const CGRect &outerBounds, const CocoaControl &cocoaWidget) -{ - CGRect innerBounds = outerBounds; - // Carbon draw parts of the view outside the rect. - // So make the rect a bit smaller to compensate - // (I wish HIThemeGetButtonBackgroundBounds worked) - if (cocoaWidget.type == Button_PopupButton) { - switch (cocoaWidget.size) { - case QStyleHelper::SizeSmall: - innerBounds.origin.x += 3; - innerBounds.origin.y += 3; - innerBounds.size.width -= 6; - innerBounds.size.height -= 7; - break; - case QStyleHelper::SizeMini: - innerBounds.origin.x += 2; - innerBounds.origin.y += 2; - innerBounds.size.width -= 5; - innerBounds.size.height -= 6; - break; - case QStyleHelper::SizeLarge: - case QStyleHelper::SizeDefault: - innerBounds.origin.x += 2; - innerBounds.origin.y += 2; - innerBounds.size.width -= 5; - innerBounds.size.height -= 6; - } - } else if (cocoaWidget.type == ComboBox) { - switch (cocoaWidget.size) { - case QStyleHelper::SizeSmall: - innerBounds.origin.x += 3; - innerBounds.origin.y += 3; - innerBounds.size.width -= 7; - innerBounds.size.height -= 8; - break; - case QStyleHelper::SizeMini: - innerBounds.origin.x += 3; - innerBounds.origin.y += 3; - innerBounds.size.width -= 4; - innerBounds.size.height -= 8; - break; - case QStyleHelper::SizeLarge: - case QStyleHelper::SizeDefault: - innerBounds.origin.x += 3; - innerBounds.origin.y += 2; - innerBounds.size.width -= 6; - innerBounds.size.height -= 8; - } - } - - return innerBounds; -} - -/** - Inside a combobox Qt places a line edit widget. The size of this widget should depend on the kind - of combobox we choose to draw. This function calculates and returns this size. -*/ -QRectF QMacStylePrivate::comboboxEditBounds(const QRectF &outerBounds, const CocoaControl &cw) -{ - QRectF ret = outerBounds; - if (cw.type == ComboBox) { - switch (cw.size) { - case QStyleHelper::SizeLarge: - ret = ret.adjusted(0, 0, -28, 0).translated(3, 4.5); - ret.setHeight(16); - break; - case QStyleHelper::SizeSmall: - ret = ret.adjusted(0, 0, -24, 0).translated(3, 2); - ret.setHeight(14); - break; - case QStyleHelper::SizeMini: - ret = ret.adjusted(0, 0, -21, 0).translated(2, 3); - ret.setHeight(11); - break; - default: - break; - } - } else if (cw.type == Button_PopupButton) { - switch (cw.size) { - case QStyleHelper::SizeLarge: - ret.adjust(10, 1, -23, -4); - break; - case QStyleHelper::SizeSmall: - ret.adjust(10, 4, -20, -3); - break; - case QStyleHelper::SizeMini: - ret.adjust(9, 0, -19, 0); - ret.setHeight(13); - break; - default: - break; - } - } - return ret; -} - -QMacStylePrivate::QMacStylePrivate() - : backingStoreNSView(nil) -{ - if (auto *ssf = QGuiApplicationPrivate::platformTheme()->font(QPlatformTheme::SmallFont)) - smallSystemFont = *ssf; - if (auto *msf = QGuiApplicationPrivate::platformTheme()->font(QPlatformTheme::MiniFont)) - miniSystemFont = *msf; -} - -QMacStylePrivate::~QMacStylePrivate() -{ - QMacAutoReleasePool pool; - for (NSView *b : cocoaControls) - [b release]; - for (NSCell *cell : cocoaCells) - [cell release]; -} - -NSView *QMacStylePrivate::cocoaControl(CocoaControl widget) const -{ - if (widget.type == QMacStylePrivate::NoControl - || widget.size == QStyleHelper::SizeDefault) - return nil; - - if (widget.type == Box) { - if (__builtin_available(macOS 10.14, *)) { - if (qt_mac_applicationIsInDarkMode()) { - // See render code in drawPrimitive(PE_FrameTabWidget) - widget.type = Box_Dark; - } - } - } - - NSView *bv = cocoaControls.value(widget, nil); - if (!bv) { - switch (widget.type) { - case Box: { - NSBox *box = [[NSBox alloc] init]; - bv = box; - box.title = @""; - box.titlePosition = NSNoTitle; - break; - } - case Box_Dark: - bv = [[QDarkNSBox alloc] init]; - break; - case Button_CheckBox: - case Button_Disclosure: - case Button_PushButton: - case Button_RadioButton: - case Button_SquareButton: { - NSButton *bc = [[NSButton alloc] init]; - bc.title = @""; - // See below for style and bezel setting. - bv = bc; - break; - } - case Button_PopupButton: - case Button_PullDown: { - NSPopUpButton *bc = [[NSPopUpButton alloc] init]; - bc.title = @""; - if (widget.type == Button_PullDown) - bc.pullsDown = YES; - bv = bc; - break; - } - case Button_WindowClose: - case Button_WindowMiniaturize: - case Button_WindowZoom: { - const NSWindowButton button = [=] { - switch (widget.type) { - case Button_WindowClose: - return NSWindowCloseButton; - case Button_WindowMiniaturize: - return NSWindowMiniaturizeButton; - case Button_WindowZoom: - return NSWindowZoomButton; - default: - break; - } - Q_UNREACHABLE(); - } (); - const auto styleMask = NSWindowStyleMaskTitled - | NSWindowStyleMaskClosable - | NSWindowStyleMaskMiniaturizable - | NSWindowStyleMaskResizable; - bv = [NSWindow standardWindowButton:button forStyleMask:styleMask]; - [bv retain]; - break; - } - case ComboBox: - bv = [[NSComboBox alloc] init]; - break; - case ProgressIndicator_Determinate: - bv = [[NSProgressIndicator alloc] init]; - break; - case ProgressIndicator_Indeterminate: - bv = [[QIndeterminateProgressIndicator alloc] init]; - break; - case Scroller_Horizontal: - bv = [[NSScroller alloc] initWithFrame:NSMakeRect(0, 0, 200, 20)]; - break; - case Scroller_Vertical: - // Cocoa sets the orientation from the view's frame - // at construction time, and it cannot be changed later. - bv = [[NSScroller alloc] initWithFrame:NSMakeRect(0, 0, 20, 200)]; - break; - case Slider_Horizontal: - bv = [[NSSlider alloc] initWithFrame:NSMakeRect(0, 0, 200, 20)]; - break; - case Slider_Vertical: - // Cocoa sets the orientation from the view's frame - // at construction time, and it cannot be changed later. - bv = [[NSSlider alloc] initWithFrame:NSMakeRect(0, 0, 20, 200)]; - break; - case SplitView_Horizontal: - bv = [[NSSplitView alloc] init]; - break; - case SplitView_Vertical: - bv = [[QVerticalSplitView alloc] init]; - break; - case TextField: - bv = [[NSTextField alloc] init]; - break; - default: - break; - } - - if ([bv isKindOfClass:[NSControl class]]) { - auto *ctrl = static_cast(bv); - switch (widget.size) { - case QStyleHelper::SizeSmall: - ctrl.controlSize = NSControlSizeSmall; - break; - case QStyleHelper::SizeMini: - ctrl.controlSize = NSControlSizeMini; - break; - default: - break; - } - } else if (widget.type == ProgressIndicator_Determinate || - widget.type == ProgressIndicator_Indeterminate) { - auto *pi = static_cast(bv); - pi.indeterminate = (widget.type == ProgressIndicator_Indeterminate); - switch (widget.size) { - case QStyleHelper::SizeSmall: - pi.controlSize = NSControlSizeSmall; - break; - case QStyleHelper::SizeMini: - pi.controlSize = NSControlSizeMini; - break; - default: - break; - } - } - - cocoaControls.insert(widget, bv); - } - - NSButtonType buttonType; - NSBezelStyle bezelStyle; - if (widget.getCocoaButtonTypeAndBezelStyle(&buttonType, &bezelStyle)) { - // FIXME We need to reset the button's type and - // bezel style properties, even when cached. - auto *button = static_cast(bv); - button.buttonType = buttonType; - button.bezelStyle = bezelStyle; - if (widget.type == Button_CheckBox) - button.allowsMixedState = YES; - } - - return bv; -} - -NSCell *QMacStylePrivate::cocoaCell(CocoaControl widget) const -{ - NSCell *cell = cocoaCells[widget]; - if (!cell) { - switch (widget.type) { - case Stepper: - cell = [[NSStepperCell alloc] init]; - break; - case Button_Disclosure: { - NSButtonCell *bc = [[NSButtonCell alloc] init]; - bc.buttonType = NSOnOffButton; - bc.bezelStyle = NSDisclosureBezelStyle; - cell = bc; - break; - } - default: - break; - } - - switch (widget.size) { - case QStyleHelper::SizeSmall: - cell.controlSize = NSControlSizeSmall; - break; - case QStyleHelper::SizeMini: - cell.controlSize = NSControlSizeMini; - break; - default: - break; - } - - cocoaCells.insert(widget, cell); - } - - return cell; -} - -void QMacStylePrivate::drawNSViewInRect(NSView *view, const QRectF &rect, QPainter *p, - __attribute__((noescape)) DrawRectBlock drawRectBlock) const -{ - QMacCGContext ctx(p); - setupNSGraphicsContext(ctx, YES); - - // FIXME: The rect that we get in is relative to the widget that we're drawing - // style on behalf of, and doesn't take into account the offset of that widget - // to the widget that owns the backingstore, which we are placing the native - // view into below. This means most of the views are placed in the upper left - // corner of backingStoreNSView, which does not map to where the actual widget - // is, and which may cause problems such as triggering a setNeedsDisplay of the - // backingStoreNSView for the wrong rect. We work around this by making the view - // layer-backed, which prevents triggering display of the backingStoreNSView, but - // but there may be other issues lurking here due to the wrong position. QTBUG-68023 - view.wantsLayer = YES; - - // FIXME: We are also setting the frame of the incoming view a lot at the call - // sites of this function, making it unclear who's actually responsible for - // maintaining the size and position of the view. In theory the call sites - // should ensure the _size_ of the view is correct, and then let this code - // take care of _positioning_ the view at the right place inside backingStoreNSView. - // For now we pass on the rect as is, to prevent any regressions until this - // can be investigated properly. - view.frame = rect.toCGRect(); - - [backingStoreNSView addSubview:view]; - - // FIXME: Based on the code below, this method isn't drawing an NSView into - // a rect, it's drawing _part of the NSView_, defined by the incoming clip - // or dirty rect, into the current graphics context. We're doing some manual - // translations at the call sites that would indicate that this relationship - // is a bit fuzzy. - const CGRect dirtyRect = rect.toCGRect(); - - if (drawRectBlock) - drawRectBlock(ctx, dirtyRect); - else - [view drawRect:dirtyRect]; - - [view removeFromSuperviewWithoutNeedingDisplay]; - - restoreNSGraphicsContext(ctx); -} - -void QMacStylePrivate::resolveCurrentNSView(QWindow *window) const -{ - backingStoreNSView = window ? (NSView *)window->winId() : nil; -} - -QMacStyle::QMacStyle() - : QCommonStyle(*new QMacStylePrivate) -{ - QMacAutoReleasePool pool; - - static QMacNotificationObserver scrollbarStyleObserver(nil, - NSPreferredScrollerStyleDidChangeNotification, []() { - // Purge destroyed scroll bars - QMacStylePrivate::scrollBars.removeAll(QPointer()); - - QEvent event(QEvent::StyleChange); - for (const auto &o : QMacStylePrivate::scrollBars) - QCoreApplication::sendEvent(o, &event); - }); - -#if QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_14) - Q_D(QMacStyle); - // FIXME: Tie this logic into theme change, or even polish/unpolish - if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave) { - d->appearanceObserver = QMacKeyValueObserver(NSApp, @"effectiveAppearance", [this] { - Q_D(QMacStyle); - for (NSView *b : d->cocoaControls) - [b release]; - d->cocoaControls.clear(); - }); - } -#endif -} - -QMacStyle::~QMacStyle() -{ -} - -void QMacStyle::polish(QPalette &) -{ -} - -void QMacStyle::polish(QApplication *) -{ -} - -void QMacStyle::unpolish(QApplication *) -{ -} - -void QMacStyle::polish(QWidget* w) -{ - if (false -#if QT_CONFIG(menu) - || qobject_cast(w) -# if QT_CONFIG(combobox) - || qobject_cast(w) -# endif -#endif -#if QT_CONFIG(mdiarea) - || qobject_cast(w) -#endif - ) { - w->setAttribute(Qt::WA_TranslucentBackground, true); - w->setAutoFillBackground(false); - } - -#if QT_CONFIG(tabbar) - if (QTabBar *tb = qobject_cast(w)) { - if (tb->documentMode()) { - w->setAttribute(Qt::WA_Hover); - w->setFont(qt_app_fonts_hash()->value("QSmallFont", QFont())); - QPalette p = w->palette(); - p.setColor(QPalette::WindowText, QColor(17, 17, 17)); - w->setPalette(p); - w->setAttribute(Qt::WA_SetPalette, false); - w->setAttribute(Qt::WA_SetFont, false); - } - } -#endif - - QCommonStyle::polish(w); - - if (QRubberBand *rubber = qobject_cast(w)) { - rubber->setWindowOpacity(0.25); - rubber->setAttribute(Qt::WA_PaintOnScreen, false); - rubber->setAttribute(Qt::WA_NoSystemBackground, false); - } - - if (qobject_cast(w)) { - w->setAttribute(Qt::WA_OpaquePaintEvent, false); - w->setAttribute(Qt::WA_Hover, true); - w->setMouseTracking(true); - } -} - -void QMacStyle::unpolish(QWidget* w) -{ - if ( -#if QT_CONFIG(menu) - qobject_cast(w) && -#endif - !w->testAttribute(Qt::WA_SetPalette)) - { - w->setPalette(QPalette()); - w->setWindowOpacity(1.0); - } - -#if QT_CONFIG(combobox) - if (QComboBox *combo = qobject_cast(w)) { - if (!combo->isEditable()) { - if (QWidget *widget = combo->findChild()) - widget->setWindowOpacity(1.0); - } - } -#endif - -#if QT_CONFIG(tabbar) - if (qobject_cast(w)) { - if (!w->testAttribute(Qt::WA_SetFont)) - w->setFont(QFont()); - if (!w->testAttribute(Qt::WA_SetPalette)) - w->setPalette(QPalette()); - } -#endif - - if (QRubberBand *rubber = qobject_cast(w)) { - rubber->setWindowOpacity(1.0); - rubber->setAttribute(Qt::WA_PaintOnScreen, true); - rubber->setAttribute(Qt::WA_NoSystemBackground, true); - } - - if (QFocusFrame *frame = qobject_cast(w)) - frame->setAttribute(Qt::WA_NoSystemBackground, true); - - QCommonStyle::unpolish(w); - - if (qobject_cast(w)) { - w->setAttribute(Qt::WA_OpaquePaintEvent, true); - w->setAttribute(Qt::WA_Hover, false); - w->setMouseTracking(false); - } -} - -int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QWidget *widget) const -{ - Q_D(const QMacStyle); - const int controlSize = getControlSize(opt, widget); - int ret = 0; - - switch (metric) { - case PM_TabCloseIndicatorWidth: - case PM_TabCloseIndicatorHeight: - ret = closeButtonSize; - break; - case PM_ToolBarIconSize: - ret = proxy()->pixelMetric(PM_LargeIconSize); - break; - case PM_FocusFrameVMargin: - case PM_FocusFrameHMargin: - ret = qt_mac_aqua_get_metric(FocusRectOutset); - break; - case PM_DialogButtonsSeparator: - ret = -5; - break; - case PM_DialogButtonsButtonHeight: { - QSize sz; - ret = d->aquaSizeConstrain(opt, 0, QStyle::CT_PushButton, QSize(-1, -1), &sz); - if (sz == QSize(-1, -1)) - ret = 32; - else - ret = sz.height(); - break; } - case PM_DialogButtonsButtonWidth: { - QSize sz; - ret = d->aquaSizeConstrain(opt, 0, QStyle::CT_PushButton, QSize(-1, -1), &sz); - if (sz == QSize(-1, -1)) - ret = 70; - else - ret = sz.width(); - break; } - - case PM_MenuBarHMargin: - ret = 8; - break; - - case PM_MenuBarVMargin: - ret = 0; - break; - - case PM_MenuBarPanelWidth: - ret = 0; - break; - - case PM_MenuButtonIndicator: - ret = toolButtonArrowSize; - break; - - case QStyle::PM_MenuDesktopFrameWidth: - ret = 5; - break; - - case PM_CheckBoxLabelSpacing: - case PM_RadioButtonLabelSpacing: - ret = [=] { - if (opt) { - if (opt->state & State_Mini) - return 4; - if (opt->state & State_Small) - return 3; - } - return 2; - } (); - break; - case PM_MenuScrollerHeight: - ret = 15; // I hate having magic numbers in here... - break; - case PM_DefaultFrameWidth: -#if QT_CONFIG(mainwindow) - if (widget && (widget->isWindow() || !widget->parentWidget() - || (qobject_cast(widget->parentWidget()) - && static_cast(widget->parentWidget())->centralWidget() == widget)) - && qobject_cast(widget)) - ret = 0; - else -#endif - // The combo box popup has no frame. - if (qstyleoption_cast(opt) != 0) - ret = 0; - else - ret = 1; - break; - case PM_MaximumDragDistance: - ret = -1; - break; - case PM_ScrollBarSliderMin: - ret = 24; - break; - case PM_SpinBoxFrameWidth: - ret = qt_mac_aqua_get_metric(EditTextFrameOutset); - break; - case PM_ButtonShiftHorizontal: - case PM_ButtonShiftVertical: - ret = 0; - break; - case PM_SliderLength: - ret = 17; - break; - // Returns the number of pixels to use for the business part of the - // slider (i.e., the non-tickmark portion). The remaining space is shared - // equally between the tickmark regions. - case PM_SliderControlThickness: - if (const QStyleOptionSlider *sl = qstyleoption_cast(opt)) { - int space = (sl->orientation == Qt::Horizontal) ? sl->rect.height() : sl->rect.width(); - int ticks = sl->tickPosition; - int n = 0; - if (ticks & QSlider::TicksAbove) - ++n; - if (ticks & QSlider::TicksBelow) - ++n; - if (!n) { - ret = space; - break; - } - - int thick = 6; // Magic constant to get 5 + 16 + 5 - if (ticks != QSlider::TicksBothSides && ticks != QSlider::NoTicks) - thick += proxy()->pixelMetric(PM_SliderLength, sl, widget) / 4; - - space -= thick; - if (space > 0) - thick += (space * 2) / (n + 2); - ret = thick; - } else { - ret = 0; - } - break; - case PM_SmallIconSize: - ret = int(QStyleHelper::dpiScaled(16.)); - break; - - case PM_LargeIconSize: - ret = int(QStyleHelper::dpiScaled(32.)); - break; - - case PM_IconViewIconSize: - ret = proxy()->pixelMetric(PM_LargeIconSize, opt, widget); - break; - - case PM_ButtonDefaultIndicator: - ret = 0; - break; - case PM_TitleBarHeight: { - NSUInteger style = NSWindowStyleMaskTitled; - if (widget && ((widget->windowFlags() & Qt::Tool) == Qt::Tool)) - style |= NSWindowStyleMaskUtilityWindow; - ret = int([NSWindow frameRectForContentRect:NSZeroRect - styleMask:style].size.height); - break; } - case QStyle::PM_TabBarTabHSpace: - switch (d->aquaSizeConstrain(opt, widget)) { - case QStyleHelper::SizeLarge: - ret = QCommonStyle::pixelMetric(metric, opt, widget); - break; - case QStyleHelper::SizeSmall: - ret = 20; - break; - case QStyleHelper::SizeMini: - ret = 16; - break; - case QStyleHelper::SizeDefault: - const QStyleOptionTab *tb = qstyleoption_cast(opt); - if (tb && tb->documentMode) - ret = 30; - else - ret = QCommonStyle::pixelMetric(metric, opt, widget); - break; - } - break; - case PM_TabBarTabVSpace: - ret = 4; - break; - case PM_TabBarTabShiftHorizontal: - case PM_TabBarTabShiftVertical: - ret = 0; - break; - case PM_TabBarBaseHeight: - ret = 0; - break; - case PM_TabBarTabOverlap: - ret = 1; - break; - case PM_TabBarBaseOverlap: - switch (d->aquaSizeConstrain(opt, widget)) { - case QStyleHelper::SizeDefault: - case QStyleHelper::SizeLarge: - ret = 11; - break; - case QStyleHelper::SizeSmall: - ret = 8; - break; - case QStyleHelper::SizeMini: - ret = 7; - break; - } - break; - case PM_ScrollBarExtent: { - const QStyleHelper::WidgetSizePolicy size = d->effectiveAquaSizeConstrain(opt, widget); - ret = static_cast([NSScroller - scrollerWidthForControlSize:static_cast(size) - scrollerStyle:[NSScroller preferredScrollerStyle]]); - break; } - case PM_IndicatorHeight: { - switch (d->aquaSizeConstrain(opt, widget)) { - case QStyleHelper::SizeDefault: - case QStyleHelper::SizeLarge: - ret = qt_mac_aqua_get_metric(CheckBoxHeight); - break; - case QStyleHelper::SizeMini: - ret = qt_mac_aqua_get_metric(MiniCheckBoxHeight); - break; - case QStyleHelper::SizeSmall: - ret = qt_mac_aqua_get_metric(SmallCheckBoxHeight); - break; - } - break; } - case PM_IndicatorWidth: { - switch (d->aquaSizeConstrain(opt, widget)) { - case QStyleHelper::SizeDefault: - case QStyleHelper::SizeLarge: - ret = qt_mac_aqua_get_metric(CheckBoxWidth); - break; - case QStyleHelper::SizeMini: - ret = qt_mac_aqua_get_metric(MiniCheckBoxWidth); - break; - case QStyleHelper::SizeSmall: - ret = qt_mac_aqua_get_metric(SmallCheckBoxWidth); - break; - } - ++ret; - break; } - case PM_ExclusiveIndicatorHeight: { - switch (d->aquaSizeConstrain(opt, widget)) { - case QStyleHelper::SizeDefault: - case QStyleHelper::SizeLarge: - ret = qt_mac_aqua_get_metric(RadioButtonHeight); - break; - case QStyleHelper::SizeMini: - ret = qt_mac_aqua_get_metric(MiniRadioButtonHeight); - break; - case QStyleHelper::SizeSmall: - ret = qt_mac_aqua_get_metric(SmallRadioButtonHeight); - break; - } - break; } - case PM_ExclusiveIndicatorWidth: { - switch (d->aquaSizeConstrain(opt, widget)) { - case QStyleHelper::SizeDefault: - case QStyleHelper::SizeLarge: - ret = qt_mac_aqua_get_metric(RadioButtonWidth); - break; - case QStyleHelper::SizeMini: - ret = qt_mac_aqua_get_metric(MiniRadioButtonWidth); - break; - case QStyleHelper::SizeSmall: - ret = qt_mac_aqua_get_metric(SmallRadioButtonWidth); - break; - } - ++ret; - break; } - case PM_MenuVMargin: - ret = 4; - break; - case PM_MenuPanelWidth: - ret = 0; - break; - case PM_ToolTipLabelFrameWidth: - ret = 0; - break; - case PM_SizeGripSize: { - QStyleHelper::WidgetSizePolicy aSize; - if (widget && widget->window()->windowType() == Qt::Tool) - aSize = QStyleHelper::SizeSmall; - else - aSize = QStyleHelper::SizeLarge; - const QSize size = qt_aqua_get_known_size(CT_SizeGrip, widget, QSize(), aSize); - ret = size.width(); - break; } - case PM_MdiSubWindowFrameWidth: - ret = 1; - break; - case PM_DockWidgetFrameWidth: - ret = 0; - break; - case PM_DockWidgetTitleMargin: - ret = 0; - break; - case PM_DockWidgetSeparatorExtent: - ret = 1; - break; - case PM_ToolBarHandleExtent: - ret = 11; - break; - case PM_ToolBarItemMargin: - ret = 0; - break; - case PM_ToolBarItemSpacing: - ret = 4; - break; - case PM_SplitterWidth: - ret = qMax(7, QApplication::globalStrut().width()); - break; - case PM_LayoutLeftMargin: - case PM_LayoutTopMargin: - case PM_LayoutRightMargin: - case PM_LayoutBottomMargin: - { - bool isWindow = false; - if (opt) { - isWindow = (opt->state & State_Window); - } else if (widget) { - isWindow = widget->isWindow(); - } - - if (isWindow) { - /* - AHIG would have (20, 8, 10) here but that makes - no sense. It would also have 14 for the top margin - but this contradicts both Builder and most - applications. - */ - return_SIZE(20, 10, 10); // AHIG - } else { - // hack to detect QTabWidget - if (widget && widget->parentWidget() - && widget->parentWidget()->sizePolicy().controlType() == QSizePolicy::TabWidget) { - if (metric == PM_LayoutTopMargin) { - /* - Builder would have 14 (= 20 - 6) instead of 12, - but that makes the tab look disproportionate. - */ - return_SIZE(12, 6, 6); // guess - } else { - return_SIZE(20 /* Builder */, 8 /* guess */, 8 /* guess */); - } - } else { - /* - Child margins are highly inconsistent in AHIG and Builder. - */ - return_SIZE(12, 8, 6); // guess - } - } - } - case PM_LayoutHorizontalSpacing: - case PM_LayoutVerticalSpacing: - return -1; - case PM_MenuHMargin: - ret = 0; - break; - case PM_ToolBarExtensionExtent: - ret = 21; - break; - case PM_ToolBarFrameWidth: - ret = 1; - break; - case PM_ScrollView_ScrollBarOverlap: - ret = [NSScroller preferredScrollerStyle] == NSScrollerStyleOverlay ? - pixelMetric(PM_ScrollBarExtent, opt, widget) : 0; - break; - default: - ret = QCommonStyle::pixelMetric(metric, opt, widget); - break; - } - return ret; -} - -QPalette QMacStyle::standardPalette() const -{ - auto platformTheme = QGuiApplicationPrivate::platformTheme(); - auto styleNames = platformTheme->themeHint(QPlatformTheme::StyleNames); - if (styleNames.toStringList().contains("macintosh")) - return *platformTheme->palette(); - else - return QStyle::standardPalette(); -} - -int QMacStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w, - QStyleHintReturn *hret) const -{ - QMacAutoReleasePool pool; - - int ret = 0; - switch (sh) { - case SH_Slider_SnapToValue: - case SH_PrintDialog_RightAlignButtons: - case SH_FontDialog_SelectAssociatedText: - case SH_MenuBar_MouseTracking: - case SH_Menu_MouseTracking: - case SH_ComboBox_ListMouseTracking: - case SH_MainWindow_SpaceBelowMenuBar: - case SH_ItemView_ChangeHighlightOnFocus: - ret = 1; - break; - case SH_ToolBox_SelectedPageTitleBold: - ret = 0; - break; - case SH_DialogButtonBox_ButtonsHaveIcons: - ret = 0; - break; - case SH_Menu_SelectionWrap: - ret = false; - break; - case SH_Menu_KeyboardSearch: - ret = true; - break; - case SH_Menu_SpaceActivatesItem: - ret = true; - break; - case SH_Slider_AbsoluteSetButtons: - ret = Qt::LeftButton|Qt::MidButton; - break; - case SH_Slider_PageSetButtons: - ret = 0; - break; - case SH_ScrollBar_ContextMenu: - ret = false; - break; - case SH_TitleBar_AutoRaise: - ret = true; - break; - case SH_Menu_AllowActiveAndDisabled: - ret = false; - break; - case SH_Menu_SubMenuPopupDelay: - ret = 100; - break; - case SH_Menu_SubMenuUniDirection: - ret = true; - break; - case SH_Menu_SubMenuSloppySelectOtherActions: - ret = false; - break; - case SH_Menu_SubMenuResetWhenReenteringParent: - ret = true; - break; - case SH_Menu_SubMenuDontStartSloppyOnLeave: - ret = true; - break; - - case SH_ScrollBar_LeftClickAbsolutePosition: { - NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; - bool result = [defaults boolForKey:@"AppleScrollerPagingBehavior"]; - if(QApplication::keyboardModifiers() & Qt::AltModifier) - ret = !result; - else - ret = result; - break; } - case SH_TabBar_PreferNoArrows: - ret = true; - break; - /* - case SH_DialogButtons_DefaultButton: - ret = QDialogButtons::Reject; - break; - */ - case SH_GroupBox_TextLabelVerticalAlignment: - ret = Qt::AlignTop; - break; - case SH_ScrollView_FrameOnlyAroundContents: - ret = QCommonStyle::styleHint(sh, opt, w, hret); - break; - case SH_Menu_FillScreenWithScroll: - ret = false; - break; - case SH_Menu_Scrollable: - ret = true; - break; - case SH_RichText_FullWidthSelection: - ret = true; - break; - case SH_BlinkCursorWhenTextSelected: - ret = false; - break; - case SH_ScrollBar_StopMouseOverSlider: - ret = true; - break; - case SH_ListViewExpand_SelectMouseType: - ret = QEvent::MouseButtonRelease; - break; - case SH_TabBar_SelectMouseType: -#if QT_CONFIG(tabbar) - if (const QStyleOptionTabBarBase *opt2 = qstyleoption_cast(opt)) { - ret = opt2->documentMode ? QEvent::MouseButtonPress : QEvent::MouseButtonRelease; - } else -#endif - { - ret = QEvent::MouseButtonRelease; - } - break; - case SH_ComboBox_Popup: - if (const QStyleOptionComboBox *cmb = qstyleoption_cast(opt)) - ret = !cmb->editable; - else - ret = 0; - break; - case SH_Workspace_FillSpaceOnMaximize: - ret = true; - break; - case SH_Widget_ShareActivation: - ret = true; - break; - case SH_Header_ArrowAlignment: - ret = Qt::AlignRight; - break; - case SH_TabBar_Alignment: { -#if QT_CONFIG(tabwidget) - if (const QTabWidget *tab = qobject_cast(w)) { - if (tab->documentMode()) { - ret = Qt::AlignLeft; - break; - } - } -#endif -#if QT_CONFIG(tabbar) - if (const QTabBar *tab = qobject_cast(w)) { - if (tab->documentMode()) { - ret = Qt::AlignLeft; - break; - } - } -#endif - ret = Qt::AlignCenter; - } break; - case SH_UnderlineShortcut: - ret = false; - break; - case SH_ToolTipLabel_Opacity: - ret = 242; // About 95% - break; - case SH_Button_FocusPolicy: - ret = Qt::TabFocus; - break; - case SH_EtchDisabledText: - ret = false; - break; - case SH_FocusFrame_Mask: { - ret = true; - if(QStyleHintReturnMask *mask = qstyleoption_cast(hret)) { - const uchar fillR = 192, fillG = 191, fillB = 190; - QImage img; - - QSize pixmapSize = opt->rect.size(); - if (!pixmapSize.isEmpty()) { - QPixmap pix(pixmapSize); - pix.fill(QColor(fillR, fillG, fillB)); - QPainter pix_paint(&pix); - proxy()->drawControl(CE_FocusFrame, opt, &pix_paint, w); - pix_paint.end(); - img = pix.toImage(); - } - - const QRgb *sptr = (QRgb*)img.bits(), *srow; - const int sbpl = img.bytesPerLine(); - const int w = sbpl/4, h = img.height(); - - QImage img_mask(img.width(), img.height(), QImage::Format_ARGB32); - QRgb *dptr = (QRgb*)img_mask.bits(), *drow; - const int dbpl = img_mask.bytesPerLine(); - - for (int y = 0; y < h; ++y) { - srow = sptr+((y*sbpl)/4); - drow = dptr+((y*dbpl)/4); - for (int x = 0; x < w; ++x) { - const int redDiff = qRed(*srow) - fillR; - const int greenDiff = qGreen(*srow) - fillG; - const int blueDiff = qBlue(*srow) - fillB; - const int diff = (redDiff * redDiff) + (greenDiff * greenDiff) + (blueDiff * blueDiff); - (*drow++) = (diff < 10) ? 0xffffffff : 0xff000000; - ++srow; - } - } - QBitmap qmask = QBitmap::fromImage(img_mask); - mask->region = QRegion(qmask); - } - break; } - case SH_TitleBar_NoBorder: - ret = 1; - break; - case SH_RubberBand_Mask: - ret = 0; - break; - case SH_ComboBox_LayoutDirection: - ret = Qt::LeftToRight; - break; - case SH_ItemView_EllipsisLocation: - ret = Qt::AlignHCenter; - break; - case SH_ItemView_ShowDecorationSelected: - ret = true; - break; - case SH_TitleBar_ModifyNotification: - ret = false; - break; - case SH_ScrollBar_RollBetweenButtons: - ret = true; - break; - case SH_WindowFrame_Mask: - ret = false; - break; - case SH_TabBar_ElideMode: - ret = Qt::ElideRight; - break; -#if QT_CONFIG(dialogbuttonbox) - case SH_DialogButtonLayout: - ret = QDialogButtonBox::MacLayout; - break; -#endif - case SH_FormLayoutWrapPolicy: - ret = QFormLayout::DontWrapRows; - break; - case SH_FormLayoutFieldGrowthPolicy: - ret = QFormLayout::FieldsStayAtSizeHint; - break; - case SH_FormLayoutFormAlignment: - ret = Qt::AlignHCenter | Qt::AlignTop; - break; - case SH_FormLayoutLabelAlignment: - ret = Qt::AlignRight; - break; - case SH_ComboBox_PopupFrameStyle: - ret = QFrame::NoFrame; - break; - case SH_MessageBox_TextInteractionFlags: - ret = Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse | Qt::TextSelectableByKeyboard; - break; - case SH_SpellCheckUnderlineStyle: - ret = QTextCharFormat::DashUnderline; - break; - case SH_MessageBox_CenterButtons: - ret = false; - break; - case SH_MenuBar_AltKeyNavigation: - ret = false; - break; - case SH_ItemView_MovementWithoutUpdatingSelection: - ret = false; - break; - case SH_FocusFrame_AboveWidget: - ret = true; - break; -#if QT_CONFIG(wizard) - case SH_WizardStyle: - ret = QWizard::MacStyle; - break; -#endif - case SH_ItemView_ArrowKeysNavigateIntoChildren: - ret = false; - break; - case SH_Menu_FlashTriggeredItem: - ret = true; - break; - case SH_Menu_FadeOutOnHide: - ret = true; - break; - case SH_ItemView_PaintAlternatingRowColorsForEmptyArea: - ret = true; - break; -#if QT_CONFIG(tabbar) - case SH_TabBar_CloseButtonPosition: - ret = QTabBar::LeftSide; - break; -#endif - case SH_DockWidget_ButtonsHaveFrame: - ret = false; - break; - case SH_ScrollBar_Transient: - if ((qobject_cast(w) && w->parent() && - qobject_cast(w->parent()->parent())) -#ifndef QT_NO_ACCESSIBILITY - || (opt && QStyleHelper::hasAncestor(opt->styleObject, QAccessible::ScrollBar)) -#endif - ) { - ret = [NSScroller preferredScrollerStyle] == NSScrollerStyleOverlay; - } - break; - case SH_ItemView_ScrollMode: - ret = QAbstractItemView::ScrollPerPixel; - break; - case SH_TitleBar_ShowToolTipsOnButtons: - // min/max/close buttons on windows don't show tool tips - ret = false; - break; - case SH_ComboBox_AllowWheelScrolling: - ret = false; - break; - case SH_SpinBox_ButtonsInsideFrame: - ret = false; - break; - case SH_Table_GridLineColor: - ret = int(qt_mac_toQColor(NSColor.gridColor).rgb()); - break; - default: - ret = QCommonStyle::styleHint(sh, opt, w, hret); - break; - } - return ret; -} - -QPixmap QMacStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, - const QStyleOption *opt) const -{ - switch (iconMode) { - case QIcon::Disabled: { - QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32); - int imgh = img.height(); - int imgw = img.width(); - QRgb pixel; - for (int y = 0; y < imgh; ++y) { - for (int x = 0; x < imgw; ++x) { - pixel = img.pixel(x, y); - img.setPixel(x, y, qRgba(qRed(pixel), qGreen(pixel), qBlue(pixel), - qAlpha(pixel) / 2)); - } - } - return QPixmap::fromImage(img); - } - default: - ; - } - return QCommonStyle::generatedIconPixmap(iconMode, pixmap, opt); -} - - -QPixmap QMacStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, - const QWidget *widget) const -{ - // The default implementation of QStyle::standardIconImplementation() is to call standardPixmap() - // I don't want infinite recursion so if we do get in that situation, just return the Window's - // standard pixmap instead (since there is no mac-specific icon then). This should be fine until - // someone changes how Windows standard - // pixmap works. - static bool recursionGuard = false; - - if (recursionGuard) - return QCommonStyle::standardPixmap(standardPixmap, opt, widget); - - recursionGuard = true; - QIcon icon = proxy()->standardIcon(standardPixmap, opt, widget); - recursionGuard = false; - int size; - switch (standardPixmap) { - default: - size = 32; - break; - case SP_MessageBoxCritical: - case SP_MessageBoxQuestion: - case SP_MessageBoxInformation: - case SP_MessageBoxWarning: - size = 64; - break; - } - return icon.pixmap(qt_getWindow(widget), QSize(size, size)); -} - -void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p, - const QWidget *w) const -{ - Q_D(const QMacStyle); - const AppearanceSync appSync; - QMacCGContext cg(p); - QWindow *window = w && w->window() ? w->window()->windowHandle() : nullptr; - d->resolveCurrentNSView(window); - switch (pe) { - case PE_IndicatorArrowUp: - case PE_IndicatorArrowDown: - case PE_IndicatorArrowRight: - case PE_IndicatorArrowLeft: { - p->save(); - p->setRenderHint(QPainter::Antialiasing); - const int xOffset = 1; // FIXME: opt->direction == Qt::LeftToRight ? 2 : -1; - qreal halfSize = 0.5 * qMin(opt->rect.width(), opt->rect.height()); - const qreal penWidth = qMax(halfSize / 3.0, 1.25); -#if QT_CONFIG(toolbutton) - if (const QToolButton *tb = qobject_cast(w)) { - // When stroking the arrow, make sure it fits in the tool button - if (tb->arrowType() != Qt::NoArrow - || tb->popupMode() == QToolButton::MenuButtonPopup) - halfSize -= penWidth; - } -#endif - - QMatrix matrix; - matrix.translate(opt->rect.center().x() + xOffset, opt->rect.center().y() + 2); - QPainterPath path; - switch(pe) { - default: - case PE_IndicatorArrowDown: - break; - case PE_IndicatorArrowUp: - matrix.rotate(180); - break; - case PE_IndicatorArrowLeft: - matrix.rotate(90); - break; - case PE_IndicatorArrowRight: - matrix.rotate(-90); - break; - } - p->setMatrix(matrix); - - path.moveTo(-halfSize, -halfSize * 0.5); - path.lineTo(0.0, halfSize * 0.5); - path.lineTo(halfSize, -halfSize * 0.5); - - const QPen arrowPen(opt->palette.text(), penWidth, - Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin); - p->strokePath(path, arrowPen); - p->restore(); - break; } -#if QT_CONFIG(tabbar) - case PE_FrameTabBarBase: - if (const QStyleOptionTabBarBase *tbb - = qstyleoption_cast(opt)) { - if (tbb->documentMode) { - p->save(); - drawTabBase(p, tbb, w); - p->restore(); - return; - } - - QRegion region(tbb->rect); - region -= tbb->tabBarRect; - p->save(); - p->setClipRegion(region); - QStyleOptionTabWidgetFrame twf; - twf.QStyleOption::operator=(*tbb); - twf.shape = tbb->shape; - switch (QMacStylePrivate::tabDirection(twf.shape)) { - case QMacStylePrivate::North: - twf.rect = twf.rect.adjusted(0, 0, 0, 10); - break; - case QMacStylePrivate::South: - twf.rect = twf.rect.adjusted(0, -10, 0, 0); - break; - case QMacStylePrivate::West: - twf.rect = twf.rect.adjusted(0, 0, 10, 0); - break; - case QMacStylePrivate::East: - twf.rect = twf.rect.adjusted(0, -10, 0, 0); - break; - } - proxy()->drawPrimitive(PE_FrameTabWidget, &twf, p, w); - p->restore(); - } - break; -#endif - case PE_PanelTipLabel: - p->fillRect(opt->rect, opt->palette.brush(QPalette::ToolTipBase)); - break; - case PE_FrameGroupBox: - if (const auto *groupBox = qstyleoption_cast(opt)) - if (groupBox->features & QStyleOptionFrame::Flat) { - QCommonStyle::drawPrimitive(pe, groupBox, p, w); - break; - } -#if QT_CONFIG(tabwidget) - Q_FALLTHROUGH(); - case PE_FrameTabWidget: -#endif - { - const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::Box, QStyleHelper::SizeLarge); - auto *box = static_cast(d->cocoaControl(cw)); - // FIXME Since macOS 10.14, simply calling drawRect: won't display anything anymore. - // The AppKit team is aware of this and has proposed a couple of solutions. - // The first solution was to call displayRectIgnoringOpacity:inContext: instead. - // However, it doesn't seem to work on 10.13. More importantly, dark mode on 10.14 - // is extremely slow. Light mode works fine. - // The second solution is to subclass NSBox and reimplement a trivial drawRect: which - // would only call super. This works without any issue on 10.13, but a double border - // shows on 10.14 in both light and dark modes. - // The code below picks what works on each version and mode. On 10.13 and earlier, we - // simply call drawRect: on a regular NSBox. On 10.14, we call displayRectIgnoringOpacity: - // inContext:, but only in light mode. In dark mode, we use a custom NSBox subclass, - // QDarkNSBox, of type NSBoxCustom. Its appearance is close enough to the real thing so - // we can use this for now. - auto adjustedRect = opt->rect; - bool needTranslation = false; - if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave - && !qt_mac_applicationIsInDarkMode()) { - // Another surprise from AppKit (SDK 10.14) - -displayRectIgnoringOpacity: - // is different from drawRect: for some Apple-known reason box is smaller - // in height than we need, resulting in tab buttons sitting too high/not - // centered. Attempts to play with insets etc did not work - the same wrong - // height. Simple translation is not working (too much space "at bottom"), - // so we make it bigger and translate (otherwise it's clipped at bottom btw). - adjustedRect.adjust(0, 0, 0, 3); - needTranslation = true; - } - d->drawNSViewInRect(box, adjustedRect, p, ^(CGContextRef ctx, const CGRect &rect) { - if (QTabWidget *tabWidget = qobject_cast(opt->styleObject)) - clipTabBarFrame(opt, this, ctx); - CGContextTranslateCTM(ctx, 0, rect.origin.y + rect.size.height); - CGContextScaleCTM(ctx, 1, -1); - if (QOperatingSystemVersion::current() < QOperatingSystemVersion::MacOSMojave - || [box isMemberOfClass:QDarkNSBox.class]) { - [box drawRect:rect]; - } else { - if (needTranslation) - CGContextTranslateCTM(ctx, 0.0, 4.0); - [box displayRectIgnoringOpacity:box.bounds inContext:NSGraphicsContext.currentContext]; - } - }); - break; - } - case PE_IndicatorToolBarSeparator: { - QPainterPath path; - if (opt->state & State_Horizontal) { - int xpoint = opt->rect.center().x(); - path.moveTo(xpoint + 0.5, opt->rect.top() + 1); - path.lineTo(xpoint + 0.5, opt->rect.bottom()); - } else { - int ypoint = opt->rect.center().y(); - path.moveTo(opt->rect.left() + 2 , ypoint + 0.5); - path.lineTo(opt->rect.right() + 1, ypoint + 0.5); - } - QPainterPathStroker theStroker; - theStroker.setCapStyle(Qt::FlatCap); - theStroker.setDashPattern(QVector() << 1 << 2); - path = theStroker.createStroke(path); - const auto dark = qt_mac_applicationIsInDarkMode() ? opt->palette.dark().color().darker() - : QColor(0, 0, 0, 119); - p->fillPath(path, dark); - } - break; - case PE_FrameWindow: - if (const QStyleOptionFrame *frame = qstyleoption_cast(opt)) { - if (w && w->inherits("QMdiSubWindow")) { - p->save(); - p->setPen(QPen(frame->palette.dark().color(), frame->lineWidth)); - p->setBrush(frame->palette.window()); - p->drawRect(frame->rect); - p->restore(); - } - } - break; - case PE_IndicatorDockWidgetResizeHandle: { - // The docwidget resize handle is drawn as a one-pixel wide line. - p->save(); - if (opt->state & State_Horizontal) { - p->setPen(QColor(160, 160, 160)); - p->drawLine(opt->rect.topLeft(), opt->rect.topRight()); - } else { - p->setPen(QColor(145, 145, 145)); - p->drawLine(opt->rect.topRight(), opt->rect.bottomRight()); - } - p->restore(); - } break; - case PE_IndicatorToolBarHandle: { - p->save(); - QPainterPath path; - int x = opt->rect.x() + 6; - int y = opt->rect.y() + 7; - static const int RectHeight = 2; - if (opt->state & State_Horizontal) { - while (y < opt->rect.height() - RectHeight - 5) { - path.moveTo(x, y); - path.addEllipse(x, y, RectHeight, RectHeight); - y += 6; - } - } else { - while (x < opt->rect.width() - RectHeight - 5) { - path.moveTo(x, y); - path.addEllipse(x, y, RectHeight, RectHeight); - x += 6; - } - } - p->setPen(Qt::NoPen); - QColor dark = opt->palette.dark().color().darker(); - dark.setAlphaF(0.50); - p->fillPath(path, dark); - p->restore(); - - break; - } - case PE_IndicatorHeaderArrow: - if (const QStyleOptionHeader *header = qstyleoption_cast(opt)) { - // In HITheme, up is down, down is up and hamburgers eat people. - if (header->sortIndicator != QStyleOptionHeader::None) - proxy()->drawPrimitive( - (header->sortIndicator == QStyleOptionHeader::SortDown) ? - PE_IndicatorArrowUp : PE_IndicatorArrowDown, header, p, w); - } - break; - case PE_IndicatorMenuCheckMark: { - QColor pc; - if (opt->state & State_On) - pc = opt->palette.highlightedText().color(); - else - pc = opt->palette.text().color(); - - QCFType checkmarkColor = CGColorCreateGenericRGB(static_cast(pc.redF()), - static_cast(pc.greenF()), - static_cast(pc.blueF()), - static_cast(pc.alphaF())); - // kCTFontUIFontSystem and others give the same result - // as kCTFontUIFontMenuItemMark. However, the latter is - // more reminiscent to HITheme's kThemeMenuItemMarkFont. - // See also the font for small- and mini-sized widgets, - // where we end up using the generic system font type. - const CTFontUIFontType fontType = (opt->state & State_Mini) ? kCTFontUIFontMiniSystem : - (opt->state & State_Small) ? kCTFontUIFontSmallSystem : - kCTFontUIFontMenuItemMark; - // Similarly for the font size, where there is a small difference - // between regular combobox and item view items, and and menu items. - // However, we ignore any difference for small- and mini-sized widgets. - const CGFloat fontSize = fontType == kCTFontUIFontMenuItemMark ? opt->fontMetrics.height() : 0.0; - QCFType checkmarkFont = CTFontCreateUIFontForLanguage(fontType, fontSize, NULL); - - CGContextSaveGState(cg); - CGContextSetShouldSmoothFonts(cg, NO); // Same as HITheme and Cocoa menu checkmarks - - // Baseline alignment tweaks for QComboBox and QMenu - const CGFloat vOffset = (opt->state & State_Mini) ? 0.0 : - (opt->state & State_Small) ? 1.0 : - 0.75; - - CGContextTranslateCTM(cg, 0, opt->rect.bottom()); - CGContextScaleCTM(cg, 1, -1); - // Translate back to the original position and add rect origin and offset - CGContextTranslateCTM(cg, opt->rect.x(), vOffset); - - // CTFont has severe difficulties finding the checkmark character among its - // glyphs. Fortunately, CTLine knows its ways inside the Cocoa labyrinth. - static const CFStringRef keys[] = { kCTFontAttributeName, kCTForegroundColorAttributeName }; - static const int numValues = sizeof(keys) / sizeof(keys[0]); - const CFTypeRef values[] = { (CFTypeRef)checkmarkFont, (CFTypeRef)checkmarkColor }; - Q_STATIC_ASSERT((sizeof(values) / sizeof(values[0])) == numValues); - QCFType attributes = CFDictionaryCreate(kCFAllocatorDefault, (const void **)keys, (const void **)values, - numValues, NULL, NULL); - // U+2713: CHECK MARK - QCFType checkmarkString = CFAttributedStringCreate(kCFAllocatorDefault, (CFStringRef)@"\u2713", attributes); - QCFType line = CTLineCreateWithAttributedString(checkmarkString); - - CTLineDraw((CTLineRef)line, cg); - CGContextFlush(cg); // CTLineDraw's documentation says it doesn't flush - - CGContextRestoreGState(cg); - break; } - case PE_IndicatorViewItemCheck: - case PE_IndicatorRadioButton: - case PE_IndicatorCheckBox: { - const bool isEnabled = opt->state & State_Enabled; - const bool isPressed = opt->state & State_Sunken; - const bool isRadioButton = (pe == PE_IndicatorRadioButton); - const auto ct = isRadioButton ? QMacStylePrivate::Button_RadioButton : QMacStylePrivate::Button_CheckBox; - const auto cs = d->effectiveAquaSizeConstrain(opt, w); - const auto cw = QMacStylePrivate::CocoaControl(ct, cs); - auto *tb = static_cast(d->cocoaControl(cw)); - tb.enabled = isEnabled; - tb.state = (opt->state & State_NoChange) ? NSMixedState : - (opt->state & State_On) ? NSOnState : NSOffState; - [tb highlight:isPressed]; - const auto vOffset = [=] { - // As measured - if (cs == QStyleHelper::SizeMini) - return ct == QMacStylePrivate::Button_CheckBox ? -0.5 : 0.5; - - return cs == QStyleHelper::SizeSmall ? 0.5 : 0.0; - } (); - d->drawNSViewInRect(tb, opt->rect, p, ^(CGContextRef ctx, const CGRect &rect) { - CGContextTranslateCTM(ctx, 0, vOffset); - [tb.cell drawInteriorWithFrame:rect inView:tb]; - }); - break; } - case PE_FrameFocusRect: - // Use the our own focus widget stuff. - break; - case PE_IndicatorBranch: { - if (!(opt->state & State_Children)) - break; - const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::Button_Disclosure, QStyleHelper::SizeLarge); - NSButtonCell *triangleCell = static_cast(d->cocoaCell(cw)); - [triangleCell setState:(opt->state & State_Open) ? NSOnState : NSOffState]; - bool viewHasFocus = (w && w->hasFocus()) || (opt->state & State_HasFocus); - [triangleCell setBackgroundStyle:((opt->state & State_Selected) && viewHasFocus) ? NSBackgroundStyleDark : NSBackgroundStyleLight]; - - d->setupNSGraphicsContext(cg, NO); - - QRect qtRect = opt->rect.adjusted(DisclosureOffset, 0, -DisclosureOffset, 0); - CGRect rect = CGRectMake(qtRect.x() + 1, qtRect.y(), qtRect.width(), qtRect.height()); - CGContextTranslateCTM(cg, rect.origin.x, rect.origin.y + rect.size.height); - CGContextScaleCTM(cg, 1, -1); - CGContextTranslateCTM(cg, -rect.origin.x, -rect.origin.y); - - [triangleCell drawBezelWithFrame:NSRectFromCGRect(rect) inView:[triangleCell controlView]]; - - d->restoreNSGraphicsContext(cg); - break; } - - case PE_Frame: { - QPen oldPen = p->pen(); - p->setPen(opt->palette.base().color().darker(140)); - p->drawRect(opt->rect.adjusted(0, 0, -1, -1)); - p->setPen(opt->palette.base().color().darker(180)); - p->drawLine(opt->rect.topLeft(), opt->rect.topRight()); - p->setPen(oldPen); - break; } - - case PE_FrameLineEdit: - if (const QStyleOptionFrame *frame = qstyleoption_cast(opt)) { - if (frame->state & State_Sunken) { - const bool isEnabled = opt->state & State_Enabled; - const bool isReadOnly = opt->state & State_ReadOnly; - const bool isRounded = frame->features & QStyleOptionFrame::Rounded; - const auto cs = d->effectiveAquaSizeConstrain(opt, w, CT_LineEdit); - const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::TextField, cs); - auto *tf = static_cast(d->cocoaControl(cw)); - tf.enabled = isEnabled; - tf.editable = !isReadOnly; - tf.bezeled = YES; - static_cast(tf.cell).bezelStyle = isRounded ? NSTextFieldRoundedBezel : NSTextFieldSquareBezel; - tf.frame = opt->rect.toCGRect(); - d->drawNSViewInRect(tf, opt->rect, p, ^(CGContextRef, const CGRect &rect) { - if (!qt_mac_applicationIsInDarkMode()) { - // In 'Dark' mode controls are transparent, so we do not - // over-paint the (potentially custom) color in the background. - // In 'Light' mode we have to care about the correct - // background color. See the comments below for PE_PanelLineEdit. - CGContextRef cgContext = NSGraphicsContext.currentContext.CGContext; - // See QMacCGContext, here we expect bitmap context created with - // color space 'kCGColorSpaceSRGB', if it's something else - we - // give up. - if (cgContext ? bool(CGBitmapContextGetColorSpace(cgContext)) : false) { - tf.drawsBackground = YES; - const QColor bgColor = frame->palette.brush(QPalette::Base).color(); - tf.backgroundColor = [NSColor colorWithSRGBRed:bgColor.redF() - green:bgColor.greenF() - blue:bgColor.blueF() - alpha:bgColor.alphaF()]; - if (bgColor.alpha() != 255) { - // No way we can have it bezeled and transparent ... - tf.bordered = YES; - } - } - } - - [tf.cell drawWithFrame:rect inView:tf]; - }); - } else { - QCommonStyle::drawPrimitive(pe, opt, p, w); - } - } - break; - case PE_PanelLineEdit: - { - const QStyleOptionFrame *panel = qstyleoption_cast(opt); - if (qt_mac_applicationIsInDarkMode() || (panel && panel->lineWidth <= 0)) { - // QCommonStyle::drawPrimitive(PE_PanelLineEdit) fill the background with - // a proper color, defined in opt->palette and then, if lineWidth > 0, it - // calls QMacStyle::drawPrimitive(PE_FrameLineEdit). We use NSTextFieldCell - // to handle PE_FrameLineEdit, which will use system-default background. - // In 'Dark' mode it's transparent and thus it's not over-painted. - QCommonStyle::drawPrimitive(pe, opt, p, w); - } else { - // In 'Light' mode, if panel->lineWidth > 0, we have to use the correct - // background color when drawing PE_FrameLineEdit, so let's call it - // directly and set the proper color there. - drawPrimitive(PE_FrameLineEdit, opt, p, w); - } - - // Draw the focus frame for widgets other than QLineEdit (e.g. for line edits in Webkit). - // Focus frame is drawn outside the rectangle passed in the option-rect. - if (panel) { -#if QT_CONFIG(lineedit) - if ((opt->state & State_HasFocus) && !qobject_cast(w)) { - int vmargin = pixelMetric(QStyle::PM_FocusFrameVMargin); - int hmargin = pixelMetric(QStyle::PM_FocusFrameHMargin); - QStyleOptionFrame focusFrame = *panel; - focusFrame.rect = panel->rect.adjusted(-hmargin, -vmargin, hmargin, vmargin); - drawControl(CE_FocusFrame, &focusFrame, p, w); - } -#endif - } - } - break; - case PE_PanelScrollAreaCorner: { - const QBrush brush(opt->palette.brush(QPalette::Base)); - p->fillRect(opt->rect, brush); - p->setPen(QPen(QColor(217, 217, 217))); - p->drawLine(opt->rect.topLeft(), opt->rect.topRight()); - p->drawLine(opt->rect.topLeft(), opt->rect.bottomLeft()); - } break; - case PE_FrameStatusBarItem: - break; - case PE_IndicatorTabClose: { - // Make close button visible only on the hovered tab. - QTabBar *tabBar = qobject_cast(w->parentWidget()); - const QWidget *closeBtn = w; - if (!tabBar) { - // QStyleSheetStyle instead of CloseButton (which has - // a QTabBar as a parent widget) uses the QTabBar itself: - tabBar = qobject_cast(const_cast(w)); - closeBtn = decltype(closeBtn)(property("_q_styleSheetRealCloseButton").value()); - } - if (tabBar) { - const bool documentMode = tabBar->documentMode(); - const QTabBarPrivate *tabBarPrivate = static_cast(QObjectPrivate::get(tabBar)); - const int hoveredTabIndex = tabBarPrivate->hoveredTabIndex(); - if (!documentMode || - (hoveredTabIndex != -1 && ((closeBtn == tabBar->tabButton(hoveredTabIndex, QTabBar::LeftSide)) || - (closeBtn == tabBar->tabButton(hoveredTabIndex, QTabBar::RightSide))))) { - const bool hover = (opt->state & State_MouseOver); - const bool selected = (opt->state & State_Selected); - const bool pressed = (opt->state & State_Sunken); - drawTabCloseButton(p, hover, selected, pressed, documentMode); - } - } - } break; - case PE_PanelStatusBar: { - // Fill the status bar with the titlebar gradient. - QLinearGradient linearGrad; - if (w ? qt_macWindowMainWindow(w->window()) : (opt->state & QStyle::State_Active)) { - linearGrad = titlebarGradientActive(); - } else { - linearGrad = titlebarGradientInactive(); - } - - linearGrad.setStart(0, opt->rect.top()); - linearGrad.setFinalStop(0, opt->rect.bottom()); - p->fillRect(opt->rect, linearGrad); - - // Draw the black separator line at the top of the status bar. - if (w ? qt_macWindowMainWindow(w->window()) : (opt->state & QStyle::State_Active)) - p->setPen(titlebarSeparatorLineActive); - else - p->setPen(titlebarSeparatorLineInactive); - p->drawLine(opt->rect.left(), opt->rect.top(), opt->rect.right(), opt->rect.top()); - - break; - } - case PE_PanelMenu: { - p->save(); - p->fillRect(opt->rect, Qt::transparent); - p->setPen(Qt::transparent); - p->setBrush(opt->palette.window()); - p->setRenderHint(QPainter::Antialiasing, true); - const QPainterPath path = d->windowPanelPath(opt->rect); - p->drawPath(path); - p->restore(); - } break; - - default: - QCommonStyle::drawPrimitive(pe, opt, p, w); - break; - } -} - -static QPixmap darkenPixmap(const QPixmap &pixmap) -{ - QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32); - int imgh = img.height(); - int imgw = img.width(); - int h, s, v, a; - QRgb pixel; - for (int y = 0; y < imgh; ++y) { - for (int x = 0; x < imgw; ++x) { - pixel = img.pixel(x, y); - a = qAlpha(pixel); - QColor hsvColor(pixel); - hsvColor.getHsv(&h, &s, &v); - s = qMin(100, s * 2); - v = v / 2; - hsvColor.setHsv(h, s, v); - pixel = hsvColor.rgb(); - img.setPixel(x, y, qRgba(qRed(pixel), qGreen(pixel), qBlue(pixel), a)); - } - } - return QPixmap::fromImage(img); -} - -void QMacStylePrivate::setupVerticalInvertedXform(CGContextRef cg, bool reverse, bool vertical, const CGRect &rect) const -{ - if (vertical) { - CGContextTranslateCTM(cg, rect.size.height, 0); - CGContextRotateCTM(cg, M_PI_2); - } - if (vertical != reverse) { - CGContextTranslateCTM(cg, rect.size.width, 0); - CGContextScaleCTM(cg, -1, 1); - } -} - -void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter *p, - const QWidget *w) const -{ - Q_D(const QMacStyle); - const AppearanceSync sync; - QMacCGContext cg(p); - QWindow *window = w && w->window() ? w->window()->windowHandle() : nullptr; - d->resolveCurrentNSView(window); - switch (ce) { - case CE_HeaderSection: - if (const QStyleOptionHeader *header = qstyleoption_cast(opt)) { - State flags = header->state; - QRect ir = header->rect; - - -#if 0 // FIXME: What's this solving exactly? - bool noVerticalHeader = true; -#if QT_CONFIG(tableview) - if (w) - if (const QTableView *table = qobject_cast(w->parentWidget())) - noVerticalHeader = !table->verticalHeader()->isVisible(); -#endif - - const bool drawLeftBorder = header->orientation == Qt::Vertical - || header->position == QStyleOptionHeader::OnlyOneSection - || (header->position == QStyleOptionHeader::Beginning && noVerticalHeader); -#endif - - const bool pressed = (flags & State_Sunken) && !(flags & State_On); - p->fillRect(ir, pressed ? header->palette.dark() : header->palette.button()); - p->setPen(QPen(header->palette.dark(), 1.0)); - if (header->orientation == Qt::Horizontal) - p->drawLine(QLineF(ir.right() + 0.5, ir.top() + headerSectionSeparatorInset, - ir.right() + 0.5, ir.bottom() - headerSectionSeparatorInset)); - else - p->drawLine(QLineF(ir.left() + headerSectionSeparatorInset, ir.bottom(), - ir.right() - headerSectionSeparatorInset, ir.bottom())); - } - - break; - case CE_HeaderLabel: - if (const QStyleOptionHeader *header = qstyleoption_cast(opt)) { - p->save(); - QRect textr = header->rect; - if (!header->icon.isNull()) { - QIcon::Mode mode = QIcon::Disabled; - if (opt->state & State_Enabled) - mode = QIcon::Normal; - int iconExtent = proxy()->pixelMetric(PM_SmallIconSize); - QPixmap pixmap = header->icon.pixmap(window, QSize(iconExtent, iconExtent), mode); - - QRect pixr = header->rect; - pixr.setY(header->rect.center().y() - (pixmap.height() / pixmap.devicePixelRatio() - 1) / 2); - proxy()->drawItemPixmap(p, pixr, Qt::AlignVCenter, pixmap); - textr.translate(pixmap.width() / pixmap.devicePixelRatio() + 2, 0); - } - - proxy()->drawItemText(p, textr, header->textAlignment | Qt::AlignVCenter, header->palette, - header->state & State_Enabled, header->text, QPalette::ButtonText); - p->restore(); - } - break; - case CE_ToolButtonLabel: - if (const QStyleOptionToolButton *tb = qstyleoption_cast(opt)) { - QStyleOptionToolButton myTb = *tb; - myTb.state &= ~State_AutoRaise; -#ifndef QT_NO_ACCESSIBILITY - if (QStyleHelper::hasAncestor(opt->styleObject, QAccessible::ToolBar)) { - QRect cr = tb->rect; - int shiftX = 0; - int shiftY = 0; - bool needText = false; - int alignment = 0; - bool down = tb->state & (State_Sunken | State_On); - if (down) { - shiftX = proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, w); - shiftY = proxy()->pixelMetric(PM_ButtonShiftVertical, tb, w); - } - // The down state is special for QToolButtons in a toolbar on the Mac - // The text is a bit bolder and gets a drop shadow and the icons are also darkened. - // This doesn't really fit into any particular case in QIcon, so we - // do the majority of the work ourselves. - if (!(tb->features & QStyleOptionToolButton::Arrow)) { - Qt::ToolButtonStyle tbstyle = tb->toolButtonStyle; - if (tb->icon.isNull() && !tb->text.isEmpty()) - tbstyle = Qt::ToolButtonTextOnly; - - switch (tbstyle) { - case Qt::ToolButtonTextOnly: { - needText = true; - alignment = Qt::AlignCenter; - break; } - case Qt::ToolButtonIconOnly: - case Qt::ToolButtonTextBesideIcon: - case Qt::ToolButtonTextUnderIcon: { - QRect pr = cr; - QIcon::Mode iconMode = (tb->state & State_Enabled) ? QIcon::Normal - : QIcon::Disabled; - QIcon::State iconState = (tb->state & State_On) ? QIcon::On - : QIcon::Off; - QPixmap pixmap = tb->icon.pixmap(window, - tb->rect.size().boundedTo(tb->iconSize), - iconMode, iconState); - - // Draw the text if it's needed. - if (tb->toolButtonStyle != Qt::ToolButtonIconOnly) { - needText = true; - if (tb->toolButtonStyle == Qt::ToolButtonTextUnderIcon) { - pr.setHeight(pixmap.size().height() / pixmap.devicePixelRatio() + 6); - cr.adjust(0, pr.bottom(), 0, -3); - alignment |= Qt::AlignCenter; - } else { - pr.setWidth(pixmap.width() / pixmap.devicePixelRatio() + 8); - cr.adjust(pr.right(), 0, 0, 0); - alignment |= Qt::AlignLeft | Qt::AlignVCenter; - } - } - if (opt->state & State_Sunken) { - pr.translate(shiftX, shiftY); - pixmap = darkenPixmap(pixmap); - } - proxy()->drawItemPixmap(p, pr, Qt::AlignCenter, pixmap); - break; } - default: - Q_ASSERT(false); - break; - } - - if (needText) { - QPalette pal = tb->palette; - QPalette::ColorRole role = QPalette::NoRole; - if (!proxy()->styleHint(SH_UnderlineShortcut, tb, w)) - alignment |= Qt::TextHideMnemonic; - if (down) - cr.translate(shiftX, shiftY); - if (tbstyle == Qt::ToolButtonTextOnly - || (tbstyle != Qt::ToolButtonTextOnly && !down)) { - QPen pen = p->pen(); - QColor light = down || isDarkMode() ? Qt::black : Qt::white; - light.setAlphaF(0.375f); - p->setPen(light); - p->drawText(cr.adjusted(0, 1, 0, 1), alignment, tb->text); - p->setPen(pen); - if (down && tbstyle == Qt::ToolButtonTextOnly) { - pal = QApplication::palette("QMenu"); - pal.setCurrentColorGroup(tb->palette.currentColorGroup()); - role = QPalette::HighlightedText; - } - } - proxy()->drawItemText(p, cr, alignment, pal, - tb->state & State_Enabled, tb->text, role); - } - } else { - QCommonStyle::drawControl(ce, &myTb, p, w); - } - } else -#endif // QT_NO_ACCESSIBILITY - { - QCommonStyle::drawControl(ce, &myTb, p, w); - } - } - break; - case CE_ToolBoxTabShape: - QCommonStyle::drawControl(ce, opt, p, w); - break; - case CE_PushButtonBevel: - if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { - if (!(btn->state & (State_Raised | State_Sunken | State_On))) - break; - - if (btn->features & QStyleOptionButton::CommandLinkButton) { - QCommonStyle::drawControl(ce, opt, p, w); - break; - } - - const bool hasFocus = btn->state & State_HasFocus; - const bool isActive = btn->state & State_Active; - - // a focused auto-default button within an active window - // takes precedence over a normal default button - if ((btn->features & QStyleOptionButton::AutoDefaultButton) - && isActive && hasFocus) - d->autoDefaultButton = btn->styleObject; - else if (d->autoDefaultButton == btn->styleObject) - d->autoDefaultButton = nullptr; - - const bool isEnabled = btn->state & State_Enabled; - const bool isPressed = btn->state & State_Sunken; - const bool isHighlighted = isActive && - ((btn->state & State_On) - || (btn->features & QStyleOptionButton::DefaultButton) - || (btn->features & QStyleOptionButton::AutoDefaultButton - && d->autoDefaultButton == btn->styleObject)); - const bool hasMenu = btn->features & QStyleOptionButton::HasMenu; - const auto ct = cocoaControlType(btn, w); - const auto cs = d->effectiveAquaSizeConstrain(btn, w); - const auto cw = QMacStylePrivate::CocoaControl(ct, cs); - auto *pb = static_cast(d->cocoaControl(cw)); - // Ensure same size and location as we used to have with HITheme. - // This is more convoluted than we initialy thought. See for example - // differences between plain and menu button frames. - const QRectF frameRect = cw.adjustedControlFrame(btn->rect); - pb.frame = frameRect.toCGRect(); - - pb.enabled = isEnabled; - [pb highlight:isPressed]; - pb.state = isHighlighted && !isPressed ? NSOnState : NSOffState; - d->drawNSViewInRect(pb, frameRect, p, ^(CGContextRef, const CGRect &r) { - [pb.cell drawBezelWithFrame:r inView:pb.superview]; - }); - [pb highlight:NO]; - - if (hasMenu && cw.type == QMacStylePrivate::Button_SquareButton) { - // Using -[NSPopuButtonCell drawWithFrame:inView:] above won't do - // it right because we don't set the text in the native button. - const int mbi = proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, btn, w); - const auto ir = frameRect.toRect(); - int arrowYOffset = 0; -#if 0 - // FIXME What's this for again? - if (!w) { - // adjustment for Qt Quick Controls - arrowYOffset -= ir.top(); - if (cw.second == QStyleHelper::SizeSmall) - arrowYOffset += 1; - } -#endif - const auto ar = visualRect(btn->direction, ir, QRect(ir.right() - mbi - 6, ir.height() / 2 - arrowYOffset, mbi, mbi)); - - QStyleOption arrowOpt = *opt; - arrowOpt.rect = ar; - proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, w); - } - - - if (btn->state & State_HasFocus) { - // TODO Remove and use QFocusFrame instead. - const int hMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin, btn, w); - const int vMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin, btn, w); - QRectF focusRect; - if (cw.type == QMacStylePrivate::Button_SquareButton) { - focusRect = frameRect; - } else { - focusRect = QRectF::fromCGRect([pb alignmentRectForFrame:pb.frame]); - if (cw.type == QMacStylePrivate::Button_PushButton) - focusRect -= pushButtonShadowMargins[cw.size]; - else if (cw.type == QMacStylePrivate::Button_PullDown) - focusRect -= pullDownButtonShadowMargins[cw.size]; - } - d->drawFocusRing(p, focusRect, hMargin, vMargin, cw); - } - } - break; - case CE_PushButtonLabel: - if (const QStyleOptionButton *b = qstyleoption_cast(opt)) { - QStyleOptionButton btn(*b); - // We really don't want the label to be drawn the same as on - // windows style if it has an icon and text, then it should be more like a - // tab. So, cheat a little here. However, if it *is* only an icon - // the windows style works great, so just use that implementation. - const bool isEnabled = btn.state & State_Enabled; - const bool hasMenu = btn.features & QStyleOptionButton::HasMenu; - const bool hasIcon = !btn.icon.isNull(); - const bool hasText = !btn.text.isEmpty(); - const bool isActive = btn.state & State_Active; - const bool isPressed = btn.state & State_Sunken; - - const auto ct = cocoaControlType(&btn, w); - - if (!hasMenu && ct != QMacStylePrivate::Button_SquareButton) { - if (isPressed - || (isActive && isEnabled - && ((btn.state & State_On) - || ((btn.features & QStyleOptionButton::DefaultButton) && !d->autoDefaultButton) - || d->autoDefaultButton == btn.styleObject))) - btn.palette.setColor(QPalette::ButtonText, Qt::white); - } - - if ((!hasIcon && !hasMenu) || (hasIcon && !hasText)) { - QCommonStyle::drawControl(ce, &btn, p, w); - } else { - QRect freeContentRect = btn.rect; - QRect textRect = itemTextRect( - btn.fontMetrics, freeContentRect, Qt::AlignCenter, isEnabled, btn.text); - if (hasMenu) { - textRect.moveTo(w ? 15 : 11, textRect.top()); // Supports Qt Quick Controls - } - // Draw the icon: - if (hasIcon) { - int contentW = textRect.width(); - if (hasMenu) - contentW += proxy()->pixelMetric(PM_MenuButtonIndicator) + 4; - QIcon::Mode mode = isEnabled ? QIcon::Normal : QIcon::Disabled; - if (mode == QIcon::Normal && btn.state & State_HasFocus) - mode = QIcon::Active; - // Decide if the icon is should be on or off: - QIcon::State state = QIcon::Off; - if (btn.state & State_On) - state = QIcon::On; - QPixmap pixmap = btn.icon.pixmap(window, btn.iconSize, mode, state); - int pixmapWidth = pixmap.width() / pixmap.devicePixelRatio(); - int pixmapHeight = pixmap.height() / pixmap.devicePixelRatio(); - contentW += pixmapWidth + QMacStylePrivate::PushButtonContentPadding; - int iconLeftOffset = freeContentRect.x() + (freeContentRect.width() - contentW) / 2; - int iconTopOffset = freeContentRect.y() + (freeContentRect.height() - pixmapHeight) / 2; - QRect iconDestRect(iconLeftOffset, iconTopOffset, pixmapWidth, pixmapHeight); - QRect visualIconDestRect = visualRect(btn.direction, freeContentRect, iconDestRect); - proxy()->drawItemPixmap(p, visualIconDestRect, Qt::AlignLeft | Qt::AlignVCenter, pixmap); - int newOffset = iconDestRect.x() + iconDestRect.width() - + QMacStylePrivate::PushButtonContentPadding - textRect.x(); - textRect.adjust(newOffset, 0, newOffset, 0); - } - // Draw the text: - if (hasText) { - textRect = visualRect(btn.direction, freeContentRect, textRect); - proxy()->drawItemText(p, textRect, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, btn.palette, - isEnabled, btn.text, QPalette::ButtonText); - } - } - } - break; -#if QT_CONFIG(combobox) - case CE_ComboBoxLabel: - if (const auto *cb = qstyleoption_cast(opt)) { - auto comboCopy = *cb; - comboCopy.direction = Qt::LeftToRight; - // The rectangle will be adjusted to SC_ComboBoxEditField with comboboxEditBounds() - QCommonStyle::drawControl(CE_ComboBoxLabel, &comboCopy, p, w); - } - break; -#endif // #if QT_CONFIG(combobox) -#if QT_CONFIG(tabbar) - case CE_TabBarTabShape: - if (const auto *tabOpt = qstyleoption_cast(opt)) { - if (tabOpt->documentMode) { - p->save(); - bool isUnified = false; - if (w) { - QRect tabRect = tabOpt->rect; - QPoint windowTabStart = w->mapTo(w->window(), tabRect.topLeft()); - isUnified = isInMacUnifiedToolbarArea(w->window()->windowHandle(), windowTabStart.y()); - } - - const int tabOverlap = proxy()->pixelMetric(PM_TabBarTabOverlap, opt, w); - drawTabShape(p, tabOpt, isUnified, tabOverlap); - - p->restore(); - return; - } - - const bool isActive = tabOpt->state & State_Active; - const bool isEnabled = tabOpt->state & State_Enabled; - const bool isPressed = tabOpt->state & State_Sunken; - const bool isSelected = tabOpt->state & State_Selected; - const auto tabDirection = QMacStylePrivate::tabDirection(tabOpt->shape); - const bool verticalTabs = tabDirection == QMacStylePrivate::East - || tabDirection == QMacStylePrivate::West; - - QStyleOptionTab::TabPosition tp = tabOpt->position; - QStyleOptionTab::SelectedPosition sp = tabOpt->selectedPosition; - if (tabOpt->direction == Qt::RightToLeft && !verticalTabs) { - if (tp == QStyleOptionTab::Beginning) - tp = QStyleOptionTab::End; - else if (tp == QStyleOptionTab::End) - tp = QStyleOptionTab::Beginning; - - if (sp == QStyleOptionTab::NextIsSelected) - sp = QStyleOptionTab::PreviousIsSelected; - else if (sp == QStyleOptionTab::PreviousIsSelected) - sp = QStyleOptionTab::NextIsSelected; - } - - // Alas, NSSegmentedControl and NSSegmentedCell are letting us down. - // We're not able to draw it at will, either calling -[drawSegment: - // inFrame:withView:], -[drawRect:] or anything in between. Besides, - // there's no public API do draw the pressed state, AFAICS. We'll use - // a push NSButton instead and clip the CGContext. - // NOTE/TODO: this is not true. On 10.13 NSSegmentedControl works with - // some (black?) magic/magic dances, on 10.14 it simply works (was - // it fixed in AppKit?). But, indeed, we cannot make a tab 'pressed' - // with NSSegmentedControl (only selected), so we stay with buttons - // (mixing buttons and NSSegmentedControl for such a simple thing - // is too much work). - - const auto cs = d->effectiveAquaSizeConstrain(opt, w); - // Extra hacks to get the proper pressed appreance when not selected or selected and inactive - const bool needsInactiveHack = (!isActive && isSelected); - const bool isBigSurOrAbove = QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSBigSur; - const auto ct = !needsInactiveHack && (isSelected || tp == QStyleOptionTab::OnlyOneTab) ? - QMacStylePrivate::Button_PushButton : - QMacStylePrivate::Button_PopupButton; - const bool isPopupButton = ct == QMacStylePrivate::Button_PopupButton; - const auto cw = QMacStylePrivate::CocoaControl(ct, cs); - auto *pb = static_cast(d->cocoaControl(cw)); - - auto vOffset = isPopupButton ? 1 : 2; - if (isBigSurOrAbove) { - // Make it 1, otherwise, the offset is very visible compared - // to the selected tab (which is not a popup button, but a - // simple NSButton). - vOffset = 1; - } - - if (tabDirection == QMacStylePrivate::East) - vOffset -= 1; - const auto outerAdjust = isPopupButton ? 1 : 4; - const auto innerAdjust = isPopupButton ? 20 : 10; - QRectF frameRect = tabOpt->rect; - if (verticalTabs) - frameRect = QRectF(frameRect.y(), frameRect.x(), frameRect.height(), frameRect.width()); - // Adjust before clipping - frameRect = frameRect.translated(0, vOffset); - switch (tp) { - case QStyleOptionTab::Beginning: - // Pressed state hack: tweak adjustments in preparation for flip below - if (!isSelected && tabDirection == QMacStylePrivate::West) - frameRect = frameRect.adjusted(-innerAdjust, 0, outerAdjust, 0); - else - frameRect = frameRect.adjusted(-outerAdjust, 0, innerAdjust, 0); - - if (isSelected && isBigSurOrAbove) { - // 1 pixed of 'roundness' is still visible on the right - // (the left is OK, it's rounded). - frameRect = frameRect.adjusted(0, 0, 1, 0); - } - - break; - case QStyleOptionTab::Middle: - frameRect = frameRect.adjusted(-innerAdjust, 0, innerAdjust, 0); - - if (isSelected && isBigSurOrAbove) { - // 1 pixel of 'roundness' is still visible on both - // sides - left and right. - frameRect = frameRect.adjusted(-1, 0, 1, 0); - } - - break; - case QStyleOptionTab::End: - // Pressed state hack: tweak adjustments in preparation for flip below - if (isSelected || tabDirection == QMacStylePrivate::West) - frameRect = frameRect.adjusted(-innerAdjust, 0, outerAdjust, 0); - else - frameRect = frameRect.adjusted(-outerAdjust, 0, innerAdjust, 0); - - if (isSelected && isBigSurOrAbove) { - // 1 pixel of 'roundness' is still visible on the left. - frameRect = frameRect.adjusted(-1, 0, 0, 0); - } - break; - case QStyleOptionTab::OnlyOneTab: - frameRect = frameRect.adjusted(-outerAdjust, 0, outerAdjust, 0); - break; - } - pb.frame = frameRect.toCGRect(); - - pb.enabled = isEnabled; - [pb highlight:isPressed]; - // Set off state when inactive. See needsInactiveHack for when it's selected - pb.state = (isActive && isSelected && !isPressed) ? NSOnState : NSOffState; - - const auto drawBezelBlock = ^(CGContextRef ctx, const CGRect &r) { - CGContextClipToRect(ctx, opt->rect.toCGRect()); - if (!isSelected || needsInactiveHack) { - // Final stage of the pressed state hack: flip NSPopupButton rendering - if (!verticalTabs && tp == QStyleOptionTab::End) { - CGContextTranslateCTM(ctx, opt->rect.right(), 0); - CGContextScaleCTM(ctx, -1, 1); - CGContextTranslateCTM(ctx, -frameRect.left(), 0); - } else if (tabDirection == QMacStylePrivate::West && tp == QStyleOptionTab::Beginning) { - CGContextTranslateCTM(ctx, 0, opt->rect.top()); - CGContextScaleCTM(ctx, 1, -1); - CGContextTranslateCTM(ctx, 0, -frameRect.right()); - } else if (tabDirection == QMacStylePrivate::East && tp == QStyleOptionTab::End) { - CGContextTranslateCTM(ctx, 0, opt->rect.bottom()); - CGContextScaleCTM(ctx, 1, -1); - CGContextTranslateCTM(ctx, 0, -frameRect.left()); - } - } - - // Rotate and translate CTM when vertical - // On macOS: positive angle is CW, negative is CCW - if (tabDirection == QMacStylePrivate::West) { - CGContextTranslateCTM(ctx, 0, frameRect.right()); - CGContextRotateCTM(ctx, -M_PI_2); - CGContextTranslateCTM(ctx, -frameRect.left(), 0); - } else if (tabDirection == QMacStylePrivate::East) { - CGContextTranslateCTM(ctx, opt->rect.right(), 0); - CGContextRotateCTM(ctx, M_PI_2); - } - - // Now, if it's a trick with a popup button, it has an arrow - // which makes no sense on tabs. - NSPopUpArrowPosition oldPosition = NSPopUpArrowAtCenter; - NSPopUpButtonCell *pbCell = nil; - auto rAdjusted = r; - if (isPopupButton && (tp == QStyleOptionTab::OnlyOneTab || isBigSurOrAbove)) { - // Note: starting from macOS BigSur NSPopupButton has this - // arrow 'button' in a different place and it became - // quite visible 'in between' inactive tabs. - pbCell = static_cast(pb.cell); - oldPosition = pbCell.arrowPosition; - pbCell.arrowPosition = NSPopUpNoArrow; - if (pb.state == NSControlStateValueOff) { - // NSPopUpButton in this state is smaller. - rAdjusted.origin.x -= 3; - rAdjusted.size.width += 6; - if (isBigSurOrAbove) { - rAdjusted.origin.y -= 1; - rAdjusted.size.height += 1; - if (tp == QStyleOptionTab::End) - rAdjusted.origin.x -= 2; - } - } - } - - [pb.cell drawBezelWithFrame:rAdjusted inView:pb.superview]; - - if (pbCell) // Restore, we may reuse it for a ComboBox. - pbCell.arrowPosition = oldPosition; - }; - - if (needsInactiveHack) { - // First, render tab as non-selected tab on a pixamp - const qreal pixelRatio = p->device()->devicePixelRatioF(); - QImage tabPixmap(opt->rect.size() * pixelRatio, QImage::Format_ARGB32_Premultiplied); - tabPixmap.setDevicePixelRatio(pixelRatio); - tabPixmap.fill(Qt::transparent); - QPainter tabPainter(&tabPixmap); - d->drawNSViewInRect(pb, frameRect, &tabPainter, ^(CGContextRef ctx, const CGRect &r) { - CGContextTranslateCTM(ctx, -opt->rect.left(), -opt->rect.top()); - drawBezelBlock(ctx, r); - }); - tabPainter.end(); - - // Then, darken it with the proper shade of gray - const qreal inactiveGray = 0.898; // As measured - const int inactiveGray8 = qRound(inactiveGray * 255.0); - const QRgb inactiveGrayRGB = qRgb(inactiveGray8, inactiveGray8, inactiveGray8); - for (int l = 0; l < tabPixmap.height(); ++l) { - auto *line = reinterpret_cast(tabPixmap.scanLine(l)); - for (int i = 0; i < tabPixmap.width(); ++i) { - if (qAlpha(line[i]) == 255) { - line[i] = inactiveGrayRGB; - } else if (qAlpha(line[i]) > 128) { - const int g = qRound(inactiveGray * qRed(line[i])); - line[i] = qRgba(g, g, g, qAlpha(line[i])); - } - } - } - - // Finally, draw the tab pixmap on the current painter - p->drawImage(opt->rect, tabPixmap); - } else { - d->drawNSViewInRect(pb, frameRect, p, drawBezelBlock); - } - - if (!isSelected && sp != QStyleOptionTab::NextIsSelected - && tp != QStyleOptionTab::End - && tp != QStyleOptionTab::OnlyOneTab) { - static const QPen separatorPen(Qt::black, 1.0); - p->save(); - p->setOpacity(isEnabled ? 0.105 : 0.06); // As measured - p->setPen(separatorPen); - if (tabDirection == QMacStylePrivate::West) { - p->drawLine(QLineF(opt->rect.left() + 1.5, opt->rect.bottom(), - opt->rect.right() - 0.5, opt->rect.bottom())); - } else if (tabDirection == QMacStylePrivate::East) { - p->drawLine(QLineF(opt->rect.left(), opt->rect.bottom(), - opt->rect.right() - 0.5, opt->rect.bottom())); - } else { - p->drawLine(QLineF(opt->rect.right(), opt->rect.top() + 1.0, - opt->rect.right(), opt->rect.bottom() - 0.5)); - } - p->restore(); - } - - // TODO Needs size adjustment to fit the focus ring - if (tabOpt->state & State_HasFocus) { - QMacStylePrivate::CocoaControlType focusRingType; - switch (tp) { - case QStyleOptionTab::Beginning: - focusRingType = verticalTabs ? QMacStylePrivate::SegmentedControl_Last - : QMacStylePrivate::SegmentedControl_First; - break; - case QStyleOptionTab::Middle: - focusRingType = QMacStylePrivate::SegmentedControl_Middle; - break; - case QStyleOptionTab::End: - focusRingType = verticalTabs ? QMacStylePrivate::SegmentedControl_First - : QMacStylePrivate::SegmentedControl_Last; - break; - case QStyleOptionTab::OnlyOneTab: - focusRingType = QMacStylePrivate::SegmentedControl_Single; - break; - } - } - } - break; - case CE_TabBarTabLabel: - if (const auto *tab = qstyleoption_cast(opt)) { - QStyleOptionTab myTab = *tab; - const auto tabDirection = QMacStylePrivate::tabDirection(tab->shape); - const bool verticalTabs = tabDirection == QMacStylePrivate::East - || tabDirection == QMacStylePrivate::West; - - // Check to see if we use have the same as the system font - // (QComboMenuItem is internal and should never be seen by the - // outside world, unless they read the source, in which case, it's - // their own fault). - const bool nonDefaultFont = p->font() != qt_app_fonts_hash()->value("QComboMenuItem"); - - if (!myTab.documentMode && (myTab.state & State_Selected) && (myTab.state & State_Active)) - if (const auto *tabBar = qobject_cast(w)) - if (!tabBar->tabTextColor(tabBar->currentIndex()).isValid()) - myTab.palette.setColor(QPalette::WindowText, Qt::white); - - if (myTab.documentMode && isDarkMode()) { - bool active = (myTab.state & State_Selected) && (myTab.state & State_Active); - myTab.palette.setColor(QPalette::WindowText, active ? Qt::white : Qt::gray); - } - - int heightOffset = 0; - if (verticalTabs) { - heightOffset = -1; - } else if (nonDefaultFont) { - if (p->fontMetrics().height() == myTab.rect.height()) - heightOffset = 2; - } - myTab.rect.setHeight(myTab.rect.height() + heightOffset); - - QCommonStyle::drawControl(ce, &myTab, p, w); - } - break; -#endif -#if QT_CONFIG(dockwidget) - case CE_DockWidgetTitle: - if (const auto *dwOpt = qstyleoption_cast(opt)) { - const bool isVertical = dwOpt->verticalTitleBar; - const auto effectiveRect = isVertical ? opt->rect.transposed() : opt->rect; - p->save(); - if (isVertical) { - p->translate(effectiveRect.left(), effectiveRect.top() + effectiveRect.width()); - p->rotate(-90); - p->translate(-effectiveRect.left(), -effectiveRect.top()); - } - - // fill title bar background - QLinearGradient linearGrad; - linearGrad.setStart(QPointF(0, 0)); - linearGrad.setFinalStop(QPointF(0, 2 * effectiveRect.height())); - linearGrad.setColorAt(0, opt->palette.button().color()); - linearGrad.setColorAt(1, opt->palette.dark().color()); - p->fillRect(effectiveRect, linearGrad); - - // draw horizontal line at bottom - p->setPen(opt->palette.dark().color()); - p->drawLine(effectiveRect.bottomLeft(), effectiveRect.bottomRight()); - - if (!dwOpt->title.isEmpty()) { - auto titleRect = proxy()->subElementRect(SE_DockWidgetTitleBarText, opt, w); - if (isVertical) - titleRect = QRect(effectiveRect.left() + opt->rect.bottom() - titleRect.bottom(), - effectiveRect.top() + titleRect.left() - opt->rect.left(), - titleRect.height(), - titleRect.width()); - - const auto text = p->fontMetrics().elidedText(dwOpt->title, Qt::ElideRight, titleRect.width()); - proxy()->drawItemText(p, titleRect, Qt::AlignCenter, dwOpt->palette, - dwOpt->state & State_Enabled, text, QPalette::WindowText); - } - p->restore(); - } - break; -#endif - case CE_FocusFrame: { - const auto *ff = qobject_cast(w); - const auto *ffw = ff ? ff->widget() : nullptr; - const auto ct = [=] { - if (ffw) { - if (ffw->inherits("QCheckBox")) - return QMacStylePrivate::Button_CheckBox; - if (ffw->inherits("QRadioButton")) - return QMacStylePrivate::Button_RadioButton; - if (ffw->inherits("QLineEdit") || ffw->inherits("QTextEdit")) - return QMacStylePrivate::TextField; - } - - return QMacStylePrivate::Box; // Not really, just make it the default - } (); - const auto cs = ffw ? (ffw->testAttribute(Qt::WA_MacMiniSize) ? QStyleHelper::SizeMini : - ffw->testAttribute(Qt::WA_MacSmallSize) ? QStyleHelper::SizeSmall : - QStyleHelper::SizeLarge) : - QStyleHelper::SizeLarge; - const int hMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin, opt, w); - const int vMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin, opt, w); - d->drawFocusRing(p, opt->rect, hMargin, vMargin, QMacStylePrivate::CocoaControl(ct, cs)); - break; } - case CE_MenuEmptyArea: - // Skip: PE_PanelMenu fills in everything - break; - case CE_MenuItem: - case CE_MenuHMargin: - case CE_MenuVMargin: - case CE_MenuTearoff: - case CE_MenuScroller: - if (const QStyleOptionMenuItem *mi = qstyleoption_cast(opt)) { - const bool active = mi->state & State_Selected; - if (active) - p->fillRect(mi->rect, mi->palette.highlight()); - - const QStyleHelper::WidgetSizePolicy widgetSize = d->aquaSizeConstrain(opt, w); - - if (ce == CE_MenuTearoff) { - p->setPen(QPen(mi->palette.dark().color(), 1, Qt::DashLine)); - p->drawLine(mi->rect.x() + 2, mi->rect.y() + mi->rect.height() / 2 - 1, - mi->rect.x() + mi->rect.width() - 4, - mi->rect.y() + mi->rect.height() / 2 - 1); - p->setPen(QPen(mi->palette.light().color(), 1, Qt::DashLine)); - p->drawLine(mi->rect.x() + 2, mi->rect.y() + mi->rect.height() / 2, - mi->rect.x() + mi->rect.width() - 4, - mi->rect.y() + mi->rect.height() / 2); - } else if (ce == CE_MenuScroller) { - const QSize scrollerSize = QSize(10, 8); - const int scrollerVOffset = 5; - const int left = mi->rect.x() + (mi->rect.width() - scrollerSize.width()) / 2; - const int right = left + scrollerSize.width(); - int top; - int bottom; - if (opt->state & State_DownArrow) { - bottom = mi->rect.y() + scrollerVOffset; - top = bottom + scrollerSize.height(); - } else { - bottom = mi->rect.bottom() - scrollerVOffset; - top = bottom - scrollerSize.height(); - } - p->save(); - p->setRenderHint(QPainter::Antialiasing); - QPainterPath path; - path.moveTo(left, bottom); - path.lineTo(right, bottom); - path.lineTo((left + right) / 2, top); - p->fillPath(path, opt->palette.buttonText()); - p->restore(); - } else if (ce != CE_MenuItem) { - break; - } - - if (mi->menuItemType == QStyleOptionMenuItem::Separator) { - CGColorRef separatorColor = [NSColor quaternaryLabelColor].CGColor; - const QRect separatorRect = QRect(mi->rect.left(), mi->rect.center().y(), mi->rect.width(), 2); - p->fillRect(separatorRect, qt_mac_toQColor(separatorColor)); - break; - } - - const int maxpmw = mi->maxIconWidth; - const bool enabled = mi->state & State_Enabled; - - int xpos = mi->rect.x() + 18; - int checkcol = maxpmw; - if (!enabled) - p->setPen(mi->palette.text().color()); - else if (active) - p->setPen(mi->palette.highlightedText().color()); - else - p->setPen(mi->palette.buttonText().color()); - - if (mi->checked) { - QStyleOption checkmarkOpt; - checkmarkOpt.initFrom(w); - - const int mw = checkcol + macItemFrame; - const int mh = mi->rect.height() + macItemFrame; - const int xp = mi->rect.x() + macItemFrame; - checkmarkOpt.rect = QRect(xp, mi->rect.y() - checkmarkOpt.fontMetrics.descent(), mw, mh); - - checkmarkOpt.state.setFlag(State_On, active); - checkmarkOpt.state.setFlag(State_Enabled, enabled); - if (widgetSize == QStyleHelper::SizeMini) - checkmarkOpt.state |= State_Mini; - else if (widgetSize == QStyleHelper::SizeSmall) - checkmarkOpt.state |= State_Small; - - // We let drawPrimitive(PE_IndicatorMenuCheckMark) pick the right color - checkmarkOpt.palette.setColor(QPalette::HighlightedText, p->pen().color()); - checkmarkOpt.palette.setColor(QPalette::Text, p->pen().color()); - - proxy()->drawPrimitive(PE_IndicatorMenuCheckMark, &checkmarkOpt, p, w); - } - if (!mi->icon.isNull()) { - QIcon::Mode mode = (mi->state & State_Enabled) ? QIcon::Normal - : QIcon::Disabled; - // Always be normal or disabled to follow the Mac style. - int smallIconSize = proxy()->pixelMetric(PM_SmallIconSize); - QSize iconSize(smallIconSize, smallIconSize); -#if QT_CONFIG(combobox) - if (const QComboBox *comboBox = qobject_cast(w)) { - iconSize = comboBox->iconSize(); - } -#endif - QPixmap pixmap = mi->icon.pixmap(window, iconSize, mode); - int pixw = pixmap.width() / pixmap.devicePixelRatio(); - int pixh = pixmap.height() / pixmap.devicePixelRatio(); - QRect cr(xpos, mi->rect.y(), checkcol, mi->rect.height()); - QRect pmr(0, 0, pixw, pixh); - pmr.moveCenter(cr.center()); - p->drawPixmap(pmr.topLeft(), pixmap); - xpos += pixw + 6; - } - - QString s = mi->text; - const auto text_flags = Qt::AlignVCenter | Qt::TextHideMnemonic - | Qt::TextSingleLine | Qt::AlignAbsolute; - int yPos = mi->rect.y(); - if (widgetSize == QStyleHelper::SizeMini) - yPos += 1; - - const bool isSubMenu = mi->menuItemType == QStyleOptionMenuItem::SubMenu; - const int tabwidth = isSubMenu ? 9 : mi->tabWidth; - - QString rightMarginText; - if (isSubMenu) - rightMarginText = QStringLiteral("\u25b6\ufe0e"); // U+25B6 U+FE0E: BLACK RIGHT-POINTING TRIANGLE - - // If present, save and remove embedded shorcut from text - const int tabIndex = s.indexOf(QLatin1Char('\t')); - if (tabIndex >= 0) { - if (!isSubMenu) // ... but ignore it if it's a submenu. - rightMarginText = s.mid(tabIndex + 1); - s = s.left(tabIndex); - } - - p->save(); - if (!rightMarginText.isEmpty()) { - p->setFont(qt_app_fonts_hash()->value("QMenuItem", p->font())); - int xp = mi->rect.right() - tabwidth - macRightBorder + 2; - if (!isSubMenu) - xp -= macItemHMargin + macItemFrame + 3; // Adjust for shortcut - p->drawText(xp, yPos, tabwidth, mi->rect.height(), text_flags | Qt::AlignRight, rightMarginText); - } - - if (!s.isEmpty()) { - const int xm = macItemFrame + maxpmw + macItemHMargin; - QFont myFont = mi->font; - // myFont may not have any "hard" flags set. We override - // the point size so that when it is resolved against the device, this font will win. - // This is mainly to handle cases where someone sets the font on the window - // and then the combo inherits it and passes it onward. At that point the resolve mask - // is very, very weak. This makes it stonger. - myFont.setPointSizeF(QFontInfo(mi->font).pointSizeF()); - - // QTBUG-65653: Our own text rendering doesn't look good enough, especially on non-retina - // displays. Worked around here while waiting for a proper fix in QCoreTextFontEngine. - // Only if we're not using QCoreTextFontEngine we do fallback to our own text rendering. - const auto *fontEngine = QFontPrivate::get(myFont)->engineForScript(QChar::Script_Common); - Q_ASSERT(fontEngine); - if (fontEngine->type() == QFontEngine::Multi) { - fontEngine = static_cast(fontEngine)->engine(0); - Q_ASSERT(fontEngine); - } - if (fontEngine->type() == QFontEngine::Mac) { - NSFont *f = (NSFont *)(CTFontRef)fontEngine->handle(); - - // Respect the menu item palette as set in the style option. - const auto pc = p->pen().color(); - NSColor *c = [NSColor colorWithSRGBRed:pc.redF() - green:pc.greenF() - blue:pc.blueF() - alpha:pc.alphaF()]; - - s = qt_mac_removeMnemonics(s); - - QMacCGContext cgCtx(p); - d->setupNSGraphicsContext(cgCtx, YES); - - // Draw at point instead of in rect, as the rect we've computed for the menu item - // is based on the font metrics we got from HarfBuzz, so we may risk having CoreText - // line-break the string if it doesn't fit the given rect. It's better to draw outside - // the rect and possibly overlap something than to have part of the text disappear. - [s.toNSString() drawAtPoint:CGPointMake(xpos, yPos) - withAttributes:@{ NSFontAttributeName:f, NSForegroundColorAttributeName:c, - NSObliquenessAttributeName: [NSNumber numberWithDouble: myFont.italic() ? 0.3 : 0.0]}]; - - d->restoreNSGraphicsContext(cgCtx); - } else { - p->setFont(myFont); - p->drawText(xpos, yPos, mi->rect.width() - xm - tabwidth + 1, - mi->rect.height(), text_flags, s); - } - } - p->restore(); - } - break; - case CE_MenuBarItem: - case CE_MenuBarEmptyArea: - if (const QStyleOptionMenuItem *mi = qstyleoption_cast(opt)) { - const bool selected = (opt->state & State_Selected) && (opt->state & State_Enabled) && (opt->state & State_Sunken); - const QBrush bg = selected ? mi->palette.highlight() : mi->palette.window(); - p->fillRect(mi->rect, bg); - - if (ce != CE_MenuBarItem) - break; - - if (!mi->icon.isNull()) { - int iconExtent = proxy()->pixelMetric(PM_SmallIconSize); - drawItemPixmap(p, mi->rect, - Qt::AlignCenter | Qt::TextHideMnemonic | Qt::TextDontClip - | Qt::TextSingleLine, - mi->icon.pixmap(window, QSize(iconExtent, iconExtent), - (mi->state & State_Enabled) ? QIcon::Normal : QIcon::Disabled)); - } else { - drawItemText(p, mi->rect, - Qt::AlignCenter | Qt::TextHideMnemonic | Qt::TextDontClip - | Qt::TextSingleLine, - mi->palette, mi->state & State_Enabled, - mi->text, selected ? QPalette::HighlightedText : QPalette::ButtonText); - } - } - break; - case CE_ProgressBarLabel: - case CE_ProgressBarGroove: - // Do nothing. All done in CE_ProgressBarContents. Only keep these for proxy style overrides. - break; - case CE_ProgressBarContents: - if (const QStyleOptionProgressBar *pb = qstyleoption_cast(opt)) { - QMacAutoReleasePool pool; - const bool isIndeterminate = (pb->minimum == 0 && pb->maximum == 0); - const bool vertical = pb->orientation == Qt::Vertical; - const bool inverted = pb->invertedAppearance; - bool reverse = (!vertical && (pb->direction == Qt::RightToLeft)); - if (inverted) - reverse = !reverse; - - QRect rect = pb->rect; - if (vertical) - rect = rect.transposed(); - const CGRect cgRect = rect.toCGRect(); - - const auto aquaSize = d->effectiveAquaSizeConstrain(opt, w); - const QProgressStyleAnimation *animation = qobject_cast(d->animation(opt->styleObject)); - QIndeterminateProgressIndicator *ipi = nil; - if (isIndeterminate || animation) - ipi = static_cast(d->cocoaControl({ QMacStylePrivate::ProgressIndicator_Indeterminate, aquaSize })); - if (isIndeterminate) { - // QIndeterminateProgressIndicator derives from NSProgressIndicator. We use a single - // instance that we start animating as soon as one of the progress bars is indeterminate. - // Since they will be in sync (as it's the case in Cocoa), we just need to draw it with - // the right geometry when the animation triggers an update. However, we can't hide it - // entirely between frames since that would stop the animation, so we just set its alpha - // value to 0. Same if we remove it from its superview. See QIndeterminateProgressIndicator - // implementation for details. - if (!animation && opt->styleObject) { - auto *animation = new QProgressStyleAnimation(d->animateSpeed(QMacStylePrivate::AquaProgressBar), opt->styleObject); - // NSProgressIndicator is heavier to draw than the HITheme API, so we reduce the frame rate a couple notches. - animation->setFrameRate(QStyleAnimation::FifteenFps); - d->startAnimation(animation); - [ipi startAnimation]; - } - - d->setupNSGraphicsContext(cg, NO); - d->setupVerticalInvertedXform(cg, reverse, vertical, cgRect); - [ipi drawWithFrame:cgRect inView:d->backingStoreNSView]; - d->restoreNSGraphicsContext(cg); - } else { - if (animation) { - d->stopAnimation(opt->styleObject); - [ipi stopAnimation]; - } - - const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::ProgressIndicator_Determinate, aquaSize); - auto *pi = static_cast(d->cocoaControl(cw)); - d->drawNSViewInRect(pi, rect, p, ^(CGContextRef ctx, const CGRect &rect) { - d->setupVerticalInvertedXform(ctx, reverse, vertical, rect); - pi.minValue = pb->minimum; - pi.maxValue = pb->maximum; - pi.doubleValue = pb->progress; - [pi drawRect:rect]; - }); - } - } - break; - case CE_SizeGrip: { - // This is not HIG kosher: Fall back to the old stuff until we decide what to do. -#ifndef QT_NO_MDIAREA - if (!w || !qobject_cast(w->parentWidget())) -#endif - break; - - if (w->testAttribute(Qt::WA_MacOpaqueSizeGrip)) - p->fillRect(opt->rect, opt->palette.window()); - - QPen lineColor = QColor(82, 82, 82, 192); - lineColor.setWidth(1); - p->save(); - p->setRenderHint(QPainter::Antialiasing); - p->setPen(lineColor); - const Qt::LayoutDirection layoutDirection = w ? w->layoutDirection() : qApp->layoutDirection(); - const int NumLines = 3; - for (int l = 0; l < NumLines; ++l) { - const int offset = (l * 4 + 3); - QPoint start, end; - if (layoutDirection == Qt::LeftToRight) { - start = QPoint(opt->rect.width() - offset, opt->rect.height() - 1); - end = QPoint(opt->rect.width() - 1, opt->rect.height() - offset); - } else { - start = QPoint(offset, opt->rect.height() - 1); - end = QPoint(1, opt->rect.height() - offset); - } - p->drawLine(start, end); - } - p->restore(); - break; - } - case CE_Splitter: - if (opt->rect.width() > 1 && opt->rect.height() > 1) { - const bool isVertical = !(opt->state & QStyle::State_Horizontal); - // Qt refers to the layout orientation, while Cocoa refers to the divider's. - const auto ct = isVertical ? QMacStylePrivate::SplitView_Horizontal : QMacStylePrivate::SplitView_Vertical; - const auto cw = QMacStylePrivate::CocoaControl(ct, QStyleHelper::SizeLarge); - auto *sv = static_cast(d->cocoaControl(cw)); - sv.frame = opt->rect.toCGRect(); - d->drawNSViewInRect(sv, opt->rect, p, ^(CGContextRef, const CGRect &rect) { - [sv drawDividerInRect:rect]; - }); - } else { - QPen oldPen = p->pen(); - p->setPen(opt->palette.dark().color()); - if (opt->state & QStyle::State_Horizontal) - p->drawLine(opt->rect.topLeft(), opt->rect.bottomLeft()); - else - p->drawLine(opt->rect.topLeft(), opt->rect.topRight()); - p->setPen(oldPen); - } - break; - case CE_RubberBand: - if (const QStyleOptionRubberBand *rubber = qstyleoption_cast(opt)) { - QColor fillColor(opt->palette.color(QPalette::Disabled, QPalette::Highlight)); - if (!rubber->opaque) { - QColor strokeColor; - // I retrieved these colors from the Carbon-Dev mailing list - strokeColor.setHsvF(0, 0, 0.86, 1.0); - fillColor.setHsvF(0, 0, 0.53, 0.25); - if (opt->rect.width() * opt->rect.height() <= 3) { - p->fillRect(opt->rect, strokeColor); - } else { - QPen oldPen = p->pen(); - QBrush oldBrush = p->brush(); - QPen pen(strokeColor); - p->setPen(pen); - p->setBrush(fillColor); - QRect adjusted = opt->rect.adjusted(1, 1, -1, -1); - if (adjusted.isValid()) - p->drawRect(adjusted); - p->setPen(oldPen); - p->setBrush(oldBrush); - } - } else { - p->fillRect(opt->rect, fillColor); - } - } - break; -#ifndef QT_NO_TOOLBAR - case CE_ToolBar: { - const QStyleOptionToolBar *toolBar = qstyleoption_cast(opt); - const bool isDarkMode = qt_mac_applicationIsInDarkMode(); - - // Unified title and toolbar drawing. In this mode the cocoa platform plugin will - // fill the top toolbar area part with a background gradient that "unifies" with - // the title bar. The following code fills the toolBar area with transparent pixels - // to make that gradient visible. - if (w) { -#if QT_CONFIG(mainwindow) - if (QMainWindow * mainWindow = qobject_cast(w->window())) { - if (toolBar && toolBar->toolBarArea == Qt::TopToolBarArea && mainWindow->unifiedTitleAndToolBarOnMac()) { - // fill with transparent pixels. - p->save(); - p->setCompositionMode(QPainter::CompositionMode_Source); - p->fillRect(opt->rect, Qt::transparent); - p->restore(); - - // Draw a horizontal separator line at the toolBar bottom if the "unified" area ends here. - // There might be additional toolbars or other widgets such as tab bars in document - // mode below. Determine this by making a unified toolbar area test for the row below - // this toolbar. - const QPoint windowToolbarEnd = w->mapTo(w->window(), opt->rect.bottomLeft()); - const bool isEndOfUnifiedArea = !isInMacUnifiedToolbarArea(w->window()->windowHandle(), windowToolbarEnd.y() + 1); - if (isEndOfUnifiedArea) { - const int margin = qt_mac_aqua_get_metric(SeparatorSize); - const auto separatorRect = QRect(opt->rect.left(), opt->rect.bottom(), opt->rect.width(), margin); - p->fillRect(separatorRect, isDarkMode ? darkModeSeparatorLine : opt->palette.dark().color()); - } - break; - } - } -#endif - } - - // draw background gradient - QLinearGradient linearGrad; - if (opt->state & State_Horizontal) - linearGrad = QLinearGradient(0, opt->rect.top(), 0, opt->rect.bottom()); - else - linearGrad = QLinearGradient(opt->rect.left(), 0, opt->rect.right(), 0); - - QColor mainWindowGradientBegin = isDarkMode ? darkMainWindowGradientBegin : lightMainWindowGradientBegin; - QColor mainWindowGradientEnd = isDarkMode ? darkMainWindowGradientEnd : lightMainWindowGradientEnd; - - linearGrad.setColorAt(0, mainWindowGradientBegin); - linearGrad.setColorAt(1, mainWindowGradientEnd); - p->fillRect(opt->rect, linearGrad); - - p->save(); - QRect toolbarRect = isDarkMode ? opt->rect.adjusted(0, 0, 0, 1) : opt->rect; - if (opt->state & State_Horizontal) { - p->setPen(isDarkMode ? darkModeSeparatorLine : mainWindowGradientBegin.lighter(114)); - p->drawLine(toolbarRect.topLeft(), toolbarRect.topRight()); - p->setPen(isDarkMode ? darkModeSeparatorLine :mainWindowGradientEnd.darker(114)); - p->drawLine(toolbarRect.bottomLeft(), toolbarRect.bottomRight()); - } else { - p->setPen(isDarkMode ? darkModeSeparatorLine : mainWindowGradientBegin.lighter(114)); - p->drawLine(toolbarRect.topLeft(), toolbarRect.bottomLeft()); - p->setPen(isDarkMode ? darkModeSeparatorLine : mainWindowGradientEnd.darker(114)); - p->drawLine(toolbarRect.topRight(), toolbarRect.bottomRight()); - } - p->restore(); - - - } break; -#endif - default: - QCommonStyle::drawControl(ce, opt, p, w); - break; - } -} - -static void setLayoutItemMargins(int left, int top, int right, int bottom, QRect *rect, Qt::LayoutDirection dir) -{ - if (dir == Qt::RightToLeft) { - rect->adjust(-right, top, -left, bottom); - } else { - rect->adjust(left, top, right, bottom); - } -} - -QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt, - const QWidget *widget) const -{ - Q_D(const QMacStyle); - QRect rect; - const int controlSize = getControlSize(opt, widget); - - switch (sr) { - case SE_ItemViewItemText: - if (const QStyleOptionViewItem *vopt = qstyleoption_cast(opt)) { - int fw = proxy()->pixelMetric(PM_FocusFrameHMargin, opt, widget); - // We add the focusframeargin between icon and text in commonstyle - rect = QCommonStyle::subElementRect(sr, opt, widget); - if (vopt->features & QStyleOptionViewItem::HasDecoration) - rect.adjust(-fw, 0, 0, 0); - } - break; - case SE_ToolBoxTabContents: - rect = QCommonStyle::subElementRect(sr, opt, widget); - break; - case SE_PushButtonContents: - if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) { - // Comment from the old HITheme days: - // "Unlike Carbon, we want the button to always be drawn inside its bounds. - // Therefore, the button is a bit smaller, so that even if it got focus, - // the focus 'shadow' will be inside. Adjust the content rect likewise." - // In the future, we should consider using -[NSCell titleRectForBounds:]. - // Since it requires configuring the NSButton fully, i.e. frame, image, - // title and font, we keep things more manual until we are more familiar - // with side effects when changing NSButton state. - const auto ct = cocoaControlType(btn, widget); - const auto cs = d->effectiveAquaSizeConstrain(btn, widget); - const auto cw = QMacStylePrivate::CocoaControl(ct, cs); - const auto frameRect = cw.adjustedControlFrame(btn->rect); - const auto titleMargins = cw.titleMargins(); - rect = (frameRect - titleMargins).toRect(); - } - break; - case SE_HeaderLabel: { - int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, opt, widget); - rect.setRect(opt->rect.x() + margin, opt->rect.y(), - opt->rect.width() - margin * 2, opt->rect.height() - 2); - if (const QStyleOptionHeader *header = qstyleoption_cast(opt)) { - // Subtract width needed for arrow, if there is one - if (header->sortIndicator != QStyleOptionHeader::None) { - if (opt->state & State_Horizontal) - rect.setWidth(rect.width() - (headerSectionArrowHeight) - (margin * 2)); - else - rect.setHeight(rect.height() - (headerSectionArrowHeight) - (margin * 2)); - } - } - rect = visualRect(opt->direction, opt->rect, rect); - break; - } - case SE_HeaderArrow: { - int h = opt->rect.height(); - int w = opt->rect.width(); - int x = opt->rect.x(); - int y = opt->rect.y(); - int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, opt, widget); - - if (opt->state & State_Horizontal) { - rect.setRect(x + w - margin * 2 - headerSectionArrowHeight, y + 5, - headerSectionArrowHeight, h - margin * 2 - 5); - } else { - rect.setRect(x + 5, y + h - margin * 2 - headerSectionArrowHeight, - w - margin * 2 - 5, headerSectionArrowHeight); - } - rect = visualRect(opt->direction, opt->rect, rect); - break; - } - case SE_ProgressBarGroove: - // Wrong in the secondary dimension, but accurate enough in the main dimension. - rect = opt->rect; - break; - case SE_ProgressBarLabel: - break; - case SE_ProgressBarContents: - rect = opt->rect; - break; - case SE_TreeViewDisclosureItem: { - rect = opt->rect; - // As previously returned by HIThemeGetButtonContentBounds - rect.setLeft(rect.left() + 2 + DisclosureOffset); - break; - } -#if QT_CONFIG(tabwidget) - case SE_TabWidgetLeftCorner: - if (const QStyleOptionTabWidgetFrame *twf - = qstyleoption_cast(opt)) { - switch (twf->shape) { - case QTabBar::RoundedNorth: - case QTabBar::TriangularNorth: - rect = QRect(QPoint(0, 0), twf->leftCornerWidgetSize); - break; - case QTabBar::RoundedSouth: - case QTabBar::TriangularSouth: - rect = QRect(QPoint(0, twf->rect.height() - twf->leftCornerWidgetSize.height()), - twf->leftCornerWidgetSize); - break; - default: - break; - } - rect = visualRect(twf->direction, twf->rect, rect); - } - break; - case SE_TabWidgetRightCorner: - if (const QStyleOptionTabWidgetFrame *twf - = qstyleoption_cast(opt)) { - switch (twf->shape) { - case QTabBar::RoundedNorth: - case QTabBar::TriangularNorth: - rect = QRect(QPoint(twf->rect.width() - twf->rightCornerWidgetSize.width(), 0), - twf->rightCornerWidgetSize); - break; - case QTabBar::RoundedSouth: - case QTabBar::TriangularSouth: - rect = QRect(QPoint(twf->rect.width() - twf->rightCornerWidgetSize.width(), - twf->rect.height() - twf->rightCornerWidgetSize.height()), - twf->rightCornerWidgetSize); - break; - default: - break; - } - rect = visualRect(twf->direction, twf->rect, rect); - } - break; - case SE_TabWidgetTabContents: - rect = QCommonStyle::subElementRect(sr, opt, widget); - if (const auto *twf = qstyleoption_cast(opt)) { - if (twf->lineWidth != 0) { - switch (QMacStylePrivate::tabDirection(twf->shape)) { - case QMacStylePrivate::North: - rect.adjust(+1, +14, -1, -1); - break; - case QMacStylePrivate::South: - rect.adjust(+1, +1, -1, -14); - break; - case QMacStylePrivate::West: - rect.adjust(+14, +1, -1, -1); - break; - case QMacStylePrivate::East: - rect.adjust(+1, +1, -14, -1); - } - } - } - break; - case SE_TabBarTabText: - if (const QStyleOptionTab *tab = qstyleoption_cast(opt)) { - QRect dummyIconRect; - d->tabLayout(tab, widget, &rect, &dummyIconRect); - } - break; - case SE_TabBarTabLeftButton: - case SE_TabBarTabRightButton: - if (const QStyleOptionTab *tab = qstyleoption_cast(opt)) { - bool selected = tab->state & State_Selected; - int verticalShift = proxy()->pixelMetric(QStyle::PM_TabBarTabShiftVertical, tab, widget); - int horizontalShift = proxy()->pixelMetric(QStyle::PM_TabBarTabShiftHorizontal, tab, widget); - int hpadding = 5; - - bool verticalTabs = tab->shape == QTabBar::RoundedEast - || tab->shape == QTabBar::RoundedWest - || tab->shape == QTabBar::TriangularEast - || tab->shape == QTabBar::TriangularWest; - - QRect tr = tab->rect; - if (tab->shape == QTabBar::RoundedSouth || tab->shape == QTabBar::TriangularSouth) - verticalShift = -verticalShift; - if (verticalTabs) { - qSwap(horizontalShift, verticalShift); - horizontalShift *= -1; - verticalShift *= -1; - } - if (tab->shape == QTabBar::RoundedWest || tab->shape == QTabBar::TriangularWest) - horizontalShift = -horizontalShift; - - tr.adjust(0, 0, horizontalShift, verticalShift); - if (selected) - { - tr.setBottom(tr.bottom() - verticalShift); - tr.setRight(tr.right() - horizontalShift); - } - - QSize size = (sr == SE_TabBarTabLeftButton) ? tab->leftButtonSize : tab->rightButtonSize; - int w = size.width(); - int h = size.height(); - int midHeight = static_cast(qCeil(float(tr.height() - h) / 2)); - int midWidth = ((tr.width() - w) / 2); - - bool atTheTop = true; - switch (tab->shape) { - case QTabBar::RoundedWest: - case QTabBar::TriangularWest: - atTheTop = (sr == SE_TabBarTabLeftButton); - break; - case QTabBar::RoundedEast: - case QTabBar::TriangularEast: - atTheTop = (sr == SE_TabBarTabRightButton); - break; - default: - if (sr == SE_TabBarTabLeftButton) - rect = QRect(tab->rect.x() + hpadding, midHeight, w, h); - else - rect = QRect(tab->rect.right() - w - hpadding, midHeight, w, h); - rect = visualRect(tab->direction, tab->rect, rect); - } - if (verticalTabs) { - if (atTheTop) - rect = QRect(midWidth, tr.y() + tab->rect.height() - hpadding - h, w, h); - else - rect = QRect(midWidth, tr.y() + hpadding, w, h); - } - } - break; -#endif - case SE_LineEditContents: - rect = QCommonStyle::subElementRect(sr, opt, widget); -#if QT_CONFIG(combobox) - if (widget && qobject_cast(widget->parentWidget())) - rect.adjust(-1, -2, 0, 0); - else -#endif - rect.adjust(-1, -1, 0, +1); - break; - case SE_CheckBoxLayoutItem: - rect = opt->rect; - if (controlSize == QStyleHelper::SizeLarge) { - setLayoutItemMargins(+2, +3, -9, -4, &rect, opt->direction); - } else if (controlSize == QStyleHelper::SizeSmall) { - setLayoutItemMargins(+1, +5, 0 /* fix */, -6, &rect, opt->direction); - } else { - setLayoutItemMargins(0, +7, 0 /* fix */, -6, &rect, opt->direction); - } - break; - case SE_ComboBoxLayoutItem: -#ifndef QT_NO_TOOLBAR - if (widget && qobject_cast(widget->parentWidget())) { - // Do nothing, because QToolbar needs the entire widget rect. - // Otherwise it will be clipped. Equivalent to - // widget->setAttribute(Qt::WA_LayoutUsesWidgetRect), but without - // all the hassle. - } else -#endif - { - rect = opt->rect; - if (controlSize == QStyleHelper::SizeLarge) { - rect.adjust(+3, +2, -3, -4); - } else if (controlSize == QStyleHelper::SizeSmall) { - setLayoutItemMargins(+2, +1, -3, -4, &rect, opt->direction); - } else { - setLayoutItemMargins(+1, 0, -2, 0, &rect, opt->direction); - } - } - break; - case SE_LabelLayoutItem: - rect = opt->rect; - setLayoutItemMargins(+1, 0 /* SHOULD be -1, done for alignment */, 0, 0 /* SHOULD be -1, done for alignment */, &rect, opt->direction); - break; - case SE_ProgressBarLayoutItem: { - rect = opt->rect; - int bottom = SIZE(3, 8, 8); - if (opt->state & State_Horizontal) { - rect.adjust(0, +1, 0, -bottom); - } else { - setLayoutItemMargins(+1, 0, -bottom, 0, &rect, opt->direction); - } - break; - } - case SE_PushButtonLayoutItem: - if (const QStyleOptionButton *buttonOpt - = qstyleoption_cast(opt)) { - if ((buttonOpt->features & QStyleOptionButton::Flat)) - break; // leave rect alone - } - rect = opt->rect; - if (controlSize == QStyleHelper::SizeLarge) { - rect.adjust(+6, +4, -6, -8); - } else if (controlSize == QStyleHelper::SizeSmall) { - rect.adjust(+5, +4, -5, -6); - } else { - rect.adjust(+1, 0, -1, -2); - } - break; - case SE_RadioButtonLayoutItem: - rect = opt->rect; - if (controlSize == QStyleHelper::SizeLarge) { - setLayoutItemMargins(+2, +2 /* SHOULD BE +3, done for alignment */, - 0, -4 /* SHOULD BE -3, done for alignment */, &rect, opt->direction); - } else if (controlSize == QStyleHelper::SizeSmall) { - rect.adjust(0, +6, 0 /* fix */, -5); - } else { - rect.adjust(0, +6, 0 /* fix */, -7); - } - break; - case SE_SliderLayoutItem: - if (const QStyleOptionSlider *sliderOpt - = qstyleoption_cast(opt)) { - rect = opt->rect; - if (sliderOpt->tickPosition == QSlider::NoTicks) { - int above = SIZE(3, 0, 2); - int below = SIZE(4, 3, 0); - if (sliderOpt->orientation == Qt::Horizontal) { - rect.adjust(0, +above, 0, -below); - } else { - rect.adjust(+above, 0, -below, 0); //### Seems that QSlider flip the position of the ticks in reverse mode. - } - } else if (sliderOpt->tickPosition == QSlider::TicksAbove) { - int below = SIZE(3, 2, 0); - if (sliderOpt->orientation == Qt::Horizontal) { - rect.setHeight(rect.height() - below); - } else { - rect.setWidth(rect.width() - below); - } - } else if (sliderOpt->tickPosition == QSlider::TicksBelow) { - int above = SIZE(3, 2, 0); - if (sliderOpt->orientation == Qt::Horizontal) { - rect.setTop(rect.top() + above); - } else { - rect.setLeft(rect.left() + above); - } - } - } - break; - case SE_FrameLayoutItem: - // hack because QStyleOptionFrame doesn't have a frameStyle member - if (const QFrame *frame = qobject_cast(widget)) { - rect = opt->rect; - switch (frame->frameStyle() & QFrame::Shape_Mask) { - case QFrame::HLine: - rect.adjust(0, +1, 0, -1); - break; - case QFrame::VLine: - rect.adjust(+1, 0, -1, 0); - break; - default: - ; - } - } - break; - case SE_GroupBoxLayoutItem: - rect = opt->rect; - if (const QStyleOptionGroupBox *groupBoxOpt = - qstyleoption_cast(opt)) { - /* - AHIG is very inconsistent when it comes to group boxes. - Basically, we make sure that (non-checkable) group boxes - and tab widgets look good when laid out side by side. - */ - if (groupBoxOpt->subControls & (QStyle::SC_GroupBoxCheckBox - | QStyle::SC_GroupBoxLabel)) { - int delta; - if (groupBoxOpt->subControls & QStyle::SC_GroupBoxCheckBox) { - delta = SIZE(8, 4, 4); // guess - } else { - delta = SIZE(15, 12, 12); // guess - } - rect.setTop(rect.top() + delta); - } - } - rect.setBottom(rect.bottom() - 1); - break; -#if QT_CONFIG(tabwidget) - case SE_TabWidgetLayoutItem: - if (const QStyleOptionTabWidgetFrame *tabWidgetOpt = - qstyleoption_cast(opt)) { - /* - AHIG specifies "12 or 14" as the distance from the window - edge. We choose 14 and since the default top margin is 20, - the overlap is 6. - */ - rect = tabWidgetOpt->rect; - if (tabWidgetOpt->shape == QTabBar::RoundedNorth) - rect.setTop(rect.top() + SIZE(6 /* AHIG */, 3 /* guess */, 2 /* AHIG */)); - } - break; -#endif -#if QT_CONFIG(dockwidget) - case SE_DockWidgetCloseButton: - case SE_DockWidgetFloatButton: - case SE_DockWidgetTitleBarText: - case SE_DockWidgetIcon: { - int iconSize = proxy()->pixelMetric(PM_SmallIconSize, opt, widget); - int buttonMargin = proxy()->pixelMetric(PM_DockWidgetTitleBarButtonMargin, opt, widget); - QRect srect = opt->rect; - - const QStyleOptionDockWidget *dwOpt - = qstyleoption_cast(opt); - bool canClose = dwOpt == 0 ? true : dwOpt->closable; - bool canFloat = dwOpt == 0 ? false : dwOpt->floatable; - - const bool verticalTitleBar = dwOpt->verticalTitleBar; - - // If this is a vertical titlebar, we transpose and work as if it was - // horizontal, then transpose again. - if (verticalTitleBar) - srect = srect.transposed(); - - do { - int right = srect.right(); - int left = srect.left(); - - QRect closeRect; - if (canClose) { - QSize sz = proxy()->standardIcon(QStyle::SP_TitleBarCloseButton, - opt, widget).actualSize(QSize(iconSize, iconSize)); - sz += QSize(buttonMargin, buttonMargin); - if (verticalTitleBar) - sz = sz.transposed(); - closeRect = QRect(left, - srect.center().y() - sz.height()/2, - sz.width(), sz.height()); - left = closeRect.right() + 1; - } - if (sr == SE_DockWidgetCloseButton) { - rect = closeRect; - break; - } - - QRect floatRect; - if (canFloat) { - QSize sz = proxy()->standardIcon(QStyle::SP_TitleBarNormalButton, - opt, widget).actualSize(QSize(iconSize, iconSize)); - sz += QSize(buttonMargin, buttonMargin); - if (verticalTitleBar) - sz = sz.transposed(); - floatRect = QRect(left, - srect.center().y() - sz.height()/2, - sz.width(), sz.height()); - left = floatRect.right() + 1; - } - if (sr == SE_DockWidgetFloatButton) { - rect = floatRect; - break; - } - - QRect iconRect; - if (const QDockWidget *dw = qobject_cast(widget)) { - QIcon icon; - if (dw->isFloating()) - icon = dw->windowIcon(); - if (!icon.isNull() - && icon.cacheKey() != QApplication::windowIcon().cacheKey()) { - QSize sz = icon.actualSize(QSize(rect.height(), rect.height())); - if (verticalTitleBar) - sz = sz.transposed(); - iconRect = QRect(right - sz.width(), srect.center().y() - sz.height()/2, - sz.width(), sz.height()); - right = iconRect.left() - 1; - } - } - if (sr == SE_DockWidgetIcon) { - rect = iconRect; - break; - } - - QRect textRect = QRect(left, srect.top(), - right - left, srect.height()); - if (sr == SE_DockWidgetTitleBarText) { - rect = textRect; - break; - } - } while (false); - - if (verticalTitleBar) { - rect = QRect(srect.left() + rect.top() - srect.top(), - srect.top() + srect.right() - rect.right(), - rect.height(), rect.width()); - } else { - rect = visualRect(opt->direction, srect, rect); - } - break; - } -#endif - default: - rect = QCommonStyle::subElementRect(sr, opt, widget); - break; - } - return rect; -} - -void QMacStylePrivate::drawToolbarButtonArrow(const QStyleOption *opt, QPainter *p) const -{ - Q_Q(const QMacStyle); - QStyleOption arrowOpt = *opt; - arrowOpt.rect = QRect(opt->rect.right() - (toolButtonArrowSize + toolButtonArrowMargin), - opt->rect.bottom() - (toolButtonArrowSize + toolButtonArrowMargin), - toolButtonArrowSize, - toolButtonArrowSize); - q->proxy()->drawPrimitive(QStyle::PE_IndicatorArrowDown, &arrowOpt, p); -} - -void QMacStylePrivate::setupNSGraphicsContext(CGContextRef cg, bool flipped) const -{ - CGContextSaveGState(cg); - [NSGraphicsContext saveGraphicsState]; - - [NSGraphicsContext setCurrentContext: - [NSGraphicsContext graphicsContextWithCGContext:cg flipped:flipped]]; -} - -void QMacStylePrivate::restoreNSGraphicsContext(CGContextRef cg) const -{ - [NSGraphicsContext restoreGraphicsState]; - CGContextRestoreGState(cg); -} - -void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p, - const QWidget *widget) const -{ - Q_D(const QMacStyle); - const AppearanceSync sync; - QMacCGContext cg(p); - QWindow *window = widget && widget->window() ? widget->window()->windowHandle() : nullptr; - d->resolveCurrentNSView(window); - switch (cc) { - case CC_ScrollBar: - if (const QStyleOptionSlider *sb = qstyleoption_cast(opt)) { - - const bool drawTrack = sb->subControls & SC_ScrollBarGroove; - const bool drawKnob = sb->subControls & SC_ScrollBarSlider; - if (!drawTrack && !drawKnob) - break; - - const bool isHorizontal = sb->orientation == Qt::Horizontal; - - if (opt && opt->styleObject && !QMacStylePrivate::scrollBars.contains(opt->styleObject)) - QMacStylePrivate::scrollBars.append(QPointer(opt->styleObject)); - - static const CGFloat knobWidths[] = { 7.0, 5.0, 5.0 }; - static const CGFloat expandedKnobWidths[] = { 11.0, 9.0, 9.0 }; - const auto cocoaSize = d->effectiveAquaSizeConstrain(opt, widget); - const CGFloat maxExpandScale = expandedKnobWidths[cocoaSize] / knobWidths[cocoaSize]; - - const bool isTransient = proxy()->styleHint(SH_ScrollBar_Transient, opt, widget); - if (!isTransient) - d->stopAnimation(opt->styleObject); - bool wasActive = false; - CGFloat opacity = 0.0; - CGFloat expandScale = 1.0; - CGFloat expandOffset = 0.0; - bool shouldExpand = false; - - if (QObject *styleObject = opt->styleObject) { - const int oldPos = styleObject->property("_q_stylepos").toInt(); - const int oldMin = styleObject->property("_q_stylemin").toInt(); - const int oldMax = styleObject->property("_q_stylemax").toInt(); - const QRect oldRect = styleObject->property("_q_stylerect").toRect(); - const QStyle::State oldState = static_cast(styleObject->property("_q_stylestate").value()); - const uint oldActiveControls = styleObject->property("_q_stylecontrols").toUInt(); - - // a scrollbar is transient when the scrollbar itself and - // its sibling are both inactive (ie. not pressed/hovered/moved) - const bool transient = isTransient && !opt->activeSubControls && !(sb->state & State_On); - - if (!transient || - oldPos != sb->sliderPosition || - oldMin != sb->minimum || - oldMax != sb->maximum || - oldRect != sb->rect || - oldState != sb->state || - oldActiveControls != sb->activeSubControls) { - - // if the scrollbar is transient or its attributes, geometry or - // state has changed, the opacity is reset back to 100% opaque - opacity = 1.0; - - styleObject->setProperty("_q_stylepos", sb->sliderPosition); - styleObject->setProperty("_q_stylemin", sb->minimum); - styleObject->setProperty("_q_stylemax", sb->maximum); - styleObject->setProperty("_q_stylerect", sb->rect); - styleObject->setProperty("_q_stylestate", static_cast(sb->state)); - styleObject->setProperty("_q_stylecontrols", static_cast(sb->activeSubControls)); - - QScrollbarStyleAnimation *anim = qobject_cast(d->animation(styleObject)); - if (transient) { - if (!anim) { - anim = new QScrollbarStyleAnimation(QScrollbarStyleAnimation::Deactivating, styleObject); - d->startAnimation(anim); - } else if (anim->mode() == QScrollbarStyleAnimation::Deactivating) { - // the scrollbar was already fading out while the - // state changed -> restart the fade out animation - anim->setCurrentTime(0); - } - } else if (anim && anim->mode() == QScrollbarStyleAnimation::Deactivating) { - d->stopAnimation(styleObject); - } - } - - QScrollbarStyleAnimation *anim = qobject_cast(d->animation(styleObject)); - if (anim && anim->mode() == QScrollbarStyleAnimation::Deactivating) { - // once a scrollbar was active (hovered/pressed), it retains - // the active look even if it's no longer active while fading out - if (oldActiveControls) - anim->setActive(true); - - wasActive = anim->wasActive(); - opacity = anim->currentValue(); - } - - shouldExpand = isTransient && (opt->activeSubControls || wasActive); - if (shouldExpand) { - if (!anim && !oldActiveControls) { - // Start expand animation only once and when entering - anim = new QScrollbarStyleAnimation(QScrollbarStyleAnimation::Activating, styleObject); - d->startAnimation(anim); - } - if (anim && anim->mode() == QScrollbarStyleAnimation::Activating) { - expandScale = 1.0 + (maxExpandScale - 1.0) * anim->currentValue(); - expandOffset = 5.5 * (1.0 - anim->currentValue()); - } else { - // Keep expanded state after the animation ends, and when fading out - expandScale = maxExpandScale; - expandOffset = 0.0; - } - } - } - - d->setupNSGraphicsContext(cg, NO /* flipped */); - - const auto controlType = isHorizontal ? QMacStylePrivate::Scroller_Horizontal : QMacStylePrivate::Scroller_Vertical; - const auto cw = QMacStylePrivate::CocoaControl(controlType, cocoaSize); - NSScroller *scroller = static_cast(d->cocoaControl(cw)); - - const QColor bgColor = QStyleHelper::backgroundColor(opt->palette, widget); - const bool hasDarkBg = bgColor.red() < 128 && bgColor.green() < 128 && bgColor.blue() < 128; - if (isTransient) { - // macOS behavior: as soon as one color channel is >= 128, - // the background is considered bright, scroller is dark. - scroller.knobStyle = hasDarkBg? NSScrollerKnobStyleLight : NSScrollerKnobStyleDark; - } else { - scroller.knobStyle = NSScrollerKnobStyleDefault; - } - - scroller.scrollerStyle = isTransient ? NSScrollerStyleOverlay : NSScrollerStyleLegacy; - - if (!setupScroller(scroller, sb)) - break; - - if (isTransient) { - CGContextBeginTransparencyLayerWithRect(cg, scroller.frame, nullptr); - CGContextSetAlpha(cg, opacity); - } - - if (drawTrack) { - // Draw the track when hovering. Expand by shifting the track rect. - if (!isTransient || opt->activeSubControls || wasActive) { - CGRect trackRect = scroller.bounds; - if (isHorizontal) - trackRect.origin.y += expandOffset; - else - trackRect.origin.x += expandOffset; - [scroller drawKnobSlotInRect:trackRect highlight:NO]; - } - } - - if (drawKnob) { - if (shouldExpand) { - // -[NSScroller drawKnob] is not useful here because any scaling applied - // will only be used to draw the hi-DPI artwork. And even if did scale, - // the stretched knob would look wrong, actually. So we need to draw the - // scroller manually when it's being hovered. - const CGFloat scrollerWidth = [NSScroller scrollerWidthForControlSize:scroller.controlSize scrollerStyle:scroller.scrollerStyle]; - const CGFloat knobWidth = knobWidths[cocoaSize] * expandScale; - // Cocoa can help get the exact knob length in the current orientation - const CGRect scrollerKnobRect = CGRectInset([scroller rectForPart:NSScrollerKnob], 1, 1); - const CGFloat knobLength = isHorizontal ? scrollerKnobRect.size.width : scrollerKnobRect.size.height; - const CGFloat knobPos = isHorizontal ? scrollerKnobRect.origin.x : scrollerKnobRect.origin.y; - const CGFloat knobOffset = qRound((scrollerWidth + expandOffset - knobWidth) / 2.0); - const CGFloat knobRadius = knobWidth / 2.0; - CGRect knobRect; - if (isHorizontal) - knobRect = CGRectMake(knobPos, knobOffset, knobLength, knobWidth); - else - knobRect = CGRectMake(knobOffset, knobPos, knobWidth, knobLength); - QCFType knobPath = CGPathCreateWithRoundedRect(knobRect, knobRadius, knobRadius, nullptr); - CGContextAddPath(cg, knobPath); - CGContextSetAlpha(cg, 0.5); - CGColorRef knobColor = hasDarkBg ? NSColor.whiteColor.CGColor : NSColor.blackColor.CGColor; - CGContextSetFillColorWithColor(cg, knobColor); - CGContextFillPath(cg); - } else { - [scroller drawKnob]; - - if (!isTransient && opt->activeSubControls) { - // The knob should appear darker (going from 0.76 down to 0.49). - // But no blending mode can help darken enough in a single pass, - // so we resort to drawing the knob twice with a small help from - // blending. This brings the gray level to a close enough 0.53. - CGContextSetBlendMode(cg, kCGBlendModePlusDarker); - [scroller drawKnob]; - } - } - } - - if (isTransient) - CGContextEndTransparencyLayer(cg); - - d->restoreNSGraphicsContext(cg); - } - break; - case CC_Slider: - if (const QStyleOptionSlider *sl = qstyleoption_cast(opt)) { - const bool isHorizontal = sl->orientation == Qt::Horizontal; - const auto ct = isHorizontal ? QMacStylePrivate::Slider_Horizontal : QMacStylePrivate::Slider_Vertical; - const auto cs = d->effectiveAquaSizeConstrain(opt, widget); - const auto cw = QMacStylePrivate::CocoaControl(ct, cs); - auto *slider = static_cast(d->cocoaControl(cw)); - if (!setupSlider(slider, sl)) - break; - - const bool hasTicks = sl->tickPosition != QSlider::NoTicks; - const bool hasDoubleTicks = sl->tickPosition == QSlider::TicksBothSides; - const bool drawKnob = sl->subControls & SC_SliderHandle; - const bool drawBar = sl->subControls & SC_SliderGroove; - const bool drawTicks = sl->subControls & SC_SliderTickmarks; - const bool isPressed = sl->state & State_Sunken; - - CGPoint pressPoint; - if (isPressed) { - const CGRect knobRect = [slider.cell knobRectFlipped:NO]; - pressPoint.x = CGRectGetMidX(knobRect); - pressPoint.y = CGRectGetMidY(knobRect); - [slider.cell startTrackingAt:pressPoint inView:slider]; - } - - d->drawNSViewInRect(slider, opt->rect, p, ^(CGContextRef ctx, const CGRect &rect) { - if (isHorizontal && sl->upsideDown) { - CGContextTranslateCTM(ctx, rect.size.width, 0); - CGContextScaleCTM(ctx, -1, 1); - } - - if (hasDoubleTicks) { - // This ain't HIG kosher: eye-proved constants - if (isHorizontal) - CGContextTranslateCTM(ctx, 0, 4); - else - CGContextTranslateCTM(ctx, 1, 0); - } - - // Since the GC is flipped, upsideDown means *not* inverted when vertical. - const bool verticalFlip = !isHorizontal && !sl->upsideDown; // FIXME: && !isSierraOrLater - -#if 0 - // FIXME: Sadly, this part doesn't work. It seems to somehow polute the - // NSSlider's internal state and, when we need to use the "else" part, - // the slider's frame is not in sync with its cell dimensions. - const bool drawAllParts = drawKnob && drawBar && (!hasTicks || drawTicks); - if (drawAllParts && !hasDoubleTicks && (!verticalFlip || drawTicks)) { - // Draw eveything at once if we're going to, except for inverted vertical - // sliders which need to be drawn part by part because of the shadow below - // the knob. Same for two-sided tickmarks. - if (verticalFlip && drawTicks) { - // Since tickmarks are always rendered symmetrically, a vertically - // flipped slider with tickmarks only needs to get its value flipped. - slider.intValue = slider.maxValue - slider.intValue + slider.minValue; - } - [slider drawRect:CGRectZero]; - } else -#endif - { - [slider calcSize]; - if (!hasDoubleTicks) - fixStaleGeometry(slider); - NSSliderCell *cell = slider.cell; - - const int numberOfTickMarks = slider.numberOfTickMarks; - // This ain't HIG kosher: force tick-less bar position. - if (hasDoubleTicks) - slider.numberOfTickMarks = 0; - - const CGRect barRect = [cell barRectFlipped:hasTicks]; - if (drawBar) { - [cell drawBarInside:barRect flipped:!verticalFlip]; - // This ain't HIG kosher: force unfilled bar look. - if (hasDoubleTicks) - slider.numberOfTickMarks = numberOfTickMarks; - } - - if (hasTicks && drawTicks) { - if (!drawBar && hasDoubleTicks) - slider.numberOfTickMarks = numberOfTickMarks; - - [cell drawTickMarks]; - - if (hasDoubleTicks) { - // This ain't HIG kosher: just slap a set of tickmarks on each side, like we used to. - CGAffineTransform tickMarksFlip; - const CGRect tickMarkRect = [cell rectOfTickMarkAtIndex:0]; - if (isHorizontal) { - tickMarksFlip = CGAffineTransformMakeTranslation(0, rect.size.height - tickMarkRect.size.height - 3); - tickMarksFlip = CGAffineTransformScale(tickMarksFlip, 1, -1); - } else { - tickMarksFlip = CGAffineTransformMakeTranslation(rect.size.width - tickMarkRect.size.width / 2, 0); - tickMarksFlip = CGAffineTransformScale(tickMarksFlip, -1, 1); - } - CGContextConcatCTM(ctx, tickMarksFlip); - [cell drawTickMarks]; - CGContextConcatCTM(ctx, CGAffineTransformInvert(tickMarksFlip)); - } - } - - if (drawKnob) { - // This ain't HIG kosher: force round knob look. - if (hasDoubleTicks) - slider.numberOfTickMarks = 0; - // Draw the knob in the symmetrical position instead of flipping. - if (verticalFlip) - slider.intValue = slider.maxValue - slider.intValue + slider.minValue; - [cell drawKnob]; - } - } - }); - - if (isPressed) - [slider.cell stopTracking:pressPoint at:pressPoint inView:slider mouseIsUp:NO]; - } - break; -#if QT_CONFIG(spinbox) - case CC_SpinBox: - if (const QStyleOptionSpinBox *sb = qstyleoption_cast(opt)) { - if (sb->frame && (sb->subControls & SC_SpinBoxFrame)) { - const auto lineEditRect = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxEditField, widget); - QStyleOptionFrame frame; - static_cast(frame) = *opt; - frame.rect = lineEditRect; - frame.state |= State_Sunken; - frame.lineWidth = 1; - frame.midLineWidth = 0; - frame.features = QStyleOptionFrame::None; - frame.frameShape = QFrame::Box; - drawPrimitive(PE_FrameLineEdit, &frame, p, widget); - } - if (sb->subControls & (SC_SpinBoxUp | SC_SpinBoxDown)) { - const QRect updown = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxUp, widget) - | proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxDown, widget); - - d->setupNSGraphicsContext(cg, NO); - - const auto aquaSize = d->effectiveAquaSizeConstrain(opt, widget); - const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::Stepper, aquaSize); - NSStepperCell *cell = static_cast(d->cocoaCell(cw)); - cell.enabled = (sb->state & State_Enabled); - - const CGRect newRect = [cell drawingRectForBounds:updown.toCGRect()]; - - const bool upPressed = sb->activeSubControls == SC_SpinBoxUp && (sb->state & State_Sunken); - const bool downPressed = sb->activeSubControls == SC_SpinBoxDown && (sb->state & State_Sunken); - const CGFloat x = CGRectGetMidX(newRect); - const CGFloat y = upPressed ? -3 : 3; // Weird coordinate shift going on. Verified with Hopper - const CGPoint pressPoint = CGPointMake(x, y); - // Pretend we're pressing the mouse on the right button. Unfortunately, NSStepperCell has no - // API to highlight a specific button. The highlighted property works only on the down button. - if (upPressed || downPressed) - [cell startTrackingAt:pressPoint inView:d->backingStoreNSView]; - - [cell drawWithFrame:newRect inView:d->backingStoreNSView]; - - if (upPressed || downPressed) - [cell stopTracking:pressPoint at:pressPoint inView:d->backingStoreNSView mouseIsUp:NO]; - - d->restoreNSGraphicsContext(cg); - } - } - break; -#endif -#if QT_CONFIG(combobox) - case CC_ComboBox: - if (const auto *combo = qstyleoption_cast(opt)) { - const bool isEnabled = combo->state & State_Enabled; - const bool isPressed = combo->state & State_Sunken; - - const auto ct = cocoaControlType(combo, widget); - const auto cs = d->effectiveAquaSizeConstrain(combo, widget); - const auto cw = QMacStylePrivate::CocoaControl(ct, cs); - auto *cc = static_cast(d->cocoaControl(cw)); - cc.enabled = isEnabled; - QRectF frameRect = cw.adjustedControlFrame(combo->rect);; - if (cw.type == QMacStylePrivate::Button_PopupButton) { - // Non-editable QComboBox - auto *pb = static_cast(cc); - // FIXME Old offsets. Try to move to adjustedControlFrame() - if (cw.size == QStyleHelper::SizeSmall) { - frameRect = frameRect.translated(0, 1); - } else if (cw.size == QStyleHelper::SizeMini) { - // Same 0.5 pt misalignment as AppKit and fit the focus ring - frameRect = frameRect.translated(2, -0.5); - } - pb.frame = frameRect.toCGRect(); - [pb highlight:isPressed]; - d->drawNSViewInRect(pb, frameRect, p, ^(CGContextRef, const CGRect &r) { - [pb.cell drawBezelWithFrame:r inView:pb.superview]; - }); - } else if (cw.type == QMacStylePrivate::ComboBox) { - // Editable QComboBox - auto *cb = static_cast(cc); - const auto frameRect = cw.adjustedControlFrame(combo->rect); - cb.frame = frameRect.toCGRect(); - - // This API was requested to Apple in rdar #36197888. We know it's safe to use up to macOS 10.13.3 - if (NSButtonCell *cell = static_cast([cc.cell qt_valueForPrivateKey:@"_buttonCell"])) { - cell.highlighted = isPressed; - } else { - // TODO Render to pixmap and darken the button manually - } - - d->drawNSViewInRect(cb, frameRect, p, ^(CGContextRef, const CGRect &r) { - // FIXME This is usually drawn in the control's superview, but we wouldn't get inactive look in this case - [cb.cell drawWithFrame:r inView:cb]; - }); - } - - if (combo->state & State_HasFocus) { - // TODO Remove and use QFocusFrame instead. - const int hMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin, combo, widget); - const int vMargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin, combo, widget); - QRectF focusRect; - if (cw.type == QMacStylePrivate::Button_PopupButton) { - focusRect = QRectF::fromCGRect([cc alignmentRectForFrame:cc.frame]); - focusRect -= pullDownButtonShadowMargins[cw.size]; - if (cw.size == QStyleHelper::SizeSmall) - focusRect = focusRect.translated(0, 1); - else if (cw.size == QStyleHelper::SizeMini) - focusRect = focusRect.translated(2, -1); - } else if (cw.type == QMacStylePrivate::ComboBox) { - focusRect = frameRect - comboBoxFocusRingMargins[cw.size]; - } - d->drawFocusRing(p, focusRect, hMargin, vMargin, cw); - } - } - break; -#endif // QT_CONFIG(combobox) - case CC_TitleBar: - if (const auto *titlebar = qstyleoption_cast(opt)) { - const bool isActive = (titlebar->state & State_Active) - && (titlebar->titleBarState & State_Active); - - p->fillRect(opt->rect, Qt::transparent); - p->setRenderHint(QPainter::Antialiasing); - p->setClipRect(opt->rect, Qt::IntersectClip); - - // FIXME A single drawPath() with 0-sized pen - // doesn't look as good as this double fillPath(). - const auto outerFrameRect = QRectF(opt->rect.adjusted(0, 0, 0, opt->rect.height())); - QPainterPath outerFramePath = d->windowPanelPath(outerFrameRect); - p->fillPath(outerFramePath, opt->palette.dark()); - - const auto frameAdjust = 1.0 / p->device()->devicePixelRatioF(); - const auto innerFrameRect = outerFrameRect.adjusted(frameAdjust, frameAdjust, -frameAdjust, 0); - QPainterPath innerFramePath = d->windowPanelPath(innerFrameRect); - if (isActive) { - QLinearGradient g; - g.setStart(QPointF(0, 0)); - g.setFinalStop(QPointF(0, 2 * opt->rect.height())); - g.setColorAt(0, opt->palette.button().color()); - g.setColorAt(1, opt->palette.dark().color()); - p->fillPath(innerFramePath, g); - } else { - p->fillPath(innerFramePath, opt->palette.button()); - } - - if (titlebar->subControls & (SC_TitleBarCloseButton - | SC_TitleBarMaxButton - | SC_TitleBarMinButton - | SC_TitleBarNormalButton)) { - const bool isHovered = (titlebar->state & State_MouseOver); - static const SubControl buttons[] = { - SC_TitleBarCloseButton, SC_TitleBarMinButton, SC_TitleBarMaxButton - }; - for (const auto sc : buttons) { - const auto ct = d->windowButtonCocoaControl(sc); - const auto cw = QMacStylePrivate::CocoaControl(ct, QStyleHelper::SizeLarge); - auto *wb = static_cast(d->cocoaControl(cw)); - wb.enabled = (sc & titlebar->subControls); - [wb highlight:(titlebar->state & State_Sunken) && (sc & titlebar->activeSubControls)]; - Q_UNUSED(isHovered); // FIXME No public API for this - - const auto buttonRect = proxy()->subControlRect(CC_TitleBar, titlebar, sc, widget); - d->drawNSViewInRect(wb, buttonRect, p, ^(CGContextRef, const CGRect &rect) { - auto *wbCell = static_cast(wb.cell); - [wbCell drawWithFrame:rect inView:wb]; - }); - } - } - - if (titlebar->subControls & SC_TitleBarLabel) { - const auto tr = proxy()->subControlRect(CC_TitleBar, titlebar, SC_TitleBarLabel, widget); - if (!titlebar->icon.isNull()) { - const auto iconExtent = proxy()->pixelMetric(PM_SmallIconSize); - const auto iconSize = QSize(iconExtent, iconExtent); - const auto iconPos = tr.x() - titlebar->icon.actualSize(iconSize).width() - qRound(titleBarIconTitleSpacing); - // Only render the icon if it'll be fully visible - if (iconPos < tr.right() - titleBarIconTitleSpacing) - p->drawPixmap(iconPos, tr.y(), titlebar->icon.pixmap(window, iconSize, QIcon::Normal)); - } - - if (!titlebar->text.isEmpty()) - drawItemText(p, tr, Qt::AlignCenter, opt->palette, isActive, titlebar->text, QPalette::Text); - } - } - break; - case CC_GroupBox: - if (const QStyleOptionGroupBox *gb - = qstyleoption_cast(opt)) { - - QStyleOptionGroupBox groupBox(*gb); - const bool flat = groupBox.features & QStyleOptionFrame::Flat; - if (!flat) - groupBox.state |= QStyle::State_Mini; // Force mini-sized checkbox to go with small-sized label - else - groupBox.subControls = groupBox.subControls & ~SC_GroupBoxFrame; // We don't like frames and ugly lines - - const bool didSetFont = widget && widget->testAttribute(Qt::WA_SetFont); - const bool didModifySubControls = !didSetFont && QApplication::desktopSettingsAware(); - if (didModifySubControls) - groupBox.subControls = groupBox.subControls & ~SC_GroupBoxLabel; - QCommonStyle::drawComplexControl(cc, &groupBox, p, widget); - if (didModifySubControls) { - const QRect rect = proxy()->subControlRect(CC_GroupBox, &groupBox, SC_GroupBoxLabel, widget); - const bool rtl = groupBox.direction == Qt::RightToLeft; - const int alignment = Qt::TextHideMnemonic | (rtl ? Qt::AlignRight : Qt::AlignLeft); - const QFont savedFont = p->font(); - if (!flat) - p->setFont(d->smallSystemFont); - proxy()->drawItemText(p, rect, alignment, groupBox.palette, groupBox.state & State_Enabled, groupBox.text, QPalette::WindowText); - if (!flat) - p->setFont(savedFont); - } - } - break; - case CC_ToolButton: - if (const QStyleOptionToolButton *tb - = qstyleoption_cast(opt)) { -#ifndef QT_NO_ACCESSIBILITY - if (QStyleHelper::hasAncestor(opt->styleObject, QAccessible::ToolBar)) { - if (tb->subControls & SC_ToolButtonMenu) { - QStyleOption arrowOpt = *tb; - arrowOpt.rect = proxy()->subControlRect(cc, tb, SC_ToolButtonMenu, widget); - arrowOpt.rect.setY(arrowOpt.rect.y() + arrowOpt.rect.height() / 2); - arrowOpt.rect.setHeight(arrowOpt.rect.height() / 2); - proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget); - } else if ((tb->features & QStyleOptionToolButton::HasMenu) - && (tb->toolButtonStyle != Qt::ToolButtonTextOnly && !tb->icon.isNull())) { - d->drawToolbarButtonArrow(tb, p); - } - if (tb->state & State_On) { - NSView *view = window ? (NSView *)window->winId() : nil; - bool isKey = false; - if (view) - isKey = [view.window isKeyWindow]; - - QBrush brush(isKey ? QColor(0, 0, 0, 28) - : QColor(0, 0, 0, 21)); - QPainterPath path; - path.addRoundedRect(QRectF(tb->rect.x(), tb->rect.y(), tb->rect.width(), tb->rect.height() + 4), 4, 4); - p->setRenderHint(QPainter::Antialiasing); - p->fillPath(path, brush); - } - proxy()->drawControl(CE_ToolButtonLabel, opt, p, widget); - } else -#endif // QT_NO_ACCESSIBILITY - { - auto bflags = tb->state; - if (tb->subControls & SC_ToolButton) - bflags |= State_Sunken; - auto mflags = tb->state; - if (tb->subControls & SC_ToolButtonMenu) - mflags |= State_Sunken; - - if (tb->subControls & SC_ToolButton) { - if (bflags & (State_Sunken | State_On | State_Raised)) { - const bool isEnabled = tb->state & State_Enabled; - const bool isPressed = tb->state & State_Sunken; - const bool isHighlighted = (tb->state & State_Active) && (tb->state & State_On); - const auto ct = QMacStylePrivate::Button_PushButton; - const auto cs = d->effectiveAquaSizeConstrain(opt, widget); - const auto cw = QMacStylePrivate::CocoaControl(ct, cs); - auto *pb = static_cast(d->cocoaControl(cw)); - pb.bezelStyle = NSShadowlessSquareBezelStyle; // TODO Use NSTexturedRoundedBezelStyle in the future. - pb.frame = opt->rect.toCGRect(); - pb.buttonType = NSPushOnPushOffButton; - pb.enabled = isEnabled; - [pb highlight:isPressed]; - pb.state = isHighlighted && !isPressed ? NSOnState : NSOffState; - const auto buttonRect = proxy()->subControlRect(cc, tb, SC_ToolButton, widget); - d->drawNSViewInRect(pb, buttonRect, p, ^(CGContextRef, const CGRect &rect) { - [pb.cell drawBezelWithFrame:rect inView:pb]; - }); - } - } - - if (tb->subControls & SC_ToolButtonMenu) { - const auto menuRect = proxy()->subControlRect(cc, tb, SC_ToolButtonMenu, widget); - QStyleOption arrowOpt = *tb; - arrowOpt.rect = QRect(menuRect.x() + ((menuRect.width() - toolButtonArrowSize) / 2), - menuRect.height() - (toolButtonArrowSize + toolButtonArrowMargin), - toolButtonArrowSize, - toolButtonArrowSize); - proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget); - } else if (tb->features & QStyleOptionToolButton::HasMenu) { - d->drawToolbarButtonArrow(tb, p); - } - QRect buttonRect = proxy()->subControlRect(CC_ToolButton, tb, SC_ToolButton, widget); - int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget); - QStyleOptionToolButton label = *tb; - label.rect = buttonRect.adjusted(fw, fw, -fw, -fw); - proxy()->drawControl(CE_ToolButtonLabel, &label, p, widget); - } - } - break; -#if QT_CONFIG(dial) - case CC_Dial: - if (const QStyleOptionSlider *dial = qstyleoption_cast(opt)) - QStyleHelper::drawDial(dial, p); - break; -#endif - default: - QCommonStyle::drawComplexControl(cc, opt, p, widget); - break; - } -} - -QStyle::SubControl QMacStyle::hitTestComplexControl(ComplexControl cc, - const QStyleOptionComplex *opt, - const QPoint &pt, const QWidget *widget) const -{ - Q_D(const QMacStyle); - SubControl sc = QStyle::SC_None; - switch (cc) { - case CC_ComboBox: - if (const QStyleOptionComboBox *cmb = qstyleoption_cast(opt)) { - sc = QCommonStyle::hitTestComplexControl(cc, cmb, pt, widget); - if (!cmb->editable && sc != QStyle::SC_None) - sc = SC_ComboBoxArrow; // A bit of a lie, but what we want - } - break; - case CC_Slider: - if (const QStyleOptionSlider *sl = qstyleoption_cast(opt)) { - if (!sl->rect.contains(pt)) - break; - - const bool hasTicks = sl->tickPosition != QSlider::NoTicks; - const bool isHorizontal = sl->orientation == Qt::Horizontal; - const auto ct = isHorizontal ? QMacStylePrivate::Slider_Horizontal : QMacStylePrivate::Slider_Vertical; - const auto cs = d->effectiveAquaSizeConstrain(opt, widget); - const auto cw = QMacStylePrivate::CocoaControl(ct, cs); - auto *slider = static_cast(d->cocoaControl(cw)); - if (!setupSlider(slider, sl)) - break; - - [slider calcSize]; - NSSliderCell *cell = slider.cell; - const auto barRect = QRectF::fromCGRect([cell barRectFlipped:hasTicks]); - const auto knobRect = QRectF::fromCGRect([cell knobRectFlipped:NO]); - if (knobRect.contains(pt)) { - sc = SC_SliderHandle; - } else if (barRect.contains(pt)) { - sc = SC_SliderGroove; - } else if (hasTicks) { - sc = SC_SliderTickmarks; - } - } - break; - case CC_ScrollBar: - if (const QStyleOptionSlider *sb = qstyleoption_cast(opt)) { - if (!sb->rect.contains(pt)) { - sc = SC_None; - break; - } - - const bool isHorizontal = sb->orientation == Qt::Horizontal; - const auto ct = isHorizontal ? QMacStylePrivate::Scroller_Horizontal : QMacStylePrivate::Scroller_Vertical; - const auto cs = d->effectiveAquaSizeConstrain(opt, widget); - const auto cw = QMacStylePrivate::CocoaControl(ct, cs); - auto *scroller = static_cast(d->cocoaControl(cw)); - if (!setupScroller(scroller, sb)) { - sc = SC_None; - break; - } - - // Since -[NSScroller testPart:] doesn't want to cooperate, we do it the - // straightforward way. In any case, macOS doesn't return line-sized changes - // with NSScroller since 10.7, according to the aforementioned method's doc. - const auto knobRect = QRectF::fromCGRect([scroller rectForPart:NSScrollerKnob]); - if (isHorizontal) { - const bool isReverse = sb->direction == Qt::RightToLeft; - if (pt.x() < knobRect.left()) - sc = isReverse ? SC_ScrollBarAddPage : SC_ScrollBarSubPage; - else if (pt.x() > knobRect.right()) - sc = isReverse ? SC_ScrollBarSubPage : SC_ScrollBarAddPage; - else - sc = SC_ScrollBarSlider; - } else { - if (pt.y() < knobRect.top()) - sc = SC_ScrollBarSubPage; - else if (pt.y() > knobRect.bottom()) - sc = SC_ScrollBarAddPage; - else - sc = SC_ScrollBarSlider; - } - } - break; - default: - sc = QCommonStyle::hitTestComplexControl(cc, opt, pt, widget); - break; - } - return sc; -} - -QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc, - const QWidget *widget) const -{ - Q_D(const QMacStyle); - QRect ret; - switch (cc) { - case CC_ScrollBar: - if (const QStyleOptionSlider *sb = qstyleoption_cast(opt)) { - const bool isHorizontal = sb->orientation == Qt::Horizontal; - const bool isReverseHorizontal = isHorizontal && (sb->direction == Qt::RightToLeft); - - NSScrollerPart part = NSScrollerNoPart; - if (sc == SC_ScrollBarSlider) { - part = NSScrollerKnob; - } else if (sc == SC_ScrollBarGroove) { - part = NSScrollerKnobSlot; - } else if (sc == SC_ScrollBarSubPage || sc == SC_ScrollBarAddPage) { - if ((!isReverseHorizontal && sc == SC_ScrollBarSubPage) - || (isReverseHorizontal && sc == SC_ScrollBarAddPage)) - part = NSScrollerDecrementPage; - else - part = NSScrollerIncrementPage; - } - // And nothing else since 10.7 - - if (part != NSScrollerNoPart) { - const auto ct = isHorizontal ? QMacStylePrivate::Scroller_Horizontal : QMacStylePrivate::Scroller_Vertical; - const auto cs = d->effectiveAquaSizeConstrain(opt, widget); - const auto cw = QMacStylePrivate::CocoaControl(ct, cs); - auto *scroller = static_cast(d->cocoaControl(cw)); - if (setupScroller(scroller, sb)) - ret = QRectF::fromCGRect([scroller rectForPart:part]).toRect(); - } - } - break; - case CC_Slider: - if (const QStyleOptionSlider *sl = qstyleoption_cast(opt)) { - const bool hasTicks = sl->tickPosition != QSlider::NoTicks; - const bool isHorizontal = sl->orientation == Qt::Horizontal; - const auto ct = isHorizontal ? QMacStylePrivate::Slider_Horizontal : QMacStylePrivate::Slider_Vertical; - const auto cs = d->effectiveAquaSizeConstrain(opt, widget); - const auto cw = QMacStylePrivate::CocoaControl(ct, cs); - auto *slider = static_cast(d->cocoaControl(cw)); - if (!setupSlider(slider, sl)) - break; - - [slider calcSize]; - NSSliderCell *cell = slider.cell; - if (sc == SC_SliderHandle) { - ret = QRectF::fromCGRect([cell knobRectFlipped:NO]).toRect(); - if (isHorizontal) { - ret.setTop(sl->rect.top()); - ret.setBottom(sl->rect.bottom()); - } else { - ret.setLeft(sl->rect.left()); - ret.setRight(sl->rect.right()); - } - } else if (sc == SC_SliderGroove) { - ret = QRectF::fromCGRect([cell barRectFlipped:hasTicks]).toRect(); - } else if (hasTicks && sc == SC_SliderTickmarks) { - const auto tickMarkRect = QRectF::fromCGRect([cell rectOfTickMarkAtIndex:0]); - if (isHorizontal) - ret = QRect(sl->rect.left(), tickMarkRect.top(), sl->rect.width(), tickMarkRect.height()); - else - ret = QRect(tickMarkRect.left(), sl->rect.top(), tickMarkRect.width(), sl->rect.height()); - } - - // Invert if needed and extend to the actual bounds of the slider - if (isHorizontal) { - if (sl->upsideDown) { - ret = QRect(sl->rect.right() - ret.right(), sl->rect.top(), ret.width(), sl->rect.height()); - } else { - ret.setTop(sl->rect.top()); - ret.setBottom(sl->rect.bottom()); - } - } else { - if (!sl->upsideDown) { - ret = QRect(sl->rect.left(), sl->rect.bottom() - ret.bottom(), sl->rect.width(), ret.height()); - } else { - ret.setLeft(sl->rect.left()); - ret.setRight(sl->rect.right()); - } - } - } - break; - case CC_TitleBar: - if (const auto *titlebar = qstyleoption_cast(opt)) { - // The title bar layout is as follows: close, min, zoom, icon, title - // [ x _ + @ Window Title ] - // Center the icon and title until it starts to overlap with the buttons. - // The icon doesn't count towards SC_TitleBarLabel, but it's still rendered - // next to the title text. See drawComplexControl(). - if (sc == SC_TitleBarLabel) { - qreal labelWidth = titlebar->fontMetrics.horizontalAdvance(titlebar->text) + 1; // FIXME Rounding error? - qreal labelHeight = titlebar->fontMetrics.height(); - - const auto lastButtonRect = proxy()->subControlRect(CC_TitleBar, titlebar, SC_TitleBarMaxButton, widget); - qreal controlsSpacing = lastButtonRect.right() + titleBarButtonSpacing; - if (!titlebar->icon.isNull()) { - const auto iconSize = proxy()->pixelMetric(PM_SmallIconSize); - const auto actualIconSize = titlebar->icon.actualSize(QSize(iconSize, iconSize)).width();; - controlsSpacing += actualIconSize + titleBarIconTitleSpacing; - } - - const qreal labelPos = qMax(controlsSpacing, (opt->rect.width() - labelWidth) / 2.0); - labelWidth = qMin(labelWidth, opt->rect.width() - (labelPos + titleBarTitleRightMargin)); - ret = QRect(labelPos, (opt->rect.height() - labelHeight) / 2, - labelWidth, labelHeight); - } else { - const auto currentButton = d->windowButtonCocoaControl(sc); - if (currentButton == QMacStylePrivate::NoControl) - break; - - QPointF buttonPos = titlebar->rect.topLeft() + QPointF(titleBarButtonSpacing, 0); - QSizeF buttonSize; - for (int ct = QMacStylePrivate::Button_WindowClose; ct <= currentButton; ct++) { - const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::CocoaControlType(ct), - QStyleHelper::SizeLarge); - auto *wb = static_cast(d->cocoaControl(cw)); - if (ct == currentButton) - buttonSize = QSizeF::fromCGSize(wb.frame.size); - else - buttonPos.rx() += wb.frame.size.width + titleBarButtonSpacing; - } - - const auto vOffset = (opt->rect.height() - buttonSize.height()) / 2.0; - ret = QRectF(buttonPos, buttonSize).translated(0, vOffset).toRect(); - } - } - break; - case CC_ComboBox: - if (const QStyleOptionComboBox *combo = qstyleoption_cast(opt)) { - const auto ct = cocoaControlType(combo, widget); - const auto cs = d->effectiveAquaSizeConstrain(combo, widget); - const auto cw = QMacStylePrivate::CocoaControl(ct, cs); - const auto editRect = QMacStylePrivate::comboboxEditBounds(cw.adjustedControlFrame(combo->rect), cw); - - switch (sc) { - case SC_ComboBoxEditField:{ - ret = editRect.toAlignedRect(); - break; } - case SC_ComboBoxArrow:{ - ret = editRect.toAlignedRect(); - ret.setX(ret.x() + ret.width()); - ret.setWidth(combo->rect.right() - ret.right()); - break; } - case SC_ComboBoxListBoxPopup:{ - if (combo->editable) { - const CGRect inner = QMacStylePrivate::comboboxInnerBounds(combo->rect.toCGRect(), cw); - const int comboTop = combo->rect.top(); - ret = QRect(qRound(inner.origin.x), - comboTop, - qRound(inner.origin.x - combo->rect.left() + inner.size.width), - editRect.bottom() - comboTop + 2); - } else { - ret = QRect(combo->rect.x() + 4 - 11, - combo->rect.y() + 1, - editRect.width() + 10 + 11, - 1); - } - break; } - default: - break; - } - } - break; - case CC_GroupBox: - if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast(opt)) { - bool checkable = groupBox->subControls & SC_GroupBoxCheckBox; - const bool flat = groupBox->features & QStyleOptionFrame::Flat; - bool hasNoText = !checkable && groupBox->text.isEmpty(); - switch (sc) { - case SC_GroupBoxLabel: - case SC_GroupBoxCheckBox: { - // Cheat and use the smaller font if we need to - const bool checkable = groupBox->subControls & SC_GroupBoxCheckBox; - const bool fontIsSet = (widget && widget->testAttribute(Qt::WA_SetFont)) - || !QApplication::desktopSettingsAware(); - const int margin = flat || hasNoText ? 0 : 9; - ret = groupBox->rect.adjusted(margin, 0, -margin, 0); - - const QFontMetricsF fm = flat || fontIsSet ? QFontMetricsF(groupBox->fontMetrics) : QFontMetricsF(d->smallSystemFont); - const QSizeF s = fm.size(Qt::AlignHCenter | Qt::AlignVCenter, qt_mac_removeMnemonics(groupBox->text), 0, nullptr); - const int tw = qCeil(s.width()); - const int h = qCeil(fm.height()); - ret.setHeight(h); - - QRect labelRect = alignedRect(groupBox->direction, groupBox->textAlignment, - QSize(tw, h), ret); - if (flat && checkable) - labelRect.moveLeft(labelRect.left() + 4); - int indicatorWidth = proxy()->pixelMetric(PM_IndicatorWidth, opt, widget); - bool rtl = groupBox->direction == Qt::RightToLeft; - if (sc == SC_GroupBoxLabel) { - if (checkable) { - int newSum = indicatorWidth + 1; - int newLeft = labelRect.left() + (rtl ? -newSum : newSum); - labelRect.moveLeft(newLeft); - if (flat) - labelRect.moveTop(labelRect.top() + 3); - else - labelRect.moveTop(labelRect.top() + 4); - } else if (flat) { - int newLeft = labelRect.left() - (rtl ? 3 : -3); - labelRect.moveLeft(newLeft); - labelRect.moveTop(labelRect.top() + 3); - } else { - int newLeft = labelRect.left() - (rtl ? 3 : 2); - labelRect.moveLeft(newLeft); - labelRect.moveTop(labelRect.top() + 4); - } - ret = labelRect; - } - - if (sc == SC_GroupBoxCheckBox) { - int left = rtl ? labelRect.right() - indicatorWidth : labelRect.left() - 1; - int top = flat ? ret.top() + 1 : ret.top() + 5; - ret.setRect(left, top, - indicatorWidth, proxy()->pixelMetric(PM_IndicatorHeight, opt, widget)); - } - break; - } - case SC_GroupBoxContents: - case SC_GroupBoxFrame: { - QFontMetrics fm = groupBox->fontMetrics; - int yOffset = 3; - if (!flat) { - if (widget && !widget->testAttribute(Qt::WA_SetFont) - && QApplication::desktopSettingsAware()) - fm = QFontMetrics(qt_app_fonts_hash()->value("QSmallFont", QFont())); - yOffset = 5; - } - - if (hasNoText) - yOffset = -qCeil(QFontMetricsF(fm).height()); - ret = opt->rect.adjusted(0, qCeil(QFontMetricsF(fm).height()) + yOffset, 0, 0); - if (sc == SC_GroupBoxContents) { - if (flat) - ret.adjust(3, -5, -3, -4); // guess too - else - ret.adjust(3, 3, -3, -4); // guess - } - } - break; - default: - ret = QCommonStyle::subControlRect(cc, groupBox, sc, widget); - break; - } - } - break; -#if QT_CONFIG(spinbox) - case CC_SpinBox: - if (const QStyleOptionSpinBox *spin = qstyleoption_cast(opt)) { - QStyleHelper::WidgetSizePolicy aquaSize = d->effectiveAquaSizeConstrain(spin, widget); - const auto fw = proxy()->pixelMetric(PM_SpinBoxFrameWidth, spin, widget); - int spinner_w; - int spinBoxSep; - switch (aquaSize) { - case QStyleHelper::SizeLarge: - spinner_w = 14; - spinBoxSep = 2; - break; - case QStyleHelper::SizeSmall: - spinner_w = 12; - spinBoxSep = 2; - break; - case QStyleHelper::SizeMini: - spinner_w = 10; - spinBoxSep = 1; - break; - default: - Q_UNREACHABLE(); - } - - switch (sc) { - case SC_SpinBoxUp: - case SC_SpinBoxDown: { - if (spin->buttonSymbols == QAbstractSpinBox::NoButtons) - break; - - const int y = fw; - const int x = spin->rect.width() - spinner_w; - ret.setRect(x + spin->rect.x(), y + spin->rect.y(), spinner_w, spin->rect.height() - y * 2); - int hackTranslateX; - switch (aquaSize) { - case QStyleHelper::SizeLarge: - hackTranslateX = 0; - break; - case QStyleHelper::SizeSmall: - hackTranslateX = -2; - break; - case QStyleHelper::SizeMini: - hackTranslateX = -1; - break; - default: - Q_UNREACHABLE(); - } - - const auto cw = QMacStylePrivate::CocoaControl(QMacStylePrivate::Stepper, aquaSize); - NSStepperCell *cell = static_cast(d->cocoaCell(cw)); - const CGRect outRect = [cell drawingRectForBounds:ret.toCGRect()]; - ret = QRectF::fromCGRect(outRect).toRect(); - - switch (sc) { - case SC_SpinBoxUp: - ret.setHeight(ret.height() / 2); - break; - case SC_SpinBoxDown: - ret.setY(ret.y() + ret.height() / 2); - break; - default: - Q_ASSERT(0); - break; - } - ret.translate(hackTranslateX, 0); // hack: position the buttons correctly (weird that we need this) - ret = visualRect(spin->direction, spin->rect, ret); - break; - } - case SC_SpinBoxEditField: - ret = spin->rect.adjusted(fw, fw, -fw, -fw); - if (spin->buttonSymbols != QAbstractSpinBox::NoButtons) { - ret.setWidth(spin->rect.width() - spinBoxSep - spinner_w); - ret = visualRect(spin->direction, spin->rect, ret); - } - break; - default: - ret = QCommonStyle::subControlRect(cc, spin, sc, widget); - break; - } - } - break; -#endif - case CC_ToolButton: - ret = QCommonStyle::subControlRect(cc, opt, sc, widget); - if (sc == SC_ToolButtonMenu) { -#ifndef QT_NO_ACCESSIBILITY - if (QStyleHelper::hasAncestor(opt->styleObject, QAccessible::ToolBar)) - ret.adjust(-toolButtonArrowMargin, 0, 0, 0); -#endif - ret.adjust(-1, 0, 0, 0); - } - break; - default: - ret = QCommonStyle::subControlRect(cc, opt, sc, widget); - break; - } - return ret; -} - -QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt, - const QSize &csz, const QWidget *widget) const -{ - Q_D(const QMacStyle); - QSize sz(csz); - bool useAquaGuideline = true; - - switch (ct) { -#if QT_CONFIG(spinbox) - case CT_SpinBox: - if (const QStyleOptionSpinBox *vopt = qstyleoption_cast(opt)) { - const bool hasButtons = (vopt->buttonSymbols != QAbstractSpinBox::NoButtons); - const int buttonWidth = hasButtons ? proxy()->subControlRect(CC_SpinBox, vopt, SC_SpinBoxUp, widget).width() : 0; - sz += QSize(buttonWidth, 0); - } - break; -#endif - case QStyle::CT_TabWidget: - // the size between the pane and the "contentsRect" (+4,+4) - // (the "contentsRect" is on the inside of the pane) - sz = QCommonStyle::sizeFromContents(ct, opt, csz, widget); - /** - This is supposed to show the relationship between the tabBar and - the stack widget of a QTabWidget. - Unfortunately ascii is not a good way of representing graphics..... - PS: The '=' line is the painted frame. - - top ---+ - | - | - | - | vvv just outside the painted frame is the "pane" - - -|- - - - - - - - - - <-+ - TAB BAR +=====^============ | +2 pixels - - - -|- - -|- - - - - - - <-+ - | | ^ ^^^ just inside the painted frame is the "contentsRect" - | | | - | overlap | - | | | - bottom ------+ <-+ +14 pixels - | - v - ------------------------------ <- top of stack widget - - - To summarize: - * 2 is the distance between the pane and the contentsRect - * The 14 and the 1's are the distance from the contentsRect to the stack widget. - (same value as used in SE_TabWidgetTabContents) - * overlap is how much the pane should overlap the tab bar - */ - // then add the size between the stackwidget and the "contentsRect" -#if QT_CONFIG(tabwidget) - if (const QStyleOptionTabWidgetFrame *twf - = qstyleoption_cast(opt)) { - QSize extra(0,0); - const int overlap = pixelMetric(PM_TabBarBaseOverlap, opt, widget); - const int gapBetweenTabbarAndStackWidget = 2 + 14 - overlap; - - const auto tabDirection = QMacStylePrivate::tabDirection(twf->shape); - if (tabDirection == QMacStylePrivate::North - || tabDirection == QMacStylePrivate::South) { - extra = QSize(2, gapBetweenTabbarAndStackWidget + 1); - } else { - extra = QSize(gapBetweenTabbarAndStackWidget + 1, 2); - } - sz+= extra; - } -#endif - break; -#if QT_CONFIG(tabbar) - case QStyle::CT_TabBarTab: - if (const QStyleOptionTab *tab = qstyleoption_cast(opt)) { - const bool differentFont = (widget && widget->testAttribute(Qt::WA_SetFont)) - || !QApplication::desktopSettingsAware(); - const auto tabDirection = QMacStylePrivate::tabDirection(tab->shape); - const bool verticalTabs = tabDirection == QMacStylePrivate::East - || tabDirection == QMacStylePrivate::West; - if (verticalTabs) - sz = sz.transposed(); - - int defaultTabHeight; - const auto cs = d->effectiveAquaSizeConstrain(opt, widget); - switch (cs) { - case QStyleHelper::SizeLarge: - if (tab->documentMode) - defaultTabHeight = 24; - else - defaultTabHeight = 21; - break; - case QStyleHelper::SizeSmall: - defaultTabHeight = 18; - break; - case QStyleHelper::SizeMini: - defaultTabHeight = 16; - break; - default: - break; - } - - const bool widthSet = !differentFont && tab->icon.isNull(); - if (widthSet) { - const auto textSize = opt->fontMetrics.size(Qt::TextShowMnemonic, tab->text); - sz.rwidth() = textSize.width(); - sz.rheight() = qMax(defaultTabHeight, textSize.height()); - } else { - sz.rheight() = qMax(defaultTabHeight, sz.height()); - } - sz.rwidth() += proxy()->pixelMetric(PM_TabBarTabHSpace, tab, widget); - - if (verticalTabs) - sz = sz.transposed(); - - int maxWidgetHeight = qMax(tab->leftButtonSize.height(), tab->rightButtonSize.height()); - int maxWidgetWidth = qMax(tab->leftButtonSize.width(), tab->rightButtonSize.width()); - - int widgetWidth = 0; - int widgetHeight = 0; - int padding = 0; - if (tab->leftButtonSize.isValid()) { - padding += 8; - widgetWidth += tab->leftButtonSize.width(); - widgetHeight += tab->leftButtonSize.height(); - } - if (tab->rightButtonSize.isValid()) { - padding += 8; - widgetWidth += tab->rightButtonSize.width(); - widgetHeight += tab->rightButtonSize.height(); - } - - if (verticalTabs) { - sz.setWidth(qMax(sz.width(), maxWidgetWidth)); - sz.setHeight(sz.height() + widgetHeight + padding); - } else { - if (widthSet) - sz.setWidth(sz.width() + widgetWidth + padding); - sz.setHeight(qMax(sz.height(), maxWidgetHeight)); - } - } - break; -#endif - case QStyle::CT_PushButton: { - if (const QStyleOptionButton *btn = qstyleoption_cast(opt)) - if (btn->features & QStyleOptionButton::CommandLinkButton) - return QCommonStyle::sizeFromContents(ct, opt, sz, widget); - - // By default, we fit the contents inside a normal rounded push button. - // Do this by add enough space around the contents so that rounded - // borders (including highlighting when active) will show. - // TODO Use QFocusFrame and get rid of these horrors. - QSize macsz; - const auto controlSize = d->effectiveAquaSizeConstrain(opt, widget, CT_PushButton, sz, &macsz); - // FIXME See comment in CT_PushButton case in qt_aqua_get_known_size(). - if (macsz.width() != -1) - sz.setWidth(macsz.width()); - else - sz.rwidth() += QMacStylePrivate::PushButtonLeftOffset + QMacStylePrivate::PushButtonRightOffset + 12; - // All values as measured from HIThemeGetButtonBackgroundBounds() - if (controlSize != QStyleHelper::SizeMini) - sz.rwidth() += 12; // We like 12 over here. - if (controlSize == QStyleHelper::SizeLarge && sz.height() > 16) - sz.rheight() += pushButtonDefaultHeight[QStyleHelper::SizeLarge] - 16; - else if (controlSize == QStyleHelper::SizeMini) - sz.setHeight(24); // FIXME Our previous HITheme-based logic returned this. - else - sz.setHeight(pushButtonDefaultHeight[controlSize]); - break; - } - case QStyle::CT_MenuItem: - if (const QStyleOptionMenuItem *mi = qstyleoption_cast(opt)) { - int maxpmw = mi->maxIconWidth; -#if QT_CONFIG(combobox) - const QComboBox *comboBox = qobject_cast(widget); -#endif - int w = sz.width(), - h = sz.height(); - if (mi->menuItemType == QStyleOptionMenuItem::Separator) { - w = 10; - h = qt_mac_aqua_get_metric(MenuSeparatorHeight); - } else { - h = mi->fontMetrics.height() + 2; - if (!mi->icon.isNull()) { -#if QT_CONFIG(combobox) - if (comboBox) { - const QSize &iconSize = comboBox->iconSize(); - h = qMax(h, iconSize.height() + 4); - maxpmw = qMax(maxpmw, iconSize.width()); - } else -#endif - { - int iconExtent = proxy()->pixelMetric(PM_SmallIconSize); - h = qMax(h, mi->icon.actualSize(QSize(iconExtent, iconExtent)).height() + 4); - } - } - } - if (mi->text.contains(QLatin1Char('\t'))) - w += 12; - else if (mi->menuItemType == QStyleOptionMenuItem::SubMenu) - w += 35; // Not quite exactly as it seems to depend on other factors - if (maxpmw) - w += maxpmw + 6; - // add space for a check. All items have place for a check too. - w += 20; -#if QT_CONFIG(combobox) - if (comboBox && comboBox->isVisible()) { - QStyleOptionComboBox cmb; - cmb.initFrom(comboBox); - cmb.editable = false; - cmb.subControls = QStyle::SC_ComboBoxEditField; - cmb.activeSubControls = QStyle::SC_None; - w = qMax(w, subControlRect(QStyle::CC_ComboBox, &cmb, - QStyle::SC_ComboBoxEditField, - comboBox).width()); - } else -#endif - { - w += 12; - } - sz = QSize(w, h); - } - break; - case CT_MenuBarItem: - if (!sz.isEmpty()) - sz += QSize(12, 4); // Constants from QWindowsStyle - break; - case CT_ToolButton: - sz.rwidth() += 10; - sz.rheight() += 10; - if (const auto *tb = qstyleoption_cast(opt)) - if (tb->features & QStyleOptionToolButton::Menu) - sz.rwidth() += toolButtonArrowMargin; - return sz; - case CT_ComboBox: - if (const auto *cb = qstyleoption_cast(opt)) { - const auto controlSize = d->effectiveAquaSizeConstrain(opt, widget); - if (!cb->editable) { - // Same as CT_PushButton, because we have to fit the focus - // ring and a non-editable combo box is a NSPopUpButton. - sz.rwidth() += QMacStylePrivate::PushButtonLeftOffset + QMacStylePrivate::PushButtonRightOffset + 12; - // All values as measured from HIThemeGetButtonBackgroundBounds() - if (controlSize != QStyleHelper::SizeMini) - sz.rwidth() += 12; // We like 12 over here. -#if 0 - // TODO Maybe support square combo boxes - if (controlSize == QStyleHelper::SizeLarge && sz.height() > 16) - sz.rheight() += popupButtonDefaultHeight[QStyleHelper::SizeLarge] - 16; - else -#endif - } else { - sz.rwidth() += 50; // FIXME Double check this - } - - // This should be enough to fit the focus ring - if (controlSize == QStyleHelper::SizeMini) - sz.setHeight(24); // FIXME Our previous HITheme-based logic returned this for CT_PushButton. - else - sz.setHeight(pushButtonDefaultHeight[controlSize]); - - return sz; - } - break; - case CT_Menu: { - if (proxy() == this) { - sz = csz; - } else { - QStyleHintReturnMask menuMask; - QStyleOption myOption = *opt; - myOption.rect.setSize(sz); - if (proxy()->styleHint(SH_Menu_Mask, &myOption, widget, &menuMask)) - sz = menuMask.region.boundingRect().size(); - } - break; } - case CT_HeaderSection:{ - const QStyleOptionHeader *header = qstyleoption_cast(opt); - sz = QCommonStyle::sizeFromContents(ct, opt, csz, widget); - if (header->text.contains(QLatin1Char('\n'))) - useAquaGuideline = false; - break; } - case CT_ScrollBar : - // Make sure that the scroll bar is large enough to display the thumb indicator. - if (const QStyleOptionSlider *slider = qstyleoption_cast(opt)) { - const int minimumSize = 24; // Smallest knob size, but Cocoa doesn't seem to care - if (slider->orientation == Qt::Horizontal) - sz = sz.expandedTo(QSize(minimumSize, sz.height())); - else - sz = sz.expandedTo(QSize(sz.width(), minimumSize)); - } - break; - case CT_ItemViewItem: - if (const QStyleOptionViewItem *vopt = qstyleoption_cast(opt)) { - sz = QCommonStyle::sizeFromContents(ct, vopt, csz, widget); - sz.setHeight(sz.height() + 2); - } - break; - - default: - sz = QCommonStyle::sizeFromContents(ct, opt, csz, widget); - } - - if (useAquaGuideline && ct != CT_PushButton) { - // TODO Probably going away at some point - QSize macsz; - if (d->aquaSizeConstrain(opt, widget, ct, sz, &macsz) != QStyleHelper::SizeDefault) { - if (macsz.width() != -1) - sz.setWidth(macsz.width()); - if (macsz.height() != -1) - sz.setHeight(macsz.height()); - } - } - - // The sizes that Carbon and the guidelines gives us excludes the focus frame. - // We compensate for this by adding some extra space here to make room for the frame when drawing: - if (const QStyleOptionComboBox *combo = qstyleoption_cast(opt)){ - if (combo->editable) { - const auto widgetSize = d->aquaSizeConstrain(opt, widget); - QMacStylePrivate::CocoaControl cw; - cw.type = combo->editable ? QMacStylePrivate::ComboBox : QMacStylePrivate::Button_PopupButton; - cw.size = widgetSize; - const CGRect diffRect = QMacStylePrivate::comboboxInnerBounds(CGRectZero, cw); - sz.rwidth() -= qRound(diffRect.size.width); - sz.rheight() -= qRound(diffRect.size.height); - } - } - return sz; -} - -void QMacStyle::drawItemText(QPainter *p, const QRect &r, int flags, const QPalette &pal, - bool enabled, const QString &text, QPalette::ColorRole textRole) const -{ - if(flags & Qt::TextShowMnemonic) - flags |= Qt::TextHideMnemonic; - QCommonStyle::drawItemText(p, r, flags, pal, enabled, text, textRole); -} - -bool QMacStyle::event(QEvent *e) -{ - Q_D(QMacStyle); - if(e->type() == QEvent::FocusIn) { - QWidget *f = 0; - QWidget *focusWidget = QApplication::focusWidget(); -#if QT_CONFIG(graphicsview) - if (QGraphicsView *graphicsView = qobject_cast(focusWidget)) { - QGraphicsItem *focusItem = graphicsView->scene() ? graphicsView->scene()->focusItem() : 0; - if (focusItem && focusItem->type() == QGraphicsProxyWidget::Type) { - QGraphicsProxyWidget *proxy = static_cast(focusItem); - if (proxy->widget()) - focusWidget = proxy->widget()->focusWidget(); - } - } -#endif - - if (focusWidget && focusWidget->testAttribute(Qt::WA_MacShowFocusRect)) { -#if QT_CONFIG(spinbox) - if (const auto sb = qobject_cast(focusWidget)) - f = sb->property("_q_spinbox_lineedit").value(); - else -#endif - f = focusWidget; - } - if (f) { - if(!d->focusWidget) - d->focusWidget = new QFocusFrame(f); - d->focusWidget->setWidget(f); - } else if(d->focusWidget) { - d->focusWidget->setWidget(0); - } - } else if(e->type() == QEvent::FocusOut) { - if(d->focusWidget) - d->focusWidget->setWidget(0); - } - return false; -} - -QIcon QMacStyle::standardIcon(StandardPixmap standardIcon, const QStyleOption *opt, - const QWidget *widget) const -{ - switch (standardIcon) { - default: - return QCommonStyle::standardIcon(standardIcon, opt, widget); - case SP_ToolBarHorizontalExtensionButton: - case SP_ToolBarVerticalExtensionButton: { - QPixmap pixmap(QLatin1String(":/qt-project.org/styles/macstyle/images/toolbar-ext.png")); - if (standardIcon == SP_ToolBarVerticalExtensionButton) { - QPixmap pix2(pixmap.height(), pixmap.width()); - pix2.setDevicePixelRatio(pixmap.devicePixelRatio()); - pix2.fill(Qt::transparent); - QPainter p(&pix2); - p.translate(pix2.width(), 0); - p.rotate(90); - p.drawPixmap(0, 0, pixmap); - return pix2; - } - return pixmap; - } - } -} - -int QMacStyle::layoutSpacing(QSizePolicy::ControlType control1, - QSizePolicy::ControlType control2, - Qt::Orientation orientation, - const QStyleOption *option, - const QWidget *widget) const -{ - const int ButtonMask = QSizePolicy::ButtonBox | QSizePolicy::PushButton; - const int controlSize = getControlSize(option, widget); - - if (control2 == QSizePolicy::ButtonBox) { - /* - AHIG seems to prefer a 12-pixel margin between group - boxes and the row of buttons. The 20 pixel comes from - Builder. - */ - if (control1 & (QSizePolicy::Frame // guess - | QSizePolicy::GroupBox // (AHIG, guess, guess) - | QSizePolicy::TabWidget // guess - | ButtonMask)) { // AHIG - return_SIZE(14, 8, 8); - } else if (control1 == QSizePolicy::LineEdit) { - return_SIZE(8, 8, 8); // Interface Builder - } else { - return_SIZE(20, 7, 7); // Interface Builder - } - } - - if ((control1 | control2) & ButtonMask) { - if (control1 == QSizePolicy::LineEdit) - return_SIZE(8, 8, 8); // Interface Builder - else if (control2 == QSizePolicy::LineEdit) { - if (orientation == Qt::Vertical) - return_SIZE(20, 7, 7); // Interface Builder - else - return_SIZE(20, 8, 8); - } - return_SIZE(14, 8, 8); // Interface Builder - } - - switch (CT2(control1, control2)) { - case CT1(QSizePolicy::Label): // guess - case CT2(QSizePolicy::Label, QSizePolicy::DefaultType): // guess - case CT2(QSizePolicy::Label, QSizePolicy::CheckBox): // AHIG - case CT2(QSizePolicy::Label, QSizePolicy::ComboBox): // AHIG - case CT2(QSizePolicy::Label, QSizePolicy::LineEdit): // guess - case CT2(QSizePolicy::Label, QSizePolicy::RadioButton): // AHIG - case CT2(QSizePolicy::Label, QSizePolicy::Slider): // guess - case CT2(QSizePolicy::Label, QSizePolicy::SpinBox): // guess - case CT2(QSizePolicy::Label, QSizePolicy::ToolButton): // guess - return_SIZE(8, 6, 5); - case CT1(QSizePolicy::ToolButton): - return 8; // AHIG - case CT1(QSizePolicy::CheckBox): - case CT2(QSizePolicy::CheckBox, QSizePolicy::RadioButton): - case CT2(QSizePolicy::RadioButton, QSizePolicy::CheckBox): - if (orientation == Qt::Vertical) - return_SIZE(8, 8, 7); // AHIG and Builder - break; - case CT1(QSizePolicy::RadioButton): - if (orientation == Qt::Vertical) - return 5; // (Builder, guess, AHIG) - } - - if (orientation == Qt::Horizontal - && (control2 & (QSizePolicy::CheckBox | QSizePolicy::RadioButton))) - return_SIZE(12, 10, 8); // guess - - if ((control1 | control2) & (QSizePolicy::Frame - | QSizePolicy::GroupBox - | QSizePolicy::TabWidget)) { - /* - These values were chosen so that nested container widgets - look good side by side. Builder uses 8, which looks way - too small, and AHIG doesn't say anything. - */ - return_SIZE(16, 10, 10); // guess - } - - if ((control1 | control2) & (QSizePolicy::Line | QSizePolicy::Slider)) - return_SIZE(12, 10, 8); // AHIG - - if ((control1 | control2) & QSizePolicy::LineEdit) - return_SIZE(10, 8, 8); // AHIG - - /* - AHIG and Builder differ by up to 4 pixels for stacked editable - comboboxes. We use some values that work fairly well in all - cases. - */ - if ((control1 | control2) & QSizePolicy::ComboBox) - return_SIZE(10, 8, 7); // guess - - /* - Builder defaults to 8, 6, 5 in lots of cases, but most of the time the - result looks too cramped. - */ - return_SIZE(10, 8, 6); // guess -} - -QT_END_NAMESPACE