From 7b55189b95b9b05587bb6de5ca22b3d8aa161096 Mon Sep 17 00:00:00 2001 From: Christian Prochaska Date: Tue, 10 Dec 2024 14:54:57 +0100 Subject: [PATCH] Initial port Issue https://github.com/genodelabs/genode/issues/5402 --- cmake/FindXKB_COMMON_X11.cmake | 22 +- cmake/Qt3rdPartyLibraryHelpers.cmake | 1 + cmake/QtBaseConfigureTests.cmake | 33 +- cmake/QtBaseGlobalTargets.cmake | 4 +- cmake/QtBuildInternalsExtra.cmake.in | 2 +- cmake/QtBuildPathsHelpers.cmake | 2 +- cmake/QtFlagHandlingHelpers.cmake | 4 + cmake/QtGenerateExtPri.cmake | 6 +- cmake/QtHostInfoConfig.cmake.in | 2 +- cmake/QtModuleHelpers.cmake | 3 +- cmake/QtPkgConfigHelpers.cmake | 2 +- cmake/QtPlatformTargetHelpers.cmake | 1 - cmake/QtPluginHelpers.cmake | 1 + cmake/QtRpathHelpers.cmake | 2 + cmake/QtSeparateDebugInfo.cmake | 1 + cmake/QtToolchainHelpers.cmake | 14 +- cmake/platforms/Platform/Genode.cmake | 9 + mkspecs/common/bsd/qplatformdefs.h | 2 + mkspecs/common/genode.conf | 49 + mkspecs/features/data/mac/objc_namespace.sh | 2 +- mkspecs/features/uikit/device_destinations.sh | 2 +- mkspecs/features/uikit/devices.py | 2 +- mkspecs/freebsd-aarch64-pc-g++/qmake.conf | 27 + .../freebsd-aarch64-pc-g++/qplatformdefs.h | 45 + mkspecs/freebsd-x86_64-pc-g++/qmake.conf | 27 + mkspecs/freebsd-x86_64-pc-g++/qplatformdefs.h | 45 + mkspecs/genode-aarch64-g++/qmake.conf | 1 + mkspecs/genode-aarch64-g++/qplatformdefs.h | 6 + mkspecs/genode-arm-g++/qmake.conf | 1 + mkspecs/genode-arm-g++/qplatformdefs.h | 6 + mkspecs/genode-x86_32-g++/qmake.conf | 1 + mkspecs/genode-x86_32-g++/qplatformdefs.h | 6 + mkspecs/genode-x86_64-g++/qmake.conf | 1 + mkspecs/genode-x86_64-g++/qplatformdefs.h | 6 + src/3rdparty/forkfd/forkfd.c | 6 +- src/corelib/CMakeLists.txt | 2 +- src/corelib/Qt6CoreMacros.cmake | 2 + src/corelib/global/qcompilerdetection.h | 2 + src/corelib/global/qlogging.cpp | 2 +- src/corelib/global/qsystemdetection.h | 4 + src/corelib/global/qtypes.h | 2 + src/corelib/global/qversiontagging.cpp | 2 +- src/corelib/global/qversiontagging.h | 2 +- src/corelib/io/qfilesystemwatcher.cpp | 2 +- src/corelib/io/qlockfile_unix.cpp | 4 +- src/corelib/io/qprocess_unix.cpp | 2 + src/corelib/kernel/qcoreapplication.cpp | 4 +- src/corelib/plugin/qlibrary_unix.cpp | 2 +- src/corelib/plugin/qplugin.h | 2 +- src/corelib/thread/qthread.h | 4 +- src/corelib/thread/qthread_unix.cpp | 6 +- src/gui/CMakeLists.txt | 6 +- src/gui/configure.cmake | 6 +- src/network/configure.cmake | 2 +- src/network/kernel/qnetworkinterface_unix.cpp | 2 +- .../qdevicediscovery_static.cpp | 4 - .../devicediscovery/qdevicediscovery_udev.cpp | 4 - .../qevdevkeyboard_defaultmap_p.h | 4 - .../evdevkeyboard/qevdevkeyboardhandler.cpp | 4 - .../input/evdevmouse/qevdevmousehandler.cpp | 5 - .../input/evdevtablet/qevdevtablethandler.cpp | 4 - .../input/evdevtouch/qevdevtouchhandler.cpp | 4 - src/plugins/platforms/CMakeLists.txt | 6 + src/plugins/platforms/genode/CMakeLists.txt | 28 + src/plugins/platforms/genode/genode.json | 3 + src/plugins/platforms/genode/genode.pro | 38 + src/plugins/platforms/genode/main.cpp | 51 + .../platforms/genode/qgenodeclipboard.cpp | 149 +++ .../platforms/genode/qgenodeclipboard.h | 74 ++ .../platforms/genode/qgenodecursor.cpp | 79 ++ src/plugins/platforms/genode/qgenodecursor.h | 45 + .../platforms/genode/qgenodeglcontext.cpp | 61 + .../platforms/genode/qgenodeglcontext.h | 43 + .../platforms/genode/qgenodeintegration.cpp | 160 +++ .../platforms/genode/qgenodeintegration.h | 74 ++ .../genode/qgenodeintegrationplugin.h | 43 + .../genode/qgenodeplatformwindow.cpp | 1104 +++++++++++++++++ .../platforms/genode/qgenodeplatformwindow.h | 236 ++++ src/plugins/platforms/genode/qgenodescreen.h | 112 ++ .../genode/qgenodesignalproxythread.h | 113 ++ .../platforms/genode/qgenodewindowsurface.cpp | 129 ++ .../platforms/genode/qgenodewindowsurface.h | 52 + .../platforms/xcb/qxcbbackingstore.cpp | 8 + src/plugins/tls/openssl/qopenssl_p.h | 7 + .../tls/openssl/qsslcontext_openssl.cpp | 15 +- .../openssl/qsslsocket_openssl_symbols.cpp | 52 +- .../openssl/qsslsocket_openssl_symbols_p.h | 59 + src/plugins/tls/openssl/qtls_openssl.cpp | 4 +- src/plugins/tls/openssl/qx509_openssl.cpp | 31 +- src/widgets/styles/qstylefactory.cpp | 8 +- util/android/android_emulator_launcher.sh | 2 +- util/testrunner/qt-testrunner.py | 2 +- util/testrunner/sanitizer-testrunner.py | 2 +- 93 files changed, 3110 insertions(+), 113 deletions(-) create mode 100644 cmake/platforms/Platform/Genode.cmake create mode 100644 mkspecs/common/genode.conf create mode 100644 mkspecs/freebsd-aarch64-pc-g++/qmake.conf create mode 100644 mkspecs/freebsd-aarch64-pc-g++/qplatformdefs.h create mode 100644 mkspecs/freebsd-x86_64-pc-g++/qmake.conf create mode 100644 mkspecs/freebsd-x86_64-pc-g++/qplatformdefs.h create mode 100644 mkspecs/genode-aarch64-g++/qmake.conf create mode 100644 mkspecs/genode-aarch64-g++/qplatformdefs.h create mode 100644 mkspecs/genode-arm-g++/qmake.conf create mode 100644 mkspecs/genode-arm-g++/qplatformdefs.h create mode 100644 mkspecs/genode-x86_32-g++/qmake.conf create mode 100644 mkspecs/genode-x86_32-g++/qplatformdefs.h create mode 100644 mkspecs/genode-x86_64-g++/qmake.conf create mode 100644 mkspecs/genode-x86_64-g++/qplatformdefs.h create mode 100644 src/plugins/platforms/genode/CMakeLists.txt create mode 100644 src/plugins/platforms/genode/genode.json create mode 100644 src/plugins/platforms/genode/genode.pro create mode 100644 src/plugins/platforms/genode/main.cpp create mode 100644 src/plugins/platforms/genode/qgenodeclipboard.cpp create mode 100644 src/plugins/platforms/genode/qgenodeclipboard.h create mode 100644 src/plugins/platforms/genode/qgenodecursor.cpp create mode 100644 src/plugins/platforms/genode/qgenodecursor.h create mode 100644 src/plugins/platforms/genode/qgenodeglcontext.cpp create mode 100644 src/plugins/platforms/genode/qgenodeglcontext.h create mode 100644 src/plugins/platforms/genode/qgenodeintegration.cpp create mode 100644 src/plugins/platforms/genode/qgenodeintegration.h create mode 100644 src/plugins/platforms/genode/qgenodeintegrationplugin.h create mode 100644 src/plugins/platforms/genode/qgenodeplatformwindow.cpp create mode 100644 src/plugins/platforms/genode/qgenodeplatformwindow.h create mode 100644 src/plugins/platforms/genode/qgenodescreen.h create mode 100644 src/plugins/platforms/genode/qgenodesignalproxythread.h create mode 100644 src/plugins/platforms/genode/qgenodewindowsurface.cpp create mode 100644 src/plugins/platforms/genode/qgenodewindowsurface.h diff --git a/cmake/FindXKB_COMMON_X11.cmake b/cmake/FindXKB_COMMON_X11.cmake index a00acb3c..e9aa2b18 100644 --- a/cmake/FindXKB_COMMON_X11.cmake +++ b/cmake/FindXKB_COMMON_X11.cmake @@ -1,10 +1,24 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause -find_package(PkgConfig QUIET) +# Find the XKB_COMMON_X11 library -pkg_check_modules(XKB_COMMON_X11 IMPORTED_TARGET "xkbcommon-x11>=0.4.1") +# Will make the target PkgConfig::XKB_COMMON_X11 available when found. +if(TARGET PkgConfig::XKB_COMMON_X11) + set(XKB_COMMON_X11_FOUND TRUE) + return() +endif() + +find_library(XKB_COMMON_X11_LIBRARY NAMES "xkbcommon-x11") +find_path(XKB_COMMON_X11_INCLUDE_DIR NAMES "xkbcommon/xkbcommon-x11.h" DOC "The XKB_COMMON_X11 Include path") + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(XKB_COMMON_X11 DEFAULT_MSG XKB_COMMON_X11_INCLUDE_DIR XKB_COMMON_X11_LIBRARY) + +mark_as_advanced(XKB_COMMON_X11_INCLUDE_DIR XKB_COMMON_X11_LIBRARY) -if (NOT TARGET PkgConfig::XKB_COMMON_X11) - set(XKB_COMMON_X11_FOUND 0) +if(XKB_COMMON_X11_FOUND) + add_library(PkgConfig::XKB_COMMON_X11 INTERFACE IMPORTED) + target_link_libraries(PkgConfig::XKB_COMMON_X11 INTERFACE "${XKB_COMMON_X11_LIBRARY}") + target_include_directories(PkgConfig::XKB_COMMON_X11 INTERFACE "${XKB_COMMON_X11_INCLUDE_DIR}") endif() diff --git a/cmake/Qt3rdPartyLibraryHelpers.cmake b/cmake/Qt3rdPartyLibraryHelpers.cmake index dca360d0..824a8fcc 100644 --- a/cmake/Qt3rdPartyLibraryHelpers.cmake +++ b/cmake/Qt3rdPartyLibraryHelpers.cmake @@ -275,6 +275,7 @@ function(qt_internal_add_3rdparty_library target) "${config_build_dir}/${INSTALL_CMAKE_NAMESPACE}${target}ConfigVersionImpl.cmake" VERSION ${PROJECT_VERSION} COMPATIBILITY AnyNewerVersion + ARCH_INDEPENDENT ) qt_internal_write_qt_package_version_file( "${INSTALL_CMAKE_NAMESPACE}${target}" diff --git a/cmake/QtBaseConfigureTests.cmake b/cmake/QtBaseConfigureTests.cmake index 7713def6..292aa038 100644 --- a/cmake/QtBaseConfigureTests.cmake +++ b/cmake/QtBaseConfigureTests.cmake @@ -94,20 +94,25 @@ function(qt_run_config_test_architecture) Here are the first few lines extracted:\n${arch_lines_output}") endif() - set(TEST_architecture 1 CACHE INTERNAL "Ran the architecture test") - set(TEST_architecture_arch "${_architecture}" CACHE INTERNAL "Target machine architecture") - list(APPEND QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT TEST_architecture_arch) - set(TEST_subarch 1 CACHE INTERNAL "Ran machine subArchitecture test") - set(TEST_subarch_result "${_sub_architecture}" CACHE INTERNAL "Target sub-architectures") - list(APPEND QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT TEST_subarch_result) - foreach(it ${_sub_architecture}) - # Equivalent to qmake's QT_CPU_FEATURES.$arch. - set(TEST_arch_${TEST_architecture_arch}_subarch_${it} 1 CACHE INTERNAL "Target sub architecture result") - list(APPEND QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT TEST_arch_${TEST_architecture_arch}_subarch_${it}) - endforeach() - set(TEST_buildAbi "${_build_abi}" CACHE INTERNAL "Target machine buildAbi") - list(APPEND QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT TEST_buildAbi) - set(QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT ${QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT} CACHE INTERNAL "Test variables that should be exported") + # + # Genode: set to FALSE for architecture-independent generated api files + # + if (TRUE) + set(TEST_architecture 1 CACHE INTERNAL "Ran the architecture test") + set(TEST_architecture_arch "${_architecture}" CACHE INTERNAL "Target machine architecture") + list(APPEND QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT TEST_architecture_arch) + set(TEST_subarch 1 CACHE INTERNAL "Ran machine subArchitecture test") + set(TEST_subarch_result "${_sub_architecture}" CACHE INTERNAL "Target sub-architectures") + list(APPEND QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT TEST_subarch_result) + foreach(it ${_sub_architecture}) + # Equivalent to qmake's QT_CPU_FEATURES.$arch. + set(TEST_arch_${TEST_architecture_arch}_subarch_${it} 1 CACHE INTERNAL "Target sub architecture result") + list(APPEND QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT TEST_arch_${TEST_architecture_arch}_subarch_${it}) + endforeach() + set(TEST_buildAbi "${_build_abi}" CACHE INTERNAL "Target machine buildAbi") + list(APPEND QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT TEST_buildAbi) + set(QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT ${QT_BASE_CONFIGURE_TESTS_VARS_TO_EXPORT} CACHE INTERNAL "Test variables that should be exported") + endif() list(JOIN _sub_architecture " " subarch_summary) set_property(GLOBAL PROPERTY qt_configure_subarch_summary "${subarch_summary}") diff --git a/cmake/QtBaseGlobalTargets.cmake b/cmake/QtBaseGlobalTargets.cmake index 9a18cdd8..3a8b16c9 100644 --- a/cmake/QtBaseGlobalTargets.cmake +++ b/cmake/QtBaseGlobalTargets.cmake @@ -41,6 +41,7 @@ write_basic_package_version_file( "${__build_internals_build_dir}/${INSTALL_CMAKE_NAMESPACE}BuildInternalsConfigVersionImpl.cmake" VERSION ${PROJECT_VERSION} COMPATIBILITY AnyNewerVersion + ARCH_INDEPENDENT ) qt_internal_write_qt_package_version_file( "${INSTALL_CMAKE_NAMESPACE}BuildInternals" @@ -111,7 +112,7 @@ qt_feature_module_end(GlobalConfig OUT_VAR_PREFIX "__GlobalConfig_") # The version script support check has to happen after we determined which linker is going # to be used. The linker decision happens in the qtbase/configure.cmake file that is processed # above. -qt_run_linker_version_script_support() +#qt_run_linker_version_script_support() qt_generate_global_config_pri_file() qt_generate_global_module_pri_file() @@ -195,6 +196,7 @@ write_basic_package_version_file( "${__GlobalConfig_build_dir}/${INSTALL_CMAKE_NAMESPACE}ConfigVersionImpl.cmake" VERSION ${PROJECT_VERSION} COMPATIBILITY AnyNewerVersion + ARCH_INDEPENDENT ) qt_internal_write_qt_package_version_file( "${INSTALL_CMAKE_NAMESPACE}" diff --git a/cmake/QtBuildInternalsExtra.cmake.in b/cmake/QtBuildInternalsExtra.cmake.in index c035a216..261dee0d 100644 --- a/cmake/QtBuildInternalsExtra.cmake.in +++ b/cmake/QtBuildInternalsExtra.cmake.in @@ -74,7 +74,7 @@ endif() set(QT_WILL_INSTALL @QT_WILL_INSTALL@ CACHE BOOL "Boolean indicating if doing a Qt prefix build (vs non-prefix build)." FORCE) -set(QT_SOURCE_TREE "@QT_SOURCE_TREE@" CACHE PATH +set(QT_SOURCE_TREE "" CACHE PATH "A path to the source tree of the previously configured QtBase project." FORCE) # Propagate decision of building tests and examples to other repositories. diff --git a/cmake/QtBuildPathsHelpers.cmake b/cmake/QtBuildPathsHelpers.cmake index edc43f2f..81dcbd90 100644 --- a/cmake/QtBuildPathsHelpers.cmake +++ b/cmake/QtBuildPathsHelpers.cmake @@ -100,7 +100,7 @@ function(qt_internal_setup_build_and_install_paths) if(QT_CONFIG_INSTALL_DIR) string(APPEND QT_CONFIG_INSTALL_DIR "/") endif() - string(APPEND QT_CONFIG_INSTALL_DIR ${__config_path_part}) + string(APPEND QT_CONFIG_INSTALL_DIR "lib/cmake") set(QT_BUILD_DIR "${QT_BUILD_DIR}" PARENT_SCOPE) set(QT_INSTALL_DIR "${QT_INSTALL_DIR}" PARENT_SCOPE) diff --git a/cmake/QtFlagHandlingHelpers.cmake b/cmake/QtFlagHandlingHelpers.cmake index 91e1de86..0a670054 100644 --- a/cmake/QtFlagHandlingHelpers.cmake +++ b/cmake/QtFlagHandlingHelpers.cmake @@ -132,6 +132,10 @@ function(qt_internal_add_link_flags_no_undefined target) set(no_undefined_flag "-Wl,--no-undefined") endif() + if (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + set(no_undefined_flag "") + endif() + set(CMAKE_REQUIRED_LINK_OPTIONS ${previous_CMAKE_REQUIRED_LINK_OPTIONS}) if (NOT HAVE_DASH_UNDEFINED_SYMBOLS AND NOT HAVE_DASH_DASH_NO_UNDEFINED) diff --git a/cmake/QtGenerateExtPri.cmake b/cmake/QtGenerateExtPri.cmake index b79ef2b7..1bbf4688 100644 --- a/cmake/QtGenerateExtPri.cmake +++ b/cmake/QtGenerateExtPri.cmake @@ -20,9 +20,9 @@ foreach(in_file ${IN_FILES}) set(first_iteration FALSE) list(JOIN incdir " " incdir) list(JOIN defines " " defines) - string(APPEND content "QMAKE_INCDIR_${uclib} = ${incdir} -QMAKE_DEFINES_${uclib} = ${defines} -") +# string(APPEND content "QMAKE_INCDIR_${uclib} = ${incdir} +#QMAKE_DEFINES_${uclib} = ${defines} +#") endif() set(config_suffix "") if(number_of_configs GREATER "1") diff --git a/cmake/QtHostInfoConfig.cmake.in b/cmake/QtHostInfoConfig.cmake.in index 7933b8b5..d0500a71 100644 --- a/cmake/QtHostInfoConfig.cmake.in +++ b/cmake/QtHostInfoConfig.cmake.in @@ -15,7 +15,7 @@ set(@var_prefix@SYSCONFDIR "@INSTALL_SYSCONFDIR@") set(@var_prefix@EXAMPLESDIR "@INSTALL_EXAMPLESDIR@") set(@var_prefix@TESTSDIR "@INSTALL_TESTSDIR@") set(@var_prefix@DESCRIPTIONSDIR "@INSTALL_DESCRIPTIONSDIR@") -set(@var_prefix@QMAKE_MKSPEC "@QT_QMAKE_TARGET_MKSPEC@") +set(@var_prefix@QMAKE_MKSPEC "") set(@var_prefix@ARCH "@TEST_architecture_arch@") set(@var_prefix@SUBARCHS "@TEST_subarch_result@") set(@var_prefix@BUILDABI "@TEST_buildAbi@") diff --git a/cmake/QtModuleHelpers.cmake b/cmake/QtModuleHelpers.cmake index 21630860..1c53e05b 100644 --- a/cmake/QtModuleHelpers.cmake +++ b/cmake/QtModuleHelpers.cmake @@ -334,7 +334,7 @@ function(qt_internal_add_module target) # FIXME: This workaround is needed because the deployment logic # for iOS and WASM just copies/embeds the directly linked library, # which will just be a versioned symlink to the actual library. - if((UIKIT OR WASM) AND BUILD_SHARED_LIBS) + if(((UIKIT OR WASM) AND BUILD_SHARED_LIBS) OR TRUE) set(version_args "") else() set(version_args @@ -758,6 +758,7 @@ set(QT_ALLOW_MISSING_TOOLS_PACKAGES TRUE)") "${config_build_dir}/${INSTALL_CMAKE_NAMESPACE}${target}ConfigVersionImpl.cmake" VERSION ${PROJECT_VERSION} COMPATIBILITY AnyNewerVersion + ARCH_INDEPENDENT ) qt_internal_write_qt_package_version_file( "${INSTALL_CMAKE_NAMESPACE}${target}" diff --git a/cmake/QtPkgConfigHelpers.cmake b/cmake/QtPkgConfigHelpers.cmake index dbe736c4..650db7c0 100644 --- a/cmake/QtPkgConfigHelpers.cmake +++ b/cmake/QtPkgConfigHelpers.cmake @@ -159,6 +159,6 @@ function(qt_internal_generate_pkg_config_file module) # This is inspired by https://gitlab.kitware.com/cmake/cmake/-/issues/20842 target_sources(${module} PRIVATE "${final_pc_path}") - qt_install(FILES "${final_pc_path}" DESTINATION "${install_dir}") + #qt_install(FILES "${final_pc_path}" DESTINATION "${CMAKE_INSTALL_PREFIX}/libdata/pkgconfig") endforeach() endfunction() diff --git a/cmake/QtPlatformTargetHelpers.cmake b/cmake/QtPlatformTargetHelpers.cmake index 54d1916f..9fdedc33 100644 --- a/cmake/QtPlatformTargetHelpers.cmake +++ b/cmake/QtPlatformTargetHelpers.cmake @@ -17,7 +17,6 @@ function(qt_internal_setup_public_platform_target) INTERFACE $ $ - $ $ ) target_compile_definitions(Platform INTERFACE ${QT_PLATFORM_DEFINITIONS}) diff --git a/cmake/QtPluginHelpers.cmake b/cmake/QtPluginHelpers.cmake index 2db9d462..cfb9f689 100644 --- a/cmake/QtPluginHelpers.cmake +++ b/cmake/QtPluginHelpers.cmake @@ -421,6 +421,7 @@ function(qt_internal_add_plugin target) "${config_build_dir}/${INSTALL_CMAKE_NAMESPACE}${target}ConfigVersionImpl.cmake" VERSION ${PROJECT_VERSION} COMPATIBILITY AnyNewerVersion + ARCH_INDEPENDENT ) qt_internal_write_qt_package_version_file( "${INSTALL_CMAKE_NAMESPACE}${target}" diff --git a/cmake/QtRpathHelpers.cmake b/cmake/QtRpathHelpers.cmake index a8e3bb5f..0d6d1cca 100644 --- a/cmake/QtRpathHelpers.cmake +++ b/cmake/QtRpathHelpers.cmake @@ -8,6 +8,8 @@ function(qt_internal_get_relative_rpath_base_token out_var) set(rpath_rel_base "@loader_path") elseif(LINUX OR SOLARIS OR FREEBSD OR HURD OR OPENBSD) set(rpath_rel_base "$ORIGIN") + elseif(CMAKE_SYSTEM_NAME MATCHES "FreeBSD") + set(rpath_rel_base "$ORIGIN") else() set(rpath_rel_base "NO_KNOWN_RPATH_REL_BASE") endif() diff --git a/cmake/QtSeparateDebugInfo.cmake b/cmake/QtSeparateDebugInfo.cmake index 61f62207..168dcb69 100644 --- a/cmake/QtSeparateDebugInfo.cmake +++ b/cmake/QtSeparateDebugInfo.cmake @@ -83,6 +83,7 @@ function(qt_internal_generate_binary_strip_wrapper) if(DEFINED CACHE{QT_INTERNAL_STRIP_SUPPORTS_KEEP_SECTION} OR QT_NO_STRIP_WRAPPER OR (NOT QT_BUILD_SHARED_LIBS) + OR 1 ) return() endif() diff --git a/cmake/QtToolchainHelpers.cmake b/cmake/QtToolchainHelpers.cmake index c8e2b778..c0e8739a 100644 --- a/cmake/QtToolchainHelpers.cmake +++ b/cmake/QtToolchainHelpers.cmake @@ -31,13 +31,13 @@ set(__qt_chainload_toolchain_file \"\${__qt_initially_configured_toolchain_file} list(APPEND init_platform "set(CMAKE_SYSTEM_PROCESSOR arm64 CACHE STRING \"\")") endif() - if(QT_QMAKE_TARGET_MKSPEC) - list(APPEND init_platform - "if(NOT QT_QMAKE_TARGET_MKSPEC)" - " set(QT_QMAKE_TARGET_MKSPEC ${QT_QMAKE_TARGET_MKSPEC} CACHE STRING \"\")" - "endif()" - ) - endif() +# if(QT_QMAKE_TARGET_MKSPEC) +# list(APPEND init_platform +# "if(NOT QT_QMAKE_TARGET_MKSPEC)" +# " set(QT_QMAKE_TARGET_MKSPEC ${QT_QMAKE_TARGET_MKSPEC} CACHE STRING \"\")" +# "endif()" +# ) +# endif() if("${QT_QMAKE_TARGET_MKSPEC}" STREQUAL "linux-g++-32" AND NOT QT_NO_AUTO_DETECT_LINUX_X86) set(__qt_toolchain_common_flags_init "-m32") diff --git a/cmake/platforms/Platform/Genode.cmake b/cmake/platforms/Platform/Genode.cmake new file mode 100644 index 00000000..b9bbf8bc --- /dev/null +++ b/cmake/platforms/Platform/Genode.cmake @@ -0,0 +1,9 @@ +set(CMAKE_FIND_LIBRARY_SUFFIXES ".lib.so") +set(CMAKE_FIND_LIBRARY_PREFIXES "lib") +set(CMAKE_SHARED_LIBRARY_SUFFIX ".lib.so") +set(CMAKE_SHARED_LIBRARY_PREFIX "lib") +set(CMAKE_SHARED_MODULE_SUFFIX ".lib.so") +set(CMAKE_SHARED_MODULE_PREFIX "lib") +set(CMAKE_DL_LIBS "") +set(CMAKE_SHARED_LIBRARY_SONAME_C_FLAG "-Wl,-soname,") +set(UNIX 1) diff --git a/mkspecs/common/bsd/qplatformdefs.h b/mkspecs/common/bsd/qplatformdefs.h index 04b801f9..4eaa9b3d 100644 --- a/mkspecs/common/bsd/qplatformdefs.h +++ b/mkspecs/common/bsd/qplatformdefs.h @@ -29,7 +29,9 @@ #include #include #include +#if 0 #include +#endif #include #include #include diff --git a/mkspecs/common/genode.conf b/mkspecs/common/genode.conf new file mode 100644 index 00000000..b3c617ea --- /dev/null +++ b/mkspecs/common/genode.conf @@ -0,0 +1,49 @@ +# +# qmake configuration for common genode +# + +MAKEFILE_GENERATOR = UNIX +QMAKE_PLATFORM = genode freebsd unix posix +CONFIG += unversioned_libname unversioned_soname + +# static libraries currently only work as 'lib*.a' +QMAKE_PREFIX_PLUGIN = lib +QMAKE_EXTENSION_PLUGIN = lib.so +QMAKE_PREFIX_SHLIB = lib +QMAKE_EXTENSION_SHLIB = lib.so +QMAKE_PREFIX_STATICLIB = lib +QMAKE_EXTENSION_STATICLIB = a + +include(../common/gcc-base-unix.conf) +include(../common/g++-unix.conf) + +# modifications to g++.conf +QMAKE_CC = $$(GENODE_QMAKE_CC) +QMAKE_CXX = $$(GENODE_QMAKE_CXX) +QMAKE_LINK = $$(GENODE_QMAKE_LINK) + +QMAKE_AR = $$(GENODE_QMAKE_AR) cqs +QMAKE_OBJCOPY = $$(GENODE_QMAKE_OBJCOPY) +QMAKE_NM = $$(GENODE_QMAKE_NM) -P +QMAKE_STRIP = $$(GENODE_QMAKE_STRIP) + +QMAKE_LFLAGS_RPATH = + +QMAKE_CFLAGS += $$(GENODE_QMAKE_CFLAGS) +QMAKE_CXXFLAGS += $$(GENODE_QMAKE_CXXFLAGS) +QMAKE_LFLAGS_APP += $$(GENODE_QMAKE_LFLAGS_APP) +QMAKE_LFLAGS_SHLIB += $$(GENODE_QMAKE_LFLAGS_SHLIB) +QMAKE_LIBS += $$(GENODE_QMAKE_LIBS) +QMAKE_INCDIR_OPENGL += $$(GENODE_QMAKE_INCDIR_OPENGL) +QMAKE_LIBS_OPENGL += $$(GENODE_QMAKE_LIBS_OPENGL) +QMAKE_INCDIR_OPENGL_ES2 += $$(GENODE_QMAKE_INCDIR_OPENGL) +QMAKE_LIBS_OPENGL_ES2 += $$(GENODE_QMAKE_LIBS_OPENGL) +QMAKE_INCDIR_EGL += $$(GENODE_QMAKE_INCDIR_EGL) +QMAKE_LIBS_EGL += $$(GENODE_QMAKE_LIBS_EGL) + +QMAKE_CXXFLAGS += $$QMAKE_CFLAGS +QMAKE_CXXFLAGS += -fpermissive + +QMAKE_LFLAGS_PLUGIN = $$QMAKE_LFLAGS_SHLIB + +load(qt_config) diff --git a/mkspecs/features/data/mac/objc_namespace.sh b/mkspecs/features/data/mac/objc_namespace.sh index abb173ef..aee04f0d 100755 --- a/mkspecs/features/data/mac/objc_namespace.sh +++ b/mkspecs/features/data/mac/objc_namespace.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/local/bin/bash # Copyright (C) 2017 The Qt Company Ltd. # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only diff --git a/mkspecs/features/uikit/device_destinations.sh b/mkspecs/features/uikit/device_destinations.sh index 2f291d41..79112c5b 100755 --- a/mkspecs/features/uikit/device_destinations.sh +++ b/mkspecs/features/uikit/device_destinations.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/local/bin/bash # Copyright (C) 2016 The Qt Company Ltd. # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only diff --git a/mkspecs/features/uikit/devices.py b/mkspecs/features/uikit/devices.py index 98498cde..709c28fd 100755 --- a/mkspecs/features/uikit/devices.py +++ b/mkspecs/features/uikit/devices.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3 +#!/usr/local/bin/python3.9 # Copyright (C) 2017 The Qt Company Ltd. # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only diff --git a/mkspecs/freebsd-aarch64-pc-g++/qmake.conf b/mkspecs/freebsd-aarch64-pc-g++/qmake.conf new file mode 100644 index 00000000..0ce58f2d --- /dev/null +++ b/mkspecs/freebsd-aarch64-pc-g++/qmake.conf @@ -0,0 +1,27 @@ +# +# qmake configuration for freebsd-aarch64-unknown-g++ +# + +MAKEFILE_GENERATOR = UNIX +QMAKE_PLATFORM = freebsd + +include(../common/bsd/bsd.conf) + +include(../common/gcc-base-unix.conf) +include(../common/g++-unix.conf) + +QMAKE_LIBS_OPENGL_ES2 = -lGLESv2 + +# modifications to g++.conf +QMAKE_CC = aarch64-unknown-freebsd13.2-gcc +QMAKE_CXX = aarch64-unknown-freebsd13.2-g++ +QMAKE_LINK = aarch64-unknown-freebsd13.2-g++ +QMAKE_LINK_SHLIB = aarch64-unknown-freebsd13.2-g++ + +# modifications to bsd.conf +QMAKE_AR = aarch64-unknown-freebsd13.2-ar cqs +QMAKE_OBJCOPY = aarch64-unknown-freebsd13.2-objcopy +QMAKE_NM = aarch64-unknown-freebsd13.2-nm -P +QMAKE_STRIP = aarch64-unknown-freebsd13.2-strip + +load(qt_config) diff --git a/mkspecs/freebsd-aarch64-pc-g++/qplatformdefs.h b/mkspecs/freebsd-aarch64-pc-g++/qplatformdefs.h new file mode 100644 index 00000000..0e3fd6b2 --- /dev/null +++ b/mkspecs/freebsd-aarch64-pc-g++/qplatformdefs.h @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the qmake spec 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 QPLATFORMDEFS_H +#define QPLATFORMDEFS_H + +#include "../common/bsd/qplatformdefs.h" + +#endif // QPLATFORMDEFS_H diff --git a/mkspecs/freebsd-x86_64-pc-g++/qmake.conf b/mkspecs/freebsd-x86_64-pc-g++/qmake.conf new file mode 100644 index 00000000..a8d52adc --- /dev/null +++ b/mkspecs/freebsd-x86_64-pc-g++/qmake.conf @@ -0,0 +1,27 @@ +# +# qmake configuration for freebsd-x86_64-pc-g++ +# + +MAKEFILE_GENERATOR = UNIX +QMAKE_PLATFORM = freebsd + +include(../common/bsd/bsd.conf) + +include(../common/gcc-base-unix.conf) +include(../common/g++-unix.conf) + +QMAKE_LIBS_OPENGL_ES2 = -lGLESv2 + +# modifications to g++.conf +QMAKE_CC = x86_64-pc-freebsd13.3-gcc +QMAKE_CXX = x86_64-pc-freebsd13.3-g++ +QMAKE_LINK = x86_64-pc-freebsd13.3-g++ +QMAKE_LINK_SHLIB = x86_64-pc-freebsd13.3-g++ + +# modifications to bsd.conf +QMAKE_AR = x86_64-pc-freebsd13.3-ar cqs +QMAKE_OBJCOPY = x86_64-pc-freebsd13.3-objcopy +QMAKE_NM = x86_64-pc-freebsd13.3-nm -P +QMAKE_STRIP = x86_64-pc-freebsd13.3-strip + +load(qt_config) diff --git a/mkspecs/freebsd-x86_64-pc-g++/qplatformdefs.h b/mkspecs/freebsd-x86_64-pc-g++/qplatformdefs.h new file mode 100644 index 00000000..0e3fd6b2 --- /dev/null +++ b/mkspecs/freebsd-x86_64-pc-g++/qplatformdefs.h @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the qmake spec 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 QPLATFORMDEFS_H +#define QPLATFORMDEFS_H + +#include "../common/bsd/qplatformdefs.h" + +#endif // QPLATFORMDEFS_H diff --git a/mkspecs/genode-aarch64-g++/qmake.conf b/mkspecs/genode-aarch64-g++/qmake.conf new file mode 100644 index 00000000..70e07ba7 --- /dev/null +++ b/mkspecs/genode-aarch64-g++/qmake.conf @@ -0,0 +1 @@ +include(../common/genode.conf) diff --git a/mkspecs/genode-aarch64-g++/qplatformdefs.h b/mkspecs/genode-aarch64-g++/qplatformdefs.h new file mode 100644 index 00000000..74258768 --- /dev/null +++ b/mkspecs/genode-aarch64-g++/qplatformdefs.h @@ -0,0 +1,6 @@ +#ifndef QPLATFORMDEFS_H +#define QPLATFORMDEFS_H + +#include "../common/bsd/qplatformdefs.h" + +#endif diff --git a/mkspecs/genode-arm-g++/qmake.conf b/mkspecs/genode-arm-g++/qmake.conf new file mode 100644 index 00000000..70e07ba7 --- /dev/null +++ b/mkspecs/genode-arm-g++/qmake.conf @@ -0,0 +1 @@ +include(../common/genode.conf) diff --git a/mkspecs/genode-arm-g++/qplatformdefs.h b/mkspecs/genode-arm-g++/qplatformdefs.h new file mode 100644 index 00000000..74258768 --- /dev/null +++ b/mkspecs/genode-arm-g++/qplatformdefs.h @@ -0,0 +1,6 @@ +#ifndef QPLATFORMDEFS_H +#define QPLATFORMDEFS_H + +#include "../common/bsd/qplatformdefs.h" + +#endif diff --git a/mkspecs/genode-x86_32-g++/qmake.conf b/mkspecs/genode-x86_32-g++/qmake.conf new file mode 100644 index 00000000..70e07ba7 --- /dev/null +++ b/mkspecs/genode-x86_32-g++/qmake.conf @@ -0,0 +1 @@ +include(../common/genode.conf) diff --git a/mkspecs/genode-x86_32-g++/qplatformdefs.h b/mkspecs/genode-x86_32-g++/qplatformdefs.h new file mode 100644 index 00000000..74258768 --- /dev/null +++ b/mkspecs/genode-x86_32-g++/qplatformdefs.h @@ -0,0 +1,6 @@ +#ifndef QPLATFORMDEFS_H +#define QPLATFORMDEFS_H + +#include "../common/bsd/qplatformdefs.h" + +#endif diff --git a/mkspecs/genode-x86_64-g++/qmake.conf b/mkspecs/genode-x86_64-g++/qmake.conf new file mode 100644 index 00000000..70e07ba7 --- /dev/null +++ b/mkspecs/genode-x86_64-g++/qmake.conf @@ -0,0 +1 @@ +include(../common/genode.conf) diff --git a/mkspecs/genode-x86_64-g++/qplatformdefs.h b/mkspecs/genode-x86_64-g++/qplatformdefs.h new file mode 100644 index 00000000..74258768 --- /dev/null +++ b/mkspecs/genode-x86_64-g++/qplatformdefs.h @@ -0,0 +1,6 @@ +#ifndef QPLATFORMDEFS_H +#define QPLATFORMDEFS_H + +#include "../common/bsd/qplatformdefs.h" + +#endif diff --git a/src/3rdparty/forkfd/forkfd.c b/src/3rdparty/forkfd/forkfd.c index 9960e45d..c23229ad 100644 --- a/src/3rdparty/forkfd/forkfd.c +++ b/src/3rdparty/forkfd/forkfd.c @@ -77,8 +77,8 @@ (defined(__NetBSD__) && __NetBSD_Version__ >= 600000000) # define HAVE_PIPE2 1 #endif -#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) || \ - defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) +#if (defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) || \ + defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__)) && !defined(__GENODE__) # define HAVE_WAIT4 1 #endif @@ -921,7 +921,7 @@ int forkfd_close(int ffd) return close(ffd); } -#if defined(__FreeBSD__) && __FreeBSD__ >= 9 +#if defined(__FreeBSD__) && __FreeBSD__ >= 9 && 0 # include "forkfd_freebsd.c" #elif defined(__linux__) # include "forkfd_linux.c" diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt index 1296ff04..317d0b5b 100644 --- a/src/corelib/CMakeLists.txt +++ b/src/corelib/CMakeLists.txt @@ -904,7 +904,7 @@ qt_internal_extend_target(Core CONDITION QT_FEATURE_filesystemwatcher AND QT_FEA io/qfilesystemwatcher_inotify.cpp io/qfilesystemwatcher_inotify_p.h ) -qt_internal_extend_target(Core CONDITION QT_FEATURE_filesystemwatcher AND UNIX AND NOT MACOS AND NOT QT_FEATURE_inotify AND (APPLE OR FREEBSD OR NETBSD OR OPENBSD) +qt_internal_extend_target(Core CONDITION QT_FEATURE_filesystemwatcher AND UNIX AND NOT MACOS AND NOT QT_FEATURE_inotify AND (APPLE OR FREEBSD OR NETBSD OR OPENBSD) AND 0 SOURCES io/qfilesystemwatcher_kqueue.cpp io/qfilesystemwatcher_kqueue_p.h ) diff --git a/src/corelib/Qt6CoreMacros.cmake b/src/corelib/Qt6CoreMacros.cmake index e082e586..cc4b4356 100644 --- a/src/corelib/Qt6CoreMacros.cmake +++ b/src/corelib/Qt6CoreMacros.cmake @@ -2407,6 +2407,8 @@ function(_qt_internal_add_library target) # CMake defaults to using .so extensions for loadable modules, aka plugins, # but Qt plugins are actually suffixed with .dylib. set_property(TARGET "${target}" PROPERTY SUFFIX ".dylib") + else() + set_property(TARGET "${target}" PROPERTY SUFFIX ".lib.so") endif() if(ANDROID) diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index 8b6288c1..e5ca150b 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -761,7 +761,9 @@ # define Q_COMPILER_ALIGNAS # define Q_COMPILER_ALIGNOF # define Q_COMPILER_INHERITING_CONSTRUCTORS +#ifndef __GENODE__ # define Q_COMPILER_THREAD_LOCAL +#endif # if Q_CC_GNU > 408 || __GNUC_PATCHLEVEL__ >= 1 # define Q_COMPILER_REF_QUALIFIERS # endif diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index 627d62ed..367aa68d 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -103,7 +103,7 @@ static int qt_gettid() pthread_threadid_np(NULL, &tid); return tid; } -#elif defined(Q_OS_FREEBSD_KERNEL) && defined(__FreeBSD_version) && __FreeBSD_version >= 900031 +#elif defined(Q_OS_FREEBSD_KERNEL) && defined(__FreeBSD_version) && __FreeBSD_version >= 900031 && !defined(Q_OS_GENODE) # include static int qt_gettid() { diff --git a/src/corelib/global/qsystemdetection.h b/src/corelib/global/qsystemdetection.h index 51881043..c7cf6f70 100644 --- a/src/corelib/global/qsystemdetection.h +++ b/src/corelib/global/qsystemdetection.h @@ -14,6 +14,7 @@ /* The operating system, must be one of: (Q_OS_x) + GENODE - Genode DARWIN - Any Darwin system (macOS, iOS, watchOS, tvOS) MACOS - macOS IOS - iOS @@ -98,6 +99,9 @@ #elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) # ifndef __FreeBSD_kernel__ # define Q_OS_FREEBSD +# ifdef __GENODE__ +# define Q_OS_GENODE +# endif # endif # define Q_OS_FREEBSD_KERNEL # define Q_OS_BSD4 diff --git a/src/corelib/global/qtypes.h b/src/corelib/global/qtypes.h index 705de1a0..e33985c1 100644 --- a/src/corelib/global/qtypes.h +++ b/src/corelib/global/qtypes.h @@ -160,7 +160,9 @@ __extension__ typedef __uint128_t quint128; #ifndef __cplusplus // In C++ mode, we define below using QIntegerForSize template +#if 0 static_assert(sizeof(ptrdiff_t) == sizeof(size_t), "Weird ptrdiff_t and size_t definitions"); +#endif typedef ptrdiff_t qptrdiff; typedef ptrdiff_t qsizetype; typedef ptrdiff_t qintptr; diff --git a/src/corelib/global/qversiontagging.cpp b/src/corelib/global/qversiontagging.cpp index a8191869..e31f926a 100644 --- a/src/corelib/global/qversiontagging.cpp +++ b/src/corelib/global/qversiontagging.cpp @@ -21,7 +21,7 @@ extern "C" { // // [1] https://sourceware.org/binutils/docs/as/Symver.html -#if defined(Q_CC_GNU) && defined(Q_OF_ELF) +#if defined(Q_CC_GNU) && defined(Q_OF_ELF) && !defined(Q_OS_GENODE) # define make_versioned_symbol2(sym, m, n, separator) \ Q_CORE_EXPORT extern __attribute__((alias("_" SSYM))) const char sym ## _ ## m ## _ ## n; \ asm(".symver " QT_STRINGIFY(sym) "_" QT_STRINGIFY(m) "_" QT_STRINGIFY(n) ", " \ diff --git a/src/corelib/global/qversiontagging.h b/src/corelib/global/qversiontagging.h index 73faf5b6..d86382a7 100644 --- a/src/corelib/global/qversiontagging.h +++ b/src/corelib/global/qversiontagging.h @@ -75,7 +75,7 @@ struct QVersionTag }; } -#if !defined(QT_NO_VERSION_TAGGING) && (defined(QT_BUILD_CORE_LIB) || defined(QT_BOOTSTRAPPED) || defined(QT_STATIC)) +#if (!defined(QT_NO_VERSION_TAGGING) && (defined(QT_BUILD_CORE_LIB) || defined(QT_BOOTSTRAPPED) || defined(QT_STATIC))) || defined(Q_OS_GENODE) // don't make tags in QtCore, bootstrapped systems or if the user asked not to # define QT_NO_VERSION_TAGGING #endif diff --git a/src/corelib/io/qfilesystemwatcher.cpp b/src/corelib/io/qfilesystemwatcher.cpp index 9ffbe31d..bdeb9582 100644 --- a/src/corelib/io/qfilesystemwatcher.cpp +++ b/src/corelib/io/qfilesystemwatcher.cpp @@ -43,7 +43,7 @@ QFileSystemWatcherEngine *QFileSystemWatcherPrivate::createNativeEngine(QObject // there is a chance that inotify may fail on Linux pre-2.6.13 (August // 2005), so we can't just new inotify directly. return QInotifyFileSystemWatcherEngine::create(parent); -#elif defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD) || defined(Q_OS_OPENBSD) || defined(QT_PLATFORM_UIKIT) +#elif (defined(Q_OS_FREEBSD) || defined(Q_OS_NETBSD) || defined(Q_OS_OPENBSD) || defined(QT_PLATFORM_UIKIT)) && !defined(Q_OS_GENODE) return QKqueueFileSystemWatcherEngine::create(parent); #elif defined(Q_OS_MACOS) return QFseventsFileSystemWatcherEngine::create(parent); diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp index 47aff8b9..ce8ab55f 100644 --- a/src/corelib/io/qlockfile_unix.cpp +++ b/src/corelib/io/qlockfile_unix.cpp @@ -44,7 +44,7 @@ # include # include # include -# if !defined(Q_OS_NETBSD) +# if !defined(Q_OS_NETBSD) && 0 # include # endif #endif @@ -215,7 +215,7 @@ QString QLockFilePrivate::processNameByPid(qint64 pid) if (get_thread_info(pid, &info) != B_OK) return QString(); return QFile::decodeName(info.name); -#elif defined(Q_OS_BSD4) && !defined(QT_PLATFORM_UIKIT) +#elif defined(Q_OS_BSD4) && !defined(QT_PLATFORM_UIKIT) && 0 # if defined(Q_OS_NETBSD) struct kinfo_proc2 kp; int mib[6] = { CTL_KERN, KERN_PROC2, KERN_PROC_PID, (int)pid, sizeof(struct kinfo_proc2), 1 }; diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp index db33cb20..c105b342 100644 --- a/src/corelib/io/qprocess_unix.cpp +++ b/src/corelib/io/qprocess_unix.cpp @@ -536,11 +536,13 @@ static int useForkFlags(const QProcessPrivate::UnixExtras *unixExtras) return FFD_USE_FORK; #endif +#if 0 // Dynamically detect whether libasan or libtsan are loaded into the // process' memory. We need this because the user's code may be compiled // with ASan or TSan, but not Qt. if (__interceptor_vfork != nullptr) return FFD_USE_FORK; +#endif if (!unixExtras || !unixExtras->childProcessModifier) return 0; // no modifier was supplied diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 124bfd91..30302ea7 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -601,7 +601,7 @@ void QCoreApplicationPrivate::initConsole() void QCoreApplicationPrivate::initLocale() { -#if defined(QT_BOOTSTRAPPED) +#if defined(QT_BOOTSTRAPPED) || defined(Q_OS_GENODE) // Don't try to control bootstrap library locale or encoding. #elif defined(Q_OS_UNIX) Q_CONSTINIT static bool qt_locale_initialized = false; @@ -2411,7 +2411,7 @@ static QString qAppFileName() # elif defined(Q_OS_LINUX) // this includes the Embedded Android builds return QFile::decodeName(qt_readlink("/proc/self/exe")); -# elif defined(AT_EXECPATH) +# elif defined(AT_EXECPATH) && !defined(Q_OS_GENODE) // seen on FreeBSD, but I suppose the other BSDs could adopt this API char execfn[PATH_MAX]; if (elf_aux_info(AT_EXECPATH, execfn, sizeof(execfn)) != 0) diff --git a/src/corelib/plugin/qlibrary_unix.cpp b/src/corelib/plugin/qlibrary_unix.cpp index 84f572a0..3f5dbad9 100644 --- a/src/corelib/plugin/qlibrary_unix.cpp +++ b/src/corelib/plugin/qlibrary_unix.cpp @@ -163,7 +163,7 @@ bool QLibraryPrivate::load_sys() prefixes.append(QString()); } -#if defined(Q_PROCESSOR_X86) && !defined(Q_OS_DARWIN) +#if defined(Q_PROCESSOR_X86) && !defined(Q_OS_DARWIN) && !defined(Q_OS_GENODE) if (qCpuHasFeature(ArchHaswell)) { auto transform = [](QStringList &list, void (*f)(QString *)) { QStringList tmp; diff --git a/src/corelib/plugin/qplugin.h b/src/corelib/plugin/qplugin.h index 909c8acd..36d65803 100644 --- a/src/corelib/plugin/qplugin.h +++ b/src/corelib/plugin/qplugin.h @@ -165,7 +165,7 @@ template class QPluginMetaDataV2 #if defined(QT_STATICPLUGIN) # define QT_PLUGIN_METADATAV2_SECTION using Payload = StaticPayload; -#elif defined(Q_OF_ELF) +#elif defined(Q_OF_ELF) && !defined(Q_OS_GENODE) # ifdef Q_CC_CLANG # define QT_PLUGIN_METADATAV2_SECTION \ __attribute__((section(".note.qt.metadata"), used, aligned(alignof(void *)), \ diff --git a/src/corelib/thread/qthread.h b/src/corelib/thread/qthread.h index 40f363ee..32c536d4 100644 --- a/src/corelib/thread/qthread.h +++ b/src/corelib/thread/qthread.h @@ -158,12 +158,12 @@ inline Qt::HANDLE QThread::currentThreadId() noexcept Qt::HANDLE tid; // typedef to void* static_assert(sizeof(tid) == sizeof(void*)); // See https://akkadia.org/drepper/tls.pdf for x86 ABI -#if defined(Q_PROCESSOR_X86_32) && ((defined(Q_OS_LINUX) && defined(__GLIBC__)) || defined(Q_OS_FREEBSD)) // x86 32-bit always uses GS +#if defined(Q_PROCESSOR_X86_32) && ((defined(Q_OS_LINUX) && defined(__GLIBC__)) || defined(Q_OS_FREEBSD)) && !defined(Q_OS_GENODE) // x86 32-bit always uses GS __asm__("movl %%gs:%c1, %0" : "=r" (tid) : "i" (2 * sizeof(void*)) : ); #elif defined(Q_PROCESSOR_X86_64) && defined(Q_OS_DARWIN) // 64bit macOS uses GS, see https://github.com/apple/darwin-xnu/blob/master/libsyscall/os/tsd.h __asm__("movq %%gs:0, %0" : "=r" (tid) : : ); -#elif defined(Q_PROCESSOR_X86_64) && ((defined(Q_OS_LINUX) && defined(__GLIBC__)) || defined(Q_OS_FREEBSD)) +#elif defined(Q_PROCESSOR_X86_64) && ((defined(Q_OS_LINUX) && defined(__GLIBC__)) || defined(Q_OS_FREEBSD)) && !defined(Q_OS_GENODE) // x86_64 Linux, BSD uses FS __asm__("movq %%fs:%c1, %0" : "=r" (tid) : "i" (2 * sizeof(void*)) : ); #elif defined(Q_PROCESSOR_X86_64) && defined(Q_OS_WIN) diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index 6694235f..ce4acc5c 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -61,7 +61,7 @@ # define SCHED_IDLE 5 #endif -#if defined(Q_OS_DARWIN) || !defined(Q_OS_ANDROID) && !defined(Q_OS_OPENBSD) && defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && (_POSIX_THREAD_PRIORITY_SCHEDULING-0 >= 0) +#if (defined(Q_OS_DARWIN) || !defined(Q_OS_ANDROID) && !defined(Q_OS_OPENBSD) && defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && (_POSIX_THREAD_PRIORITY_SCHEDULING-0 >= 0)) && !defined(Q_OS_GENODE) #define QT_HAS_THREAD_PRIORITY_SCHEDULING #endif @@ -414,7 +414,7 @@ int QThread::idealThreadCount() noexcept } else { cores = (int)psd.psd_proc_cnt; } -#elif (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) || defined(Q_OS_FREEBSD) +#elif ((defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)) || defined(Q_OS_FREEBSD)) && !defined(Q_OS_GENODE) # if defined(Q_OS_FREEBSD) && !defined(CPU_COUNT_S) # define CPU_COUNT_S(setsize, cpusetp) ((int)BIT_COUNT(setsize, cpusetp)) // match the Linux API for simplicity @@ -437,7 +437,7 @@ int QThread::idealThreadCount() noexcept return 1; } cores = CPU_COUNT_S(sizeof(cpu_set_t) * size, cpuset.data()); -#elif defined(Q_OS_BSD4) +#elif defined(Q_OS_BSD4) && !defined(Q_OS_GENODE) // OpenBSD, NetBSD, BSD/OS, Darwin (macOS, iOS, etc.) size_t len = sizeof(cores); int mib[2]; diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index dded14bb..83645896 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -343,7 +343,8 @@ if(QT_FEATURE_opengl) endif() elseif(NOT QT_FEATURE_opengl_dynamic) - target_link_libraries(Gui PUBLIC WrapOpenGL::WrapOpenGL) +# target_link_libraries(Gui PUBLIC WrapOpenGL::WrapOpenGL) + target_link_libraries(Gui PUBLIC mesa egl) endif() endif() @@ -439,7 +440,8 @@ qt_internal_extend_target(Gui CONDITION QT_FEATURE_egl opengl/platform/egl/qeglstreamconvenience.cpp opengl/platform/egl/qeglstreamconvenience_p.h opengl/platform/egl/qt_egl_p.h LIBRARIES - EGL::EGL +# EGL::EGL + egl ) # These two headers are always installed, their contents are guarded with diff --git a/src/gui/configure.cmake b/src/gui/configure.cmake index 222073ad..09b9ed74 100644 --- a/src/gui/configure.cmake +++ b/src/gui/configure.cmake @@ -767,7 +767,7 @@ qt_feature("opengles32" PUBLIC qt_feature("opengl-desktop" LABEL "Desktop OpenGL" AUTODETECT NOT WIN32 - CONDITION ( WIN32 AND ( MSVC OR WrapOpenGL_FOUND ) ) OR ( NOT WATCHOS AND NOT WIN32 AND NOT WASM AND WrapOpenGL_FOUND ) + #CONDITION ( WIN32 AND ( MSVC OR WrapOpenGL_FOUND ) ) OR ( NOT WATCHOS AND NOT WIN32 AND NOT WASM AND WrapOpenGL_FOUND ) ENABLE INPUT_opengl STREQUAL 'desktop' DISABLE INPUT_opengl STREQUAL 'es2' OR INPUT_opengl STREQUAL 'dynamic' OR INPUT_opengl STREQUAL 'no' ) @@ -806,7 +806,7 @@ qt_feature("openvg" PUBLIC ) qt_feature("egl" PUBLIC LABEL "EGL" - CONDITION ( QT_FEATURE_opengl OR QT_FEATURE_openvg ) AND EGL_FOUND AND ( QT_FEATURE_dlopen OR NOT UNIX OR INTEGRITY ) + CONDITION ( QT_FEATURE_opengl OR QT_FEATURE_openvg ) AND ( QT_FEATURE_dlopen OR NOT UNIX OR INTEGRITY ) ) qt_feature_definition("egl" "QT_NO_EGL" NEGATE VALUE "1") qt_feature("egl_x11" PRIVATE @@ -915,7 +915,7 @@ qt_feature("xcb" PUBLIC SECTION "Platform plugins" LABEL "XCB" AUTODETECT NOT APPLE - CONDITION QT_FEATURE_thread AND TARGET XCB::XCB AND TEST_xcb_syslibs AND QT_FEATURE_xkbcommon_x11 + CONDITION QT_FEATURE_thread AND TARGET XCB::XCB AND QT_FEATURE_xkbcommon_x11 ) qt_feature("xcb-glx-plugin" PUBLIC LABEL "GLX Plugin" diff --git a/src/network/configure.cmake b/src/network/configure.cmake index f24f739c..52b754e2 100644 --- a/src/network/configure.cmake +++ b/src/network/configure.cmake @@ -7,7 +7,7 @@ #### Libraries -qt_find_package(WrapBrotli PROVIDED_TARGETS WrapBrotli::WrapBrotliDec MODULE_NAME network QMAKE_LIB brotli) +#qt_find_package(WrapBrotli PROVIDED_TARGETS WrapBrotli::WrapBrotliDec MODULE_NAME network QMAKE_LIB brotli) qt_find_package(Libproxy PROVIDED_TARGETS PkgConfig::Libproxy MODULE_NAME network QMAKE_LIB libproxy) qt_find_package(GSSAPI PROVIDED_TARGETS GSSAPI::GSSAPI MODULE_NAME network QMAKE_LIB gssapi) qt_find_package(GLIB2 OPTIONAL_COMPONENTS GOBJECT PROVIDED_TARGETS GLIB2::GOBJECT MODULE_NAME core QMAKE_LIB gobject) diff --git a/src/network/kernel/qnetworkinterface_unix.cpp b/src/network/kernel/qnetworkinterface_unix.cpp index 082d83e9..234e1d06 100644 --- a/src/network/kernel/qnetworkinterface_unix.cpp +++ b/src/network/kernel/qnetworkinterface_unix.cpp @@ -377,7 +377,7 @@ static void getAddressExtraInfo(QNetworkAddressEntry *entry, struct sockaddr *sa Q_UNUSED(ifname); } -# elif defined(Q_OS_BSD4) +# elif defined(Q_OS_BSD4) && 0 QT_BEGIN_INCLUDE_NAMESPACE # include #if defined(QT_PLATFORM_UIKIT) diff --git a/src/platformsupport/devicediscovery/qdevicediscovery_static.cpp b/src/platformsupport/devicediscovery/qdevicediscovery_static.cpp index 03a77aaa..2a104c7e 100644 --- a/src/platformsupport/devicediscovery/qdevicediscovery_static.cpp +++ b/src/platformsupport/devicediscovery/qdevicediscovery_static.cpp @@ -11,11 +11,7 @@ #include #include -#ifdef Q_OS_FREEBSD -#include -#else #include -#endif #include /* android (and perhaps some other linux-derived stuff) don't define everything diff --git a/src/platformsupport/devicediscovery/qdevicediscovery_udev.cpp b/src/platformsupport/devicediscovery/qdevicediscovery_udev.cpp index 45043818..6c20c806 100644 --- a/src/platformsupport/devicediscovery/qdevicediscovery_udev.cpp +++ b/src/platformsupport/devicediscovery/qdevicediscovery_udev.cpp @@ -10,11 +10,7 @@ #include #include -#ifdef Q_OS_FREEBSD -#include -#else #include -#endif QT_BEGIN_NAMESPACE diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboard_defaultmap_p.h b/src/platformsupport/input/evdevkeyboard/qevdevkeyboard_defaultmap_p.h index 02ed8463..95bcb453 100644 --- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboard_defaultmap_p.h +++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboard_defaultmap_p.h @@ -17,11 +17,7 @@ #include "qnamespace.h" #include "private/qglobal_p.h" -#ifdef Q_OS_FREEBSD -#include -#else #include "linux/input.h" -#endif // no QT_BEGIN_NAMESPACE, since we include it internally... diff --git a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp index 48fba799..876986a5 100644 --- a/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp +++ b/src/platformsupport/input/evdevkeyboard/qevdevkeyboardhandler.cpp @@ -17,11 +17,7 @@ #include #include -#ifdef Q_OS_FREEBSD -#include -#else #include -#endif #ifndef input_event_sec #define input_event_sec time.tv_sec diff --git a/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp b/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp index 8d98cb1e..27ed635a 100644 --- a/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp +++ b/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp @@ -17,12 +17,7 @@ #include -#ifdef Q_OS_FREEBSD -#include -#else -#include #include -#endif #define TEST_BIT(array, bit) (array[bit/8] & (1<<(bit%8))) diff --git a/src/platformsupport/input/evdevtablet/qevdevtablethandler.cpp b/src/platformsupport/input/evdevtablet/qevdevtablethandler.cpp index 109ab0f2..045fb93b 100644 --- a/src/platformsupport/input/evdevtablet/qevdevtablethandler.cpp +++ b/src/platformsupport/input/evdevtablet/qevdevtablethandler.cpp @@ -10,11 +10,7 @@ #include #include #include -#ifdef Q_OS_FREEBSD -#include -#else #include -#endif QT_BEGIN_NAMESPACE diff --git a/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp b/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp index 09375393..4adb5d0c 100644 --- a/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp +++ b/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp @@ -17,11 +17,7 @@ #include -#ifdef Q_OS_FREEBSD -#include -#else #include -#endif #ifndef input_event_sec #define input_event_sec time.tv_sec diff --git a/src/plugins/platforms/CMakeLists.txt b/src/plugins/platforms/CMakeLists.txt index 69071a22..ec90fbaa 100644 --- a/src/plugins/platforms/CMakeLists.txt +++ b/src/plugins/platforms/CMakeLists.txt @@ -1,6 +1,10 @@ # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: BSD-3-Clause +add_subdirectory(genode) + +if(FALSE) + if(ANDROID) add_subdirectory(android) endif() @@ -56,3 +60,5 @@ endif() if(QT_FEATURE_vkkhrdisplay) add_subdirectory(vkkhrdisplay) endif() + +endif() diff --git a/src/plugins/platforms/genode/CMakeLists.txt b/src/plugins/platforms/genode/CMakeLists.txt new file mode 100644 index 00000000..a28291e4 --- /dev/null +++ b/src/plugins/platforms/genode/CMakeLists.txt @@ -0,0 +1,28 @@ +qt_internal_add_plugin(QGenodeIntegrationPlugin + OUTPUT_NAME qgenode + PLUGIN_TYPE platforms + DEFAULT_IF ${QT_QPA_DEFAULT_PLATFORM} MATCHES genode + SOURCES + main.cpp + qgenodeclipboard.cpp + qgenodecursor.cpp + qgenodeglcontext.cpp + qgenodeintegration.cpp + qgenodeplatformwindow.cpp + qgenodewindowsurface.cpp + qgenodeclipboard.h + qgenodeintegrationplugin.h + qgenodeplatformwindow.h + qgenodescreen.h + qgenodesignalproxythread.h + qgenodewindowsurface.h + DEFINES + QT_NO_FOREACH + EXCEPTIONS + LIBRARIES + Qt::Core + Qt::CorePrivate + Qt::Gui + Qt::GuiPrivate + ld +) diff --git a/src/plugins/platforms/genode/genode.json b/src/plugins/platforms/genode/genode.json new file mode 100644 index 00000000..604fac48 --- /dev/null +++ b/src/plugins/platforms/genode/genode.json @@ -0,0 +1,3 @@ +{ + "Keys": [ "genode" ] +} diff --git a/src/plugins/platforms/genode/genode.pro b/src/plugins/platforms/genode/genode.pro new file mode 100644 index 00000000..a2869172 --- /dev/null +++ b/src/plugins/platforms/genode/genode.pro @@ -0,0 +1,38 @@ +TARGET = qgenode + +QT += \ + core-private \ + egl_support-private \ + eventdispatcher_support-private \ + fontdatabase_support-private \ + gui-private + +CONFIG += exceptions c++2a + +DEFINES += QT_NO_FOREACH + +SOURCES = main.cpp \ + qgenodeclipboard.cpp \ + qgenodecursor.cpp \ + qgenodeglcontext.cpp \ + qgenodeintegration.cpp \ + qgenodeplatformwindow.cpp \ + qgenodewindowsurface.cpp + +HEADERS = qgenodeclipboard.h \ + qgenodeintegrationplugin.h \ + qgenodeplatformwindow.h \ + qgenodescreen.h \ + qgenodesignalproxythread.h \ + qgenodewindowsurface.h + +OTHER_FILES += genode.json + +LIBS += -l:ld.lib.so + +qtConfig(freetype): QMAKE_USE_PRIVATE += freetype + +PLUGIN_TYPE = platforms +PLUGIN_CLASS_NAME = QGenodeIntegrationPlugin +!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = - +load(qt_plugin) diff --git a/src/plugins/platforms/genode/main.cpp b/src/plugins/platforms/genode/main.cpp new file mode 100644 index 00000000..f28eb9d1 --- /dev/null +++ b/src/plugins/platforms/genode/main.cpp @@ -0,0 +1,51 @@ +/* + * \brief Genode QPA plugin + * \author Christian Prochaska + * \date 2013-05-08 + */ + +/* + * Copyright (C) 2013-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +/* libc includes */ +#include + +/* Qt includes */ +#include "qgenodeintegrationplugin.h" + +Genode::Env *QGenodeIntegrationPlugin::_env = nullptr; + +extern "C" void initialize_qpa_plugin(Genode::Env &env) __attribute__ ((visibility ("default"))); +void initialize_qpa_plugin(Genode::Env &env) +{ + QGenodeIntegrationPlugin::env(env); +} + + +QT_BEGIN_NAMESPACE + + +QStringList QGenodeIntegrationPlugin::keys() const +{ + QStringList list; + list << "Gui"; + return list; +} + + +QPlatformIntegration *QGenodeIntegrationPlugin::create(const QString& system, const QStringList& paramList) +{ + Q_UNUSED(paramList); + if (system.toLower() == "genode") { + assert(_env != nullptr); + return new QGenodeIntegration(*_env); + } + + return 0; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/genode/qgenodeclipboard.cpp b/src/plugins/platforms/genode/qgenodeclipboard.cpp new file mode 100644 index 00000000..615eff59 --- /dev/null +++ b/src/plugins/platforms/genode/qgenodeclipboard.cpp @@ -0,0 +1,149 @@ +/* + * \brief QGenodeClipboard + * \author Christian Prochaska + * \date 2015-09-18 + */ + +/* + * Copyright (C) 2015-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#include "qgenodeclipboard.h" + +#ifndef QT_NO_CLIPBOARD + +/* Genode includes */ +#include + +/* Qt includes */ +#include + +QT_BEGIN_NAMESPACE + + +static constexpr bool verbose = false; + + +QGenodeClipboard::QGenodeClipboard(Genode::Env &env, QGenodeSignalProxyThread &signal_proxy) +: _signal_proxy(signal_proxy), + _clipboard_signal_handler(env.ep(), *this, &QGenodeClipboard::_handle_clipboard_changed) +{ + try { + + Genode::Attached_rom_dataspace config(env, "config"); + + if (config.xml().attribute_value("clipboard", false)) { + + try { + + _clipboard_ds = new Genode::Attached_rom_dataspace(env, "clipboard"); + + _clipboard_ds->sigh(_clipboard_signal_handler); + _clipboard_ds->update(); + + } catch (...) { } + + try { + _clipboard_reporter = new Genode::Reporter(env, "clipboard"); + _clipboard_reporter->enabled(true); + } catch (...) { } + + } + } catch (...) { } + + connect(&_signal_proxy, SIGNAL(clipboard_changed_signal()), + this, SLOT(_clipboard_changed()), + Qt::QueuedConnection); +} + + +QGenodeClipboard::~QGenodeClipboard() +{ + free(_decoded_clipboard_content); + delete _clipboard_ds; + delete _clipboard_reporter; +} + + +void QGenodeClipboard::_handle_clipboard_changed() +{ + _signal_proxy.clipboard_changed(); +} + + +void QGenodeClipboard::_clipboard_changed() +{ + emitChanged(QClipboard::Clipboard); +} + + +QMimeData *QGenodeClipboard::mimeData(QClipboard::Mode mode) +{ + if (!supportsMode(mode) || !_clipboard_ds) + return 0; + + _clipboard_ds->update(); + + if (!_clipboard_ds->valid()) { + if (verbose) + Genode::error("invalid clipboard dataspace"); + return 0; + } + + char *xml_data = _clipboard_ds->local_addr(); + + try { + Genode::Xml_node node(xml_data); + + if (!node.has_type("clipboard")) { + Genode::error("invalid clipboard xml syntax"); + return 0; + } + + free(_decoded_clipboard_content); + + _decoded_clipboard_content = (char*)malloc(node.content_size()); + + if (!_decoded_clipboard_content) { + Genode::error("could not allocate buffer for decoded clipboard content"); + return 0; + } + + _mimedata->setText(QString::fromUtf8(_decoded_clipboard_content, + node.decoded_content(_decoded_clipboard_content, + node.content_size()))); + + } catch (Genode::Xml_node::Invalid_syntax) { + Genode::error("invalid clipboard xml syntax"); + return 0; + } + + return _mimedata; +} + + +void QGenodeClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode) +{ + if (!data || !data->hasText() || !supportsMode(mode)) + return; + + QString text = data->text(); + QByteArray utf8text = text.toUtf8(); + + if (!_clipboard_reporter) + return; + + try { + Genode::Reporter::Xml_generator xml(*_clipboard_reporter, [&] () { + xml.append_sanitized(utf8text.constData(), utf8text.size()); }); + } catch (...) { + Genode::error("could not write clipboard data"); + } +} + +QT_END_NAMESPACE + +#endif /* QT_NO_CLIPBOARD */ diff --git a/src/plugins/platforms/genode/qgenodeclipboard.h b/src/plugins/platforms/genode/qgenodeclipboard.h new file mode 100644 index 00000000..ca5d6b95 --- /dev/null +++ b/src/plugins/platforms/genode/qgenodeclipboard.h @@ -0,0 +1,74 @@ +/* + * \brief QGenodeClipboard + * \author Christian Prochaska + * \date 2015-09-18 + */ + +/* + * Copyright (C) 2015-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _QGENODECLIPBOARD_H_ +#define _QGENODECLIPBOARD_H_ + +#include + +#ifndef QT_NO_CLIPBOARD + +/* Genode includes */ +#include +#include +#include + +/* Qt includes */ +#include + +/* local includes */ +#include "qgenodesignalproxythread.h" + +QT_BEGIN_NAMESPACE + +class QGenodeClipboard : public QObject, public QPlatformClipboard +{ + Q_OBJECT + + private: + + QGenodeSignalProxyThread &_signal_proxy; + + Genode::Attached_rom_dataspace *_clipboard_ds = nullptr; + Genode::Io_signal_handler _clipboard_signal_handler; + + void _handle_clipboard_changed(); + + Genode::Reporter *_clipboard_reporter = nullptr; + + char *_decoded_clipboard_content = nullptr; + + QMember _mimedata; + + /* + * Genode signals are handled as Qt signals to avoid blocking in the + * Genode signal handler, which could cause nested signal handler + * execution. + */ + + private Q_SLOTS: + + void _clipboard_changed(); + + public: + + QGenodeClipboard(Genode::Env &env, QGenodeSignalProxyThread &signal_proxy); + ~QGenodeClipboard(); + QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard) override; + void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard) override; +}; + +QT_END_NAMESPACE + +#endif /* QT_NO_CLIPBOARD */ +#endif /* _QGENODECLIPBOARD_H_ */ diff --git a/src/plugins/platforms/genode/qgenodecursor.cpp b/src/plugins/platforms/genode/qgenodecursor.cpp new file mode 100644 index 00000000..c17908c0 --- /dev/null +++ b/src/plugins/platforms/genode/qgenodecursor.cpp @@ -0,0 +1,79 @@ +/* + * \brief QGenodeCursor + * \author Christian Prochaska + * \date 2017-11-13 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + + +/* Genode includes */ +#include + +/* Qt includes */ +#include +#include "qgenodecursor.h" + +QT_BEGIN_NAMESPACE + +QGenodeCursor::QGenodeCursor(Genode::Env &env) +{ + try { + _shape_report_connection.construct(env, "shape", sizeof(Pointer::Shape_report)); + _shape_report_ds.construct(env.rm(), _shape_report_connection->dataspace()); + _shape_report = _shape_report_ds->local_addr(); + } catch (Genode::Service_denied) { } +} + +void QGenodeCursor::changeCursor(QCursor *widgetCursor, QWindow *window) +{ + Q_UNUSED(window); + +#ifndef QT_NO_CURSOR + + if (!_shape_report) + return; + + const Qt::CursorShape shape = widgetCursor ? + widgetCursor->shape() : + Qt::ArrowCursor; + + _shape_report->visible = (shape != Qt::BlankCursor); + + QImage cursor; + + if (shape == Qt::BitmapCursor) { + // application supplied cursor + cursor = widgetCursor->pixmap().toImage(); + _shape_report->x_hot = widgetCursor->hotSpot().x(); + _shape_report->y_hot = widgetCursor->hotSpot().y(); + } else { + // system cursor + QPlatformCursorImage platformImage(0, 0, 0, 0, 0, 0); + platformImage.set(shape); + cursor = *platformImage.image(); + _shape_report->x_hot = platformImage.hotspot().x(); + _shape_report->y_hot = platformImage.hotspot().y(); + } + + cursor = cursor.convertToFormat(QImage::Format_RGBA8888); + + _shape_report->width = cursor.width(); + _shape_report->height = cursor.height(); + + memcpy(_shape_report->shape, cursor.constBits(), + cursor.width() * cursor.height() * 4); + + _shape_report_connection->submit(sizeof(Pointer::Shape_report)); + +#else // !QT_NO_CURSOR + Q_UNUSED(widgetCursor); +#endif +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/genode/qgenodecursor.h b/src/plugins/platforms/genode/qgenodecursor.h new file mode 100644 index 00000000..63ddc442 --- /dev/null +++ b/src/plugins/platforms/genode/qgenodecursor.h @@ -0,0 +1,45 @@ +/* + * \brief QGenodeCursor + * \author Christian Prochaska + * \date 2017-11-13 + */ + +/* + * Copyright (C) 2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + + +#ifndef _QGENODECURSOR_H_ +#define _QGENODECURSOR_H_ + +/* Genode includes */ +#include +#include +#include + +/* Qt includes */ +#include + +QT_BEGIN_NAMESPACE + +class QGenodeCursor : public QPlatformCursor +{ + private: + + Genode::Constructible _shape_report_connection; + Genode::Constructible _shape_report_ds; + Pointer::Shape_report *_shape_report { nullptr }; + + public: + + QGenodeCursor(Genode::Env &env); + + virtual void changeCursor(QCursor *widgetCursor, QWindow *window) override; +}; + +QT_END_NAMESPACE + +#endif /* _QGENODECURSOR_H_ */ diff --git a/src/plugins/platforms/genode/qgenodeglcontext.cpp b/src/plugins/platforms/genode/qgenodeglcontext.cpp new file mode 100644 index 00000000..5cee103d --- /dev/null +++ b/src/plugins/platforms/genode/qgenodeglcontext.cpp @@ -0,0 +1,61 @@ +/* + * \brief QGenodeGLContext + * \author Christian Prochaska + * \date 2013-11-18 + */ + +/* + * Copyright (C) 2013-2022 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +/* Genode includes */ +#include + +/* EGL includes */ +#include + +/* Qt includes */ +#include +#include +//#include +//#include + +/* local includes */ +#include "qgenodeplatformwindow.h" +#include "qgenodeglcontext.h" + +static const bool qnglc_verbose = false; + +QT_BEGIN_NAMESPACE + +QGenodeGLContext::QGenodeGLContext(const QSurfaceFormat &format, + QPlatformOpenGLContext *share, + EGLDisplay egl_display) +: QEGLPlatformContext(format, share, egl_display, 0) { } + + +EGLSurface QGenodeGLContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface) +{ + if (surface->surface()->surfaceClass() == QSurface::Window) { + return static_cast(surface)->eglSurface(eglConfig()); + } else { + return static_cast(surface)->pbuffer(); + } +} + + +void QGenodeGLContext::swapBuffers(QPlatformSurface *surface) +{ + if (qnglc_verbose) + Genode::log(__func__, " called"); + + QEGLPlatformContext::swapBuffers(surface); + + QGenodePlatformWindow *w = static_cast(surface); + w->refresh(0, 0, w->geometry().width(), w->geometry().height()); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/genode/qgenodeglcontext.h b/src/plugins/platforms/genode/qgenodeglcontext.h new file mode 100644 index 00000000..37cc32dd --- /dev/null +++ b/src/plugins/platforms/genode/qgenodeglcontext.h @@ -0,0 +1,43 @@ +/* + * \brief QGenodeGLContext + * \author Christian Prochaska + * \date 2013-11-18 + */ + +/* + * Copyright (C) 2013-2022 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef QGENODEGLCONTEXT_H +#define QGENODEGLCONTEXT_H + +#include +#include + +#include + + +QT_BEGIN_NAMESPACE + + +class QGenodeGLContext : public QEGLPlatformContext +{ + public: + + QGenodeGLContext(const QSurfaceFormat &format, + QPlatformOpenGLContext *share, + EGLDisplay egl_display); + + void swapBuffers(QPlatformSurface *surface) final; + + protected: + + EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) final; +}; + +QT_END_NAMESPACE + +#endif // QGENODEGLCONTEXT_H diff --git a/src/plugins/platforms/genode/qgenodeintegration.cpp b/src/plugins/platforms/genode/qgenodeintegration.cpp new file mode 100644 index 00000000..61630743 --- /dev/null +++ b/src/plugins/platforms/genode/qgenodeintegration.cpp @@ -0,0 +1,160 @@ +/* + * \brief QGenodeIntegration + * \author Christian Prochaska + * \date 2013-05-08 + */ + +/* + * Copyright (C) 2013-2022 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +/* Qt includes */ +#include +#include +#include + +#include "qgenodeclipboard.h" +#include "qgenodeglcontext.h" +#include "qgenodeintegration.h" +#include "qgenodeplatformwindow.h" +#include "qgenodescreen.h" +#include "qgenodewindowsurface.h" +#include "QtGui/private/qeglpbuffer_p.h" +#include "QtGui/private/qgenericunixeventdispatcher_p.h" +#include "QtGui/private/qfreetypefontdatabase_p.h" + +QT_BEGIN_NAMESPACE + +static const bool verbose = false; + + +QGenodeIntegration::QGenodeIntegration(Genode::Env &env) +: _env(env), + _genode_screen(new QGenodeScreen(env, _signal_proxy)) +{ + if (!eglBindAPI(EGL_OPENGL_API)) + qFatal("eglBindAPI() failed"); + + m_eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); + + if (m_eglDisplay == EGL_NO_DISPLAY) + qFatal("eglGetDisplay() failed"); + + int major = -1; + int minor = -1; + if (!eglInitialize(m_eglDisplay, &major, &minor)) + qFatal("eglInitialize() failed"); + + if (verbose) + Genode::log("eglInitialize() returned major: ", major, ", minor: ", minor); +} + + +bool QGenodeIntegration::hasCapability(QPlatformIntegration::Capability cap) const +{ + switch (cap) { + case ThreadedPixmaps: return true; + case OpenGL: return true; + case ThreadedOpenGL: return true; + case RasterGLSurface: return true; + default: return QPlatformIntegration::hasCapability(cap); + } +} + + +QPlatformWindow *QGenodeIntegration::createPlatformWindow(QWindow *window) const +{ + if (verbose) + qDebug() << "QGenodeIntegration::createPlatformWindow(" << window << ")"; + + return new QGenodePlatformWindow(_env, _signal_proxy, window, m_eglDisplay); +} + + +QPlatformBackingStore *QGenodeIntegration::createPlatformBackingStore(QWindow *window) const +{ + if (verbose) + qDebug() << "QGenodeIntegration::createPlatformBackingStore(" << window << ")"; + return new QGenodeWindowSurface(window); +} + + +QAbstractEventDispatcher *QGenodeIntegration::createEventDispatcher() const +{ + if (verbose) + qDebug() << "QGenodeIntegration::createEventDispatcher()"; + return createUnixEventDispatcher(); +} + + +void QGenodeIntegration::initialize() +{ + QWindowSystemInterface::handleScreenAdded(_genode_screen); + + QString icStr = QPlatformInputContextFactory::requested(); + if (icStr.isNull()) + icStr = QLatin1String("compose"); + m_inputContext.reset(QPlatformInputContextFactory::create(icStr)); +} + + +QPlatformFontDatabase *QGenodeIntegration::fontDatabase() const +{ + static QFreeTypeFontDatabase db; + return &db; +} + + +#ifndef QT_NO_CLIPBOARD +QPlatformClipboard *QGenodeIntegration::clipboard() const +{ + static QGenodeClipboard cb(_env, _signal_proxy); + return &cb; +} +#endif + + +QPlatformOffscreenSurface *QGenodeIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const +{ + return new QEGLPbuffer(m_eglDisplay, surface->requestedFormat(), surface); +} + +QPlatformOpenGLContext *QGenodeIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const +{ + QSurfaceFormat format(context->format()); + + return new QGenodeGLContext(format, context->shareHandle(), m_eglDisplay); +} + +QPlatformInputContext *QGenodeIntegration::inputContext() const +{ + return m_inputContext.data(); +} + +QPlatformNativeInterface *QGenodeIntegration::nativeInterface() const +{ + return const_cast(this); +} + +void *QGenodeIntegration::nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) +{ + if (resource == "eglconfig") { + if (context->handle()) + return static_cast(context->handle())->eglConfig(); + } + + return nullptr; +} + +void *QGenodeIntegration::nativeResourceForIntegration(const QByteArray &resource) +{ + if (resource == "egldisplay") + return m_eglDisplay; + + return nullptr; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/genode/qgenodeintegration.h b/src/plugins/platforms/genode/qgenodeintegration.h new file mode 100644 index 00000000..8637ee17 --- /dev/null +++ b/src/plugins/platforms/genode/qgenodeintegration.h @@ -0,0 +1,74 @@ +/* + * \brief QGenodeIntegration + * \author Christian Prochaska + * \date 2013-05-08 + */ + +/* + * Copyright (C) 2013-2022 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + + +#ifndef _QGENODEINTEGRATION_H_ +#define _QGENODEINTEGRATION_H_ + +#include + +#include + +#include +#include +#include +#include + +#include "qgenodescreen.h" +#include "qgenodesignalproxythread.h" + +QT_BEGIN_NAMESPACE + +class QGenodeIntegration : public QPlatformIntegration, public QPlatformNativeInterface +{ + private: + + Genode::Env &_env; + mutable QGenodeSignalProxyThread _signal_proxy; + QGenodeScreen *_genode_screen; + QScopedPointer m_inputContext; + EGLDisplay m_eglDisplay; + + public: + + QGenodeIntegration(Genode::Env &env); + + void initialize() Q_DECL_OVERRIDE; + bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE; + + QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE; + QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const Q_DECL_OVERRIDE; + + QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE; + + QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE; + +#ifndef QT_NO_CLIPBOARD + QPlatformClipboard *clipboard() const Q_DECL_OVERRIDE; +#endif + QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const Q_DECL_OVERRIDE; + + QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE; + + QPlatformInputContext *inputContext() const Q_DECL_OVERRIDE; + + QPlatformNativeInterface *nativeInterface() const override; + + // QPlatformNativeInterface + void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) override; + void *nativeResourceForIntegration(const QByteArray &resource) override; +}; + +QT_END_NAMESPACE + +#endif /* _QGENODEINTEGRATION_H_ */ diff --git a/src/plugins/platforms/genode/qgenodeintegrationplugin.h b/src/plugins/platforms/genode/qgenodeintegrationplugin.h new file mode 100644 index 00000000..b1e79837 --- /dev/null +++ b/src/plugins/platforms/genode/qgenodeintegrationplugin.h @@ -0,0 +1,43 @@ +/* + * \brief Genode QPA plugin + * \author Christian Prochaska + * \date 2013-05-08 + */ + +/* + * Copyright (C) 2013-2017 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _QGENODEINTEGRATIONPLUGIN_H_ +#define _QGENODEINTEGRATIONPLUGIN_H_ + +/* Genode includes */ +#include + +/* Qt includes */ +#include +#include "qgenodeintegration.h" + +QT_BEGIN_NAMESPACE + +class QGenodeIntegrationPlugin : public QPlatformIntegrationPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QPlatformIntegrationFactoryInterface_iid FILE "genode.json") + +private: + static Genode::Env *_env; + +public: + QStringList keys() const; + QPlatformIntegration *create(const QString&, const QStringList&) override; + + static void env(Genode::Env &env) { _env = &env; } +}; + +QT_END_NAMESPACE + +#endif /* _QGENODEINTEGRATIONPLUGIN_H_ */ diff --git a/src/plugins/platforms/genode/qgenodeplatformwindow.cpp b/src/plugins/platforms/genode/qgenodeplatformwindow.cpp new file mode 100644 index 00000000..84d1216e --- /dev/null +++ b/src/plugins/platforms/genode/qgenodeplatformwindow.cpp @@ -0,0 +1,1104 @@ +/* + * \brief QGenodePlatformWindow + * \author Christian Prochaska + * \author Christian Helmuth + * \date 2013-05-08 + */ + +/* + * Copyright (C) 2013-2022 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + + +/* Genode includes */ +#include +#include + +/* Qt includes */ +#include +#include +#include +#include + +#include "qgenodeplatformwindow.h" +#include "qgenodesignalproxythread.h" + +QT_BEGIN_NAMESPACE + +static const bool qnpw_verbose = false/*true*/; + +QStringList QGenodePlatformWindow::_gui_session_label_list; + +QPointingDevice * QGenodePlatformWindow::_init_touch_device() +{ + QVector::iterator i = _touch_points.begin(); + for (unsigned n = 0; i != _touch_points.end(); ++i, ++n) { + i->id = n; + i->state = QEventPoint::State::Released; + } + + QPointingDevice *dev = + new QPointingDevice("Genode multi-touch device", + 0, + QInputDevice::DeviceType::TouchScreen, + QPointingDevice::PointerType::Finger, + QInputDevice::Capability::Position, + 16, + 0); + + QWindowSystemInterface::registerInputDevice(dev); + + return dev; +} + +void QGenodePlatformWindow::_process_touch_events(QList const &events) +{ + if (events.empty()) return; + + for (QList::const_iterator i = events.begin(); i != events.end(); ++i) { + + i->handle_touch([&] (Input::Touch_id id, int x, int y) { + QList touch_points; + + if (id.value >= _touch_points.size()) { + Genode::warning("drop touch input, out of bounds"); + return; + } + + QWindowSystemInterface::TouchPoint &otp = _touch_points[id.value]; + QWindowSystemInterface::TouchPoint tp; + + tp.id = id.value; + tp.area = QRectF(QPointF(0, 0), QSize(1, 1)); + + /* report 1x1 rectangular area centered at screen coordinates */ + tp.area.moveCenter(QPointF(x, y)); + + tp.state = otp.state == QEventPoint::State::Released + ? QEventPoint::State::Pressed : QEventPoint::State::Updated; + tp.pressure = 1; + + otp = tp; + touch_points.push_back(tp); + QWindowSystemInterface::handleTouchEvent(0, _touch_device, touch_points); + }); + + i->handle_touch_release([&] (Input::Touch_id id) { + QList touch_points; + + if (id.value >= _touch_points.size()) { + Genode::warning("drop touch input, out of bounds"); + return; + } + + QWindowSystemInterface::TouchPoint &otp = _touch_points[id.value]; + QWindowSystemInterface::TouchPoint tp; + + tp.id = id.value; + tp.area = otp.area; + tp.state = QEventPoint::State::Released; + tp.pressure = 0; + + otp = tp; + touch_points.push_back(tp); + QWindowSystemInterface::handleTouchEvent(0, _touch_device, touch_points); + }); + } +} + + +QGenodePlatformWindow::Mapped_key +QGenodePlatformWindow::_mapped_key_from_codepoint(Codepoint codepoint) +{ + /* special keys: function-key unicodes */ + switch (codepoint.value) { + case 0x0008: return Mapped_key { Qt::Key_Backspace }; + case 0x0009: return Mapped_key { Qt::Key_Tab }; + case 0x000a: return Mapped_key { Qt::Key_Return }; + case 0x001b: return Mapped_key { Qt::Key_Escape }; + case 0xf700: return Mapped_key { Qt::Key_Up }; + case 0xf701: return Mapped_key { Qt::Key_Down }; + case 0xf702: return Mapped_key { Qt::Key_Left }; + case 0xf703: return Mapped_key { Qt::Key_Right }; + case 0xf704: return Mapped_key { Qt::Key_F1 }; + case 0xf705: return Mapped_key { Qt::Key_F2 }; + case 0xf706: return Mapped_key { Qt::Key_F3 }; + case 0xf707: return Mapped_key { Qt::Key_F4 }; + case 0xf708: return Mapped_key { Qt::Key_F5 }; + case 0xf709: return Mapped_key { Qt::Key_F6 }; + case 0xf70a: return Mapped_key { Qt::Key_F7 }; + case 0xf70b: return Mapped_key { Qt::Key_F8 }; + case 0xf70c: return Mapped_key { Qt::Key_F9 }; + case 0xf70d: return Mapped_key { Qt::Key_F10 }; + case 0xf70e: return Mapped_key { Qt::Key_F11 }; + case 0xf70f: return Mapped_key { Qt::Key_F12 }; + case 0xf727: return Mapped_key { Qt::Key_Insert }; + case 0xf728: return Mapped_key { Qt::Key_Delete }; + case 0xf729: return Mapped_key { Qt::Key_Home }; + case 0xf72b: return Mapped_key { Qt::Key_End }; + case 0xf72c: return Mapped_key { Qt::Key_PageUp }; + case 0xf72d: return Mapped_key { Qt::Key_PageDown }; + default: break; + }; + + /* + * Qt key enums are equal to the corresponding Unicode codepoints of the + * upper-case character. + */ + + /* printable keys */ + if ((codepoint.value >= (unsigned)Qt::Key_Space) && + (codepoint.value <= (unsigned)Qt::Key_ydiaeresis)) + return Mapped_key { Qt::Key(QChar(codepoint.value).toUpper().unicode()), codepoint }; + + return Mapped_key { }; +} + + +QGenodePlatformWindow::Mapped_key QGenodePlatformWindow::_map_key(Input::Keycode key, + Codepoint codepoint, + Mapped_key::Event e) +{ + /* non-printable key mappings */ + switch (key) { + case Input::KEY_ENTER: return Mapped_key { Qt::Key_Return }; + case Input::KEY_KPENTER: return Mapped_key { Qt::Key_Return }; /* resolves aliasing on repeat */ + case Input::KEY_ESC: return Mapped_key { Qt::Key_Escape }; + case Input::KEY_TAB: return Mapped_key { Qt::Key_Tab }; + case Input::KEY_BACKSPACE: return Mapped_key { Qt::Key_Backspace }; + case Input::KEY_INSERT: return Mapped_key { Qt::Key_Insert }; + case Input::KEY_DELETE: return Mapped_key { Qt::Key_Delete }; + case Input::KEY_PRINT: return Mapped_key { Qt::Key_Print }; + case Input::KEY_CLEAR: return Mapped_key { Qt::Key_Clear }; + case Input::KEY_HOME: return Mapped_key { Qt::Key_Home }; + case Input::KEY_END: return Mapped_key { Qt::Key_End }; + case Input::KEY_LEFT: return Mapped_key { Qt::Key_Left }; + case Input::KEY_UP: return Mapped_key { Qt::Key_Up }; + case Input::KEY_RIGHT: return Mapped_key { Qt::Key_Right }; + case Input::KEY_DOWN: return Mapped_key { Qt::Key_Down }; + case Input::KEY_PAGEUP: return Mapped_key { Qt::Key_PageUp }; + case Input::KEY_PAGEDOWN: return Mapped_key { Qt::Key_PageDown }; + case Input::KEY_LEFTSHIFT: return Mapped_key { Qt::Key_Shift }; + case Input::KEY_RIGHTSHIFT: return Mapped_key { Qt::Key_Shift }; + case Input::KEY_LEFTCTRL: return Mapped_key { Qt::Key_Control }; + case Input::KEY_RIGHTCTRL: return Mapped_key { Qt::Key_Control }; + case Input::KEY_LEFTMETA: return Mapped_key { Qt::Key_Meta }; + case Input::KEY_RIGHTMETA: return Mapped_key { Qt::Key_Meta }; + case Input::KEY_LEFTALT: return Mapped_key { Qt::Key_Alt }; + case Input::KEY_RIGHTALT: return Mapped_key { Qt::Key_AltGr }; + case Input::KEY_COMPOSE: return Mapped_key { Qt::Key_Menu }; + case Input::KEY_CAPSLOCK: return Mapped_key { Qt::Key_CapsLock }; + case Input::KEY_SYSRQ: return Mapped_key { Qt::Key_SysReq }; + case Input::KEY_SCROLLLOCK: return Mapped_key { Qt::Key_ScrollLock }; + case Input::KEY_PAUSE: return Mapped_key { Qt::Key_Pause }; + case Input::KEY_F1: return Mapped_key { Qt::Key_F1 }; + case Input::KEY_F2: return Mapped_key { Qt::Key_F2 }; + case Input::KEY_F3: return Mapped_key { Qt::Key_F3 }; + case Input::KEY_F4: return Mapped_key { Qt::Key_F4 }; + case Input::KEY_F5: return Mapped_key { Qt::Key_F5 }; + case Input::KEY_F6: return Mapped_key { Qt::Key_F6 }; + case Input::KEY_F7: return Mapped_key { Qt::Key_F7 }; + case Input::KEY_F8: return Mapped_key { Qt::Key_F8 }; + case Input::KEY_F9: return Mapped_key { Qt::Key_F9 }; + case Input::KEY_F10: return Mapped_key { Qt::Key_F10 }; + case Input::KEY_F11: return Mapped_key { Qt::Key_F11 }; + case Input::KEY_F12: return Mapped_key { Qt::Key_F12 }; + case Input::KEY_F13: return Mapped_key { Qt::Key_F13 }; + case Input::KEY_F14: return Mapped_key { Qt::Key_F14 }; + case Input::KEY_F15: return Mapped_key { Qt::Key_F15 }; + case Input::KEY_F16: return Mapped_key { Qt::Key_F16 }; + case Input::KEY_F17: return Mapped_key { Qt::Key_F17 }; + case Input::KEY_F18: return Mapped_key { Qt::Key_F18 }; + case Input::KEY_F19: return Mapped_key { Qt::Key_F19 }; + case Input::KEY_F20: return Mapped_key { Qt::Key_F20 }; + case Input::KEY_F21: return Mapped_key { Qt::Key_F21 }; + case Input::KEY_F22: return Mapped_key { Qt::Key_F22 }; + case Input::KEY_F23: return Mapped_key { Qt::Key_F23 }; + case Input::KEY_F24: return Mapped_key { Qt::Key_F24 }; + case Input::KEY_BACK: return Mapped_key { Qt::Key_Back }; + case Input::KEY_FORWARD: return Mapped_key { Qt::Key_Forward }; + case Input::KEY_VOLUMEDOWN: return Mapped_key { Qt::Key_VolumeDown }; + case Input::KEY_MUTE: return Mapped_key { Qt::Key_VolumeMute }; + case Input::KEY_VOLUMEUP: return Mapped_key { Qt::Key_VolumeUp }; + case Input::KEY_PREVIOUSSONG: return Mapped_key { Qt::Key_MediaPrevious }; + case Input::KEY_PLAYPAUSE: return Mapped_key { Qt::Key_MediaTogglePlayPause }; + case Input::KEY_NEXTSONG: return Mapped_key { Qt::Key_MediaNext }; + + default: break; + }; + + /* + * We remember the mapping of pressed keys (but not repeated codepoints) in + * '_pressed' to derive the release mapping. + */ + + switch (e) { + case Mapped_key::PRESSED: + case Mapped_key::REPEAT: + { + Mapped_key const mapped_key = _mapped_key_from_codepoint(codepoint); + if (mapped_key.key != Qt::Key_unknown) { + /* do not insert repeated codepoints */ + if (e == Mapped_key::PRESSED) + _pressed.insert(key, mapped_key.key); + + return mapped_key; + } + } break; + + case Mapped_key::RELEASED: + if (Qt::Key qt_key = _pressed.take(key)) { + return Mapped_key { qt_key }; + } + break; + } + + /* dead keys and aborted sequences end up here */ + Genode::warning("key (", Input::key_name(key), ",", (unsigned)key, + ",U+", Genode::Hex((unsigned short)codepoint.value, + Genode::Hex::OMIT_PREFIX, Genode::Hex::PAD), + ") lacks Qt mapping"); + return Mapped_key { Qt::Key_unknown, codepoint }; +} + + +void QGenodePlatformWindow::_key_event(Input::Keycode key, Codepoint codepoint, + Mapped_key::Event e) +{ + bool const pressed = e != Mapped_key::RELEASED; + + Qt::KeyboardModifier current_modifier = Qt::NoModifier; + + /* FIXME ignores two keys for one modifier were pressed and only one was released */ + switch (key) { + case Input::KEY_LEFTALT: current_modifier = Qt::AltModifier; break; + case Input::KEY_LEFTCTRL: + case Input::KEY_RIGHTCTRL: current_modifier = Qt::ControlModifier; break; + case Input::KEY_LEFTSHIFT: + case Input::KEY_RIGHTSHIFT: current_modifier = Qt::ShiftModifier; break; + default: break; + } + + _keyboard_modifiers.setFlag(current_modifier, pressed); + + QEvent::Type const event_type = pressed ? QEvent::KeyPress : QEvent::KeyRelease; + Mapped_key const mapped_key = _map_key(key, codepoint, e); + char32_t const unicode = mapped_key.codepoint.valid() + ? mapped_key.codepoint.value : 0; + bool const autorepeat = e == Mapped_key::REPEAT; + + QWindowSystemInterface::handleExtendedKeyEvent(window(), + event_type, + mapped_key.key, + _keyboard_modifiers, + key, 0, int(_keyboard_modifiers), + unicode ? QString::fromUcs4(&unicode, 1) : QString(), + autorepeat); +} + + +void QGenodePlatformWindow::_mouse_button_event(Input::Keycode button, bool press) +{ + Qt::MouseButton current_mouse_button = Qt::NoButton; + + switch (button) { + case Input::BTN_LEFT: current_mouse_button = Qt::LeftButton; break; + case Input::BTN_RIGHT: current_mouse_button = Qt::RightButton; break; + case Input::BTN_MIDDLE: current_mouse_button = Qt::MiddleButton; break; + case Input::BTN_SIDE: current_mouse_button = Qt::ExtraButton1; break; + case Input::BTN_EXTRA: current_mouse_button = Qt::ExtraButton2; break; + case Input::BTN_FORWARD: current_mouse_button = Qt::ExtraButton3; break; + case Input::BTN_BACK: current_mouse_button = Qt::ExtraButton4; break; + case Input::BTN_TASK: current_mouse_button = Qt::ExtraButton5; break; + default: return; + } + + _mouse_button_state.setFlag(current_mouse_button, press); + + /* on mouse click, make this window the focused window */ + if (press) requestActivateWindow(); + + QWindowSystemInterface::handleMouseEvent(window(), + _local_position(), + _mouse_position, + _mouse_button_state, + current_mouse_button, + press ? QEvent::MouseButtonPress + : QEvent::MouseButtonRelease, + _keyboard_modifiers); +} + + +void QGenodePlatformWindow::_handle_input() +{ + _signal_proxy.input(); +} + + +void QGenodePlatformWindow::_handle_hover_enter() +{ + if (!_hovered) { + + /* + * If a different window was hovered before and has + * not processed its leave event yet, let it report + * the leave event now to update the hover state of + * the previously hovered widget ('qt_last_mouse_receiver' + * in 'qwidgetwindow.cpp') before the variable gets + * updated with the new hovered widget. + */ + + for (QWindow *window : QGuiApplication::topLevelWindows()) + if (window->handle()) { + QGenodePlatformWindow *platform_window = + static_cast(window->handle()); + platform_window->handle_hover_leave(); + } + + _hovered = true; + QWindowSystemInterface::handleEnterEvent(window()); + } +} + + +void QGenodePlatformWindow::handle_hover_leave() +{ + if (_hovered) { + _hovered = false; + QWindowSystemInterface::handleLeaveEvent(window()); + } +} + + +void QGenodePlatformWindow::_input() +{ + QList touch_events; + + _input_session.for_each_event([&] (Input::Event const &event) { + + if (event.hover_leave()) { + handle_hover_leave(); + return; + } + + event.handle_absolute_motion([&] (int x, int y) { + + _handle_hover_enter(); + + _mouse_position = QPoint(x, y); + + QWindowSystemInterface::handleMouseEvent(window(), + _local_position(), + _mouse_position, + _mouse_button_state, + Qt::NoButton, + QEvent::MouseMove, + _keyboard_modifiers); + }); + + event.handle_press([&] (Input::Keycode key, Codepoint codepoint) { + if (key > 0 && key < 0x100) + _key_event(key, codepoint, Mapped_key::PRESSED); + else if (key >= Input::BTN_LEFT && key <= Input::BTN_TASK) + _mouse_button_event(key, true); + }); + + event.handle_release([&] (Input::Keycode key) { + if (key > 0 && key < 0x100) + _key_event(key, Codepoint { Codepoint::INVALID }, Mapped_key::RELEASED); + else if (key >= Input::BTN_LEFT && key <= Input::BTN_TASK) + _mouse_button_event(key, false); + }); + + event.handle_repeat([&] (Codepoint codepoint) { + _key_event(Input::KEY_UNKNOWN, codepoint, Mapped_key::REPEAT); + }); + + event.handle_wheel([&] (int, int y) { + QWindowSystemInterface::handleWheelEvent(window(), + _local_position(), + _local_position(), + QPoint(), + QPoint(0, y * 120), + _keyboard_modifiers); }); + + if (event.touch() || event.touch_release()) + touch_events.push_back(event); + }); + + /* process all gathered touch events */ + _process_touch_events(touch_events); +} + + +void QGenodePlatformWindow::_handle_info_changed() +{ + _signal_proxy.info_changed(); +} + + +void QGenodePlatformWindow::_info_changed() +{ + bool window_area_valid = false; + + Gui::Area const window_area = _gui_connection.window().convert( + [&] (Gui::Rect rect) { window_area_valid = true; return rect.area; }, + [&] (Gui::Undefined) { return Gui::Area { 1, 1 }; }); + + if (!window_area_valid) + return; + + if ((window_area.w == 0) && (window_area.h == 0)) { + /* interpret a size of 0x0 as indication to close the window */ + QWindowSystemInterface::handleCloseEvent(window()); + /* don't actually set geometry to 0x0; either close or remain open */ + return; + } + + if (window_area != _current_window_area) { + + QRect geo(geometry()); + geo.setWidth (window_area.w); + geo.setHeight(window_area.h); + + QWindowSystemInterface::handleGeometryChange(window(), geo); + QWindowSystemInterface::handleExposeEvent(window(), + QRect(QPoint(0, 0), + geo.size())); + + setGeometry(geo); + } +} + + +void QGenodePlatformWindow::_create_view() +{ + if (_view_valid) + return; + + if (window()->type() == Qt::Desktop) + return; + + if (window()->type() == Qt::Dialog) { + if (!_view_id.constructed()) + _view_id.construct(_view_ref, _gui_connection.view_ids); + _gui_connection.view(_view_id->id(), { }); + _view_valid = true; + return; + } + + if (window()->transientParent()) { + + QGenodePlatformWindow *parent_platform_window = + static_cast(window()->transientParent()->handle()); + + Gui::View_ref parent_view_ref { }; + Gui::View_ids::Element parent_view_id { parent_view_ref, _gui_connection.view_ids }; + + _gui_connection.associate(parent_view_id.id(), parent_platform_window->view_cap()); + + if (!_view_id.constructed()) + _view_id.construct(_view_ref, _gui_connection.view_ids); + + _gui_connection.child_view(_view_id->id(), parent_view_id.id(), { }); + + _gui_connection.release_view_id(parent_view_id.id()); + + _view_valid = true; + + return; + } + + if (!_view_id.constructed()) + _view_id.construct(_view_ref, _gui_connection.view_ids); + + _gui_connection.view(_view_id->id(), { }); + _view_valid = true; +} + + +void QGenodePlatformWindow::_destroy_view() +{ + if (!_view_valid) + return; + + _gui_connection.destroy_view(_view_id->id()); + _view_valid = false; +} + + +void QGenodePlatformWindow::_init_view(const QRect &geo) +{ + if (!_view_valid) + return; + + typedef Gui::Session::Command Command; + + _gui_connection.enqueue(_view_id->id(), + Gui::Rect(Gui::Point(geo.x(), geo.y()), + Gui::Area(geo.width(), geo.height()))); + + _gui_connection.enqueue(_view_id->id(), _title.constData()); + + if (_raise) { + _gui_connection.enqueue(_view_id->id()); + _raise = false; + } + + _gui_connection.execute(); +} + + +void QGenodePlatformWindow::_adjust_and_set_geometry(const QRect &rect) +{ + QRect adjusted_rect(rect); + + if (!window()->transientParent()) { + /* Currently, top level windows must start at (0,0) */ + adjusted_rect.moveTo(0, 0); + } else if (window()->type() == Qt::ToolTip) { + /* improve tooltip visibility */ + if (adjusted_rect.topLeft().y() + adjusted_rect.height() > + window()->transientParent()->geometry().height()) { + int dy = -adjusted_rect.height() - + (adjusted_rect.topLeft().y() - QCursor::pos().y()); + adjusted_rect.translate(0, dy); + } + } + + QPlatformWindow::setGeometry(adjusted_rect); + + Framebuffer::Mode const mode { .area = { (unsigned)adjusted_rect.width(), + (unsigned)adjusted_rect.height() }, + .alpha = false }; + _gui_connection.buffer(mode); + + _current_window_area = mode.area; + + _framebuffer_changed = true; + _geometry_changed = true; + + if (_egl_surface != EGL_NO_SURFACE) { + eglDestroySurface(_egl_display, _egl_surface); + _egl_surface = EGL_NO_SURFACE; + } + + emit framebuffer_changed(); +} + + +QString QGenodePlatformWindow::_sanitize_label(QString label) +{ + enum { MAX_LABEL = 25 }; + + /* remove any occurences of '"' */ + label.remove("\""); + + /* truncate label and append '..' */ + if (label.length() > MAX_LABEL) { + label.truncate(MAX_LABEL - 2); + label.append(".."); + } + + /* Make sure that the window is distinguishable by the layouter */ + if (label.isEmpty()) + label = QString("Untitled Window"); + + if (_gui_session_label_list.contains(label)) + for (unsigned int i = 2; ; i++) { + QString versioned_label = label + "." + QString::number(i); + if (!_gui_session_label_list.contains(versioned_label)) { + label = versioned_label; + break; + } + } + + return label; +} + + +QGenodePlatformWindow::QGenodePlatformWindow(Genode::Env &env, + QGenodeSignalProxyThread &signal_proxy, + QWindow *window, + EGLDisplay egl_display) +: QPlatformWindow(window), + _env(env), + _signal_proxy(signal_proxy), + _gui_session_label(_sanitize_label(window->title())), + _gui_connection(env, _gui_session_label.toStdString().c_str()), + _gui_session(_gui_connection.cap()), + _framebuffer_session(_gui_session.framebuffer()), + _input_session(env.rm(), _gui_session.input()), + _ev_buf(env.rm(), _input_session.dataspace()), + _egl_display(egl_display), + _input_signal_handler(_env.ep(), *this, + &QGenodePlatformWindow::_handle_input), + _info_changed_signal_handler(_env.ep(), *this, + &QGenodePlatformWindow::_handle_info_changed), + _touch_device(_init_touch_device()) +{ + if (qnpw_verbose) + if (window->transientParent()) + qDebug() << "QGenodePlatformWindow(): child window of" << window->transientParent(); + + _gui_session_label_list.append(_gui_session_label); + + _input_session.sigh(_input_signal_handler); + + _gui_connection.info_sigh(_info_changed_signal_handler); + + /* + * Popup menus and tooltips should never get a window decoration, + * therefore we set a top level Qt window as 'transient parent'. + */ + if (!window->transientParent() && + ((window->type() == Qt::Popup) || (window->type() == Qt::ToolTip))) { + QWindow *top_window = QGuiApplication::topLevelWindows().first(); + window->setTransientParent(top_window); + } + + _adjust_and_set_geometry(geometry()); + + connect(&signal_proxy, SIGNAL(input_signal()), + this, SLOT(_input()), + Qt::QueuedConnection); + + connect(&signal_proxy, SIGNAL(info_changed_signal()), + this, SLOT(_info_changed()), + Qt::QueuedConnection); + + _info_changed(); +} + +QGenodePlatformWindow::~QGenodePlatformWindow() +{ + _gui_session_label_list.removeOne(_gui_session_label); +} + +QSurfaceFormat QGenodePlatformWindow::format() const +{ + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::format()"; + return QPlatformWindow::format(); +} + +void QGenodePlatformWindow::setGeometry(const QRect &rect) +{ + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::setGeometry(" << rect << ")"; + + _adjust_and_set_geometry(rect); + + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::setGeometry() finished"; +} + +QRect QGenodePlatformWindow::geometry() const +{ + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::geometry(): returning" << QPlatformWindow::geometry(); + return QPlatformWindow::geometry(); +} + +QMargins QGenodePlatformWindow::frameMargins() const +{ + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::frameMargins()"; + return QPlatformWindow::frameMargins(); +} + +void QGenodePlatformWindow::setVisible(bool visible) +{ + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::setVisible(" << visible << ")"; + + if (visible) { + + _create_view(); + + QRect g(geometry()); + + if (window()->transientParent()) { + /* translate global position to parent-relative position */ + g.moveTo(window()->transientParent()->mapFromGlobal(g.topLeft())); + } + + _init_view(g); + + /* + * 'QWindowSystemInterface::handleExposeEvent()' was previously called + * via 'QPlatformWindow::setVisible()', but that method also called + * 'QWindowSystemInterface::flushWindowSystemEvents()', which had the + * negative effect that a button with a visible tooltip "lost" the + * mouse release event on a fast click, apparently because it got + * handled too early (during tooltip cleanup). + */ + QRect expose_rect(QPoint(), g.size()); + QWindowSystemInterface::handleExposeEvent(window(), expose_rect); + + /* + * xcb sends an enter event when a popup menu opens and this + * appears to be necessary for correct button display in some cases. + */ + if (window()->type() == Qt::Popup) + QWindowSystemInterface::handleEnterEvent(window()); + + } else { + + _destroy_view(); + + QWindowSystemInterface::handleExposeEvent(window(), QRegion()); + + /* + * xcb sends an enter event when a popup menu is closed and this + * appears to be necessary for correct button display in some cases. + */ + if (window()->type() == Qt::Popup) + QWindowSystemInterface::handleEnterEvent(window()->transientParent(), + QCursor::pos()); + } + + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::setVisible() finished"; +} + +void QGenodePlatformWindow::setWindowFlags(Qt::WindowFlags flags) +{ + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::setWindowFlags(" << flags << ")"; + + QPlatformWindow::setWindowFlags(flags); + + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::setWindowFlags() finished"; +} + +void QGenodePlatformWindow::setWindowState(Qt::WindowStates state) +{ + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::setWindowState(" << state << ")"; + + QPlatformWindow::setWindowState(state); + + if ((state == Qt::WindowMaximized) || (state == Qt::WindowFullScreen)) { + QRect screen_geometry { screen()->geometry() }; + QWindowSystemInterface::handleGeometryChange(window(), screen_geometry); + QWindowSystemInterface::handleExposeEvent(window(), + QRect(QPoint(0, 0), + screen_geometry.size())); + setGeometry(screen_geometry); + } +} + +WId QGenodePlatformWindow::winId() const +{ + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::winId()"; + return WId(this); +} + +void QGenodePlatformWindow::setParent(const QPlatformWindow *) +{ + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::setParent()"; + + /* don't call the base class function which only prints a warning */ +} + +void QGenodePlatformWindow::setWindowTitle(const QString &title) +{ + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::setWindowTitle(" << title << ")"; + + QPlatformWindow::setWindowTitle(title); + + _title = title.toLocal8Bit(); + + typedef Gui::Session::Command Command; + + if (_view_valid) { + _gui_connection.enqueue(_view_id->id(), _title.constData()); + _gui_connection.execute(); + } + + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::setWindowTitle() finished"; +} + +void QGenodePlatformWindow::setWindowFilePath(const QString &title) +{ + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::setWindowFilePath(" << title << ")"; + QPlatformWindow::setWindowFilePath(title); +} + +void QGenodePlatformWindow::setWindowIcon(const QIcon &icon) +{ + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::setWindowIcon()"; + QPlatformWindow::setWindowIcon(icon); +} + +void QGenodePlatformWindow::raise() +{ + if (_view_valid) { + /* bring the view to the top */ + _gui_connection.enqueue(_view_id->id()); + _gui_connection.execute(); + } else { + _raise = true; + } + + /* don't call the base class function which only prints a warning */ +} + +void QGenodePlatformWindow::lower() +{ + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::lower()"; + + /* don't call the base class function which only prints a warning */ +} + +bool QGenodePlatformWindow::isExposed() const +{ + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::isExposed()"; + return QPlatformWindow::isExposed(); +} + +bool QGenodePlatformWindow::isActive() const +{ + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::isActive()"; + return QPlatformWindow::isActive(); +} + +bool QGenodePlatformWindow::isEmbedded() const +{ + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::isEmbedded()"; + return QPlatformWindow::isEmbedded(); +} + +QPoint QGenodePlatformWindow::mapToGlobal(const QPoint &pos) const +{ + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::mapToGlobal(" << pos << ")"; + return QPlatformWindow::mapToGlobal(pos); +} + +QPoint QGenodePlatformWindow::mapFromGlobal(const QPoint &pos) const +{ + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::mapFromGlobal(" << pos << ")"; + return QPlatformWindow::mapFromGlobal(pos); +} + +void QGenodePlatformWindow::propagateSizeHints() +{ + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::propagateSizeHints()"; + + /* don't call the base class function which only prints a warning */ +} + +void QGenodePlatformWindow::setOpacity(qreal level) +{ + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::setOpacity(" << level << ")"; + + /* don't call the base class function which only prints a warning */ +} + +void QGenodePlatformWindow::setMask(const QRegion ®ion) +{ + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::setMask(" << region << ")"; + + /* don't call the base class function which only prints a warning */ +} + +void QGenodePlatformWindow::requestActivateWindow() +{ + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::requestActivateWindow()"; + QPlatformWindow::requestActivateWindow(); +} + +void QGenodePlatformWindow::handleContentOrientationChange(Qt::ScreenOrientation orientation) +{ + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::handleContentOrientationChange()"; + QPlatformWindow::handleContentOrientationChange(orientation); +} + +qreal QGenodePlatformWindow::devicePixelRatio() const +{ + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::devicePixelRatio()"; + return QPlatformWindow::devicePixelRatio(); +} + +bool QGenodePlatformWindow::setKeyboardGrabEnabled(bool) +{ + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::setKeyboardGrabEnabled()"; + + /* don't call the base class function which only prints a warning */ + + return false; +} + +bool QGenodePlatformWindow::setMouseGrabEnabled(bool) +{ + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::setMouseGrabEnabled()"; + + /* don't call the base class function which only prints a warning */ + + return false; +} + +bool QGenodePlatformWindow::setWindowModified(bool modified) +{ + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::setWindowModified()"; + return QPlatformWindow::setWindowModified(modified); +} + +bool QGenodePlatformWindow::windowEvent(QEvent *event) +{ + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::windowEvent(" << event->type() << ")"; + return QPlatformWindow::windowEvent(event); +} + +bool QGenodePlatformWindow::startSystemResize(Qt::Edges edges) +{ + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::startSystemResize()"; + return QPlatformWindow::startSystemResize(edges); +} + +void QGenodePlatformWindow::setFrameStrutEventsEnabled(bool enabled) +{ + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::setFrameStrutEventsEnabled()"; + QPlatformWindow::setFrameStrutEventsEnabled(enabled); +} + +bool QGenodePlatformWindow::frameStrutEventsEnabled() const +{ + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::frameStrutEventsEnabled()"; + return QPlatformWindow::frameStrutEventsEnabled(); +} + +/* functions used by the window surface */ + +unsigned char *QGenodePlatformWindow::framebuffer() +{ + if (qnpw_verbose) + qDebug() << "QGenodePlatformWindow::framebuffer()" << _framebuffer; + + /* + * The new framebuffer is acquired in this function to avoid a time span when + * the GUI buffer would be black and not refilled yet by Qt. + */ + + if (_framebuffer_changed) { + + _framebuffer_changed = false; + + if (_framebuffer != nullptr) + _env.rm().detach((Genode::addr_t)_framebuffer); + + Genode::Region_map::Attr attr { }; + attr.writeable = true; + _env.rm().attach(_framebuffer_session.dataspace(), attr).with_result( + [&] (Genode::Region_map::Range range) { + _framebuffer = (unsigned char*)range.start; }, + [&] (Genode::Region_map::Attach_error) { + _framebuffer = nullptr; + Genode::error("could not attach framebuffer"); + } + ); + } + + return _framebuffer; +} + +void QGenodePlatformWindow::refresh(int x, int y, int w, int h) +{ + if (qnpw_verbose) + qDebug("QGenodePlatformWindow::refresh(%d, %d, %d, %d)", x, y, w, h); + + if (_geometry_changed) { + + _geometry_changed = false; + + if (window()->isVisible()) { + + QRect g(geometry()); + + if (window()->transientParent()) { + /* translate global position to parent-relative position */ + g.moveTo(window()->transientParent()->mapFromGlobal(g.topLeft())); + } + + if (_view_valid) { + typedef Gui::Session::Command Command; + _gui_connection.enqueue(_view_id->id(), + Gui::Rect(Gui::Point(g.x(), g.y()), + Gui::Area(g.width(), g.height()))); + _gui_connection.execute(); + } + } + } + + _framebuffer_session.refresh(x, y, w, h); +} + +EGLSurface QGenodePlatformWindow::eglSurface(EGLConfig egl_config) +{ + if (_egl_surface == EGL_NO_SURFACE) { + + QRect geo = geometry(); + + Genode_egl_window egl_window = { geo.width(), + geo.height(), + framebuffer(), + PIXMAP }; + + _egl_surface = eglCreatePixmapSurface(_egl_display, + egl_config, + &egl_window, 0); + + if (_egl_surface == EGL_NO_SURFACE) + qFatal("eglCreatePixmapSurface() failed"); + } + + return _egl_surface; +} + +Gui::Session_client &QGenodePlatformWindow::gui_session() +{ + return _gui_session; +} + +Gui::View_capability QGenodePlatformWindow::view_cap() const +{ + if (_view_valid) { + QGenodePlatformWindow *non_const_platform_window = + const_cast(this); + return non_const_platform_window->_gui_connection.view_capability(_view_id->id()); + } + + return Gui::View_capability(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/genode/qgenodeplatformwindow.h b/src/plugins/platforms/genode/qgenodeplatformwindow.h new file mode 100644 index 00000000..8ee9f2c5 --- /dev/null +++ b/src/plugins/platforms/genode/qgenodeplatformwindow.h @@ -0,0 +1,236 @@ +/* + * \brief QGenodePlatformWindow + * \author Christian Prochaska + * \author Christian Helmuth + * \date 2013-05-08 + */ + +/* + * Copyright (C) 2013-2022 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + + +#ifndef _QGENODEPLATFORMWINDOW_H_ +#define _QGENODEPLATFORMWINDOW_H_ + +/* Genode includes */ +#include +#include +#include + +/* libc includes */ +#include + +/* EGL includes */ +#include + +/* Qt includes */ +#include +#include +#include + +/* Qoost includes */ +#include + +class QGenodeSignalProxyThread; + +QT_BEGIN_NAMESPACE + +class __attribute__ ((visibility ("default"))) QGenodePlatformWindow; +class QGenodePlatformWindow : public QObject, public QPlatformWindow +{ + Q_OBJECT + + private: + + Genode::Env &_env; + QGenodeSignalProxyThread &_signal_proxy; + QString _gui_session_label; + static QStringList _gui_session_label_list; + Gui::Connection _gui_connection; + Gui::Session_client _gui_session; + Framebuffer::Session_client _framebuffer_session; + unsigned char *_framebuffer { nullptr }; + bool _framebuffer_changed { false }; + bool _geometry_changed { false }; + Gui::Area _current_window_area; + Input::Session_client _input_session; + Genode::Attached_dataspace _ev_buf; + QPoint _mouse_position { }; + Qt::KeyboardModifiers _keyboard_modifiers { }; + Qt::MouseButtons _mouse_button_state { }; + QByteArray _title { }; + EGLDisplay _egl_display; + EGLSurface _egl_surface { EGL_NO_SURFACE }; + bool _hovered { false }; + bool _raise { true }; + + Gui::View_ref _view_ref { }; + Genode::Constructible _view_id { }; + bool _view_valid { false }; + + QPoint _local_position() const + { + return QPoint(_mouse_position.x() - geometry().x(), + _mouse_position.y() - geometry().y()); + } + + + typedef Genode::Codepoint Codepoint; + + struct Mapped_key + { + enum Event { PRESSED, RELEASED, REPEAT }; + + Qt::Key key { Qt::Key_unknown }; + Codepoint codepoint { Codepoint::INVALID }; + }; + + QHash _pressed; + + Mapped_key _mapped_key_from_codepoint(Codepoint); + Mapped_key _map_key(Input::Keycode, Codepoint, Mapped_key::Event); + void _key_event(Input::Keycode, Codepoint, Mapped_key::Event); + void _mouse_button_event(Input::Keycode, bool press); + + Genode::Io_signal_handler _input_signal_handler; + Genode::Io_signal_handler _info_changed_signal_handler; + + void _handle_input(); + void _handle_info_changed(); + + QVector _touch_points { 16 }; + QPointingDevice *_touch_device; + QPointingDevice *_init_touch_device(); + + void _process_touch_events(QList const &events); + + void _create_view(); + void _init_view(const QRect &geo); + void _destroy_view(); + + void _adjust_and_set_geometry(const QRect &rect); + + QString _sanitize_label(QString label); + + void _handle_hover_enter(); + + /* + * Genode signals are handled as Qt signals to avoid blocking in the + * Genode signal handler, which could cause nested signal handler + * execution. + */ + + private Q_SLOTS: + + void _input(); + void _info_changed(); + + public: + + QGenodePlatformWindow(Genode::Env &env, + QGenodeSignalProxyThread &signal_proxy, + QWindow *window, + EGLDisplay egl_display); + + ~QGenodePlatformWindow(); + + QSurfaceFormat format() const override; + + void setGeometry(const QRect &rect) override; + + QRect geometry() const override; + + QMargins frameMargins() const override; + + void setVisible(bool visible) override; + + void setWindowFlags(Qt::WindowFlags flags) override; + + void setWindowState(Qt::WindowStates state) override; + + WId winId() const override; + + void setParent(const QPlatformWindow *window) override; + + void setWindowTitle(const QString &title) override; + + void setWindowFilePath(const QString &title) override; + + void setWindowIcon(const QIcon &icon) override; + + void raise() override; + + void lower() override; + + bool isExposed() const override; + + bool isActive() const override; + + bool isEmbedded() const override; + + QPoint mapToGlobal(const QPoint &pos) const override; + + QPoint mapFromGlobal(const QPoint &pos) const override; + + void propagateSizeHints() override; + + void setOpacity(qreal level) override; + + void setMask(const QRegion ®ion) override; + + void requestActivateWindow() override; + + void handleContentOrientationChange(Qt::ScreenOrientation orientation) override; + + qreal devicePixelRatio() const override; + + bool setKeyboardGrabEnabled(bool grab) override; + + bool setMouseGrabEnabled(bool grab) override; + + bool setWindowModified(bool modified) override; + + bool windowEvent(QEvent *event) override; + + bool startSystemResize(Qt::Edges edges) override; + + void setFrameStrutEventsEnabled(bool enabled) override; + + bool frameStrutEventsEnabled() const override; + + + /* for QGenodeWindowSurface */ + + unsigned char *framebuffer(); + + void refresh(int x, int y, int w, int h); + + + /* for QGenodeGLContext */ + + EGLSurface eglSurface(EGLConfig egl_config); + + + /* for QGenodeViewWidget */ + + Gui::Session_client &gui_session(); + Gui::View_capability view_cap() const; + + + /* for any QGenodePlatformWindow */ + + void handle_hover_leave(); + + signals: + + void framebuffer_changed(); + +}; + +QT_END_NAMESPACE + +#endif /* _QGENODEPLATFORMWINDOW_H_ */ diff --git a/src/plugins/platforms/genode/qgenodescreen.h b/src/plugins/platforms/genode/qgenodescreen.h new file mode 100644 index 00000000..89efb722 --- /dev/null +++ b/src/plugins/platforms/genode/qgenodescreen.h @@ -0,0 +1,112 @@ +/* + * \brief QGenodeScreen + * \author Christian Prochaska + * \date 2013-05-08 + */ + +/* + * Copyright (C) 2013-2023 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + + +#ifndef _QGENODESCREEN_H_ +#define _QGENODESCREEN_H_ + +/* Genode includes */ +#include + +/* Qt includes */ +#include +#include + +#include + +#include "qgenodecursor.h" +#include "qgenodesignalproxythread.h" + +QT_BEGIN_NAMESPACE + +class QGenodeScreen : public QObject, public QPlatformScreen +{ + Q_OBJECT + + private: + + Genode::Env &_env; + QRect _geometry; + + QGenodeSignalProxyThread &_signal_proxy; + + Gui::Connection _gui { _env, "QGenodeScreen" }; + + Genode::Io_signal_handler + _info_changed_signal_handler{_env.ep(), *this, + &QGenodeScreen::_handle_info_changed}; + + void _handle_info_changed() + { + _signal_proxy.screen_info_changed(); + } + + private slots: + + void _info_changed() + { + Gui::Area const screen_area = _gui.panorama().convert( + [&] (Gui::Rect rect) { return rect.area; }, + [&] (Gui::Undefined) { return Gui::Area { 1, 1 }; }); + + _geometry.setRect(0, 0, screen_area.w, + screen_area.h); + + QWindowSystemInterface::handleScreenGeometryChange(screen(), + _geometry, + _geometry); + } + + public: + + QGenodeScreen(Genode::Env &env, + QGenodeSignalProxyThread &signal_proxy) + : _env(env), + _signal_proxy(signal_proxy) + { + _gui.info_sigh(_info_changed_signal_handler); + + connect(&_signal_proxy, SIGNAL(screen_info_changed_signal()), + this, SLOT(_info_changed()), + Qt::QueuedConnection); + + Gui::Area const screen_area = _gui.panorama().convert( + [&] (Gui::Rect rect) { return rect.area; }, + [&] (Gui::Undefined) { return Gui::Area { 1, 1 }; }); + + _geometry.setRect(0, 0, screen_area.w, + screen_area.h); + } + + QRect geometry() const override { return _geometry; } + int depth() const override { return 32; } + QImage::Format format() const override{ return QImage::Format_RGB32; } + QDpi logicalDpi() const override { return QDpi(80, 80); }; + + QSizeF physicalSize() const override + { + /* 'overrideDpi()' takes 'QT_FONT_DPI' into account */ + static const int dpi = overrideDpi(logicalDpi()).first; + return QSizeF(geometry().size()) / dpi * qreal(25.4); + } + + QPlatformCursor *cursor() const override + { + static QGenodeCursor instance(_env); + return &instance; + } +}; + +QT_END_NAMESPACE + +#endif /* _QGENODESCREEN_H_ */ diff --git a/src/plugins/platforms/genode/qgenodesignalproxythread.h b/src/plugins/platforms/genode/qgenodesignalproxythread.h new file mode 100644 index 00000000..1a77a9eb --- /dev/null +++ b/src/plugins/platforms/genode/qgenodesignalproxythread.h @@ -0,0 +1,113 @@ +/* + * \brief Signal proxy thread to avoid libc execution context nesting issues + * \author Christian Prochaska + * \date 2020-08-13 + */ + +/* + * Copyright (C) 2020 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _QGENODESIGNALPROXYTHREAD_H_ +#define _QGENODESIGNALPROXYTHREAD_H_ + +/* Genode includes */ +#include + +/* Qt includes */ +#include + +class QGenodeSignalProxyThread : public QThread +{ + Q_OBJECT + + private: + + Genode::Blockade _blockade; + + bool _quit { false }; + bool _input { false }; + bool _info_changed { false }; + bool _screen_info_changed { false }; + bool _clipboard_changed { false }; + + protected: + + void run() override + { + for (;;) { + + _blockade.block(); + + if (_quit) + break; + + if (_input) { + _input = false; + input_signal(); + } + + if (_info_changed) { + _info_changed = false; + info_changed_signal(); + } + + if (_screen_info_changed) { + _screen_info_changed = false; + screen_info_changed_signal(); + } + + if (_clipboard_changed) { + _clipboard_changed = false; + clipboard_changed_signal(); + } + } + } + + public: + + QGenodeSignalProxyThread() { start(); } + + ~QGenodeSignalProxyThread() + { + _quit = true; + _blockade.wakeup(); + wait(); + } + + void input() + { + _input = true; + _blockade.wakeup(); + } + + void info_changed() + { + _info_changed = true; + _blockade.wakeup(); + } + + void screen_info_changed() + { + _screen_info_changed = true; + _blockade.wakeup(); + } + + void clipboard_changed() + { + _clipboard_changed = true; + _blockade.wakeup(); + } + + Q_SIGNALS: + + void input_signal(); + void info_changed_signal(); + void screen_info_changed_signal(); + void clipboard_changed_signal(); +}; + +#endif /* _QGENODESIGNALPROXYTHREAD_H_ */ diff --git a/src/plugins/platforms/genode/qgenodewindowsurface.cpp b/src/plugins/platforms/genode/qgenodewindowsurface.cpp new file mode 100644 index 00000000..b2ad25e9 --- /dev/null +++ b/src/plugins/platforms/genode/qgenodewindowsurface.cpp @@ -0,0 +1,129 @@ +/* + * \brief QGenodeWindowSurface + * \author Christian Prochaska + * \date 2013-05-08 + */ + +/* + * Copyright (C) 2013-2022 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +/* Genode includes */ +#include + +/* Qt includes */ +#include + +#include + +#include + +#include "qgenodeplatformwindow.h" + +#include "qgenodewindowsurface.h" + +#include + +static const bool verbose = false; + +QT_BEGIN_NAMESPACE + +QGenodeWindowSurface::QGenodeWindowSurface(QWindow *window) + : QPlatformBackingStore(window), _framebuffer_changed(true) +{ + //qDebug() << "QGenodeWindowSurface::QGenodeWindowSurface:" << (long)this; + + /* Calling 'QWindow::winId()' ensures that the platform window has been created */ + window->winId(); + + _platform_window = static_cast(window->handle()); + connect(_platform_window, SIGNAL(framebuffer_changed()), this, SLOT(framebuffer_changed())); +} + +QPaintDevice *QGenodeWindowSurface::paintDevice() +{ + if (verbose) + qDebug() << "QGenodeWindowSurface::paintDevice()"; + + if (_framebuffer_changed) { + + _framebuffer_changed = false; + + /* + * It can happen that 'resize()' was not called yet, so the size needs + * to be obtained from the window. + */ + QImage::Format format = QGuiApplication::primaryScreen()->handle()->format(); + QRect geo = _platform_window->geometry(); + _image = QImage(geo.width(), geo.height(), format); + + if (verbose) + qDebug() << "QGenodeWindowSurface::paintDevice(): w =" << geo.width() << ", h =" << geo.height(); + } + + if (verbose) + qDebug() << "QGenodeWindowSurface::paintDevice() finished"; + + return &_image; +} + +void QGenodeWindowSurface::flush(QWindow *window, const QRegion ®ion, const QPoint &offset) +{ + if (verbose) + qDebug() << "QGenodeWindowSurface::flush(" + << "window =" << window + << ", region =" << region + << ", offset =" << offset + << ")"; + + if (offset != QPoint(0, 0)) { + Genode::warning("QGenodeWindowSurface::flush(): offset not handled"); + } + + QImage::Format format = QGuiApplication::primaryScreen()->handle()->format(); + QRect geo = _platform_window->geometry(); + + QImage framebuffer_image(_platform_window->framebuffer(), + geo.width(), geo.height(), + format); + + QPainter framebuffer_painter(&framebuffer_image); + + for (QRect rect : region) { + + /* + * It happened that after resizing a window, the given flush region was + * bigger than the current window size, so clipping is necessary here. + */ + + rect &= _image.rect(); + + framebuffer_painter.drawImage(rect, _image, rect); + + _platform_window->refresh(rect.x(), + rect.y(), + rect.width(), + rect.height()); + } +} + +QImage QGenodeWindowSurface::toImage() const +{ + return _image; +} + +void QGenodeWindowSurface::resize(const QSize &size, const QRegion &) +{ + if (verbose) + qDebug() << "QGenodeWindowSurface::resize:" << this << size; +} + +void QGenodeWindowSurface::framebuffer_changed() +{ + _framebuffer_changed = true; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/genode/qgenodewindowsurface.h b/src/plugins/platforms/genode/qgenodewindowsurface.h new file mode 100644 index 00000000..591e2ff5 --- /dev/null +++ b/src/plugins/platforms/genode/qgenodewindowsurface.h @@ -0,0 +1,52 @@ +/* + * \brief QGenodeWindowSurface + * \author Christian Prochaska + * \date 2013-05-08 + */ + +/* + * Copyright (C) 2013-2022 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + + +#ifndef _QGENODEWINDOWSURFACE_H_ +#define _QGENODEWINDOWSURFACE_H_ + +#include + +class QGenodePlatformWindow; + +QT_BEGIN_NAMESPACE + +class QGenodeWindowSurface : public QObject, public QPlatformBackingStore +{ + Q_OBJECT + + private: + + QGenodePlatformWindow *_platform_window; + QImage _image; + bool _framebuffer_changed; + + public: + + QGenodeWindowSurface(QWindow *window); + + QPaintDevice *paintDevice() override; + void flush(QWindow *window, const QRegion ®ion, const QPoint &offset) override; + void resize(const QSize &size, const QRegion &staticContents) override; + + /* needed for RasterGLSurface */ + QImage toImage() const override; + + public slots: + + void framebuffer_changed(); +}; + +QT_END_NAMESPACE + +#endif /* _QGENODEWINDOWSURFACE_H_ */ diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp index 0659cf9f..e1c356b8 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp +++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp @@ -13,7 +13,9 @@ #include #include +#if 0 #include +#endif #include #include @@ -370,6 +372,7 @@ void QXcbBackingStoreImage::createShmSegment(size_t segmentSize) bool QXcbBackingStoreImage::createSystemVShmSegment(xcb_connection_t *c, size_t segmentSize, xcb_shm_segment_info_t *shmInfo) { +#if 0 const int id = shmget(IPC_PRIVATE, segmentSize, IPC_CREAT | 0600); if (id == -1) { qCWarning(lcQpaXcb, "shmget() failed (%d: %s) for size %zu", errno, strerror(errno), segmentSize); @@ -406,6 +409,9 @@ bool QXcbBackingStoreImage::createSystemVShmSegment(xcb_connection_t *c, size_t shmInfo->shmaddr = static_cast(addr); } return true; +#else + return false; +#endif } void QXcbBackingStoreImage::destroyShmSegment() @@ -425,10 +431,12 @@ void QXcbBackingStoreImage::destroyShmSegment() } else #endif { +#if 0 if (shmdt(m_shm_info.shmaddr) == -1) { qCWarning(lcQpaXcb, "shmdt() failed (%d: %s) for %p", errno, strerror(errno), m_shm_info.shmaddr); } +#endif m_shm_info.shmid = 0; // unused } m_shm_info.shmaddr = nullptr; diff --git a/src/plugins/tls/openssl/qopenssl_p.h b/src/plugins/tls/openssl/qopenssl_p.h index 370b9746..82c2e394 100644 --- a/src/plugins/tls/openssl/qopenssl_p.h +++ b/src/plugins/tls/openssl/qopenssl_p.h @@ -70,6 +70,13 @@ QT_BEGIN_NAMESPACE +#ifndef DTLS_ANY_VERSION +#define DTLS_ANY_VERSION 0x1FFFF +#endif +#ifndef TLS_ANY_VERSION +#define TLS_ANY_VERSION 0x10000 +#endif + struct QSslErrorEntry { int code = 0; int depth = 0; diff --git a/src/plugins/tls/openssl/qsslcontext_openssl.cpp b/src/plugins/tls/openssl/qsslcontext_openssl.cpp index ef0e6391..c6821eb9 100644 --- a/src/plugins/tls/openssl/qsslcontext_openssl.cpp +++ b/src/plugins/tls/openssl/qsslcontext_openssl.cpp @@ -49,9 +49,9 @@ extern "C" int q_verify_cookie_callback(SSL *ssl, const unsigned char *cookie, } #endif // dtls -#ifdef TLS1_3_VERSION +#if defined(TLS1_3_VERSION) && !defined(LIBRESSL_VERSION_NUMBER) extern "C" int q_ssl_sess_set_new_cb(SSL *context, SSL_SESSION *session); -#endif // TLS1_3_VERSION +#endif // TLS1_3_VERSION && LIBRESSL_VERSION_NUMBE static inline QString msgErrorSettingBackendConfig(const QString &why) { @@ -370,9 +370,11 @@ QT_WARNING_POP return; } +#ifndef LIBRESSL_VERSION_NUMBER // A nasty hacked OpenSSL using a level that will make our auto-tests fail: if (q_SSL_CTX_get_security_level(sslContext->ctx) > 1 && *forceSecurityLevel()) q_SSL_CTX_set_security_level(sslContext->ctx, 1); +#endif // LIBRESSL_VERSION_NUMBER const long anyVersion = #if QT_CONFIG(dtls) @@ -663,14 +665,14 @@ QT_WARNING_POP q_SSL_CTX_set_verify(sslContext->ctx, verificationMode, verificationCallback); } -#ifdef TLS1_3_VERSION +#if defined(TLS1_3_VERSION) && !defined(LIBRESSL_VERSION_NUMBER) // NewSessionTicket callback: if (mode == QSslSocket::SslClientMode && !isDtls) { q_SSL_CTX_sess_set_new_cb(sslContext->ctx, q_ssl_sess_set_new_cb); q_SSL_CTX_set_session_cache_mode(sslContext->ctx, SSL_SESS_CACHE_CLIENT); } -#endif // TLS1_3_VERSION +#endif // TLS1_3_VERSION && LIBRESSL_VERSION_NUMBER #if QT_CONFIG(dtls) // DTLS cookies: @@ -758,6 +760,7 @@ void QSslContext::applyBackendConfig(QSslContext *sslContext) } #endif // ocsp +#ifndef LIBRESSL_VERSION_NUMBER QSharedPointer cctx(q_SSL_CONF_CTX_new(), &q_SSL_CONF_CTX_free); if (cctx) { q_SSL_CONF_CTX_set_ssl_ctx(cctx.data(), sslContext->ctx); @@ -804,7 +807,9 @@ void QSslContext::applyBackendConfig(QSslContext *sslContext) sslContext->errorStr = msgErrorSettingBackendConfig(QSslSocket::tr("SSL_CONF_finish() failed")); sslContext->errorCode = QSslError::UnspecifiedError; } - } else { + } else +#endif // LIBRESSL_VERSION_NUMBER + { sslContext->errorStr = msgErrorSettingBackendConfig(QSslSocket::tr("SSL_CONF_CTX_new() failed")); sslContext->errorCode = QSslError::UnspecifiedError; } diff --git a/src/plugins/tls/openssl/qsslsocket_openssl_symbols.cpp b/src/plugins/tls/openssl/qsslsocket_openssl_symbols.cpp index 4aa9ca6f..51de3e48 100644 --- a/src/plugins/tls/openssl/qsslsocket_openssl_symbols.cpp +++ b/src/plugins/tls/openssl/qsslsocket_openssl_symbols.cpp @@ -112,23 +112,36 @@ DEFINEFUNC(const BIO_METHOD *, BIO_s_mem, void, DUMMYARG, return nullptr, return DEFINEFUNC2(int, BN_is_word, BIGNUM *a, a, BN_ULONG w, w, return 0, return) DEFINEFUNC(int, EVP_CIPHER_CTX_reset, EVP_CIPHER_CTX *c, c, return 0, return) DEFINEFUNC(int, EVP_PKEY_up_ref, EVP_PKEY *a, a, return 0, return) +#ifdef OPENSSL_NO_DEPRECATED_3_0 DEFINEFUNC2(EVP_PKEY_CTX *, EVP_PKEY_CTX_new, EVP_PKEY *pkey, pkey, ENGINE *e, e, return nullptr, return) DEFINEFUNC(int, EVP_PKEY_param_check, EVP_PKEY_CTX *ctx, ctx, return 0, return) DEFINEFUNC(void, EVP_PKEY_CTX_free, EVP_PKEY_CTX *ctx, ctx, return, return) +#endif // OPENSSL_NO_DEPRECATED_3_0 +#ifndef LIBRESSL_VERSION_NUMBER DEFINEFUNC(int, OPENSSL_sk_num, OPENSSL_STACK *a, a, return -1, return) DEFINEFUNC2(void, OPENSSL_sk_pop_free, OPENSSL_STACK *a, a, void (*b)(void*), b, return, DUMMYARG) DEFINEFUNC(OPENSSL_STACK *, OPENSSL_sk_new_null, DUMMYARG, DUMMYARG, return nullptr, return) DEFINEFUNC2(void, OPENSSL_sk_push, OPENSSL_STACK *a, a, void *b, b, return, DUMMYARG) DEFINEFUNC(void, OPENSSL_sk_free, OPENSSL_STACK *a, a, return, DUMMYARG) DEFINEFUNC2(void *, OPENSSL_sk_value, OPENSSL_STACK *a, a, int b, b, return nullptr, return) +#else +DEFINEFUNC(int, sk_num, STACK *a, a, return -1, return) +DEFINEFUNC2(void, sk_pop_free, STACK *a, a, void (*b)(void*), b, return, DUMMYARG) +DEFINEFUNC(_STACK *, sk_new_null, DUMMYARG, DUMMYARG, return nullptr, return) +DEFINEFUNC2(void, sk_push, _STACK *a, a, void *b, b, return, DUMMYARG) +DEFINEFUNC(void, sk_free, _STACK *a, a, return, DUMMYARG) +DEFINEFUNC2(void *, sk_value, STACK *a, a, int b, b, return nullptr, return) +#endif // LIBRESSL_VERSION_NUMBER DEFINEFUNC(int, SSL_session_reused, SSL *a, a, return 0, return) DEFINEFUNC2(qssloptions, SSL_CTX_set_options, SSL_CTX *ctx, ctx, qssloptions op, op, return 0, return) using info_callback = void (*) (const SSL *ssl, int type, int val); DEFINEFUNC2(void, SSL_set_info_callback, SSL *ssl, ssl, info_callback cb, cb, return, return) DEFINEFUNC(const char *, SSL_alert_type_string, int value, value, return nullptr, return) DEFINEFUNC(const char *, SSL_alert_desc_string_long, int value, value, return nullptr, return) +#ifndef LIBRESSL_VERSION_NUMBER DEFINEFUNC(int, SSL_CTX_get_security_level, const SSL_CTX *ctx, ctx, return -1, return) DEFINEFUNC2(void, SSL_CTX_set_security_level, SSL_CTX *ctx, ctx, int level, level, return, return) +#endif // LIBRESSL_VERSION_NUMBER #ifdef TLS1_3_VERSION DEFINEFUNC2(int, SSL_CTX_set_ciphersuites, SSL_CTX *ctx, ctx, const char *str, str, return 0, return) DEFINEFUNC2(void, SSL_set_psk_use_session_callback, SSL *ssl, ssl, q_SSL_psk_use_session_cb_func_t callback, callback, return, DUMMYARG) @@ -154,7 +167,11 @@ DEFINEFUNC2(void, X509_STORE_set_verify_cb, X509_STORE *a, a, X509_STORE_CTX_ver DEFINEFUNC3(int, X509_STORE_set_ex_data, X509_STORE *a, a, int idx, idx, void *data, data, return 0, return) DEFINEFUNC2(void *, X509_STORE_get_ex_data, X509_STORE *r, r, int idx, idx, return nullptr, return) DEFINEFUNC(STACK_OF(X509) *, X509_STORE_CTX_get0_chain, X509_STORE_CTX *a, a, return nullptr, return) +#ifndef LIBRESSL_VERSION_NUMBER DEFINEFUNC3(void, CRYPTO_free, void *str, str, const char *file, file, int line, line, return, DUMMYARG) +#else +DEFINEFUNC(void, CRYPTO_free, void *a, a, return, DUMMYARG) +#endif DEFINEFUNC3(int, CRYPTO_memcmp, const void * in_a, in_a, const void * in_b, in_b, size_t len, len, return 1, return); DEFINEFUNC(long, OpenSSL_version_num, void, DUMMYARG, return 0, return) DEFINEFUNC(const char *, OpenSSL_version, int a, a, return nullptr, return) @@ -193,7 +210,9 @@ DEFINEFUNC5(int, OCSP_id_get0_info, ASN1_OCTET_STRING **piNameHash, piNameHash, ASN1_OCTET_STRING **piKeyHash, piKeyHash, ASN1_INTEGER **pserial, pserial, OCSP_CERTID *cid, cid, return 0, return) DEFINEFUNC2(OCSP_RESPONSE *, OCSP_response_create, int status, status, OCSP_BASICRESP *bs, bs, return nullptr, return) +#if !defined(LIBRESSL_VERSION_NUMBER) || (LIBRESSL_VERSION_NUMBER >= 0x3050000fL) DEFINEFUNC(const STACK_OF(X509) *, OCSP_resp_get0_certs, const OCSP_BASICRESP *bs, bs, return nullptr, return) +#endif DEFINEFUNC2(int, OCSP_id_cmp, OCSP_CERTID *a, a, OCSP_CERTID *b, b, return -1, return) DEFINEFUNC7(OCSP_SINGLERESP *, OCSP_basic_add1_status, OCSP_BASICRESP *r, r, OCSP_CERTID *c, c, int s, s, int re, re, ASN1_TIME *rt, rt, ASN1_TIME *t, t, ASN1_TIME *n, n, return nullptr, return) @@ -214,7 +233,9 @@ DEFINEFUNC(long, ASN1_INTEGER_get, ASN1_INTEGER *a, a, return 0, return) DEFINEFUNC2(int, ASN1_INTEGER_cmp, const ASN1_INTEGER *a, a, const ASN1_INTEGER *b, b, return 1, return) DEFINEFUNC(int, ASN1_STRING_length, ASN1_STRING *a, a, return 0, return) DEFINEFUNC2(int, ASN1_STRING_to_UTF8, unsigned char **a, a, ASN1_STRING *b, b, return 0, return) +#if !defined(LIBRESSL_VERSION_NUMBER) || (LIBRESSL_VERSION_NUMBER >= 0x3060000fL) DEFINEFUNC2(int, ASN1_TIME_to_tm, const ASN1_TIME *s, s, struct tm *tm, tm, return 0, return) +#endif DEFINEFUNC4(long, BIO_ctrl, BIO *a, a, int b, b, long c, c, void *d, d, return -1, return) DEFINEFUNC(int, BIO_free, BIO *a, a, return 0, return) DEFINEFUNC2(BIO *, BIO_new_mem_buf, void *a, a, int b, b, return nullptr, return) @@ -289,12 +310,14 @@ DEFINEFUNC3(int, SSL_CTX_use_certificate_file, SSL_CTX *a, a, const char *b, b, DEFINEFUNC2(int, SSL_CTX_use_PrivateKey, SSL_CTX *a, a, EVP_PKEY *b, b, return -1, return) DEFINEFUNC3(int, SSL_CTX_use_PrivateKey_file, SSL_CTX *a, a, const char *b, b, int c, c, return -1, return) DEFINEFUNC(X509_STORE *, SSL_CTX_get_cert_store, const SSL_CTX *a, a, return nullptr, return) +#ifndef LIBRESSL_VERSION_NUMBER DEFINEFUNC(SSL_CONF_CTX *, SSL_CONF_CTX_new, DUMMYARG, DUMMYARG, return nullptr, return); DEFINEFUNC(void, SSL_CONF_CTX_free, SSL_CONF_CTX *a, a, return ,return); DEFINEFUNC2(void, SSL_CONF_CTX_set_ssl_ctx, SSL_CONF_CTX *a, a, SSL_CTX *b, b, return, return); DEFINEFUNC2(unsigned int, SSL_CONF_CTX_set_flags, SSL_CONF_CTX *a, a, unsigned int b, b, return 0, return); DEFINEFUNC(int, SSL_CONF_CTX_finish, SSL_CONF_CTX *a, a, return 0, return); DEFINEFUNC3(int, SSL_CONF_cmd, SSL_CONF_CTX *a, a, const char *b, b, const char *c, c, return 0, return); +#endif DEFINEFUNC(void, SSL_free, SSL *a, a, return, DUMMYARG) DEFINEFUNC(STACK_OF(SSL_CIPHER) *, SSL_get_ciphers, const SSL *a, a, return nullptr, return) DEFINEFUNC(const SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return nullptr, return) @@ -761,8 +784,8 @@ static LoadedOpenSsl loadOpenSsl() libcrypto->setFileNameAndVersion("crypto"_L1, shlibVersion); #elif defined(SHLIB_VERSION_NUMBER) // first attempt: the canonical name is libssl.so. - libssl->setFileNameAndVersion("ssl"_L1, SHLIB_VERSION_NUMBER ""_L1); - libcrypto->setFileNameAndVersion("crypto"_L1, SHLIB_VERSION_NUMBER ""_L1); + libssl->setFileNameAndVersion("/usr/lib/libssl"_L1, SHLIB_VERSION_NUMBER ""_L1); + libcrypto->setFileNameAndVersion("/usr/lib/libcrypto"_L1, SHLIB_VERSION_NUMBER ""_L1); #endif // OPENSSL_SHLIB_VERSION if (libcrypto->load() && libssl->load()) { @@ -795,8 +818,8 @@ static LoadedOpenSsl loadOpenSsl() libssl->setFileNameAndVersion("ssl"_L1 + suffix, -1); libcrypto->setFileNameAndVersion("crypto"_L1 + suffix, -1); # else - libssl->setFileNameAndVersion("ssl"_L1, -1); - libcrypto->setFileNameAndVersion("crypto"_L1, -1); + libssl->setFileNameAndVersion("/usr/lib/libssl"_L1, -1); + libcrypto->setFileNameAndVersion("/usr/lib/libcrypto"_L1, -1); # endif if (libcrypto->load() && libssl->load()) { // libssl.so.0 and libcrypto.so.0 found @@ -865,21 +888,34 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(EVP_CIPHER_CTX_reset) RESOLVEFUNC(AUTHORITY_INFO_ACCESS_free) RESOLVEFUNC(EVP_PKEY_up_ref) +#ifdef OPENSSL_NO_DEPRECATED_3_0 RESOLVEFUNC(EVP_PKEY_CTX_new) RESOLVEFUNC(EVP_PKEY_param_check) RESOLVEFUNC(EVP_PKEY_CTX_free) +#endif // OPENSSL_NO_DEPRECATED_3_0 +#if !defined(LIBRESSL_VERSION_NUMBER) RESOLVEFUNC(OPENSSL_sk_new_null) RESOLVEFUNC(OPENSSL_sk_push) RESOLVEFUNC(OPENSSL_sk_free) RESOLVEFUNC(OPENSSL_sk_num) RESOLVEFUNC(OPENSSL_sk_pop_free) RESOLVEFUNC(OPENSSL_sk_value) +#else + RESOLVEFUNC(sk_new_null) + RESOLVEFUNC(sk_push) + RESOLVEFUNC(sk_free) + RESOLVEFUNC(sk_num) + RESOLVEFUNC(sk_pop_free) + RESOLVEFUNC(sk_value) +#endif RESOLVEFUNC(SSL_CTX_set_options) RESOLVEFUNC(SSL_set_info_callback) RESOLVEFUNC(SSL_alert_type_string) RESOLVEFUNC(SSL_alert_desc_string_long) +#if !defined(LIBRESSL_VERSION_NUMBER) RESOLVEFUNC(SSL_CTX_get_security_level) RESOLVEFUNC(SSL_CTX_set_security_level) +#endif #ifdef TLS1_3_VERSION RESOLVEFUNC(SSL_CTX_set_ciphersuites) RESOLVEFUNC(SSL_set_psk_use_session_callback) @@ -961,7 +997,9 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(OCSP_check_validity) RESOLVEFUNC(OCSP_cert_to_id) RESOLVEFUNC(OCSP_id_get0_info) - RESOLVEFUNC(OCSP_resp_get0_certs) +#if !defined(LIBRESSL_VERSION_NUMBER) || (LIBRESSL_VERSION_NUMBER >= 0x3050000fL) + RESOLVEFUNC(OCSP_resp_get0_certs) +#endif RESOLVEFUNC(OCSP_basic_sign) RESOLVEFUNC(OCSP_response_create) RESOLVEFUNC(i2d_OCSP_RESPONSE) @@ -1056,12 +1094,14 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(SSL_CTX_use_PrivateKey) RESOLVEFUNC(SSL_CTX_use_PrivateKey_file) RESOLVEFUNC(SSL_CTX_get_cert_store); +#ifndef LIBRESSL_VERSION_NUMBER RESOLVEFUNC(SSL_CONF_CTX_new); RESOLVEFUNC(SSL_CONF_CTX_free); RESOLVEFUNC(SSL_CONF_CTX_set_ssl_ctx); RESOLVEFUNC(SSL_CONF_CTX_set_flags); RESOLVEFUNC(SSL_CONF_CTX_finish); RESOLVEFUNC(SSL_CONF_cmd); +#endif RESOLVEFUNC(SSL_accept) RESOLVEFUNC(SSL_clear) RESOLVEFUNC(SSL_connect) @@ -1121,7 +1161,9 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(RSA_free) RESOLVEFUNC(DH_bits) +#if !defined(LIBRESSL_VERSION_NUMBER) || (LIBRESSL_VERSION_NUMBER >= 0x3050000fL) RESOLVEFUNC(DSA_bits) +#endif RESOLVEFUNC(RSA_bits) #ifndef OPENSSL_NO_EC diff --git a/src/plugins/tls/openssl/qsslsocket_openssl_symbols_p.h b/src/plugins/tls/openssl/qsslsocket_openssl_symbols_p.h index c954d177..4176c18f 100644 --- a/src/plugins/tls/openssl/qsslsocket_openssl_symbols_p.h +++ b/src/plugins/tls/openssl/qsslsocket_openssl_symbols_p.h @@ -46,6 +46,13 @@ QT_BEGIN_NAMESPACE #define DUMMYARG +#ifdef LIBRESSL_VERSION_NUMBER +typedef _STACK STACK; +typedef STACK OPENSSL_STACK; +typedef void OPENSSL_INIT_SETTINGS; +typedef int (*X509_STORE_CTX_verify_cb)(int ok,X509_STORE_CTX *ctx); +#endif + #if !defined QT_LINKED_OPENSSL // **************** Shared declarations ****************** // ret func(arg) @@ -203,15 +210,32 @@ const BIO_METHOD *q_BIO_s_mem(); void q_AUTHORITY_INFO_ACCESS_free(AUTHORITY_INFO_ACCESS *a); int q_EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *c); int q_EVP_PKEY_up_ref(EVP_PKEY *a); +#ifdef OPENSSL_NO_DEPRECATED_3_0 EVP_PKEY_CTX *q_EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e); void q_EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx); +#endif // OPENSSL_NO_DEPRECATED_3_0 int q_EVP_PKEY_param_check(EVP_PKEY_CTX *ctx); +#ifndef LIBRESSL_VERSION_NUMBER int q_OPENSSL_sk_num(OPENSSL_STACK *a); void q_OPENSSL_sk_pop_free(OPENSSL_STACK *a, void (*b)(void *)); OPENSSL_STACK *q_OPENSSL_sk_new_null(); void q_OPENSSL_sk_push(OPENSSL_STACK *st, void *data); void q_OPENSSL_sk_free(OPENSSL_STACK *a); void * q_OPENSSL_sk_value(OPENSSL_STACK *a, int b); +#else // LIBRESSL_VERSION_NUMBER +int q_sk_num(STACK *a); +#define q_OPENSSL_sk_num(a) q_sk_num(a) +void q_sk_pop_free(STACK *a, void (*b)(void *)); +#define q_OPENSSL_sk_pop_free(a, b) q_sk_pop_free(a, b) +STACK *q_sk_new_null(); +#define q_OPENSSL_sk_new_null() q_sk_new_null() +void q_sk_push(STACK *st, void *data); +#define q_OPENSSL_sk_push(st, data) q_sk_push(st, data) +void q_sk_free(STACK *a); +#define q_OPENSSL_sk_free q_sk_free +void * q_sk_value(STACK *a, int b); +#define q_OPENSSL_sk_value(a, b) q_sk_value(a, b) +#endif // LIBRESSL_VERSION_NUMBER int q_SSL_session_reused(SSL *a); qssloptions q_SSL_CTX_set_options(SSL_CTX *ctx, qssloptions op); int q_OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings); @@ -237,8 +261,14 @@ STACK_OF(X509) *q_X509_STORE_CTX_get0_chain(X509_STORE_CTX *ctx); # define q_SSL_load_error_strings() q_OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS \ | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL) +#ifndef LIBRESSL_VERSION_NUMBER #define q_SKM_sk_num(st) q_OPENSSL_sk_num((OPENSSL_STACK *)st) #define q_SKM_sk_value(type, st,i) (type *)q_OPENSSL_sk_value((OPENSSL_STACK *)st, i) +#else // LIBRESSL_VERSION_NUMBER +#define q_SKM_sk_num(type, st) ((int (*)(const STACK_OF(type) *))q_sk_num)(st) +#define q_SKM_sk_value(type, st,i) ((type * (*)(const STACK_OF(type) *, int))q_sk_value)(st, i) +#endif // LIBRESSL_VERSION_NUMBER + #define q_OPENSSL_add_all_algorithms_conf() q_OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \ | OPENSSL_INIT_ADD_ALL_DIGESTS \ @@ -423,12 +453,14 @@ int q_SSL_CTX_use_certificate_file(SSL_CTX *a, const char *b, int c); int q_SSL_CTX_use_PrivateKey(SSL_CTX *a, EVP_PKEY *b); int q_SSL_CTX_use_PrivateKey_file(SSL_CTX *a, const char *b, int c); X509_STORE *q_SSL_CTX_get_cert_store(const SSL_CTX *a); +#ifndef LIBRESSL_VERSION_NUMBER SSL_CONF_CTX *q_SSL_CONF_CTX_new(); void q_SSL_CONF_CTX_free(SSL_CONF_CTX *a); void q_SSL_CONF_CTX_set_ssl_ctx(SSL_CONF_CTX *a, SSL_CTX *b); unsigned int q_SSL_CONF_CTX_set_flags(SSL_CONF_CTX *a, unsigned int b); int q_SSL_CONF_CTX_finish(SSL_CONF_CTX *a); int q_SSL_CONF_cmd(SSL_CONF_CTX *a, const char *b, const char *c); +#endif // LIBRESSL_VERSION_NUMBER void q_SSL_free(SSL *a); STACK_OF(SSL_CIPHER) *q_SSL_get_ciphers(const SSL *a); const SSL_CIPHER *q_SSL_get_current_cipher(SSL *a); @@ -536,14 +568,26 @@ void q_PKCS12_free(PKCS12 *pkcs12); #define q_BIO_get_mem_data(b, pp) (int)q_BIO_ctrl(b,BIO_CTRL_INFO,0,(char *)pp) #define q_BIO_pending(b) (int)q_BIO_ctrl(b,BIO_CTRL_PENDING,0,NULL) #define q_SSL_CTX_set_mode(ctx,op) q_SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,(op),NULL) +#ifndef LIBRESSL_VERSION_NUMBER #define q_sk_GENERAL_NAME_num(st) q_SKM_sk_num((st)) +#else +#define q_sk_GENERAL_NAME_num(st) q_SKM_sk_num(GENERAL_NAME, (st)) +#endif #define q_sk_GENERAL_NAME_value(st, i) q_SKM_sk_value(GENERAL_NAME, (st), (i)) void q_GENERAL_NAME_free(GENERAL_NAME *a); +#ifndef LIBRESSL_VERSION_NUMBER #define q_sk_X509_num(st) q_SKM_sk_num((st)) +#else +#define q_sk_X509_num(st) q_SKM_sk_num(X509, (st)) +#endif #define q_sk_X509_value(st, i) q_SKM_sk_value(X509, (st), (i)) +#ifndef LIBRESSL_VERSION_NUMBER #define q_sk_SSL_CIPHER_num(st) q_SKM_sk_num((st)) +#else +#define q_sk_SSL_CIPHER_num(st) q_SKM_sk_num(SSL_CIPHER, (st)) +#endif #define q_sk_SSL_CIPHER_value(st, i) q_SKM_sk_value(SSL_CIPHER, (st), (i)) #define q_SSL_CTX_add_extra_chain_cert(ctx,x509) \ q_SSL_CTX_ctrl(ctx,SSL_CTRL_EXTRA_CHAIN_CERT,0,(char *)x509) @@ -645,7 +689,11 @@ int q_OCSP_check_validity(ASN1_GENERALIZEDTIME *thisupd, ASN1_GENERALIZEDTIME *n int q_OCSP_id_get0_info(ASN1_OCTET_STRING **piNameHash, ASN1_OBJECT **pmd, ASN1_OCTET_STRING **pikeyHash, ASN1_INTEGER **pserial, OCSP_CERTID *cid); +#if defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x3050000fL +#define q_OCSP_resp_get0_certs(bs) ((bs)->certs) +#else const STACK_OF(X509) *q_OCSP_resp_get0_certs(const OCSP_BASICRESP *bs); +#endif OCSP_CERTID *q_OCSP_cert_to_id(const EVP_MD *dgst, X509 *subject, X509 *issuer); void q_OCSP_CERTID_free(OCSP_CERTID *cid); int q_OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b); @@ -664,8 +712,15 @@ int q_OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b); void *q_CRYPTO_malloc(size_t num, const char *file, int line); #define q_OPENSSL_malloc(num) q_CRYPTO_malloc(num, "", 0) + +#ifndef LIBRESSL_VERSION_NUMBER void q_CRYPTO_free(void *str, const char *file, int line); # define q_OPENSSL_free(addr) q_CRYPTO_free(addr, "", 0) +#else +void q_CRYPTO_free(void *a); +# define q_OPENSSL_free(addr) q_CRYPTO_free(addr) +#endif + int q_CRYPTO_memcmp(const void * in_a, const void * in_b, size_t len); void q_SSL_set_info_callback(SSL *ssl, void (*cb) (const SSL *ssl, int type, int val)); @@ -729,7 +784,11 @@ int q_EVP_PKEY_set1_DH(EVP_PKEY *a, DH *b); int q_DH_bits(DH *dh); int q_RSA_bits(RSA *a); +#if defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER < 0x3050000fL) +#define q_DSA_bits(dsa) q_BN_num_bits((dsa)->p) +#else int q_DSA_bits(DSA *a); +#endif int q_EVP_PKEY_assign(EVP_PKEY *a, int b, void *r); int q_EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b); diff --git a/src/plugins/tls/openssl/qtls_openssl.cpp b/src/plugins/tls/openssl/qtls_openssl.cpp index 031ccd9d..67e6f3b3 100644 --- a/src/plugins/tls/openssl/qtls_openssl.cpp +++ b/src/plugins/tls/openssl/qtls_openssl.cpp @@ -1438,13 +1438,13 @@ bool TlsCryptographOpenSSL::initSslContext() else if (mode == QSslSocket::SslServerMode) q_SSL_set_psk_server_callback(ssl, &q_ssl_psk_server_callback); -#if OPENSSL_VERSION_NUMBER >= 0x10101006L +#if OPENSSL_VERSION_NUMBER >= 0x10101006L && !defined(LIBRESSL_VERSION_NUMBER) // Set the client callback for TLSv1.3 PSK if (mode == QSslSocket::SslClientMode && QSslSocket::sslLibraryBuildVersionNumber() >= 0x10101006L) { q_SSL_set_psk_use_session_callback(ssl, &q_ssl_psk_use_session_callback); } -#endif // openssl version >= 0x10101006L +#endif // OPENSSL_VERSION_NUMBER >= 0x10101006L && !defined(LIBRESSL_VERSION_NUMBER) #endif // OPENSSL_NO_PSK diff --git a/src/plugins/tls/openssl/qx509_openssl.cpp b/src/plugins/tls/openssl/qx509_openssl.cpp index 0cd3749f..0f798a9e 100644 --- a/src/plugins/tls/openssl/qx509_openssl.cpp +++ b/src/plugins/tls/openssl/qx509_openssl.cpp @@ -64,7 +64,12 @@ QMultiMap mapFromX509Name(X509_NAME *name) unsigned char *data = nullptr; int size = q_ASN1_STRING_to_UTF8(&data, q_X509_NAME_ENTRY_get_data(e)); info.insert(name, QString::fromUtf8((char*)data, size)); - q_CRYPTO_free(data, nullptr, 0); +#ifndef LIBRESSL_VERSION_NUMBER + q_CRYPTO_free(data, nullptr, 0); +#else + q_CRYPTO_free(data); +#endif + } return info; @@ -75,11 +80,27 @@ QDateTime dateTimeFromASN1(const ASN1_TIME *aTime) QDateTime result; tm lTime; +#if defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER < 0x3060000fL) + const char *data; + size_t len; + int type; + + data = (const char*)ASN1_STRING_get0_data((const ASN1_STRING *)aTime); + len = ASN1_STRING_length(aTime); + type = ASN1_STRING_type(aTime); + + if (ASN1_time_parse(data, len, &lTime, type) == type) { + QDate resDate(lTime.tm_year + 1900, lTime.tm_mon + 1, lTime.tm_mday); + QTime resTime(lTime.tm_hour, lTime.tm_min, lTime.tm_sec); + result = QDateTime(resDate, resTime, Qt::UTC); + } +#else if (q_ASN1_TIME_to_tm(aTime, &lTime)) { QDate resDate(lTime.tm_year + 1900, lTime.tm_mon + 1, lTime.tm_mday); QTime resTime(lTime.tm_hour, lTime.tm_min, lTime.tm_sec); result = QDateTime(resDate, resTime, QTimeZone::UTC); } +#endif return result; } @@ -190,7 +211,11 @@ QVariant x509UnknownExtensionToValue(X509_EXTENSION *ext) QVariantList list; bool isMap = false; +#ifdef LIBRESSL_VERSION_NUMBER + for (int j = 0; j < q_SKM_sk_num(CONF_VALUE, val); j++) { +#else for (int j = 0; j < q_SKM_sk_num(val); j++) { +#endif CONF_VALUE *nval = q_SKM_sk_value(CONF_VALUE, val, j); if (nval->name && nval->value) { isMap = true; @@ -286,7 +311,11 @@ QVariant x509ExtensionToValue(X509_EXTENSION *ext) if (!info) return {}; QVariantMap result; +#if defined LIBRESSL_VERSION_NUMBER + for (int i=0; i < q_SKM_sk_num(ACCESS_DESCRIPTION, info); i++) { +#else for (int i=0; i < q_SKM_sk_num(info); i++) { +#endif ACCESS_DESCRIPTION *ad = q_SKM_sk_value(ACCESS_DESCRIPTION, info, i); GENERAL_NAME *name = ad->location; diff --git a/src/widgets/styles/qstylefactory.cpp b/src/widgets/styles/qstylefactory.cpp index fc87b2b0..a2c2edb5 100644 --- a/src/widgets/styles/qstylefactory.cpp +++ b/src/widgets/styles/qstylefactory.cpp @@ -97,13 +97,13 @@ QStringList QStyleFactory::keys() const PluginKeyMap::const_iterator cend = keyMap.constEnd(); for (PluginKeyMap::const_iterator it = keyMap.constBegin(); it != cend; ++it) list.append(it.value()); -#if QT_CONFIG(style_windows) - if (!list.contains("Windows"_L1)) - list << "Windows"_L1; -#endif #if QT_CONFIG(style_fusion) if (!list.contains("Fusion"_L1)) list << "Fusion"_L1; +#endif +#if QT_CONFIG(style_windows) + if (!list.contains("Windows"_L1)) + list << "Windows"_L1; #endif return list; } diff --git a/util/android/android_emulator_launcher.sh b/util/android/android_emulator_launcher.sh index fb58e86b..4e4c00fa 100755 --- a/util/android/android_emulator_launcher.sh +++ b/util/android/android_emulator_launcher.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/local/bin/bash # Copyright (C) 2021 The Qt Company Ltd. # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 # This util launches the Android emulator and ensures it doesn't stuck/freeze diff --git a/util/testrunner/qt-testrunner.py b/util/testrunner/qt-testrunner.py index 2305e4b4..53c514f3 100755 --- a/util/testrunner/qt-testrunner.py +++ b/util/testrunner/qt-testrunner.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3 +#!/usr/local/bin/python3.9 # Copyright (C) 2021 The Qt Company Ltd. # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 diff --git a/util/testrunner/sanitizer-testrunner.py b/util/testrunner/sanitizer-testrunner.py index f992c489..6396ff36 100755 --- a/util/testrunner/sanitizer-testrunner.py +++ b/util/testrunner/sanitizer-testrunner.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3 +#!/usr/local/bin/python3.9 # Copyright (C) 2022 The Qt Company Ltd. # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0