diff --git a/cmake/platforms/android/app/build.gradle.kts.in b/cmake/platforms/android/app/build.gradle.kts.in
index 1de18242..ff2fd8a2 100644
--- a/cmake/platforms/android/app/build.gradle.kts.in
+++ b/cmake/platforms/android/app/build.gradle.kts.in
@@ -93,3 +93,9 @@ dependencies {
androidTestImplementation(libs.ext.junit)
androidTestImplementation(libs.espresso.core)*/
}
+
+java {
+ toolchain {
+ languageVersion = JavaLanguageVersion.of(17)
+ }
+}
diff --git a/cmake/platforms/android/app/src/main/AndroidManifest.xml.in b/cmake/platforms/android/app/src/main/AndroidManifest.xml.in
index 1d7781b8..3cde4ff5 100644
--- a/cmake/platforms/android/app/src/main/AndroidManifest.xml.in
+++ b/cmake/platforms/android/app/src/main/AndroidManifest.xml.in
@@ -5,23 +5,24 @@
+
+
+
+ android:icon="@mipmap/ic_launcher"
+ android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
+ android:launchMode="singleInstance"
+ android:hardwareAccelerated="true"
+ android:configChanges="keyboard|keyboardHidden|orientation|density|screenSize|screenLayout">
-
@@ -29,7 +30,4 @@
-
-
-
\ No newline at end of file
diff --git a/cmake/platforms/android/app/src/main/java/org/yup/YupActivity.java.in b/cmake/platforms/android/app/src/main/java/org/yup/YupActivity.java.in
new file mode 100644
index 00000000..25061816
--- /dev/null
+++ b/cmake/platforms/android/app/src/main/java/org/yup/YupActivity.java.in
@@ -0,0 +1,24 @@
+package org.yup;
+
+import org.libsdl.app.SDLActivity;
+
+public class YupActivity extends SDLActivity
+{
+ /**
+ * This method is called by SDL before loading the native shared libraries.
+ * It can be overridden to provide names of shared libraries to be loaded.
+ * The default implementation returns the defaults. It never returns null.
+ * An array returned by a new implementation must at least contain "SDL2".
+ * Also keep in mind that the order the libraries are loaded may matter.
+ *
+ * @return names of shared libraries to be loaded (e.g. "SDL2", "main").
+ */
+ @Override
+ protected String[] getLibraries()
+ {
+ return new String[]
+ {
+ "@YUP_ANDROID_TARGET_NAME@"
+ };
+ }
+}
diff --git a/cmake/yup.cmake b/cmake/yup.cmake
index e13acd31..056eac60 100644
--- a/cmake/yup.cmake
+++ b/cmake/yup.cmake
@@ -54,7 +54,7 @@ function (_yup_setup_platform)
if (CMAKE_SYSTEM_NAME MATCHES "WindowsStore")
set (yup_platform "uwp")
else()
- set (yup_platform "win32")
+ set (yup_platform "windows")
endif()
else()
diff --git a/cmake/yup_audio_plugin.cmake b/cmake/yup_audio_plugin.cmake
index 0458d552..59093353 100644
--- a/cmake/yup_audio_plugin.cmake
+++ b/cmake/yup_audio_plugin.cmake
@@ -37,8 +37,8 @@ function (yup_audio_plugin)
include (FetchContent)
if (NOT "${yup_platform}" MATCHES "^(emscripten)$")
- _yup_fetch_glfw3()
- list (APPEND additional_libraries glfw)
+ _yup_fetch_sdl2()
+ list (APPEND additional_libraries sdl2::sdl2)
# ==== Fetch plugins SDKS
if (YUP_ARG_PLUGIN_CREATE_CLAP)
diff --git a/cmake/yup_dependencies.cmake b/cmake/yup_dependencies.cmake
index bffc1de4..a179c218 100644
--- a/cmake/yup_dependencies.cmake
+++ b/cmake/yup_dependencies.cmake
@@ -19,30 +19,44 @@
#==============================================================================
-function (_yup_fetch_glfw3)
- FetchContent_Declare (glfw
- GIT_REPOSITORY https://github.com/kunitoki/glfw.git
- GIT_TAG dev/android_support
+function (_yup_fetch_sdl2)
+ if (TARGET sdl2::sdl2)
+ return()
+ endif()
+
+ FetchContent_Declare (SDL2
+ GIT_REPOSITORY https://github.com/libsdl-org/SDL.git
+ GIT_TAG release-2.30.10
+ SOURCE_DIR ${CMAKE_BINARY_DIR}/externals/SDL2
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE)
- set (GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
- set (GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
- set (GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
- set (GLFW_BUILD_WAYLAND OFF CACHE BOOL "" FORCE)
- set (GLFW_INSTALL OFF CACHE STRING "" FORCE)
+ set (BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
+ set (SDL_SHARED OFF CACHE BOOL "" FORCE)
+ set (SDL_STATIC ON CACHE BOOL "" FORCE)
+ set (SDL_STATIC_PIC ON CACHE BOOL "" FORCE)
+ set (SDL_AUDIO_ENABLED_BY_DEFAULT OFF CACHE BOOL "" FORCE)
+
+ FetchContent_MakeAvailable (SDL2)
- FetchContent_MakeAvailable (glfw)
+ set_target_properties (SDL2-static PROPERTIES
+ POSITION_INDEPENDENT_CODE ON
+ FOLDER "Thirdparty")
- set_target_properties (glfw PROPERTIES FOLDER "Thirdparty")
+ add_library (sdl2::sdl2 ALIAS SDL2-static)
endfunction()
#==============================================================================
function (_yup_fetch_perfetto)
+ if (TARGET perfetto::perfetto)
+ return()
+ endif()
+
FetchContent_Declare (Perfetto
GIT_REPOSITORY https://android.googlesource.com/platform/external/perfetto
GIT_TAG v42.0
+ SOURCE_DIR ${CMAKE_BINARY_DIR}/externals/Perfetto
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE)
@@ -59,7 +73,7 @@ function (_yup_fetch_perfetto)
"$")
set_target_properties (perfetto PROPERTIES
- POSITION_INDEPENDENT_CODE TRUE
+ POSITION_INDEPENDENT_CODE ON
FOLDER "Thirdparty")
if (WIN32)
diff --git a/cmake/yup_embed_binary.cmake b/cmake/yup_embed_binary.cmake
index c2ebf8a3..ab01534a 100644
--- a/cmake/yup_embed_binary.cmake
+++ b/cmake/yup_embed_binary.cmake
@@ -35,7 +35,8 @@ function (yup_add_embedded_binary_resources library_name)
target_include_directories (${library_name} PUBLIC "${CMAKE_CURRENT_BINARY_DIR}")
target_compile_features (${library_name} PUBLIC cxx_std_17)
- set_target_properties (${library_name} PROPERTIES POSITION_INDEPENDENT_CODE ON)
+ set_target_properties (${library_name} PROPERTIES
+ POSITION_INDEPENDENT_CODE ON)
file (WRITE "${binary_header_path}"
"#pragma once\n"
diff --git a/cmake/yup_modules.cmake b/cmake/yup_modules.cmake
index b276067c..b8cc172d 100644
--- a/cmake/yup_modules.cmake
+++ b/cmake/yup_modules.cmake
@@ -70,12 +70,12 @@ function (_yup_module_collect_sources folder output_variable)
foreach (extension ${source_extensions})
file (GLOB found_source_files "${base_path}*${extension}")
- if (NOT "${yup_platform}" MATCHES "^(win32|uwp)$")
- list (FILTER found_source_files EXCLUDE REGEX "${base_path}*_windows${extension}")
+ if (NOT "${yup_platform}" MATCHES "^(windows|uwp)$")
+ list (FILTER found_source_files EXCLUDE REGEX "${base_path}*_microsoft${extension}")
endif()
- if (NOT "${yup_platform}" MATCHES "^(win32)$")
- list (FILTER found_source_files EXCLUDE REGEX "${base_path}*_win32${extension}")
+ if (NOT "${yup_platform}" MATCHES "^(windows)$")
+ list (FILTER found_source_files EXCLUDE REGEX "${base_path}*_windows${extension}")
endif()
if (NOT "${yup_platform}" MATCHES "^(uwp)$")
@@ -115,9 +115,7 @@ function (_yup_module_collect_sources folder output_variable)
list (FILTER found_source_files EXCLUDE REGEX "${base_path}*_posix${extension}")
endif()
- foreach (source ${found_source_files})
- list (APPEND all_module_sources ${source})
- endforeach()
+ list (APPEND all_module_sources ${found_source_files})
endforeach()
set (module_sources "")
@@ -173,7 +171,7 @@ function (_yup_module_setup_target module_name
module_frameworks
module_dependencies
module_arc_enabled)
- if ("${yup_platform}" MATCHES "^(win32|uwp)$")
+ if ("${yup_platform}" MATCHES "^(windows|uwp)$")
list (APPEND module_defines NOMINMAX=1 WIN32_LEAN_AND_MEAN=1)
endif()
@@ -221,7 +219,7 @@ endfunction()
#==============================================================================
function (_yup_module_setup_plugin_client_clap target_name plugin_client_target folder_name)
- if (NOT "${yup_platform}" MATCHES "^(osx|linux|win32)$")
+ if (NOT "${yup_platform}" MATCHES "^(osx|linux|windows)$")
return()
endif()
@@ -345,13 +343,23 @@ function (yup_add_module module_path)
# ==== Setup Platform-Specific Configurations
if ("${yup_platform}" MATCHES "^(ios)$")
- list (APPEND module_dependencies ${module_iosDeps})
- list (APPEND module_defines ${module_iosDefines})
- list (APPEND module_options ${module_iosOptions})
- list (APPEND module_libs ${module_iosLibs})
- _yup_resolve_variable_paths ("${module_iosSearchpaths}" module_iosSearchpaths)
- list (APPEND module_searchpaths ${module_iosSearchpaths})
- _yup_module_prepare_frameworks ("${module_iosFrameworks}" "${module_iosWeakFrameworks}" module_frameworks)
+ if (PLATFORM MATCHES "^(SIMULATOR.*)$")
+ list (APPEND module_dependencies ${module_iosSimDeps})
+ list (APPEND module_defines ${module_iosSimDefines})
+ list (APPEND module_options ${module_iosSimOptions})
+ list (APPEND module_libs ${module_iosSimLibs})
+ _yup_resolve_variable_paths ("${module_iosSimSearchpaths}" module_iosSimSearchpaths)
+ list (APPEND module_searchpaths ${module_iosSimSearchpaths})
+ _yup_module_prepare_frameworks ("${module_iosSimFrameworks}" "${module_iosSimWeakFrameworks}" module_frameworks)
+ else()
+ list (APPEND module_dependencies ${module_iosDeps})
+ list (APPEND module_defines ${module_iosDefines})
+ list (APPEND module_options ${module_iosOptions})
+ list (APPEND module_libs ${module_iosLibs})
+ _yup_resolve_variable_paths ("${module_iosSearchpaths}" module_iosSearchpaths)
+ list (APPEND module_searchpaths ${module_iosSearchpaths})
+ _yup_module_prepare_frameworks ("${module_iosFrameworks}" "${module_iosWeakFrameworks}" module_frameworks)
+ endif()
elseif ("${yup_platform}" MATCHES "^(osx)$")
list (APPEND module_dependencies ${module_osxDeps})
@@ -390,7 +398,7 @@ function (yup_add_module module_path)
_yup_resolve_variable_paths ("${module_androidSearchpaths}" module_androidSearchpaths)
list (APPEND module_searchpaths ${module_androidSearchpaths})
- elseif ("${yup_platform}" MATCHES "^(win32|uwp)$")
+ elseif ("${yup_platform}" MATCHES "^(windows|uwp)$")
list (APPEND module_dependencies ${module_windowsDeps})
list (APPEND module_defines ${module_windowsDefines})
list (APPEND module_options ${module_windowsOptions})
diff --git a/cmake/yup_platforms.cmake b/cmake/yup_platforms.cmake
index 28633cab..b0d56f36 100644
--- a/cmake/yup_platforms.cmake
+++ b/cmake/yup_platforms.cmake
@@ -23,7 +23,7 @@ function (_yup_prepare_gradle_android)
set (options "")
set (one_value_args
MIN_SDK_VERSION COMPILE_SDK_VERSION TARGET_SDK_VERSION
- TARGET_NAME ABI TOOLCHAIN PLATFORM STL CPP_VERSION CMAKE_VERSION
+ TARGET_NAME TARGET_ICON ABI TOOLCHAIN PLATFORM STL CPP_VERSION CMAKE_VERSION
APPLICATION_ID APPLICATION_NAMESPACE APPLICATION_CMAKELISTS_PATH APPLICATION_VERSION)
set (multi_value_args "")
@@ -38,8 +38,8 @@ function (_yup_prepare_gradle_android)
_yup_set_default (YUP_ANDROID_PLATFORM "android-${YUP_ANDROID_MIN_SDK_VERSION}")
_yup_set_default (YUP_ANDROID_STL "c++_shared")
_yup_set_default (YUP_ANDROID_CPP_VERSION "17")
- _yup_set_default (YUP_ANDROID_APPLICATION_ID "com.yup.default_app")
- _yup_set_default (YUP_ANDROID_APPLICATION_NAMESPACE "${YUP_ANDROID_APPLICATION_ID}")
+ _yup_set_default (YUP_ANDROID_APPLICATION_NAMESPACE "org.yup")
+ _yup_set_default (YUP_ANDROID_APPLICATION_ID "org.yup.default_app")
_yup_set_default (YUP_ANDROID_APPLICATION_VERSION "1.0")
_yup_set_default (YUP_ANDROID_APPLICATION_PATH "${CMAKE_CURRENT_SOURCE_DIR}")
_yup_set_default (YUP_ANDROID_ABI "arm64-v8a")
@@ -55,6 +55,7 @@ function (_yup_prepare_gradle_android)
configure_file (${BASE_FILES_PATH}/settings.gradle.kts.in ${CMAKE_CURRENT_BINARY_DIR}/settings.gradle.kts)
configure_file (${BASE_FILES_PATH}/app/build.gradle.kts.in ${CMAKE_CURRENT_BINARY_DIR}/app/build.gradle.kts)
configure_file (${BASE_FILES_PATH}/app/proguard-rules.pro.in ${CMAKE_CURRENT_BINARY_DIR}/app/proguard-rules.pro)
+ configure_file (${BASE_FILES_PATH}/app/src/main/java/org/yup/YupActivity.java.in ${CMAKE_CURRENT_BINARY_DIR}/app/src/main/java/org/yup/YupActivity.java)
configure_file (${BASE_FILES_PATH}/app/src/main/AndroidManifest.xml.in ${CMAKE_CURRENT_BINARY_DIR}/app/src/main/AndroidManifest.xml)
configure_file (${BASE_FILES_PATH}/gradle/libs.versions.toml.in ${CMAKE_CURRENT_BINARY_DIR}/gradle/libs.versions.toml COPYONLY)
configure_file (${BASE_FILES_PATH}/gradle/wrapper/gradle-wrapper.jar.in ${CMAKE_CURRENT_BINARY_DIR}/gradle/wrapper/gradle-wrapper.jar COPYONLY)
@@ -62,6 +63,36 @@ function (_yup_prepare_gradle_android)
configure_file (${BASE_FILES_PATH}/gradlew.in ${CMAKE_CURRENT_BINARY_DIR}/gradlew COPYONLY)
configure_file (${BASE_FILES_PATH}/gradlew.bat.in ${CMAKE_CURRENT_BINARY_DIR}/gradlew.bat COPYONLY)
configure_file (${BASE_FILES_PATH}/gradle.properties.in ${CMAKE_CURRENT_BINARY_DIR}/gradle.properties COPYONLY)
+
+ # Copy icons
+ if (YUP_ANDROID_TARGET_ICON)
+ set (base_icon_path "${CMAKE_CURRENT_BINARY_DIR}/app/src/main/res")
+
+ find_program (sips_program sips)
+ if (sips_program)
+ file (MAKE_DIRECTORY ${base_icon_path}/mipmap-ldpi RESULT result)
+ _yup_execute_process_or_fail (${sips_program} -z 36 36 "${YUP_ANDROID_TARGET_ICON}" --out "${base_icon_path}/mipmap-ldpi/ic_launcher.png")
+ file (MAKE_DIRECTORY ${base_icon_path}/mipmap-mdpi RESULT result)
+ _yup_execute_process_or_fail (${sips_program} -z 48 48 "${YUP_ANDROID_TARGET_ICON}" --out "${base_icon_path}/mipmap-mdpi/ic_launcher.png")
+ file (MAKE_DIRECTORY ${base_icon_path}/mipmap-hdpi RESULT result)
+ _yup_execute_process_or_fail (${sips_program} -z 72 72 "${YUP_ANDROID_TARGET_ICON}" --out "${base_icon_path}/mipmap-hdpi/ic_launcher.png")
+ file (MAKE_DIRECTORY ${base_icon_path}/mipmap-xhdpi RESULT result)
+ _yup_execute_process_or_fail (${sips_program} -z 96 96 "${YUP_ANDROID_TARGET_ICON}" --out "${base_icon_path}/mipmap-xhdpi/ic_launcher.png")
+ file (MAKE_DIRECTORY ${base_icon_path}/mipmap-xxhdpi RESULT result)
+ _yup_execute_process_or_fail (${sips_program} -z 144 144 "${YUP_ANDROID_TARGET_ICON}" --out "${base_icon_path}/mipmap-xxhdpi/ic_launcher.png")
+ file (MAKE_DIRECTORY ${base_icon_path}/mipmap-xxxhdpi RESULT result)
+ _yup_execute_process_or_fail (${sips_program} -z 192 192 "${YUP_ANDROID_TARGET_ICON}" --out "${base_icon_path}/mipmap-xxxhdpi/ic_launcher.png")
+ else()
+ configure_file (${YUP_ANDROID_TARGET_ICON} ${base_icon_path}/mipmap-xxxhdpi/ic_launcher.png COPYONLY)
+ endif()
+ endif()
+
endfunction()
#==============================================================================
+
+function (_yup_copy_sdl2_activity_android)
+ set (JAVA_SOURCE_RELATIVE_FOLDER app/src/main/java)
+ set (SOURCE_FOLDER ${CMAKE_BINARY_DIR}/externals/SDL2/android-project/${JAVA_SOURCE_RELATIVE_FOLDER}/org)
+ file (COPY ${SOURCE_FOLDER} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/${JAVA_SOURCE_RELATIVE_FOLDER})
+endfunction()
diff --git a/cmake/yup_standalone.cmake b/cmake/yup_standalone.cmake
index 57f29a57..2308a9bb 100644
--- a/cmake/yup_standalone.cmake
+++ b/cmake/yup_standalone.cmake
@@ -24,23 +24,28 @@ function (yup_standalone_app)
set (options "")
set (one_value_args
# Globals
- TARGET_NAME TARGET_VERSION TARGET_CONSOLE TARGET_IDE_GROUP TARGET_APP_ID TARGET_APP_NAMESPACE TARGET_ICON
+ TARGET_NAME TARGET_VERSION TARGET_CONSOLE TARGET_IDE_GROUP TARGET_APP_NAMESPACE TARGET_ICON TARGET_CXX_STANDARD
# Emscripten
INITIAL_MEMORY PTHREAD_POOL_SIZE CUSTOM_PLIST CUSTOM_SHELL)
set (multi_value_args
# Globals
- DEFINITIONS MODULES LINK_OPTIONS
+ DEFINITIONS COMPILE_OPTIONS MODULES LINK_OPTIONS
# Emscripten
PRELOAD_FILES)
cmake_parse_arguments (YUP_ARG "${options}" "${one_value_args}" "${multi_value_args}" ${ARGN})
+ _yup_set_default (YUP_ARG_TARGET_CXX_STANDARD 17)
+ _yup_set_default (YUP_ARG_TARGET_ICON "${CMAKE_SOURCE_DIR}/cmake/resources/app-icon.png")
+
set (target_name "${YUP_ARG_TARGET_NAME}")
set (target_version "${YUP_ARG_TARGET_VERSION}")
set (target_console "${YUP_ARG_TARGET_CONSOLE}")
- set (target_app_id "${YUP_ARG_TARGET_APP_ID}")
+ set (target_icon "${YUP_ARG_TARGET_ICON}")
set (target_app_namespace "${YUP_ARG_TARGET_APP_NAMESPACE}")
+ set (target_app_identifier "${target_app_namespace}.${target_name}")
set (target_resources "")
+ set (target_cxx_standard "${YUP_ARG_TARGET_CXX_STANDARD}")
set (additional_definitions "")
set (additional_options "")
set (additional_libraries "")
@@ -49,20 +54,31 @@ function (yup_standalone_app)
_yup_set_default (target_console OFF)
_yup_make_short_version ("${target_version}" target_version_short)
+ # ==== Output status
+ _yup_message (STATUS "${target_name} - Configuring standalone application")
+
# ==== Setup Android platform, build gradle stage
if (YUP_TARGET_ANDROID)
+ _yup_message (STATUS "${target_name} - Creating java gradle project")
_yup_prepare_gradle_android(
TARGET_NAME ${target_name}
- APPLICATION_ID ${target_app_id}
+ TARGET_ICON ${target_icon}
+ APPLICATION_ID ${target_app_identifier}
APPLICATION_NAMESPACE ${target_app_namespace}
APPLICATION_VERSION ${target_version})
+
+ _yup_message (STATUS "${target_name} - Copying SDL2 java activity to application")
+ _yup_fetch_sdl2()
+ _yup_copy_sdl2_activity_android()
+
return()
endif()
# ==== Find dependencies
- if (NOT "${yup_platform}" MATCHES "^(emscripten|ios)$")
- _yup_fetch_glfw3()
- list (APPEND additional_libraries glfw)
+ if (NOT "${yup_platform}" MATCHES "^(emscripten)$")
+ _yup_message (STATUS "${target_name} - Fetching SDL2 library")
+ _yup_fetch_sdl2()
+ list (APPEND additional_libraries sdl2::sdl2)
endif()
# ==== Enable profiling
@@ -74,7 +90,7 @@ function (yup_standalone_app)
# ==== Prepare executable
set (executable_options "")
if (NOT "${target_console}")
- if ("${yup_platform}" MATCHES "^(win32)$")
+ if ("${yup_platform}" MATCHES "^(windows)$")
set (executable_options "WIN32")
elseif ("${yup_platform}" MATCHES "^(osx)$")
set (executable_options "MACOSX_BUNDLE")
@@ -87,16 +103,16 @@ function (yup_standalone_app)
add_executable (${target_name} ${executable_options})
endif()
- target_compile_features (${target_name} PRIVATE cxx_std_17)
+ target_compile_features (${target_name} PRIVATE cxx_std_${target_cxx_standard})
# ==== Per platform configuration
if ("${yup_platform}" MATCHES "^(osx|ios)$")
if (NOT "${target_console}")
_yup_set_default (YUP_ARG_CUSTOM_PLIST "${CMAKE_SOURCE_DIR}/cmake/platforms/${yup_platform}/Info.plist")
- _yup_valid_identifier_string ("${target_app_namespace}" target_app_namespace)
+ _yup_valid_identifier_string ("${target_app_identifier}" target_app_identifier)
- _yup_set_default (YUP_ARG_TARGET_ICON "${CMAKE_SOURCE_DIR}/cmake/resources/app-icon.png")
- _yup_convert_png_to_icns ("${YUP_ARG_TARGET_ICON}" "${CMAKE_CURRENT_BINARY_DIR}/icons" target_iconset)
+ _yup_message (STATUS "${target_name} - Converting application input icon to apple .icns format")
+ _yup_convert_png_to_icns ("${target_icon}" "${CMAKE_CURRENT_BINARY_DIR}/icons" target_iconset)
get_filename_component (target_iconset_name "${target_iconset}" NAME)
target_sources (${target_name} PRIVATE ${target_iconset})
list (APPEND target_resources "${target_iconset}")
@@ -105,7 +121,7 @@ function (yup_standalone_app)
BUNDLE ON
CXX_EXTENSIONS OFF
MACOSX_BUNDLE_EXECUTABLE_NAME "${target_name}"
- MACOSX_BUNDLE_GUI_IDENTIFIER "${target_app_namespace}"
+ MACOSX_BUNDLE_GUI_IDENTIFIER "${target_app_identifier}"
MACOSX_BUNDLE_BUNDLE_NAME "${target_name}"
MACOSX_BUNDLE_BUNDLE_VERSION "${target_version}"
MACOSX_BUNDLE_LONG_VERSION_STRING "${target_version}"
@@ -113,7 +129,7 @@ function (yup_standalone_app)
MACOSX_BUNDLE_INFO_PLIST "${YUP_ARG_CUSTOM_PLIST}"
MACOSX_BUNDLE_ICON_FILE "${target_iconset_name}"
RESOURCE "${target_resources}"
- XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "${target_app_namespace}")
+ XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "${target_app_identifier}")
endif()
@@ -129,8 +145,8 @@ function (yup_standalone_app)
if (NOT "${target_console}")
set_target_properties (${target_name} PROPERTIES SUFFIX ".html")
- list (APPEND additional_definitions RIVE_WEBGL=1)
- list (APPEND additional_link_options -sUSE_GLFW=3 -sMAX_WEBGL_VERSION=2)
+ list (APPEND additional_options -sUSE_SDL=2)
+ list (APPEND additional_link_options -sUSE_SDL=2 -sMAX_WEBGL_VERSION=2)
endif()
_yup_set_default (YUP_ARG_CUSTOM_SHELL "${CMAKE_SOURCE_DIR}/cmake/platforms/${yup_platform}/shell.html")
@@ -189,7 +205,7 @@ function (yup_standalone_app)
# ==== Definitions and link libraries
target_compile_options (${target_name} PRIVATE
${additional_options}
- ${YUP_ARG_OPTIONS})
+ ${YUP_ARG_COMPILE_OPTIONS})
target_compile_definitions (${target_name} PRIVATE
$,DEBUG=1,NDEBUG=1>
diff --git a/cmake/yup_utilities.cmake b/cmake/yup_utilities.cmake
index 2ea845ac..d9b5757b 100644
--- a/cmake/yup_utilities.cmake
+++ b/cmake/yup_utilities.cmake
@@ -27,6 +27,16 @@ endfunction()
#==============================================================================
+function (_yup_bool_to_string value output_variable)
+ if (value)
+ set (${output_variable} "true" PARENT_SCOPE)
+ else()
+ set (${output_variable} "false" PARENT_SCOPE)
+ endif()
+endfunction()
+
+#==============================================================================
+
function (_yup_valid_identifier_string identifier output_variable)
string (REPLACE "_" "-" identifier ${identifier})
set (${output_variable} "${identifier}" PARENT_SCOPE)
diff --git a/examples/app/CMakeLists.txt b/examples/app/CMakeLists.txt
index 8a8231ee..c2a3c1cb 100644
--- a/examples/app/CMakeLists.txt
+++ b/examples/app/CMakeLists.txt
@@ -23,9 +23,10 @@ cmake_minimum_required (VERSION 3.28)
set (target_name example_app)
set (target_version "1.0.0")
+project (${target_name} VERSION ${target_version})
+
# ==== Prepare Android build
if (ANDROID)
- # project (${target_name} VERSION ${target_version})
include (../../cmake/yup.cmake)
_yup_setup_platform()
_yup_add_default_modules ("${CMAKE_CURRENT_LIST_DIR}/../..")
@@ -37,7 +38,7 @@ yup_standalone_app (
TARGET_VERSION ${target_version}
TARGET_IDE_GROUP "Examples"
TARGET_APP_ID "org.yup.${target_name}"
- TARGET_APP_NAMESPACE "org.yup.${target_name}"
+ TARGET_APP_NAMESPACE "org.yup"
MODULES
juce_core
juce_events
diff --git a/examples/console/CMakeLists.txt b/examples/console/CMakeLists.txt
index 7f56c4fa..85ba322d 100644
--- a/examples/console/CMakeLists.txt
+++ b/examples/console/CMakeLists.txt
@@ -23,9 +23,10 @@ cmake_minimum_required(VERSION 3.28)
set (target_name example_console)
set (target_version "1.0.0")
+project (${target_name} VERSION ${target_version})
+
# ==== Prepare Android build
if (ANDROID)
- # project (${target_name} VERSION ${target_version})
include (../../cmake/yup.cmake)
_yup_setup_platform()
_yup_add_default_modules ("${CMAKE_CURRENT_LIST_DIR}/../..")
@@ -37,7 +38,7 @@ yup_standalone_app (
TARGET_VERSION ${target_version}
TARGET_IDE_GROUP "Examples"
TARGET_APP_ID "org.yup.${target_name}"
- TARGET_APP_NAMESPACE "org.yup.${target_name}"
+ TARGET_APP_NAMESPACE "org.yup"
TARGET_CONSOLE ON
MODULES
juce_core
diff --git a/examples/graphics/CMakeLists.txt b/examples/graphics/CMakeLists.txt
index 5a3870db..dafe555b 100644
--- a/examples/graphics/CMakeLists.txt
+++ b/examples/graphics/CMakeLists.txt
@@ -26,24 +26,24 @@ set (target_version "1.0.0")
project (${target_name} VERSION ${target_version})
# ==== Prepare Android build
+set (link_libraries "")
if (ANDROID)
- # project (${target_name} VERSION ${target_version})
include (../../cmake/yup.cmake)
_yup_setup_platform()
_yup_add_default_modules ("${CMAKE_CURRENT_LIST_DIR}/../..")
-endif()
-# ==== Prepare Android build
-yup_add_embedded_binary_resources (
- "${target_name}_binary_data"
- OUT_DIR BinaryData
- HEADER BinaryData.h
- NAMESPACE yup
- RESOURCE_NAMES
- RobotoRegularFont
- RESOURCES
- ${CMAKE_CURRENT_LIST_DIR}/data/Roboto-Regular.ttf
-)
+ yup_add_embedded_binary_resources (
+ "${target_name}_binary_data"
+ OUT_DIR BinaryData
+ HEADER BinaryData.h
+ NAMESPACE yup
+ RESOURCE_NAMES
+ RobotoRegularFont
+ RESOURCES
+ "${CMAKE_CURRENT_LIST_DIR}/data/Roboto-Regular.ttf")
+
+ set (link_libraries "${target_name}_binary_data")
+endif()
# ==== Prepare target
yup_standalone_app (
@@ -51,7 +51,7 @@ yup_standalone_app (
TARGET_VERSION ${target_version}
TARGET_IDE_GROUP "Examples"
TARGET_APP_ID "org.yup.${target_name}"
- TARGET_APP_NAMESPACE "org.yup.${target_name}"
+ TARGET_APP_NAMESPACE "org.yup"
PRELOAD_FILES
"${CMAKE_CURRENT_LIST_DIR}/data/Roboto-Regular.ttf@data/Roboto-Regular.ttf"
MODULES
@@ -66,8 +66,7 @@ yup_standalone_app (
sheenbidi
rive
rive_renderer
- "${target_name}_binary_data"
-)
+ ${link_libraries})
# ==== Prepare sources
if (NOT YUP_TARGET_ANDROID)
diff --git a/examples/graphics/source/main.cpp b/examples/graphics/source/main.cpp
index e91f4a4d..6910946e 100644
--- a/examples/graphics/source/main.cpp
+++ b/examples/graphics/source/main.cpp
@@ -28,6 +28,10 @@
#include
#include // For sine wave generation
+#if JUCE_ANDROID
+#include
+#endif
+
//==============================================================================
class SineWaveGenerator
@@ -138,19 +142,23 @@ class CustomWindow
setTitle ("main");
// Load the font
- yup::File fontFilePath =
+#if JUCE_ANDROID
+ yup::MemoryBlock mb (yup::RobotoRegularFont_data, yup::RobotoRegularFont_size);
+ if (auto result = font.loadFromData (mb, factory); result.failed())
+ yup::Logger::outputDebugString (result.getErrorMessage());
+#else
#if JUCE_WASM
- yup::File ("/data")
+ auto fontFilePath = yup::File ("/data")
#else
- yup::File (__FILE__).getParentDirectory().getSiblingFile ("data")
+ auto fontFilePath = yup::File (__FILE__).getParentDirectory().getSiblingFile ("data")
#endif
- .getChildFile ("Roboto-Regular.ttf");
+ .getChildFile ("Roboto-Regular.ttf");
if (auto result = font.loadFromFile (fontFilePath, factory); result.failed())
yup::Logger::outputDebugString (result.getErrorMessage());
+#endif
// Initialize the audio device
- deviceManager.addAudioCallback (this);
deviceManager.initialiseWithDefaultDevices (0, 2);
// Initialize sine wave generators
@@ -162,6 +170,8 @@ class CustomWindow
sineWaveGenerators[i]->setFrequency (440.0 * std::pow (1.1, i), sampleRate);
}
+ deviceManager.addAudioCallback (this);
+
// Add sliders
for (int i = 0; i < totalRows * totalColumns; ++i)
{
@@ -193,6 +203,7 @@ class CustomWindow
~CustomWindow() override
{
+ deviceManager.removeAudioCallback (this);
deviceManager.closeAudioDevice();
}
@@ -371,6 +382,14 @@ struct Application : yup::YUPApplication
window = std::make_unique();
window->centreWithSize ({ 800, 800 });
+
+#if JUCE_IOS || JUCE_ANDROID
+ window->centreWithSize ({ 1080, 2400 });
+ // window->setFullScreen(true);
+#else
+ window->centreWithSize ({ 800, 800 });
+#endif
+
window->setVisible (true);
}
diff --git a/examples/plugin/CMakeLists.txt b/examples/plugin/CMakeLists.txt
index f3b54cc5..61befee3 100644
--- a/examples/plugin/CMakeLists.txt
+++ b/examples/plugin/CMakeLists.txt
@@ -23,6 +23,8 @@ cmake_minimum_required(VERSION 3.28)
set (target_name example_plugin)
set (target_version "1.0.0")
+project (${target_name} VERSION ${target_version})
+
yup_add_embedded_binary_resources (
"${target_name}_binary_data"
OUT_DIR BinaryData
@@ -39,7 +41,7 @@ yup_audio_plugin (
TARGET_VERSION ${target_version}
TARGET_IDE_GROUP "Examples"
TARGET_APP_ID "org.yup.${target_name}"
- TARGET_APP_NAMESPACE "org.yup.${target_name}"
+ TARGET_APP_NAMESPACE "org.yup"
PLUGIN_ID "org.yup.YupCLAP"
PLUGIN_NAME "YupCLAPPZ"
PLUGIN_VENDOR "org.yup"
diff --git a/examples/render/CMakeLists.txt b/examples/render/CMakeLists.txt
index ab59dd3b..f21f1cf7 100644
--- a/examples/render/CMakeLists.txt
+++ b/examples/render/CMakeLists.txt
@@ -25,7 +25,7 @@ set (target_version "1.0.0")
project (${target_name} VERSION ${target_version})
-set (rive_file "data/seasynth.riv")
+set (rive_file "data/alien.riv")
# ==== Prepare Android build
set (link_libraries "")
@@ -42,8 +42,8 @@ if (ANDROID)
RESOURCE_NAMES
RiveFile
RESOURCES
- ${CMAKE_CURRENT_LIST_DIR}/${rive_file}
- )
+ "${CMAKE_CURRENT_LIST_DIR}/${rive_file}")
+
set (link_libraries "${target_name}_binary_data")
endif()
@@ -53,8 +53,7 @@ yup_standalone_app (
TARGET_VERSION ${target_version}
TARGET_IDE_GROUP "Examples"
TARGET_APP_ID "org.yup.${target_name}"
- TARGET_APP_NAMESPACE "org.yup.${target_name}"
- LINK_OPTIONS ${link_options}
+ TARGET_APP_NAMESPACE "org.yup"
INITIAL_MEMORY 268435456
PRELOAD_FILES
"${CMAKE_CURRENT_LIST_DIR}/${rive_file}@data/artboard.riv"
@@ -70,8 +69,7 @@ yup_standalone_app (
sheenbidi
rive
rive_renderer
- ${link_libraries}
-)
+ ${link_libraries})
# ==== Prepare sources
if (NOT YUP_TARGET_ANDROID)
diff --git a/examples/render/source/main.cpp b/examples/render/source/main.cpp
index d9e6b027..70f16fde 100644
--- a/examples/render/source/main.cpp
+++ b/examples/render/source/main.cpp
@@ -40,7 +40,7 @@ class CustomWindow
CustomWindow()
// Fluid and continuous animations needs continuous repainting
: yup::DocumentWindow (yup::ComponentNative::Options()
- .withFlags (yup::ComponentNative::defaultFlags | yup::ComponentNative::renderContinuous),
+ .withRenderContinuous (true),
{})
{
// Set title
@@ -84,17 +84,20 @@ class CustomWindow
//for (int i = 0; i < totalRows * totalColumns; ++i)
// artboards.getUnchecked (i)->setBounds (getLocalBounds().reduced (100.0f));
+ if (artboards.size() != totalRows * totalColumns)
+ return;
+
auto bounds = getLocalBounds().reduced (50);
auto width = bounds.getWidth() / totalColumns;
auto height = bounds.getHeight() / totalRows;
- for (int i = 0; i < totalRows && artboards.size(); ++i)
+ for (int i = 0; i < totalRows; ++i)
{
auto row = bounds.removeFromTop (height);
for (int j = 0; j < totalColumns; ++j)
{
auto col = row.removeFromLeft (width);
- artboards.getUnchecked (i * totalRows + j)->setBounds (col.largestFittingSquare());
+ artboards.getUnchecked (j * totalRows + i)->setBounds (col.largestFittingSquare());
}
}
}
@@ -118,8 +121,8 @@ class CustomWindow
break;
case yup::KeyPress::textPKey:
- for (int i = 0; i < totalRows * totalColumns; ++i)
- artboards[i]->setPaused (! artboards[i]->isPaused());
+ for (auto& artboard : artboards)
+ artboard->setPaused (! artboard->isPaused());
break;
case yup::KeyPress::textZKey:
@@ -168,8 +171,8 @@ class CustomWindow
}
yup::OwnedArray artboards;
- int totalRows = 4;
- int totalColumns = 4;
+ int totalRows = 2;
+ int totalColumns = 1;
};
//==============================================================================
@@ -195,7 +198,13 @@ struct Application : yup::YUPApplication
yup::Logger::outputDebugString ("Starting app " + commandLineParameters);
window = std::make_unique();
+
+#if JUCE_IOS || JUCE_ANDROID
+ window->centreWithSize ({ 1080, 2400 });
+#else
window->centreWithSize ({ 1280, 866 });
+#endif
+
window->setVisible (true);
}
diff --git a/justfile b/justfile
index 13629ed2..88184540 100644
--- a/justfile
+++ b/justfile
@@ -15,6 +15,10 @@ ios:
cmake -G Xcode -B build -DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/ios.cmake -DPLATFORM=OS64
-open build/yup.xcodeproj
+ios_simulator:
+ cmake -G Xcode -B build -DCMAKE_TOOLCHAIN_FILE=cmake/toolchains/ios.cmake -DPLATFORM=SIMULATORARM64
+ -open build/yup.xcodeproj
+
android:
cmake -G "Unix Makefiles" -B build -DYUP_TARGET_ANDROID=ON
-open -a /Applications/Android\ Studio.app build/examples/render
diff --git a/modules/juce_audio_basics/juce_audio_basics.h b/modules/juce_audio_basics/juce_audio_basics.h
index a765d1c7..99cd94f0 100644
--- a/modules/juce_audio_basics/juce_audio_basics.h
+++ b/modules/juce_audio_basics/juce_audio_basics.h
@@ -58,6 +58,7 @@
dependencies: juce_core
osxFrameworks: Accelerate
iosFrameworks: Accelerate
+ iosSimFrameworks: Accelerate
END_JUCE_MODULE_DECLARATION
diff --git a/modules/juce_audio_devices/juce_audio_devices.h b/modules/juce_audio_devices/juce_audio_devices.h
index ebc35291..2960a0c8 100644
--- a/modules/juce_audio_devices/juce_audio_devices.h
+++ b/modules/juce_audio_devices/juce_audio_devices.h
@@ -58,6 +58,7 @@
dependencies: juce_audio_basics juce_events
osxFrameworks: CoreAudio CoreMIDI AudioToolbox
iosFrameworks: CoreAudio CoreMIDI AudioToolbox AVFoundation
+ iosSimFrameworks: CoreAudio CoreMIDI AudioToolbox AVFoundation
linuxPackages: alsa
androidDeps: oboe_library
mingwLibs: winmm
diff --git a/modules/juce_core/juce_core.h b/modules/juce_core/juce_core.h
index e947d2ae..275f58a6 100644
--- a/modules/juce_core/juce_core.h
+++ b/modules/juce_core/juce_core.h
@@ -58,6 +58,7 @@
dependencies: zlib
osxFrameworks: Cocoa Foundation IOKit Security
iosFrameworks: Foundation UIKit
+ iosSimFrameworks: Foundation UIKit
linuxLibs: rt dl pthread
androidLibs: log android
androidSearchpaths: {ANDROID_NDK}/sources/android/cpufeatures
diff --git a/modules/juce_core/misc/juce_FlagSet.h b/modules/juce_core/misc/juce_FlagSet.h
index c9f530a1..35f25169 100644
--- a/modules/juce_core/misc/juce_FlagSet.h
+++ b/modules/juce_core/misc/juce_FlagSet.h
@@ -166,6 +166,20 @@ class FlagSet
return FlagSet (flags | other.flags);
}
+ /** Binary OR operator to combine this FlagSet with another.
+
+ Combines the flags of this FlagSet with another by performing a bitwise OR operation.
+
+ @param other Another FlagSet to combine with this one.
+
+ @return The current FlagSet.
+ */
+ constexpr FlagSet& operator|= (FlagSet other) noexcept
+ {
+ flags = (flags | other.flags);
+ return *this;
+ }
+
/** Binary AND operator to intersect flags from two FlagSets.
Produces a new FlagSet containing only the flags that are set in both this and another FlagSet by performing a
@@ -180,6 +194,20 @@ class FlagSet
return FlagSet (flags & other.flags);
}
+ /** Binary AND operator to combine this FlagSet with another.
+
+ Combines the flags of this FlagSet with another by performing a bitwise AND operation.
+
+ @param other Another FlagSet to combine with this one.
+
+ @return The current FlagSet.
+ */
+ constexpr FlagSet& operator&= (FlagSet other) noexcept
+ {
+ flags = (flags & other.flags);
+ return *this;
+ }
+
/** Unary NOT operator to invert flags in the FlagSet.
Creates a new FlagSet where all flags are inverted (i.e., 1's become 0's and vice versa) from this FlagSet.
diff --git a/modules/juce_core/native/juce_BasicNativeHeaders.h b/modules/juce_core/native/juce_BasicNativeHeaders.h
index d70e4d52..2d26bdd8 100644
--- a/modules/juce_core/native/juce_BasicNativeHeaders.h
+++ b/modules/juce_core/native/juce_BasicNativeHeaders.h
@@ -45,10 +45,6 @@
#if JUCE_MAC || JUCE_IOS
#if JUCE_IOS
-#if JUCE_MODULE_AVAILABLE_juce_opengl
-#define GLES_SILENCE_DEPRECATION 1
-#endif
-
#define Component CarbonDummyCompName
#import
#undef Component
@@ -57,14 +53,12 @@
#import
#import
#include
-#else
-#if JUCE_MODULE_AVAILABLE_juce_opengl
-#define GL_SILENCE_DEPRECATION 1
-#endif
+#else
#import
#import
#include
+
#endif
#include
@@ -195,8 +189,8 @@
params: list of params (bracketed)
*/
#define JUCE_LOAD_WINAPI_FUNCTION(dll, functionName, localFunctionName, returnType, params) \
-typedef returnType (WINAPI* type##localFunctionName) params; \
-type##localFunctionName localFunctionName = (type##localFunctionName) dll.getFunction (#functionName);
+ typedef returnType (WINAPI* type##localFunctionName) params; \
+ type##localFunctionName localFunctionName = (type##localFunctionName) dll.getFunction (#functionName);
//==============================================================================
#elif JUCE_LINUX
diff --git a/modules/juce_core/native/juce_Threads_android.cpp b/modules/juce_core/native/juce_Threads_android.cpp
index 1c61c991..e2976908 100644
--- a/modules/juce_core/native/juce_Threads_android.cpp
+++ b/modules/juce_core/native/juce_Threads_android.cpp
@@ -46,7 +46,7 @@ namespace juce
*/
#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \
-FIELD (activityInfo, "activityInfo", "Landroid/content/pm/ActivityInfo;")
+ FIELD (activityInfo, "activityInfo", "Landroid/content/pm/ActivityInfo;")
DECLARE_JNI_CLASS (AndroidResolveInfo, "android/content/pm/ResolveInfo")
#undef JNI_CLASS_MEMBERS
@@ -79,7 +79,7 @@ static void JNICALL juce_JavainitialiseJUCE (JNIEnv* env, jobject /*jclass*/, jo
Thread::initialiseJUCE (env, context);
}
-extern "C" jint JNIEXPORT JNI_OnLoad (JavaVM* vm, void*)
+extern "C" jint JNIEXPORT juce_JNI_OnLoad (JavaVM* vm, void*)
{
// Huh? JNI_OnLoad was called two times!
jassert (androidJNIJavaVM == nullptr);
diff --git a/modules/juce_events/juce_events.cpp b/modules/juce_events/juce_events.cpp
index f7aceb05..b5f1edc7 100644
--- a/modules/juce_events/juce_events.cpp
+++ b/modules/juce_events/juce_events.cpp
@@ -38,7 +38,7 @@
*/
#ifdef JUCE_EVENTS_H_INCLUDED
- /* When you add this cpp file to your project, you mustn't include it in a file where you've
+/* When you add this cpp file to your project, you mustn't include it in a file where you've
already included any other headers - just put it inside a file on its own, possibly with your config
flags preceding it, but don't include anything else. That also includes avoiding any automatic prefix
header files that the compiler may be using.
@@ -76,8 +76,9 @@
#include
#elif JUCE_ANDROID
-#define GLFW_INCLUDE_NONE
-#include
+#include
+
+#include
#endif
@@ -101,7 +102,7 @@
//==============================================================================
#if JUCE_MAC || JUCE_IOS
-#include "native/juce_MessageQueue_mac.h"
+#include "native/juce_MessageQueue_apple.h"
#if JUCE_MAC
#include "native/juce_MessageManager_mac.mm"
#else
diff --git a/modules/juce_events/juce_events.h b/modules/juce_events/juce_events.h
index 5788bf19..1feb37fb 100644
--- a/modules/juce_events/juce_events.h
+++ b/modules/juce_events/juce_events.h
@@ -76,11 +76,11 @@
#endif
#if JUCE_WINDOWS && JUCE_EVENTS_INCLUDE_WINRT_WRAPPER
- // If this header file is missing then you are probably attempting to use WinRT
- // functionality without the WinRT libraries installed on your system. Try installing
- // the latest Windows Standalone SDK and maybe also adding the path to the WinRT
- // headers to your build system. This path should have the form
- // "C:\Program Files (x86)\Windows Kits\10\Include\10.0.14393.0\winrt".
+// If this header file is missing then you are probably attempting to use WinRT
+// functionality without the WinRT libraries installed on your system. Try installing
+// the latest Windows Standalone SDK and maybe also adding the path to the WinRT
+// headers to your build system. This path should have the form
+// "C:\Program Files (x86)\Windows Kits\10\Include\10.0.14393.0\winrt".
#include
#include
#endif
diff --git a/modules/juce_events/messages/juce_ApplicationBase.cpp b/modules/juce_events/messages/juce_ApplicationBase.cpp
index 3510ea68..bbe8e9d5 100644
--- a/modules/juce_events/messages/juce_ApplicationBase.cpp
+++ b/modules/juce_events/messages/juce_ApplicationBase.cpp
@@ -103,7 +103,7 @@ void JUCEApplicationBase::sendUnhandledException (const std::exception* const e,
}
//==============================================================================
-#if ! (JUCE_IOS || JUCE_ANDROID)
+#if ! (JUCE_IOS || JUCE_ANDROID || JUCE_EMSCRIPTEN)
#define JUCE_HANDLE_MULTIPLE_INSTANCES 1
#endif
@@ -188,7 +188,7 @@ StringArray JUCE_CALLTYPE JUCEApplicationBase::getCommandLineParameterArray()
#else
-#if JUCE_IOS && JUCE_MODULE_AVAILABLE_juce_gui_basics
+#if JUCE_IOS && JUCE_MODULE_AVAILABLE_yup_gui
extern int juce_iOSMain (int argc, const char* argv[], void* classPtr);
#endif
@@ -196,10 +196,6 @@ extern int juce_iOSMain (int argc, const char* argv[], void* classPtr);
extern void initialiseNSApplication();
#endif
-#if (JUCE_LINUX || JUCE_BSD) && JUCE_MODULE_AVAILABLE_juce_gui_extra && (! defined(JUCE_WEB_BROWSER) || JUCE_WEB_BROWSER)
-extern "C" int juce_gtkWebkitMain (int argc, const char* const* argv);
-#endif
-
#if JUCE_WINDOWS || JUCE_ANDROID
const char* const* juce_argv = nullptr;
int juce_argc = 0;
@@ -244,12 +240,7 @@ int JUCEApplicationBase::main (int argc, const char* argv[])
initialiseNSApplication();
#endif
-#if (JUCE_LINUX || JUCE_BSD) && JUCE_MODULE_AVAILABLE_juce_gui_extra && (! defined(JUCE_WEB_BROWSER) || JUCE_WEB_BROWSER)
- if (argc >= 2 && String (argv[1]) == "--juce-gtkwebkitfork-child")
- return juce_gtkWebkitMain (argc, argv);
-#endif
-
-#if JUCE_IOS && JUCE_MODULE_AVAILABLE_juce_gui_basics
+#if JUCE_IOS && JUCE_MODULE_AVAILABLE_yup_gui
return juce_iOSMain (argc, argv, iOSCustomDelegate);
#else
@@ -261,8 +252,26 @@ int JUCEApplicationBase::main (int argc, const char* argv[])
#endif
//==============================================================================
+#if JUCE_ANDROID
+extern "C" jint JNIEXPORT juce_JNI_OnLoad (JavaVM* vm, void*);
+#endif
+
int JUCEApplicationBase::main()
{
+#if JUCE_ANDROID
+ auto env = (JNIEnv*) SDL_AndroidGetJNIEnv();
+ auto clazz = (jobject) SDL_AndroidGetActivity();
+ JavaVM* vm = nullptr;
+
+ if (env != nullptr && env->GetJavaVM (&vm) == 0)
+ {
+ juce_JNI_OnLoad (vm, nullptr);
+
+ JNIClassBase::initialiseAllClasses (env, clazz);
+ Thread::initialiseJUCE (env, clazz);
+ }
+#endif
+
ScopedJuceInitialiser_GUI libraryInitialiser;
jassert (createInstance != nullptr);
diff --git a/modules/juce_events/messages/juce_ApplicationBase.h b/modules/juce_events/messages/juce_ApplicationBase.h
index a30a7ba6..a782b477 100644
--- a/modules/juce_events/messages/juce_ApplicationBase.h
+++ b/modules/juce_events/messages/juce_ApplicationBase.h
@@ -326,19 +326,19 @@ class JUCE_API JUCEApplicationBase
//==============================================================================
#if JUCE_CATCH_UNHANDLED_EXCEPTIONS || DOXYGEN
- /** The JUCE_TRY/JUCE_CATCH_EXCEPTION wrappers can be used to pass any uncaught exceptions to
+/** The JUCE_TRY/JUCE_CATCH_EXCEPTION wrappers can be used to pass any uncaught exceptions to
the JUCEApplicationBase::sendUnhandledException() method.
This functionality can be enabled with the JUCE_CATCH_UNHANDLED_EXCEPTIONS macro.
*/
#define JUCE_TRY try
- /** The JUCE_TRY/JUCE_CATCH_EXCEPTION wrappers can be used to pass any uncaught exceptions to
+/** The JUCE_TRY/JUCE_CATCH_EXCEPTION wrappers can be used to pass any uncaught exceptions to
the JUCEApplicationBase::sendUnhandledException() method.
This functionality can be enabled with the JUCE_CATCH_UNHANDLED_EXCEPTIONS macro.
*/
-#define JUCE_CATCH_EXCEPTION \
-catch (const std::exception& e) { juce::JUCEApplicationBase::sendUnhandledException (&e, __FILE__, __LINE__); } \
-catch (...) { juce::JUCEApplicationBase::sendUnhandledException (nullptr, __FILE__, __LINE__); }
+#define JUCE_CATCH_EXCEPTION \
+ catch (const std::exception& e) { juce::JUCEApplicationBase::sendUnhandledException (&e, __FILE__, __LINE__); } \
+ catch (...) { juce::JUCEApplicationBase::sendUnhandledException (nullptr, __FILE__, __LINE__); }
#else
#define JUCE_TRY
diff --git a/modules/juce_events/messages/juce_Initialisation.h b/modules/juce_events/messages/juce_Initialisation.h
index 2a057793..589ec09c 100644
--- a/modules/juce_events/messages/juce_Initialisation.h
+++ b/modules/juce_events/messages/juce_Initialisation.h
@@ -111,6 +111,9 @@ class JUCE_API ScopedJuceInitialiser_GUI final
int __stdcall WinMain(struct HINSTANCE__*, struct HINSTANCE__*, char*, int) \
JUCE_END_IGNORE_WARNINGS_MSVC
#define JUCE_MAIN_FUNCTION_ARGS
+#elif JUCE_ANDROID && JUCE_MODULE_AVAILABLE_yup_gui
+#define JUCE_MAIN_FUNCTION extern "C" int SDL_main(int argc, char* argv[])
+#define JUCE_MAIN_FUNCTION_ARGS argc, (const char**)argv
#else
#define JUCE_MAIN_FUNCTION int main(int argc, char* argv[])
#define JUCE_MAIN_FUNCTION_ARGS argc, (const char**)argv
@@ -150,21 +153,6 @@ class JUCE_API ScopedJuceInitialiser_GUI final
return juce::JUCEApplicationBase::main(JUCE_MAIN_FUNCTION_ARGS); \
}
-#elif JUCE_ANDROID
-
-#define JUCE_CREATE_APPLICATION_DEFINE(AppClass) \
- extern "C" juce::JUCEApplicationBase* juce_CreateApplication() \
- { \
- return new AppClass(); \
- }
-
-#define JUCE_MAIN_FUNCTION_DEFINITION \
- int main() \
- { \
- juce::JUCEApplicationBase::createInstance = &juce_CreateApplication; \
- return juce::JUCEApplicationBase::main(0, nullptr); \
- }
-
#else
#define JUCE_CREATE_APPLICATION_DEFINE(AppClass) \
diff --git a/modules/juce_events/messages/juce_MessageManager.h b/modules/juce_events/messages/juce_MessageManager.h
index de8cbab6..41dbb480 100644
--- a/modules/juce_events/messages/juce_MessageManager.h
+++ b/modules/juce_events/messages/juce_MessageManager.h
@@ -91,8 +91,7 @@ class JUCE_API MessageManager final
*/
void stopDispatchLoop();
- /** Returns true if the stopDispatchLoop() method has been called.
- */
+ /** Returns true if the stopDispatchLoop() method has been called. */
bool hasStopMessageBeenSent() const noexcept { return quitMessagePosted.get() != 0; }
#if JUCE_MODAL_LOOPS_PERMITTED
@@ -104,6 +103,10 @@ class JUCE_API MessageManager final
bool runDispatchLoopUntil (int millisecondsToRunFor);
#endif
+ //==============================================================================
+ /** Register an event loop callback that will be processed in the event loop. */
+ void registerEventLoopCallback (std::function loopCallbackToSet);
+
//==============================================================================
/** Asynchronously invokes a function or C++11 lambda on the message thread.
@@ -488,7 +491,7 @@ class JUCE_API MessageManagerLock : private Thread::Listener
created, which could happen if you accidentally invoke it during a static constructor.
*/
#define JUCE_ASSERT_MESSAGE_MANAGER_IS_LOCKED \
-jassert (juce::MessageManager::existsAndIsLockedByCurrentThread());
+ jassert (juce::MessageManager::existsAndIsLockedByCurrentThread());
/** This macro is used to catch unsafe use of functions which expect to only be called
on the message thread.
@@ -496,12 +499,12 @@ jassert (juce::MessageManager::existsAndIsLockedByCurrentThread());
created, which could happen if you accidentally invoke it during a static constructor.
*/
#define JUCE_ASSERT_MESSAGE_THREAD \
-jassert (juce::MessageManager::existsAndIsCurrentThread());
+ jassert (juce::MessageManager::existsAndIsCurrentThread());
/** This macro is used to catch unsafe use of functions which expect to not be called
outside the lifetime of the MessageManager.
*/
#define JUCE_ASSERT_MESSAGE_MANAGER_EXISTS \
-jassert (juce::MessageManager::getInstanceWithoutCreating() != nullptr);
+ jassert (juce::MessageManager::getInstanceWithoutCreating() != nullptr);
} // namespace juce
diff --git a/modules/juce_events/native/juce_MessageManager_ios.mm b/modules/juce_events/native/juce_MessageManager_ios.mm
index efcdf567..308d0b09 100644
--- a/modules/juce_events/native/juce_MessageManager_ios.mm
+++ b/modules/juce_events/native/juce_MessageManager_ios.mm
@@ -90,12 +90,12 @@
#endif
//==============================================================================
-static std::unique_ptr messageQueue;
+static std::unique_ptr messageQueue;
void MessageManager::doPlatformSpecificInitialisation()
{
if (messageQueue == nullptr)
- messageQueue.reset(new MessageQueue());
+ messageQueue.reset(new InternalMessageQueue());
}
void MessageManager::doPlatformSpecificShutdown()
@@ -116,4 +116,10 @@
// N/A on current iOS
}
+void MessageManager::registerEventLoopCallback(std::function loopCallbackToSet)
+{
+ jassert(messageQueue);
+ messageQueue->registerEventLoopCallback(std::move(loopCallbackToSet));
+}
+
} // namespace juce
diff --git a/modules/juce_events/native/juce_MessageManager_mac.mm b/modules/juce_events/native/juce_MessageManager_mac.mm
index ed4f4dd7..4ca02f83 100644
--- a/modules/juce_events/native/juce_MessageManager_mac.mm
+++ b/modules/juce_events/native/juce_MessageManager_mac.mm
@@ -316,7 +316,7 @@ static String quotedIfContainsSpaces(NSString* file)
return juceStringToNS("juce_" + String::toHexString(File::getSpecialLocation(File::currentExecutableFile).hashCode64()));
}
- MessageQueue messageQueue;
+ InternalMessageQueue messageQueue;
id delegate;
};
@@ -448,6 +448,12 @@ void initialiseNSApplication()
userInfo:info];
}
+void MessageManager::registerEventLoopCallback(std::function loopCallbackToSet)
+{
+ jassert(appDelegate != nil);
+ appDelegate->messageQueue.registerEventLoopCallback(std::move(loopCallbackToSet));
+}
+
//==============================================================================
#if JUCE_MAC
struct MountedVolumeListChangeDetector::Pimpl
diff --git a/modules/juce_events/native/juce_MessageQueue_mac.h b/modules/juce_events/native/juce_MessageQueue_apple.h
similarity index 87%
rename from modules/juce_events/native/juce_MessageQueue_mac.h
rename to modules/juce_events/native/juce_MessageQueue_apple.h
index 143bc3c9..330519fc 100644
--- a/modules/juce_events/native/juce_MessageQueue_mac.h
+++ b/modules/juce_events/native/juce_MessageQueue_apple.h
@@ -41,11 +41,10 @@ namespace juce
{
//==============================================================================
-/* An internal message pump class used in OSX and iOS. */
-class MessageQueue
+class InternalMessageQueue
{
public:
- MessageQueue()
+ InternalMessageQueue()
{
#if JUCE_IOS
runLoop = CFRunLoopGetCurrent();
@@ -61,12 +60,17 @@ class MessageQueue
CFRunLoopAddSource (runLoop, runLoopSource.get(), kCFRunLoopCommonModes);
}
- ~MessageQueue() noexcept
+ ~InternalMessageQueue() noexcept
{
CFRunLoopRemoveSource (runLoop, runLoopSource.get(), kCFRunLoopCommonModes);
CFRunLoopSourceInvalidate (runLoopSource.get());
}
+ void registerEventLoopCallback (std::function loopCallbackToSet)
+ {
+ loopCallback = std::move (loopCallbackToSet);
+ }
+
void post (MessageManager::MessageBase* const message)
{
messages.add (message);
@@ -77,6 +81,7 @@ class MessageQueue
ReferenceCountedArray messages;
CFRunLoopRef runLoop;
CFUniquePtr runLoopSource;
+ std::function loopCallback;
void wakeUp() noexcept
{
@@ -105,6 +110,9 @@ class MessageQueue
void runLoopCallback() noexcept
{
+ if (loopCallback)
+ loopCallback();
+
for (int i = 4; --i >= 0;)
if (! deliverNextMessage())
return;
@@ -114,7 +122,7 @@ class MessageQueue
static void runLoopSourceCallback (void* info) noexcept
{
- static_cast (info)->runLoopCallback();
+ static_cast (info)->runLoopCallback();
}
};
diff --git a/modules/juce_events/native/juce_Messaging_android.cpp b/modules/juce_events/native/juce_Messaging_android.cpp
index 91dde29f..2b0984a9 100644
--- a/modules/juce_events/native/juce_Messaging_android.cpp
+++ b/modules/juce_events/native/juce_Messaging_android.cpp
@@ -50,6 +50,12 @@ class InternalMessageQueue
clearSingletonInstance();
}
+ //==============================================================================
+ void registerEventLoopCallback (std::function loopCallbackToSet)
+ {
+ loopCallback = std::move (loopCallbackToSet);
+ }
+
//==============================================================================
void postMessage (MessageManager::MessageBase* const msg) noexcept
{
@@ -65,7 +71,8 @@ class InternalMessageQueue
for (;;)
{
- glfwPollEvents();
+ if (loopCallback)
+ loopCallback();
{
const ScopedLock sl (lock);
@@ -79,7 +86,7 @@ class InternalMessageQueue
if (returnIfNoPendingMessages)
return false;
- Thread::sleep(1); // TODO - Make this better somehow ?
+ Thread::sleep (1); // TODO - Make this better somehow ?
}
else
{
@@ -102,6 +109,7 @@ class InternalMessageQueue
private:
CriticalSection lock;
ReferenceCountedArray queue;
+ std::function loopCallback;
};
JUCE_IMPLEMENT_SINGLETON (InternalMessageQueue)
@@ -119,10 +127,10 @@ void MessageManager::doPlatformSpecificShutdown()
namespace detail
{
- bool dispatchNextMessageOnSystemQueue (bool returnIfNoPendingMessages)
- {
- return InternalMessageQueue::getInstance()->dispatchNextMessage (returnIfNoPendingMessages);
- }
+bool dispatchNextMessageOnSystemQueue (bool returnIfNoPendingMessages)
+{
+ return InternalMessageQueue::getInstance()->dispatchNextMessage (returnIfNoPendingMessages);
+}
} // namespace detail
bool MessageManager::postMessageToSystemQueue (MessageManager::MessageBase* const message)
@@ -136,6 +144,23 @@ void MessageManager::broadcastMessage (const String&)
{
}
+void MessageManager::registerEventLoopCallback (std::function loopCallbackToSet)
+{
+ InternalMessageQueue::getInstance()->registerEventLoopCallback (std::move (loopCallbackToSet));
+}
+
+//==============================================================================
+/*
+extern "C" jint JNIEXPORT JNI_OnLoad2 (JavaVM* vm, void*);
+//extern "C" jint JNIEXPORT JNI_OnLoad (JavaVM *vm, void*);
+
+ //JNI_OnLoad (nativeApp->activity->vm, nullptr);
+ JNI_OnLoad2 (nativeApp->activity->vm, nullptr);
+
+ // JNIClassBase::initialiseAllClasses (nativeApp->activity->env, nativeApp->activity->clazz);
+ Thread::initialiseJUCE (nativeApp->activity->env, nativeApp->activity->clazz);
+*/
+
//==============================================================================
void juce_juceEventsAndroidStartApp()
{
diff --git a/modules/juce_events/native/juce_Messaging_emscripten.cpp b/modules/juce_events/native/juce_Messaging_emscripten.cpp
index e04e322d..4845d706 100644
--- a/modules/juce_events/native/juce_Messaging_emscripten.cpp
+++ b/modules/juce_events/native/juce_Messaging_emscripten.cpp
@@ -37,6 +37,8 @@ class InternalMessageQueue
public:
InternalMessageQueue()
{
+ emscripten_set_main_loop (dispatchLoopInternal, 0, 0);
+
createDirIfNotExists (File::userHomeDirectory);
createDirIfNotExists (File::userDocumentsDirectory);
createDirIfNotExists (File::userMusicDirectory);
@@ -55,11 +57,17 @@ class InternalMessageQueue
clearSingletonInstance();
}
+ //==============================================================================
+ void registerEventLoopCallback (std::function loopCallbackToSet)
+ {
+ loopCallback = std::move (loopCallbackToSet);
+ }
+
//==============================================================================
bool postMessage (MessageManager::MessageBase* const msg)
{
{
- const ScopedLock sl (lock);
+ const ScopedLock sl (lock);
eventQueue.add (msg);
}
@@ -70,6 +78,8 @@ class InternalMessageQueue
//==============================================================================
void runDispatchLoop()
{
+ emscripten_cancel_main_loop();
+
constexpr int framesPerSeconds = 0;
constexpr int simulateInfiniteLoop = 1;
emscripten_set_main_loop (dispatchLoopInternal, framesPerSeconds, simulateInfiniteLoop);
@@ -93,6 +103,9 @@ class InternalMessageQueue
{
Timer::callPendingTimersSynchronously();
+ if (loopCallback)
+ loopCallback();
+
ReferenceCountedArray currentEvents;
{
@@ -111,6 +124,7 @@ class InternalMessageQueue
CriticalSection lock;
ReferenceCountedArray eventQueue;
+ std::function loopCallback;
};
JUCE_IMPLEMENT_SINGLETON (InternalMessageQueue)
@@ -127,13 +141,13 @@ void MessageManager::doPlatformSpecificShutdown()
namespace detail
{
- bool dispatchNextMessageOnSystemQueue (const bool returnIfNoPendingMessages)
- {
- Logger::outputDebugString ("*** Modal loops are not possible in Emscripten!! Exiting...");
- exit (1);
+bool dispatchNextMessageOnSystemQueue (const bool returnIfNoPendingMessages)
+{
+ Logger::outputDebugString ("*** Modal loops are not possible in Emscripten!! Exiting...");
+ exit (1);
- return true;
- }
+ return true;
+}
} // namespace detail
bool MessageManager::postMessageToSystemQueue (MessageManager::MessageBase* const message)
@@ -157,4 +171,8 @@ void MessageManager::stopDispatchLoop()
quitMessagePosted = true;
}
+void MessageManager::registerEventLoopCallback (std::function loopCallbackToSet)
+{
+ InternalMessageQueue::getInstance()->registerEventLoopCallback (std::move (loopCallbackToSet));
+}
} // namespace juce
diff --git a/modules/juce_events/native/juce_Messaging_linux.cpp b/modules/juce_events/native/juce_Messaging_linux.cpp
index 2a3b2600..b8895949 100644
--- a/modules/juce_events/native/juce_Messaging_linux.cpp
+++ b/modules/juce_events/native/juce_Messaging_linux.cpp
@@ -245,6 +245,11 @@ struct InternalRunLoop
void removeListener (LinuxEventLoopInternal::Listener& listener) { listeners.remove (&listener); }
+ void registerEventLoopCallback (std::function loopCallbackToSet)
+ {
+ loopCallback = std::move (loopCallbackToSet);
+ }
+
//==============================================================================
JUCE_DECLARE_SINGLETON (InternalRunLoop, false)
@@ -299,6 +304,8 @@ struct InternalRunLoop
std::vector pfds;
ListenerList listeners;
+
+ std::function loopCallback;
};
JUCE_IMPLEMENT_SINGLETON (InternalRunLoop)
@@ -306,24 +313,24 @@ JUCE_IMPLEMENT_SINGLETON (InternalRunLoop)
//==============================================================================
namespace LinuxErrorHandling
{
- static bool keyboardBreakOccurred = false;
+static bool keyboardBreakOccurred = false;
- static void keyboardBreakSignalHandler (int sig)
- {
- if (sig == SIGINT)
- keyboardBreakOccurred = true;
- }
+static void keyboardBreakSignalHandler (int sig)
+{
+ if (sig == SIGINT)
+ keyboardBreakOccurred = true;
+}
- static void installKeyboardBreakHandler()
- {
- struct sigaction saction;
- sigset_t maskSet;
- sigemptyset (&maskSet);
- saction.sa_handler = keyboardBreakSignalHandler;
- saction.sa_mask = maskSet;
- saction.sa_flags = 0;
- sigaction (SIGINT, &saction, nullptr);
- }
+static void installKeyboardBreakHandler()
+{
+ struct sigaction saction;
+ sigset_t maskSet;
+ sigemptyset (&maskSet);
+ saction.sa_handler = keyboardBreakSignalHandler;
+ saction.sa_mask = maskSet;
+ saction.sa_flags = 0;
+ sigaction (SIGINT, &saction, nullptr);
+}
} // namespace LinuxErrorHandling
//==============================================================================
@@ -358,30 +365,35 @@ void MessageManager::broadcastMessage (const String&)
// TODO
}
+void MessageManager::registerEventLoopCallback (std::function loopCallbackToSet)
+{
+ InternalRunLoop::getInstance()->registerEventLoopCallback (std::move (loopCallbackToSet));
+}
+
namespace detail
{
- // this function expects that it will NEVER be called simultaneously for two concurrent threads
- bool dispatchNextMessageOnSystemQueue (bool returnIfNoPendingMessages)
+// this function expects that it will NEVER be called simultaneously for two concurrent threads
+bool dispatchNextMessageOnSystemQueue (bool returnIfNoPendingMessages)
+{
+ for (;;)
{
- for (;;)
- {
- if (LinuxErrorHandling::keyboardBreakOccurred)
- JUCEApplicationBase::quit();
+ if (LinuxErrorHandling::keyboardBreakOccurred)
+ JUCEApplicationBase::quit();
- if (auto* runLoop = InternalRunLoop::getInstanceWithoutCreating())
- {
- if (runLoop->dispatchPendingEvents())
- break;
+ if (auto* runLoop = InternalRunLoop::getInstanceWithoutCreating())
+ {
+ if (runLoop->dispatchPendingEvents())
+ break;
- if (returnIfNoPendingMessages)
- return false;
+ if (returnIfNoPendingMessages)
+ return false;
- runLoop->sleepUntilNextEvent (2000);
- }
+ runLoop->sleepUntilNextEvent (2000);
}
-
- return true;
}
+
+ return true;
+}
} // namespace detail
//==============================================================================
diff --git a/modules/juce_events/native/juce_Messaging_windows.cpp b/modules/juce_events/native/juce_Messaging_windows.cpp
index ce7a3dfe..9d100e98 100644
--- a/modules/juce_events/native/juce_Messaging_windows.cpp
+++ b/modules/juce_events/native/juce_Messaging_windows.cpp
@@ -70,6 +70,12 @@ class InternalMessageQueue
JUCE_DECLARE_SINGLETON (InternalMessageQueue, false)
+ //==============================================================================
+ void registerEventLoopCallback (std::function loopCallbackToSet)
+ {
+ loopCallback = std::move (loopCallbackToSet);
+ }
+
//==============================================================================
void broadcastMessage (const String& message)
{
@@ -235,6 +241,9 @@ class InternalMessageQueue
{
ReferenceCountedArray messagesToDispatch;
+ if (loopCallback)
+ loopCallback();
+
{
const ScopedLock sl (lock);
@@ -261,6 +270,7 @@ class InternalMessageQueue
CriticalSection lock;
ReferenceCountedArray messageQueue;
+ std::function loopCallback;
//==============================================================================
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (InternalMessageQueue)
@@ -274,13 +284,13 @@ const TCHAR InternalMessageQueue::messageWindowName[] = _T("JUCEWindow");
namespace detail
{
- bool dispatchNextMessageOnSystemQueue (bool returnIfNoPendingMessages)
- {
- if (auto* queue = InternalMessageQueue::getInstanceWithoutCreating())
- return queue->dispatchNextMessage (returnIfNoPendingMessages);
+bool dispatchNextMessageOnSystemQueue (bool returnIfNoPendingMessages)
+{
+ if (auto* queue = InternalMessageQueue::getInstanceWithoutCreating())
+ return queue->dispatchNextMessage (returnIfNoPendingMessages);
- return false;
- }
+ return false;
+}
} // namespace detail
@@ -301,6 +311,11 @@ void MessageManager::broadcastMessage (const String& value)
queue->broadcastMessage (value);
}
+void MessageManager::registerEventLoopCallback (std::function loopCallbackToSet)
+{
+ InternalMessageQueue::getInstance()->registerEventLoopCallback (std::move (loopCallbackToSet));
+}
+
//==============================================================================
void MessageManager::doPlatformSpecificInitialisation()
{
diff --git a/modules/yup_graphics/fonts/yup_StyledText.cpp b/modules/yup_graphics/fonts/yup_StyledText.cpp
index 1ae5639a..27f615f6 100644
--- a/modules/yup_graphics/fonts/yup_StyledText.cpp
+++ b/modules/yup_graphics/fonts/yup_StyledText.cpp
@@ -64,6 +64,7 @@ void StyledText::appendText (const Font& font,
{
textRuns.push_back (append (font, size, lineHeight, text));
+ jassert (font.getFont() != nullptr);
paragraphs = font.getFont()->shapeText (unicodeChars, textRuns);
}
diff --git a/modules/yup_graphics/native/yup_GraphicsContext_gl.cpp b/modules/yup_graphics/native/yup_GraphicsContext_gl.cpp
index f3aae3d6..71bc2549 100644
--- a/modules/yup_graphics/native/yup_GraphicsContext_gl.cpp
+++ b/modules/yup_graphics/native/yup_GraphicsContext_gl.cpp
@@ -27,8 +27,7 @@
#include "rive/renderer/gl/render_target_gl.hpp"
#if RIVE_DESKTOP_GL || JUCE_ANDROID
-#define GLFW_INCLUDE_NONE
-#include
+#include
#endif
namespace yup
@@ -78,7 +77,7 @@ class LowLevelRenderContextGL : public GraphicsContext
{
#if RIVE_DESKTOP_GL
// Load the OpenGL API using glad.
- if (! gladLoadCustomLoader ((GLADloadproc) glfwGetProcAddress))
+ if (! gladLoadCustomLoader ((GLADloadproc) SDL_GL_GetProcAddress))
{
fprintf (stderr, "Failed to initialize glad.\n");
exit (-1);
@@ -100,7 +99,7 @@ class LowLevelRenderContextGL : public GraphicsContext
printf ("GL_ANGLE_shader_pixel_local_storage_coherent: %i\n", GLAD_GL_ANGLE_shader_pixel_local_storage_coherent);
#endif
-#if DEBUG && !RIVE_ANDROID
+#if DEBUG && ! RIVE_ANDROID
int n;
glGetIntegerv (GL_NUM_EXTENSIONS, &n);
for (size_t i = 0; i < n; ++i)
diff --git a/modules/yup_graphics/native/yup_GraphicsContext_metal.cpp b/modules/yup_graphics/native/yup_GraphicsContext_metal.cpp
index 2aa6ac73..94b1cc95 100644
--- a/modules/yup_graphics/native/yup_GraphicsContext_metal.cpp
+++ b/modules/yup_graphics/native/yup_GraphicsContext_metal.cpp
@@ -23,6 +23,8 @@
#include "rive/renderer/rive_renderer.hpp"
#include "rive/renderer/metal/render_context_metal_impl.h"
+#include
+
namespace yup
{
@@ -45,8 +47,14 @@ class LowLevelRenderContextMetal : public GraphicsContext
float dpiScale (void* window) const override
{
+#if TARGET_OS_IOS
+ UIWindow* uiWindow = (__bridge UIWindow*) window;
+ UIScreen* screen = [uiWindow screen] ?: [UIScreen mainScreen];
+ return screen.nativeScale;
+#else
NSWindow* nsWindow = (__bridge NSWindow*) window;
return m_fiddleOptions.retinaDisplay ? nsWindow.backingScaleFactor : 1.0f;
+#endif
}
rive::Factory* factory() override { return m_plsContext.get(); }
@@ -57,9 +65,11 @@ class LowLevelRenderContextMetal : public GraphicsContext
void onSizeChanged (void* window, int width, int height, uint32_t sampleCount) override
{
+#if ! TARGET_OS_IOS
NSWindow* nsWindow = (__bridge NSWindow*) window;
NSView* view = [nsWindow contentView];
view.wantsLayer = YES;
+#endif
m_swapchain = [CAMetalLayer layer];
m_swapchain.device = m_gpu;
@@ -67,9 +77,18 @@ class LowLevelRenderContextMetal : public GraphicsContext
m_swapchain.framebufferOnly = ! m_fiddleOptions.readableFramebuffer;
m_swapchain.pixelFormat = MTLPixelFormatBGRA8Unorm;
m_swapchain.contentsScale = dpiScale (window);
- m_swapchain.displaySyncEnabled = YES;
m_swapchain.maximumDrawableCount = 2;
+#if ! TARGET_OS_IOS
+ m_swapchain.displaySyncEnabled = YES;
+#endif
+
+#if TARGET_OS_IOS
+ UIView* view = (__bridge UIView*) window;
+ m_swapchain.frame = view.bounds;
+ [view.layer addSublayer:m_swapchain];
+#else
view.layer = m_swapchain;
+#endif
auto plsContextImpl = m_plsContext->static_impl_cast();
m_renderTarget = plsContextImpl->makeRenderTarget (MTLPixelFormatBGRA8Unorm, width, height);
diff --git a/modules/yup_graphics/yup_graphics.cpp b/modules/yup_graphics/yup_graphics.cpp
index 801c53f5..5aad1874 100644
--- a/modules/yup_graphics/yup_graphics.cpp
+++ b/modules/yup_graphics/yup_graphics.cpp
@@ -51,9 +51,14 @@
#if YUP_RIVE_USE_METAL
#import
-#import
#import
+#if JUCE_MAC
+#import
+#else
+#import
+#endif
+
#include "native/yup_GraphicsContext_metal.cpp"
#endif
diff --git a/modules/yup_graphics/yup_graphics.h b/modules/yup_graphics/yup_graphics.h
index ca082869..20a81ec5 100644
--- a/modules/yup_graphics/yup_graphics.h
+++ b/modules/yup_graphics/yup_graphics.h
@@ -36,6 +36,7 @@
dependencies: juce_core rive rive_renderer
osxFrameworks: Metal
iosFrameworks: Metal
+ iosSimFrameworks: Metal
searchpaths: native
enableARC: 1
diff --git a/modules/yup_gui/component/yup_Component.h b/modules/yup_gui/component/yup_Component.h
index 72755f18..f6e4ca6e 100644
--- a/modules/yup_gui/component/yup_Component.h
+++ b/modules/yup_gui/component/yup_Component.h
@@ -191,6 +191,7 @@ class JUCE_API Component
friend class ComponentNative;
friend class GLFWComponentNative;
+ friend class SDL2ComponentNative;
friend class WeakReference;
using MouseListenerList = ListenerList>>;
diff --git a/modules/yup_gui/component/yup_ComponentNative.h b/modules/yup_gui/component/yup_ComponentNative.h
index 53a4928b..f59df160 100644
--- a/modules/yup_gui/component/yup_ComponentNative.h
+++ b/modules/yup_gui/component/yup_ComponentNative.h
@@ -28,16 +28,20 @@ class Component;
class JUCE_API ComponentNative
{
struct decoratedWindowTag;
+ struct resizableWindowTag;
struct renderContinuousTag;
+ struct allowHighDensityDisplayTag;
public:
//==============================================================================
- using Flags = FlagSet;
+ using Flags = FlagSet;
static inline constexpr Flags noFlags = Flags();
static inline constexpr Flags decoratedWindow = Flags::declareValue();
+ static inline constexpr Flags resizableWindow = Flags::declareValue();
static inline constexpr Flags renderContinuous = Flags::declareValue();
- static inline constexpr Flags defaultFlags = decoratedWindow;
+ static inline constexpr Flags allowHighDensityDisplay = Flags::declareValue();
+ static inline constexpr Flags defaultFlags = decoratedWindow | resizableWindow | allowHighDensityDisplay;
//==============================================================================
/** Configuration options for creating a native component. */
@@ -52,6 +56,33 @@ class JUCE_API ComponentNative
return *this;
}
+ Options& withResizableWindow (bool shouldAllowResizing) noexcept
+ {
+ if (shouldAllowResizing)
+ flags |= resizableWindow;
+ else
+ flags &= ~resizableWindow;
+ return *this;
+ }
+
+ Options& withRenderContinuous (bool shouldRenderContinuous) noexcept
+ {
+ if (shouldRenderContinuous)
+ flags |= renderContinuous;
+ else
+ flags &= ~renderContinuous;
+ return *this;
+ }
+
+ Options& withAllowedHighDensityDisplay (bool shouldAllowHighDensity) noexcept
+ {
+ if (shouldAllowHighDensity)
+ flags |= allowHighDensityDisplay;
+ else
+ flags &= ~allowHighDensityDisplay;
+ return *this;
+ }
+
Options& withGraphicsApi (std::optional newGraphicsApi) noexcept
{
graphicsApi = newGraphicsApi;
diff --git a/modules/yup_gui/keyboard/yup_KeyModifiers.h b/modules/yup_gui/keyboard/yup_KeyModifiers.h
index 99641288..f6dfad59 100644
--- a/modules/yup_gui/keyboard/yup_KeyModifiers.h
+++ b/modules/yup_gui/keyboard/yup_KeyModifiers.h
@@ -173,7 +173,7 @@ class JUCE_API KeyModifiers
return ! (*this == other);
}
-private:
+ //==============================================================================
static constexpr int shiftMask = 0x0001;
static constexpr int controlMask = 0x0002;
static constexpr int altMask = 0x0004;
@@ -181,6 +181,7 @@ class JUCE_API KeyModifiers
static constexpr int capsLockMask = 0x0010;
static constexpr int numLockMask = 0x0020;
+private:
int32_t modifiers = 0;
};
diff --git a/modules/yup_gui/native/yup_Windowing_ios.mm b/modules/yup_gui/native/yup_Windowing_ios.mm
new file mode 100644
index 00000000..6a429f4e
--- /dev/null
+++ b/modules/yup_gui/native/yup_Windowing_ios.mm
@@ -0,0 +1,91 @@
+/*
+ ==============================================================================
+
+ This file is part of the YUP library.
+ Copyright (c): return { KeyPress::xxx, modifiers, sc }; - kunitoki@gmail.com
+
+ YUP is an open source library subject to open-source licensing.
+
+ The code included in this file is provided under the terms of the ISC license
+ http://www.isc.org/downloads/software-support-policy/isc-license. Permission
+ to use, copy, modify, and/or distribute this software for any purpose with or
+ without fee is hereby granted provided that the above copyright notice and
+ this permission notice appear in all copies.
+
+ YUP IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
+ EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
+ DISCLAIMED.
+
+ ==============================================================================
+*/
+
+/** This class is used to handle the iOS-specific parts of the YupWindowing class. */
+@interface YupApplicationDelegate : NSObject
+
+@end
+
+@implementation YupApplicationDelegate
+
+- (id)init
+{
+ self = [super init];
+ return self;
+}
+
+- (void)dealloc
+{
+ [super dealloc];
+}
+
+- (void)applicationDidFinishLaunching:(UIApplication* __unused)application
+{
+ if (auto* app = juce::JUCEApplicationBase::createInstance())
+ {
+ if (!app->initialiseApp())
+ exit(app->shutdownApp());
+ }
+ else
+ {
+ jassertfalse;
+ }
+}
+
+- (void)applicationWillTerminate:(UIApplication* __unused)application
+{
+ juce::JUCEApplicationBase::appWillTerminateByForce();
+}
+
+- (void)applicationDidEnterBackground:(UIApplication* __unused)application
+{
+ if (auto* app = juce::JUCEApplicationBase::getInstance())
+ app->suspended();
+}
+
+- (void)applicationWillEnterForeground:(UIApplication* __unused)application
+{
+ if (auto* app = juce::JUCEApplicationBase::getInstance())
+ app->resumed();
+}
+
+- (void)applicationDidBecomeActive:(UIApplication* __unused)application
+{
+}
+
+- (void)applicationWillResignActive:(UIApplication* __unused)application
+{
+}
+
+@end
+
+namespace juce
+{
+
+int juce_iOSMain(int argc, const char* argv[], void* customDelegatePtr);
+int juce_iOSMain(int argc, const char* argv[], void* customDelegatePtr)
+{
+ Class delegateClass = (customDelegatePtr != nullptr ? reinterpret_cast(customDelegatePtr) : [YupApplicationDelegate class]);
+
+ return UIApplicationMain(argc, const_cast(argv), nil, NSStringFromClass(delegateClass));
+}
+
+} // namespace juce
diff --git a/modules/yup_gui/native/yup_Windowing_glfw.cpp b/modules/yup_gui/native/yup_Windowing_sdl2.cpp
similarity index 54%
rename from modules/yup_gui/native/yup_Windowing_glfw.cpp
rename to modules/yup_gui/native/yup_Windowing_sdl2.cpp
index 89a0bd56..8d5f9d1f 100644
--- a/modules/yup_gui/native/yup_Windowing_glfw.cpp
+++ b/modules/yup_gui/native/yup_Windowing_sdl2.cpp
@@ -24,173 +24,172 @@ namespace yup
//==============================================================================
-MouseEvent::Buttons toMouseButton (int button) noexcept
+MouseEvent::Buttons toMouseButton (Uint8 sdlButton) noexcept
{
- if (button == GLFW_MOUSE_BUTTON_LEFT)
- return MouseEvent::Buttons::leftButton;
+ switch (sdlButton)
+ {
+ case SDL_BUTTON_LEFT:
+ return MouseEvent::Buttons::leftButton;
- else if (button == GLFW_MOUSE_BUTTON_RIGHT)
- return MouseEvent::Buttons::rightButton;
+ case SDL_BUTTON_RIGHT:
+ return MouseEvent::Buttons::rightButton;
- else if (button == GLFW_MOUSE_BUTTON_MIDDLE)
- return MouseEvent::Buttons::middleButton;
+ case SDL_BUTTON_MIDDLE:
+ return MouseEvent::Buttons::middleButton;
- return MouseEvent::Buttons::noButtons;
+ default:
+ return MouseEvent::Buttons::noButtons;
+ }
}
//==============================================================================
-int convertKeyToModifier (int key) noexcept
+KeyModifiers toKeyModifiers (Uint16 sdlMod) noexcept
{
- int mod = 0;
-
- if (key == GLFW_KEY_LEFT_CONTROL || key == GLFW_KEY_RIGHT_CONTROL)
- mod = GLFW_MOD_CONTROL;
+ int modifiers;
- else if (key == GLFW_KEY_LEFT_SHIFT || key == GLFW_KEY_RIGHT_SHIFT)
- mod = GLFW_MOD_SHIFT;
+ if (sdlMod & KMOD_CTRL)
+ modifiers |= KeyModifiers::controlMask;
- else if (key == GLFW_KEY_LEFT_ALT || key == GLFW_KEY_RIGHT_ALT)
- mod = GLFW_MOD_ALT;
+ if (sdlMod & KMOD_SHIFT)
+ modifiers |= KeyModifiers::shiftMask;
- else if (key == GLFW_KEY_LEFT_SUPER || key == GLFW_KEY_RIGHT_SUPER)
- mod = GLFW_MOD_SUPER;
+ if (sdlMod & KMOD_ALT)
+ modifiers |= KeyModifiers::altMask;
- return mod;
-}
+ if (sdlMod & KMOD_GUI)
+ modifiers |= KeyModifiers::superMask;
-KeyModifiers toKeyModifiers (int modifiers) noexcept
-{
- return { modifiers };
+ return modifiers;
}
// clang-format off
-KeyPress toKeyPress (int key, int scancode, int modifiers) noexcept
+KeyPress toKeyPress (SDL_Keycode key, SDL_Scancode scancode, KeyModifiers modifiers) noexcept
{
const char32_t sc = static_cast (scancode);
switch (key)
{
- case GLFW_KEY_SPACE: return { KeyPress::spaceKey, modifiers, sc };
- case GLFW_KEY_APOSTROPHE: return { KeyPress::apostropheKey, modifiers, sc };
- case GLFW_KEY_COMMA: return { KeyPress::commaKey, modifiers, sc };
- case GLFW_KEY_MINUS: return { KeyPress::minusKey, modifiers, sc };
- case GLFW_KEY_PERIOD: return { KeyPress::periodKey, modifiers, sc };
- case GLFW_KEY_SLASH: return { KeyPress::slashKey, modifiers, sc };
- case GLFW_KEY_0: return { KeyPress::number0Key, modifiers, sc };
- case GLFW_KEY_1: return { KeyPress::number1Key, modifiers, sc };
- case GLFW_KEY_2: return { KeyPress::number2Key, modifiers, sc };
- case GLFW_KEY_3: return { KeyPress::number3Key, modifiers, sc };
- case GLFW_KEY_4: return { KeyPress::number4Key, modifiers, sc };
- case GLFW_KEY_5: return { KeyPress::number5Key, modifiers, sc };
- case GLFW_KEY_6: return { KeyPress::number6Key, modifiers, sc };
- case GLFW_KEY_7: return { KeyPress::number7Key, modifiers, sc };
- case GLFW_KEY_8: return { KeyPress::number8Key, modifiers, sc };
- case GLFW_KEY_9: return { KeyPress::number9Key, modifiers, sc };
- case GLFW_KEY_SEMICOLON: return { KeyPress::semicolonKey, modifiers, sc };
- case GLFW_KEY_EQUAL: return { KeyPress::equalKey, modifiers, sc };
- case GLFW_KEY_A: return { KeyPress::textAKey, modifiers, sc };
- case GLFW_KEY_B: return { KeyPress::textBKey, modifiers, sc };
- case GLFW_KEY_C: return { KeyPress::textCKey, modifiers, sc };
- case GLFW_KEY_D: return { KeyPress::textDKey, modifiers, sc };
- case GLFW_KEY_E: return { KeyPress::textEKey, modifiers, sc };
- case GLFW_KEY_F: return { KeyPress::textFKey, modifiers, sc };
- case GLFW_KEY_G: return { KeyPress::textGKey, modifiers, sc };
- case GLFW_KEY_H: return { KeyPress::textHKey, modifiers, sc };
- case GLFW_KEY_I: return { KeyPress::textIKey, modifiers, sc };
- case GLFW_KEY_J: return { KeyPress::textJKey, modifiers, sc };
- case GLFW_KEY_K: return { KeyPress::textKKey, modifiers, sc };
- case GLFW_KEY_L: return { KeyPress::textLKey, modifiers, sc };
- case GLFW_KEY_M: return { KeyPress::textMKey, modifiers, sc };
- case GLFW_KEY_N: return { KeyPress::textNKey, modifiers, sc };
- case GLFW_KEY_O: return { KeyPress::textOKey, modifiers, sc };
- case GLFW_KEY_P: return { KeyPress::textPKey, modifiers, sc };
- case GLFW_KEY_Q: return { KeyPress::textQKey, modifiers, sc };
- case GLFW_KEY_R: return { KeyPress::textRKey, modifiers, sc };
- case GLFW_KEY_S: return { KeyPress::textSKey, modifiers, sc };
- case GLFW_KEY_T: return { KeyPress::textTKey, modifiers, sc };
- case GLFW_KEY_U: return { KeyPress::textUKey, modifiers, sc };
- case GLFW_KEY_V: return { KeyPress::textVKey, modifiers, sc };
- case GLFW_KEY_W: return { KeyPress::textWKey, modifiers, sc };
- case GLFW_KEY_X: return { KeyPress::textXKey, modifiers, sc };
- case GLFW_KEY_Y: return { KeyPress::textYKey, modifiers, sc };
- case GLFW_KEY_Z: return { KeyPress::textZKey, modifiers, sc };
- case GLFW_KEY_LEFT_BRACKET: return { KeyPress::leftBracketKey, modifiers, sc };
- case GLFW_KEY_BACKSLASH: return { KeyPress::backslashKey, modifiers, sc };
- case GLFW_KEY_RIGHT_BRACKET: return { KeyPress::rightBracketKey, modifiers, sc };
- case GLFW_KEY_GRAVE_ACCENT: return { KeyPress::graveAccentKey, modifiers, sc };
- case GLFW_KEY_WORLD_1: return { KeyPress::world1Key, modifiers, sc };
- case GLFW_KEY_WORLD_2: return { KeyPress::world2Key, modifiers, sc };
- case GLFW_KEY_ESCAPE: return { KeyPress::escapeKey, modifiers, sc };
- case GLFW_KEY_ENTER: return { KeyPress::enterKey, modifiers, sc };
- case GLFW_KEY_TAB: return { KeyPress::tabKey, modifiers, sc };
- case GLFW_KEY_BACKSPACE: return { KeyPress::backspaceKey, modifiers, sc };
- case GLFW_KEY_INSERT: return { KeyPress::insertKey, modifiers, sc };
- case GLFW_KEY_DELETE: return { KeyPress::deleteKey, modifiers, sc };
- case GLFW_KEY_RIGHT: return { KeyPress::rightKey, modifiers, sc };
- case GLFW_KEY_LEFT: return { KeyPress::leftKey, modifiers, sc };
- case GLFW_KEY_DOWN: return { KeyPress::downKey, modifiers, sc };
- case GLFW_KEY_UP: return { KeyPress::upKey, modifiers, sc };
- case GLFW_KEY_PAGE_UP: return { KeyPress::pageUpKey, modifiers, sc };
- case GLFW_KEY_PAGE_DOWN: return { KeyPress::pageDownKey, modifiers, sc };
- case GLFW_KEY_HOME: return { KeyPress::homeKey, modifiers, sc };
- case GLFW_KEY_END: return { KeyPress::endKey, modifiers, sc };
- case GLFW_KEY_CAPS_LOCK: return { KeyPress::capsLockKey, modifiers, sc };
- case GLFW_KEY_SCROLL_LOCK: return { KeyPress::scrollLockKey, modifiers, sc };
- case GLFW_KEY_NUM_LOCK: return { KeyPress::numLockKey, modifiers, sc };
- case GLFW_KEY_PRINT_SCREEN: return { KeyPress::printScreenKey, modifiers, sc };
- case GLFW_KEY_PAUSE: return { KeyPress::pauseKey, modifiers, sc };
- case GLFW_KEY_F1: return { KeyPress::f1Key, modifiers, sc };
- case GLFW_KEY_F2: return { KeyPress::f2Key, modifiers, sc };
- case GLFW_KEY_F3: return { KeyPress::f3Key, modifiers, sc };
- case GLFW_KEY_F4: return { KeyPress::f4Key, modifiers, sc };
- case GLFW_KEY_F5: return { KeyPress::f5Key, modifiers, sc };
- case GLFW_KEY_F6: return { KeyPress::f6Key, modifiers, sc };
- case GLFW_KEY_F7: return { KeyPress::f7Key, modifiers, sc };
- case GLFW_KEY_F8: return { KeyPress::f8Key, modifiers, sc };
- case GLFW_KEY_F9: return { KeyPress::f9Key, modifiers, sc };
- case GLFW_KEY_F10: return { KeyPress::f10Key, modifiers, sc };
- case GLFW_KEY_F11: return { KeyPress::f11Key, modifiers, sc };
- case GLFW_KEY_F12: return { KeyPress::f12Key, modifiers, sc };
- case GLFW_KEY_F13: return { KeyPress::f13Key, modifiers, sc };
- case GLFW_KEY_F14: return { KeyPress::f14Key, modifiers, sc };
- case GLFW_KEY_F15: return { KeyPress::f15Key, modifiers, sc };
- case GLFW_KEY_F16: return { KeyPress::f16Key, modifiers, sc };
- case GLFW_KEY_F17: return { KeyPress::f17Key, modifiers, sc };
- case GLFW_KEY_F18: return { KeyPress::f18Key, modifiers, sc };
- case GLFW_KEY_F19: return { KeyPress::f19Key, modifiers, sc };
- case GLFW_KEY_F20: return { KeyPress::f20Key, modifiers, sc };
- case GLFW_KEY_F21: return { KeyPress::f21Key, modifiers, sc };
- case GLFW_KEY_F22: return { KeyPress::f22Key, modifiers, sc };
- case GLFW_KEY_F23: return { KeyPress::f23Key, modifiers, sc };
- case GLFW_KEY_F24: return { KeyPress::f24Key, modifiers, sc };
- case GLFW_KEY_F25: return { KeyPress::f25Key, modifiers, sc };
- case GLFW_KEY_KP_0: return { KeyPress::kp0Key, modifiers, sc };
- case GLFW_KEY_KP_1: return { KeyPress::kp1Key, modifiers, sc };
- case GLFW_KEY_KP_2: return { KeyPress::kp2Key, modifiers, sc };
- case GLFW_KEY_KP_3: return { KeyPress::kp3Key, modifiers, sc };
- case GLFW_KEY_KP_4: return { KeyPress::kp4Key, modifiers, sc };
- case GLFW_KEY_KP_5: return { KeyPress::kp5Key, modifiers, sc };
- case GLFW_KEY_KP_6: return { KeyPress::kp6Key, modifiers, sc };
- case GLFW_KEY_KP_7: return { KeyPress::kp7Key, modifiers, sc };
- case GLFW_KEY_KP_8: return { KeyPress::kp8Key, modifiers, sc };
- case GLFW_KEY_KP_9: return { KeyPress::kp9Key, modifiers, sc };
- case GLFW_KEY_KP_DECIMAL: return { KeyPress::kpDecimalKey, modifiers, sc };
- case GLFW_KEY_KP_DIVIDE: return { KeyPress::kpDivideKey, modifiers, sc };
- case GLFW_KEY_KP_MULTIPLY: return { KeyPress::kpMultiplyKey, modifiers, sc };
- case GLFW_KEY_KP_SUBTRACT: return { KeyPress::kpSubtractKey, modifiers, sc };
- case GLFW_KEY_KP_ADD: return { KeyPress::kpAddKey, modifiers, sc };
- case GLFW_KEY_KP_ENTER: return { KeyPress::kpEnterKey, modifiers, sc };
- case GLFW_KEY_KP_EQUAL: return { KeyPress::kpEqualKey, modifiers, sc };
- case GLFW_KEY_LEFT_SHIFT: return { KeyPress::leftShiftKey, modifiers, sc };
- case GLFW_KEY_LEFT_CONTROL: return { KeyPress::leftControlKey, modifiers, sc };
- case GLFW_KEY_LEFT_ALT: return { KeyPress::leftAltKey, modifiers, sc };
- case GLFW_KEY_LEFT_SUPER: return { KeyPress::leftSuperKey, modifiers, sc };
- case GLFW_KEY_RIGHT_SHIFT: return { KeyPress::rightShiftKey, modifiers, sc };
- case GLFW_KEY_RIGHT_CONTROL: return { KeyPress::rightControlKey, modifiers, sc };
- case GLFW_KEY_RIGHT_ALT: return { KeyPress::rightAltKey, modifiers, sc };
- case GLFW_KEY_RIGHT_SUPER: return { KeyPress::rightSuperKey, modifiers, sc };
- case GLFW_KEY_MENU: return { KeyPress::menuKey, modifiers, sc };
+ case SDLK_SPACE: return { KeyPress::spaceKey, modifiers, sc };
+ //case SDLK_APOSTROPHE: return { KeyPress::apostropheKey, modifiers, sc };
+ case SDLK_COMMA: return { KeyPress::commaKey, modifiers, sc };
+ case SDLK_MINUS: return { KeyPress::minusKey, modifiers, sc };
+ case SDLK_PERIOD: return { KeyPress::periodKey, modifiers, sc };
+ case SDLK_SLASH: return { KeyPress::slashKey, modifiers, sc };
+ case SDLK_0: return { KeyPress::number0Key, modifiers, sc };
+ case SDLK_1: return { KeyPress::number1Key, modifiers, sc };
+ case SDLK_2: return { KeyPress::number2Key, modifiers, sc };
+ case SDLK_3: return { KeyPress::number3Key, modifiers, sc };
+ case SDLK_4: return { KeyPress::number4Key, modifiers, sc };
+ case SDLK_5: return { KeyPress::number5Key, modifiers, sc };
+ case SDLK_6: return { KeyPress::number6Key, modifiers, sc };
+ case SDLK_7: return { KeyPress::number7Key, modifiers, sc };
+ case SDLK_8: return { KeyPress::number8Key, modifiers, sc };
+ case SDLK_9: return { KeyPress::number9Key, modifiers, sc };
+ case SDLK_SEMICOLON: return { KeyPress::semicolonKey, modifiers, sc };
+ case SDLK_EQUALS: return { KeyPress::equalKey, modifiers, sc };
+ case SDLK_a: return { KeyPress::textAKey, modifiers, sc };
+ case SDLK_b: return { KeyPress::textBKey, modifiers, sc };
+ case SDLK_c: return { KeyPress::textCKey, modifiers, sc };
+ case SDLK_d: return { KeyPress::textDKey, modifiers, sc };
+ case SDLK_e: return { KeyPress::textEKey, modifiers, sc };
+ case SDLK_f: return { KeyPress::textFKey, modifiers, sc };
+ case SDLK_g: return { KeyPress::textGKey, modifiers, sc };
+ case SDLK_h: return { KeyPress::textHKey, modifiers, sc };
+ case SDLK_i: return { KeyPress::textIKey, modifiers, sc };
+ case SDLK_j: return { KeyPress::textJKey, modifiers, sc };
+ case SDLK_k: return { KeyPress::textKKey, modifiers, sc };
+ case SDLK_l: return { KeyPress::textLKey, modifiers, sc };
+ case SDLK_m: return { KeyPress::textMKey, modifiers, sc };
+ case SDLK_n: return { KeyPress::textNKey, modifiers, sc };
+ case SDLK_o: return { KeyPress::textOKey, modifiers, sc };
+ case SDLK_p: return { KeyPress::textPKey, modifiers, sc };
+ case SDLK_q: return { KeyPress::textQKey, modifiers, sc };
+ case SDLK_r: return { KeyPress::textRKey, modifiers, sc };
+ case SDLK_s: return { KeyPress::textSKey, modifiers, sc };
+ case SDLK_t: return { KeyPress::textTKey, modifiers, sc };
+ case SDLK_u: return { KeyPress::textUKey, modifiers, sc };
+ case SDLK_v: return { KeyPress::textVKey, modifiers, sc };
+ case SDLK_w: return { KeyPress::textWKey, modifiers, sc };
+ case SDLK_x: return { KeyPress::textXKey, modifiers, sc };
+ case SDLK_y: return { KeyPress::textYKey, modifiers, sc };
+ case SDLK_z: return { KeyPress::textZKey, modifiers, sc };
+ case SDLK_LEFTBRACKET: return { KeyPress::leftBracketKey, modifiers, sc };
+ case SDLK_BACKSLASH: return { KeyPress::backslashKey, modifiers, sc };
+ case SDLK_RIGHTBRACKET: return { KeyPress::rightBracketKey, modifiers, sc };
+ //case SDLK_GRAVE_ACCENT: return { KeyPress::graveAccentKey, modifiers, sc };
+ //case SDLK_WORLD_1: return { KeyPress::world1Key, modifiers, sc };
+ //case SDLK_WORLD_2: return { KeyPress::world2Key, modifiers, sc };
+ case SDLK_ESCAPE: return { KeyPress::escapeKey, modifiers, sc };
+ case SDLK_RETURN: return { KeyPress::enterKey, modifiers, sc };
+ case SDLK_TAB: return { KeyPress::tabKey, modifiers, sc };
+ case SDLK_BACKSPACE: return { KeyPress::backspaceKey, modifiers, sc };
+ case SDLK_INSERT: return { KeyPress::insertKey, modifiers, sc };
+ case SDLK_DELETE: return { KeyPress::deleteKey, modifiers, sc };
+ case SDLK_RIGHT: return { KeyPress::rightKey, modifiers, sc };
+ case SDLK_LEFT: return { KeyPress::leftKey, modifiers, sc };
+ case SDLK_DOWN: return { KeyPress::downKey, modifiers, sc };
+ case SDLK_UP: return { KeyPress::upKey, modifiers, sc };
+ case SDLK_PAGEUP: return { KeyPress::pageUpKey, modifiers, sc };
+ case SDLK_PAGEDOWN: return { KeyPress::pageDownKey, modifiers, sc };
+ case SDLK_HOME: return { KeyPress::homeKey, modifiers, sc };
+ case SDLK_END: return { KeyPress::endKey, modifiers, sc };
+ case SDLK_CAPSLOCK: return { KeyPress::capsLockKey, modifiers, sc };
+ case SDLK_SCROLLLOCK: return { KeyPress::scrollLockKey, modifiers, sc };
+ case SDLK_NUMLOCKCLEAR: return { KeyPress::numLockKey, modifiers, sc };
+ case SDLK_PRINTSCREEN: return { KeyPress::printScreenKey, modifiers, sc };
+ case SDLK_PAUSE: return { KeyPress::pauseKey, modifiers, sc };
+ case SDLK_F1: return { KeyPress::f1Key, modifiers, sc };
+ case SDLK_F2: return { KeyPress::f2Key, modifiers, sc };
+ case SDLK_F3: return { KeyPress::f3Key, modifiers, sc };
+ case SDLK_F4: return { KeyPress::f4Key, modifiers, sc };
+ case SDLK_F5: return { KeyPress::f5Key, modifiers, sc };
+ case SDLK_F6: return { KeyPress::f6Key, modifiers, sc };
+ case SDLK_F7: return { KeyPress::f7Key, modifiers, sc };
+ case SDLK_F8: return { KeyPress::f8Key, modifiers, sc };
+ case SDLK_F9: return { KeyPress::f9Key, modifiers, sc };
+ case SDLK_F10: return { KeyPress::f10Key, modifiers, sc };
+ case SDLK_F11: return { KeyPress::f11Key, modifiers, sc };
+ case SDLK_F12: return { KeyPress::f12Key, modifiers, sc };
+ case SDLK_F13: return { KeyPress::f13Key, modifiers, sc };
+ case SDLK_F14: return { KeyPress::f14Key, modifiers, sc };
+ case SDLK_F15: return { KeyPress::f15Key, modifiers, sc };
+ case SDLK_F16: return { KeyPress::f16Key, modifiers, sc };
+ case SDLK_F17: return { KeyPress::f17Key, modifiers, sc };
+ case SDLK_F18: return { KeyPress::f18Key, modifiers, sc };
+ case SDLK_F19: return { KeyPress::f19Key, modifiers, sc };
+ case SDLK_F20: return { KeyPress::f20Key, modifiers, sc };
+ case SDLK_F21: return { KeyPress::f21Key, modifiers, sc };
+ case SDLK_F22: return { KeyPress::f22Key, modifiers, sc };
+ case SDLK_F23: return { KeyPress::f23Key, modifiers, sc };
+ case SDLK_F24: return { KeyPress::f24Key, modifiers, sc };
+ //case SDLK_F25: return { KeyPress::f25Key, modifiers, sc };
+ case SDLK_KP_0: return { KeyPress::kp0Key, modifiers, sc };
+ case SDLK_KP_1: return { KeyPress::kp1Key, modifiers, sc };
+ case SDLK_KP_2: return { KeyPress::kp2Key, modifiers, sc };
+ case SDLK_KP_3: return { KeyPress::kp3Key, modifiers, sc };
+ case SDLK_KP_4: return { KeyPress::kp4Key, modifiers, sc };
+ case SDLK_KP_5: return { KeyPress::kp5Key, modifiers, sc };
+ case SDLK_KP_6: return { KeyPress::kp6Key, modifiers, sc };
+ case SDLK_KP_7: return { KeyPress::kp7Key, modifiers, sc };
+ case SDLK_KP_8: return { KeyPress::kp8Key, modifiers, sc };
+ case SDLK_KP_9: return { KeyPress::kp9Key, modifiers, sc };
+ case SDLK_KP_DECIMAL: return { KeyPress::kpDecimalKey, modifiers, sc };
+ case SDLK_KP_DIVIDE: return { KeyPress::kpDivideKey, modifiers, sc };
+ case SDLK_KP_POWER: return { KeyPress::kpMultiplyKey, modifiers, sc };
+ case SDLK_KP_MINUS: return { KeyPress::kpSubtractKey, modifiers, sc };
+ case SDLK_KP_PLUS: return { KeyPress::kpAddKey, modifiers, sc };
+ case SDLK_KP_ENTER: return { KeyPress::kpEnterKey, modifiers, sc };
+ case SDLK_KP_EQUALS: return { KeyPress::kpEqualKey, modifiers, sc };
+ case SDLK_LSHIFT: return { KeyPress::leftShiftKey, modifiers, sc };
+ case SDLK_LCTRL: return { KeyPress::leftControlKey, modifiers, sc };
+ case SDLK_LALT: return { KeyPress::leftAltKey, modifiers, sc };
+ case SDLK_LGUI: return { KeyPress::leftSuperKey, modifiers, sc };
+ case SDLK_RSHIFT: return { KeyPress::rightShiftKey, modifiers, sc };
+ case SDLK_RCTRL: return { KeyPress::rightControlKey, modifiers, sc };
+ case SDLK_RALT: return { KeyPress::rightAltKey, modifiers, sc };
+ case SDLK_RGUI: return { KeyPress::rightSuperKey, modifiers, sc };
+ case SDLK_MENU: return { KeyPress::menuKey, modifiers, sc };
default:
break;
@@ -203,6 +202,36 @@ KeyPress toKeyPress (int key, int scancode, int modifiers) noexcept
//==============================================================================
+void* getNativeWindowHandle (SDL_Window* window)
+{
+ if (window == nullptr)
+ return nullptr;
+
+ SDL_SysWMinfo wmInfo;
+ SDL_VERSION (&wmInfo.version);
+ if (SDL_GetWindowWMInfo (window, &wmInfo))
+ {
+#if JUCE_MAC
+ return (__bridge void*) wmInfo.info.cocoa.window; // NSWindow*
+
+#elif JUCE_IOS
+ return (__bridge void*) wmInfo.info.uikit.window; // UIWindow*
+
+#elif JUCE_WINDOWS
+ return wmInfo.info.win.window; // HWND
+
+#elif JUCE_LINUX
+ return reinterpret_cast (wmInfo.info.x11.window); // X11 Window
+
+#elif JUCE_ANDROID
+ return reinterpret_cast (wmInfo.info.android.window); // ANativeWindow*
+
+#endif
+ }
+
+ return nullptr;
+}
+
Rectangle getNativeWindowPosition (void* nativeDisplay, void* nativeWindow)
{
#if JUCE_WINDOWS
@@ -240,11 +269,11 @@ Rectangle getNativeWindowPosition (void* nativeDisplay, void* nativeWindow)
#endif
}
-void setNativeParent (void* nativeDisplay, void* nativeWindow, GLFWwindow* window)
+void setNativeParent (void* nativeDisplay, void* nativeWindow, SDL_Window* window)
{
#if JUCE_WINDOWS
HWND hpar = reinterpret_cast (nativeWindow);
- HWND hwnd = reinterpret_cast (glfwGetWin32Window (window));
+ HWND hwnd = reinterpret_cast (getNativeWindowHandle (window));
SetParent (hwnd, hpar);
long style = GetWindowLong (hwnd, GWL_STYLE);
@@ -256,7 +285,7 @@ void setNativeParent (void* nativeDisplay, void* nativeWindow, GLFWwindow* windo
#elif JUCE_MAC
NSWindow* parentWindow = [reinterpret_cast (nativeWindow) window];
- NSWindow* currentWindow = glfwGetCocoaWindow (window);
+ NSWindow* currentWindow = reinterpret_cast (getNativeWindowHandle (window));
[parentWindow addChildWindow:currentWindow ordered:NSWindowAbove];
#elif JUCE_LINUX
@@ -272,7 +301,7 @@ GraphicsContext::Api getGraphicsContextApi (const std::optional getCursorPosition() const;
+
//==============================================================================
void handleMouseMoveOrDrag (const Point& localPosition);
void handleMouseDown (const Point& localPosition, MouseEvent::Buttons button, KeyModifiers modifiers);
@@ -428,22 +478,15 @@ class GLFWComponentNative final
void handleMoved (int xpos, int ypos);
void handleResized (int width, int height);
void handleFocusChanged (bool gotFocus);
- void handleContentScaleChanged (float xscale, float yscale);
+ void handleContentScaleChanged();
void handleUserTriedToCloseWindow();
//==============================================================================
- Point getCursorPosition() const;
+ void handleWindowEvent (const SDL_WindowEvent& windowEvent);
//==============================================================================
- static void glfwWindowContentScale (GLFWwindow* window, float xscale, float yscale);
- static void glfwWindowClose (GLFWwindow* window);
- static void glfwWindowPos (GLFWwindow* window, int xpos, int ypos);
- static void glfwWindowSize (GLFWwindow* window, int width, int height);
- static void glfwWindowFocus (GLFWwindow* window, int focused);
- static void glfwMouseMove (GLFWwindow* window, double x, double y);
- static void glfwMousePress (GLFWwindow* window, int button, int action, int mods);
- static void glfwMouseScroll (GLFWwindow* window, double xoffset, double yoffset);
- static void glfwKeyPress (GLFWwindow* window, int key, int scancode, int action, int mods);
+ void handleEvent (SDL_Event* event);
+ static int eventDispatcher (void* userdata, SDL_Event* event);
private:
void updateComponentUnderMouse (const MouseEvent& event);
@@ -453,9 +496,13 @@ class GLFWComponentNative final
void startRendering();
void stopRendering();
- GLFWwindow* window = nullptr;
+ SDL_Window* window = nullptr;
+ SDL_Renderer* windowRenderer = nullptr;
+ SDL_GLContext windowContext = nullptr;
+
void* parentWindow = nullptr;
String windowTitle;
+ uint32 windowFlags = 0;
GraphicsContext::Api currentGraphicsApi;
@@ -473,7 +520,7 @@ class GLFWComponentNative final
WeakReference lastComponentFocused;
WeakReference lastComponentUnderMouse;
- int keyState[GLFW_KEY_LAST] = {};
+ HashMap keyState;
MouseEvent::Buttons currentMouseButtons = MouseEvent::noButtons;
KeyModifiers currentKeyModifiers;
@@ -494,21 +541,15 @@ class GLFWComponentNative final
static constexpr int defaultForcedRedraws = 2;
Rectangle currentRepaintArea;
-
-#if JUCE_MAC
- id gpu = nil;
- id queue = nil;
- CAMetalLayer* swapchain = nullptr;
-#endif
};
//==============================================================================
-std::atomic_flag GLFWComponentNative::isInitialised = ATOMIC_FLAG_INIT;
+std::atomic_flag SDL2ComponentNative::isInitialised = ATOMIC_FLAG_INIT;
//==============================================================================
-GLFWComponentNative::GLFWComponentNative (Component& component,
+SDL2ComponentNative::SDL2ComponentNative (Component& component,
const Options& options,
void* parent)
: ComponentNative (component, options.flags)
@@ -520,66 +561,49 @@ GLFWComponentNative::GLFWComponentNative (Component& component,
, desiredFrameRate (options.framerateRedraw.value_or (60.0f))
, shouldRenderContinuous (options.flags.test (renderContinuous))
{
-#if JUCE_MAC
- if (currentGraphicsApi == GraphicsContext::Metal)
- {
- gpu = MTLCreateSystemDefaultDevice();
- queue = [gpu newCommandQueue];
- swapchain = [CAMetalLayer layer];
- swapchain.device = gpu;
- swapchain.opaque = YES;
- }
-#endif
+ SDL_AddEventWatch (eventDispatcher, this);
+
+ // Setup window hints and get flags
+ windowFlags = setContextWindowHints (currentGraphicsApi);
+
+ if (options.flags.test (resizableWindow))
+ windowFlags |= SDL_WINDOW_RESIZABLE;
+
+ if (component.isVisible())
+ windowFlags |= SDL_WINDOW_SHOWN;
+ else
+ windowFlags |= SDL_WINDOW_HIDDEN;
+
+ if (options.flags.test (allowHighDensityDisplay))
+ windowFlags |= SDL_WINDOW_ALLOW_HIGHDPI;
- // Setup window hints
- setContextWindowHints (currentGraphicsApi);
+ if (! options.flags.test (decoratedWindow))
+ windowFlags |= SDL_WINDOW_BORDERLESS;
- glfwWindowHint (GLFW_VISIBLE, component.isVisible() ? GLFW_TRUE : GLFW_FALSE);
- glfwWindowHint (GLFW_DECORATED, options.flags.test (decoratedWindow) ? GLFW_TRUE : GLFW_FALSE);
+ SDL_SetHint (SDL_HINT_ORIENTATIONS, "Portrait PortraitUpsideDown LandscapeLeft LandscapeRight");
- // Create the window and parent it
- auto monitor = component.isFullScreen() ? glfwGetPrimaryMonitor() : nullptr;
- window = glfwCreateWindow (1, 1, component.getTitle().toRawUTF8(), monitor, nullptr);
+ // Create the window, renderer and parent it
+ window = SDL_CreateWindow (component.getTitle().toRawUTF8(),
+ SDL_WINDOWPOS_UNDEFINED,
+ SDL_WINDOWPOS_UNDEFINED,
+ 1,
+ 1,
+ windowFlags);
if (window == nullptr)
return; // TODO - raise something ?
+ windowRenderer = SDL_CreateRenderer (window, -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED);
+
+ SDL_SetWindowData (window, "self", this);
+
if (parent != nullptr)
setNativeParent (nullptr, parent, window);
-#if JUCE_MAC
- if (currentGraphicsApi == GraphicsContext::Metal)
- {
- NSWindow* nswindow = glfwGetCocoaWindow (window);
- nswindow.contentView.layer = swapchain;
- nswindow.contentView.wantsLayer = YES;
- }
-#endif
-
// Create the rendering context
- if (currentGraphicsApi == GraphicsContext::OpenGL)
- {
- glfwMakeContextCurrent (window);
-#if ! (JUCE_EMSCRIPTEN && RIVE_WEBGL)
- glfwSwapInterval (0);
-#endif
- }
-
context = GraphicsContext::createContext (currentGraphicsApi, GraphicsContext::Options {});
if (context == nullptr)
return; // TODO - raise something ?
- // Setup callbacks
- glfwSetWindowUserPointer (window, this);
- glfwSetWindowContentScaleCallback (window, glfwWindowContentScale);
- glfwSetWindowCloseCallback (window, glfwWindowClose);
- glfwSetWindowSizeCallback (window, glfwWindowSize);
- glfwSetWindowPosCallback (window, glfwWindowPos);
- glfwSetWindowFocusCallback (window, glfwWindowFocus);
- glfwSetCursorPosCallback (window, glfwMouseMove);
- glfwSetMouseButtonCallback (window, glfwMousePress);
- glfwSetScrollCallback (window, glfwMouseScroll);
- glfwSetKeyCallback (window, glfwKeyPress);
-
// Resize after callbacks are in place
setBounds (
{ screenBounds.getX(),
@@ -591,16 +615,19 @@ GLFWComponentNative::GLFWComponentNative (Component& component,
startRendering();
}
-GLFWComponentNative::~GLFWComponentNative()
+SDL2ComponentNative::~SDL2ComponentNative()
{
// Stop the rendering
stopRendering();
- // Destroy the window
+ // Destroy the renderer and window
+ if (windowRenderer != nullptr)
+ SDL_DestroyRenderer (windowRenderer);
+
if (window != nullptr)
{
- glfwSetWindowUserPointer (window, nullptr);
- glfwDestroyWindow (window);
+ SDL_SetWindowData (window, "self", nullptr);
+ SDL_DestroyWindow (window);
}
window = nullptr;
@@ -608,24 +635,24 @@ GLFWComponentNative::~GLFWComponentNative()
//==============================================================================
-void GLFWComponentNative::setTitle (const String& title)
+void SDL2ComponentNative::setTitle (const String& title)
{
if (windowTitle == title)
return;
if (window != nullptr)
- glfwSetWindowTitle (window, title.toRawUTF8());
+ SDL_SetWindowTitle (window, title.toRawUTF8());
windowTitle = title;
}
-String GLFWComponentNative::getTitle() const
+String SDL2ComponentNative::getTitle() const
{
#if ! (JUCE_EMSCRIPTEN && RIVE_WEBGL)
if (window == nullptr)
return {};
- if (auto title = glfwGetWindowTitle (window))
+ if (auto title = SDL_GetWindowTitle (window))
return String::fromUTF8 (title);
#endif
@@ -634,70 +661,70 @@ String GLFWComponentNative::getTitle() const
//==============================================================================
-void GLFWComponentNative::setVisible (bool shouldBeVisible)
+void SDL2ComponentNative::setVisible (bool shouldBeVisible)
{
if (window == nullptr)
return;
if (shouldBeVisible)
- glfwShowWindow (window);
+ SDL_ShowWindow (window);
else
- glfwHideWindow (window);
+ SDL_HideWindow (window);
}
-bool GLFWComponentNative::isVisible() const
+bool SDL2ComponentNative::isVisible() const
{
- return window != nullptr && glfwGetWindowAttrib (window, GLFW_VISIBLE) != 0;
+ return window != nullptr && (SDL_GetWindowFlags (window) & SDL_WINDOW_SHOWN) != 0;
}
//==============================================================================
-void GLFWComponentNative::setSize (const Size& size)
+void SDL2ComponentNative::setSize (const Size& size)
{
setBounds (screenBounds.withSize (size));
}
-Size GLFWComponentNative::getSize() const
+Size SDL2ComponentNative::getSize() const
{
int width = 0, height = 0;
if (window != nullptr)
- glfwGetWindowSize (window, &width, &height);
+ SDL_GetWindowSize (window, &width, &height);
return { width, height };
}
-Size GLFWComponentNative::getContentSize() const
+Size SDL2ComponentNative::getContentSize() const
{
int width = 0, height = 0;
- if (window != nullptr)
- glfwGetFramebufferSize (window, &width, &height);
+ if (windowRenderer != nullptr)
+ SDL_GetRendererOutputSize (windowRenderer, &width, &height);
return { width, height };
}
-Point GLFWComponentNative::getPosition() const
+Point SDL2ComponentNative::getPosition() const
{
return screenBounds.getPosition();
}
-void GLFWComponentNative::setPosition (const Point& newPosition)
+void SDL2ComponentNative::setPosition (const Point& newPosition)
{
if (window == nullptr || screenBounds.getPosition() == newPosition)
return;
- glfwSetWindowPos (window, newPosition.getX(), newPosition.getY());
+ SDL_SetWindowPosition (window, newPosition.getX(), newPosition.getY());
screenBounds = screenBounds.withPosition (newPosition);
}
-Rectangle GLFWComponentNative::getBounds() const
+Rectangle SDL2ComponentNative::getBounds() const
{
return screenBounds;
}
-void GLFWComponentNative::setBounds (const Rectangle& newBounds)
+void SDL2ComponentNative::setBounds (const Rectangle& newBounds)
{
#if JUCE_ANDROID
screenBounds = Rectangle (0, 0, getSize());
@@ -710,7 +737,7 @@ void GLFWComponentNative::setBounds (const Rectangle& newBounds)
#if JUCE_EMSCRIPTEN && RIVE_WEBGL
const double devicePixelRatio = emscripten_get_device_pixel_ratio();
- glfwSetWindowSize (window,
+ SDL_SetWindowSize (window,
static_cast (newBounds.getWidth() * devicePixelRatio),
static_cast (newBounds.getHeight() * devicePixelRatio));
@@ -720,16 +747,16 @@ void GLFWComponentNative::setBounds (const Rectangle& newBounds)
#else
if (! isFullScreen() && isDecorated())
- glfwGetWindowFrameSize (window, &leftMargin, &topMargin, &rightMargin, &bottomMargin);
+ SDL_GetWindowBordersSize (window, &leftMargin, &topMargin, &rightMargin, &bottomMargin);
- glfwSetWindowSize (window,
+ SDL_SetWindowSize (window,
jmax (1, newBounds.getWidth() - leftMargin - rightMargin),
jmax (1, newBounds.getHeight() - topMargin - bottomMargin));
#endif
//setPosition (newBounds.getPosition().translated (leftMargin, topMargin));
- glfwSetWindowPos (window, newBounds.getX() + leftMargin, newBounds.getY() + topMargin);
+ SDL_SetWindowPosition (window, newBounds.getX() + leftMargin, newBounds.getY() + topMargin);
screenBounds = newBounds;
@@ -738,7 +765,7 @@ void GLFWComponentNative::setBounds (const Rectangle& newBounds)
//==============================================================================
-void GLFWComponentNative::setFullScreen (bool shouldBeFullScreen)
+void SDL2ComponentNative::setFullScreen (bool shouldBeFullScreen)
{
if (window == nullptr)
return;
@@ -750,16 +777,7 @@ void GLFWComponentNative::setFullScreen (bool shouldBeFullScreen)
#else
lastScreenBounds = screenBounds;
- auto monitor = glfwGetPrimaryMonitor();
- const GLFWvidmode* mode = glfwGetVideoMode (monitor);
-
- glfwSetWindowMonitor (window,
- monitor,
- 0,
- 0,
- mode->width,
- mode->height,
- mode->refreshRate);
+ SDL_SetWindowFullscreen (window, SDL_WINDOW_FULLSCREEN); // SDL_SetWindowDisplayMode
#endif
}
else
@@ -767,47 +785,48 @@ void GLFWComponentNative::setFullScreen (bool shouldBeFullScreen)
#if JUCE_EMSCRIPTEN
emscripten_exit_fullscreen();
#else
- glfwSetWindowMonitor (window,
- nullptr,
- component.getX(),
- component.getY(),
- component.getWidth(),
- component.getHeight(),
- GLFW_DONT_CARE);
+ SDL_RestoreWindow (window);
+ SDL_SetWindowSize (window, component.getWidth(), component.getHeight());
+ SDL_SetWindowPosition (window, component.getX(), component.getY());
setBounds (lastScreenBounds);
#endif
}
}
-bool GLFWComponentNative::isFullScreen() const
+bool SDL2ComponentNative::isFullScreen() const
{
- return window != nullptr && glfwGetWindowMonitor (window) != nullptr;
+ return window != nullptr && (SDL_GetWindowFlags (window) & SDL_WINDOW_FULLSCREEN) != 0;
}
//==============================================================================
-bool GLFWComponentNative::isDecorated() const
+bool SDL2ComponentNative::isDecorated() const
{
- return window != nullptr && glfwGetWindowAttrib (window, GLFW_DECORATED) != 0;
+ return window != nullptr && (SDL_GetWindowFlags (window) & SDL_WINDOW_BORDERLESS) == 0;
}
//==============================================================================
-void GLFWComponentNative::setOpacity (float opacity)
+void SDL2ComponentNative::setOpacity (float opacity)
{
if (window != nullptr)
- glfwSetWindowOpacity (window, jlimit (0.0f, 1.0f, opacity));
+ SDL_SetWindowOpacity (window, jlimit (0.0f, 1.0f, opacity));
}
-float GLFWComponentNative::getOpacity() const
+float SDL2ComponentNative::getOpacity() const
{
- return window != nullptr ? glfwGetWindowOpacity (window) : 1.0f;
+ float opacity = 1.0f;
+
+ if (window != nullptr)
+ SDL_GetWindowOpacity (window, &opacity);
+
+ return opacity;
}
//==============================================================================
-void GLFWComponentNative::setFocusedComponent (Component* comp)
+void SDL2ComponentNative::setFocusedComponent (Component* comp)
{
if (lastComponentFocused != nullptr)
; // TODO
@@ -815,41 +834,41 @@ void GLFWComponentNative::setFocusedComponent (Component* comp)
lastComponentFocused = comp;
}
-Component* GLFWComponentNative::getFocusedComponent() const
+Component* SDL2ComponentNative::getFocusedComponent() const
{
return lastComponentFocused;
}
//==============================================================================
-bool GLFWComponentNative::isContinuousRepaintingEnabled() const
+bool SDL2ComponentNative::isContinuousRepaintingEnabled() const
{
return shouldRenderContinuous;
}
-void GLFWComponentNative::enableContinuousRepainting (bool shouldBeEnabled)
+void SDL2ComponentNative::enableContinuousRepainting (bool shouldBeEnabled)
{
shouldRenderContinuous = shouldBeEnabled;
}
-bool GLFWComponentNative::isAtomicModeEnabled() const
+bool SDL2ComponentNative::isAtomicModeEnabled() const
{
return renderAtomicMode;
}
-void GLFWComponentNative::enableAtomicMode (bool shouldBeEnabled)
+void SDL2ComponentNative::enableAtomicMode (bool shouldBeEnabled)
{
renderAtomicMode = shouldBeEnabled;
component.repaint();
}
-bool GLFWComponentNative::isWireframeEnabled() const
+bool SDL2ComponentNative::isWireframeEnabled() const
{
return renderWireframe;
}
-void GLFWComponentNative::enableWireframe (bool shouldBeEnabled)
+void SDL2ComponentNative::enableWireframe (bool shouldBeEnabled)
{
renderWireframe = shouldBeEnabled;
@@ -858,7 +877,7 @@ void GLFWComponentNative::enableWireframe (bool shouldBeEnabled)
//==============================================================================
-void GLFWComponentNative::repaint (const Rectangle& rect)
+void SDL2ComponentNative::repaint (const Rectangle& rect)
{
if (! currentRepaintArea.isEmpty())
currentRepaintArea = currentRepaintArea.smallestContainingRectangle (rect);
@@ -868,36 +887,35 @@ void GLFWComponentNative::repaint (const Rectangle& rect)
triggerRenderingUpdate();
}
-Rectangle GLFWComponentNative::getRepaintArea() const
+Rectangle SDL2ComponentNative::getRepaintArea() const
{
return currentRepaintArea;
}
//==============================================================================
-float GLFWComponentNative::getScaleDpi() const
+float SDL2ComponentNative::getScaleDpi() const
{
return context != nullptr ? context->dpiScale (getNativeHandle()) : 1.0f;
}
-float GLFWComponentNative::getCurrentFrameRate() const
+float SDL2ComponentNative::getCurrentFrameRate() const
{
return currentFrameRate.load (std::memory_order_relaxed);
}
-float GLFWComponentNative::getDesiredFrameRate() const
+float SDL2ComponentNative::getDesiredFrameRate() const
{
return desiredFrameRate;
}
//==============================================================================
-Point GLFWComponentNative::getCursorPosition() const
+Point SDL2ComponentNative::getCursorPosition() const
{
- double x = 0.0, y = 0.0;
+ int x = 0, y = 0;
- if (window != nullptr)
- glfwGetCursorPos (window, &x, &y);
+ SDL_GetMouseState (&x, &y);
return {
static_cast (x),
@@ -907,39 +925,21 @@ Point GLFWComponentNative::getCursorPosition() const
//==============================================================================
-rive::Factory* GLFWComponentNative::getFactory()
+rive::Factory* SDL2ComponentNative::getFactory()
{
return context ? context->factory() : nullptr;
}
//==============================================================================
-void* GLFWComponentNative::getNativeHandle() const
+void* SDL2ComponentNative::getNativeHandle() const
{
- if (window == nullptr)
- return nullptr;
-
-#if JUCE_MAC
- return (__bridge void*) glfwGetCocoaWindow (window);
-
-#elif JUCE_WINDOWS
- return glfwGetWin32Window (window);
-
-#elif JUCE_LINUX
- return reinterpret_cast (glfwGetX11Window (window));
-
-#elif JUCE_ANDROID
- return reinterpret_cast (glfwGetAndroidApp()->window);
-
-#else
- return nullptr;
-
-#endif
+ return getNativeWindowHandle (window);
}
//==============================================================================
-void GLFWComponentNative::run()
+void SDL2ComponentNative::run()
{
const double maxFrameTimeSeconds = 1.0 / static_cast (desiredFrameRate);
const double maxFrameTimeMs = maxFrameTimeSeconds * 1000.0;
@@ -994,7 +994,7 @@ void GLFWComponentNative::run()
}
}
-void GLFWComponentNative::handleAsyncUpdate()
+void SDL2ComponentNative::handleAsyncUpdate()
{
if (! isThreadRunning() || ! isInitialised.test_and_set())
return;
@@ -1004,14 +1004,14 @@ void GLFWComponentNative::handleAsyncUpdate()
renderEvent.signal();
}
-void GLFWComponentNative::timerCallback()
+void SDL2ComponentNative::timerCallback()
{
renderContext();
}
//==============================================================================
-void GLFWComponentNative::renderContext()
+void SDL2ComponentNative::renderContext()
{
auto [contentWidth, contentHeight] = getContentSize();
if (context == nullptr || contentWidth == 0 || contentHeight == 0)
@@ -1070,7 +1070,7 @@ void GLFWComponentNative::renderContext()
// Swap buffers
if (window != nullptr && currentGraphicsApi == GraphicsContext::OpenGL)
- glfwSwapBuffers (window);
+ SDL_GL_SwapWindow (window);
if (! renderContinuous)
{
@@ -1083,7 +1083,7 @@ void GLFWComponentNative::renderContext()
//==============================================================================
-void GLFWComponentNative::triggerRenderingUpdate()
+void SDL2ComponentNative::triggerRenderingUpdate()
{
if (shouldRenderContinuous)
return;
@@ -1094,7 +1094,7 @@ void GLFWComponentNative::triggerRenderingUpdate()
//==============================================================================
-void GLFWComponentNative::startRendering()
+void SDL2ComponentNative::startRendering()
{
#if (JUCE_EMSCRIPTEN && RIVE_WEBGL) && ! defined(__EMSCRIPTEN_PTHREADS__)
startTimerHz (desiredFrameRate);
@@ -1103,7 +1103,7 @@ void GLFWComponentNative::startRendering()
#endif
}
-void GLFWComponentNative::stopRendering()
+void SDL2ComponentNative::stopRendering()
{
#if (JUCE_EMSCRIPTEN && RIVE_WEBGL) && ! defined(__EMSCRIPTEN_PTHREADS__)
stopTimer();
@@ -1118,7 +1118,7 @@ void GLFWComponentNative::stopRendering()
//==============================================================================
-void GLFWComponentNative::handleMouseMoveOrDrag (const Point& localPosition)
+void SDL2ComponentNative::handleMouseMoveOrDrag (const Point& localPosition)
{
auto event = MouseEvent()
.withButtons (currentMouseButtons)
@@ -1148,7 +1148,7 @@ void GLFWComponentNative::handleMouseMoveOrDrag (const Point& localPositi
lastMouseMovePosition = localPosition;
}
-void GLFWComponentNative::handleMouseDown (const Point& localPosition, MouseEvent::Buttons button, KeyModifiers modifiers)
+void SDL2ComponentNative::handleMouseDown (const Point& localPosition, MouseEvent::Buttons button, KeyModifiers modifiers)
{
currentMouseButtons = static_cast (currentMouseButtons | button);
currentKeyModifiers = modifiers;
@@ -1192,7 +1192,7 @@ void GLFWComponentNative::handleMouseDown (const Point& localPosition, Mo
lastMouseMovePosition = localPosition;
}
-void GLFWComponentNative::handleMouseUp (const Point& localPosition, MouseEvent::Buttons button, KeyModifiers modifiers)
+void SDL2ComponentNative::handleMouseUp (const Point& localPosition, MouseEvent::Buttons button, KeyModifiers modifiers)
{
currentMouseButtons = static_cast (currentMouseButtons & ~button);
currentKeyModifiers = modifiers;
@@ -1229,7 +1229,7 @@ void GLFWComponentNative::handleMouseUp (const Point& localPosition, Mous
//==============================================================================
-void GLFWComponentNative::handleMouseWheel (const Point& localPosition, const MouseWheelData& wheelData)
+void SDL2ComponentNative::handleMouseWheel (const Point& localPosition, const MouseWheelData& wheelData)
{
auto event = MouseEvent()
.withButtons (currentMouseButtons)
@@ -1262,10 +1262,10 @@ void GLFWComponentNative::handleMouseWheel (const Point& localPosition, c
//==============================================================================
-void GLFWComponentNative::handleKeyDown (const KeyPress& keys, const Point& cursorPosition)
+void SDL2ComponentNative::handleKeyDown (const KeyPress& keys, const Point& cursorPosition)
{
currentKeyModifiers = keys.getModifiers();
- keyState[keys.getKey()] = 1;
+ keyState.set (keys.getKey(), 1);
if (lastComponentFocused != nullptr)
lastComponentFocused->internalKeyDown (keys, cursorPosition);
@@ -1273,10 +1273,10 @@ void GLFWComponentNative::handleKeyDown (const KeyPress& keys, const Point& cursorPosition)
+void SDL2ComponentNative::handleKeyUp (const KeyPress& keys, const Point& cursorPosition)
{
currentKeyModifiers = keys.getModifiers();
- keyState[keys.getKey()] = 0;
+ keyState.set (keys.getKey(), 0);
if (lastComponentFocused != nullptr)
lastComponentFocused->internalKeyUp (keys, cursorPosition);
@@ -1286,14 +1286,14 @@ void GLFWComponentNative::handleKeyUp (const KeyPress& keys, const Point&
//==============================================================================
-void GLFWComponentNative::handleMoved (int xpos, int ypos)
+void SDL2ComponentNative::handleMoved (int xpos, int ypos)
{
component.internalMoved (xpos, ypos);
screenBounds = screenBounds.withPosition (xpos, ypos);
}
-void GLFWComponentNative::handleResized (int width, int height)
+void SDL2ComponentNative::handleResized (int width, int height)
{
component.internalResized (width, height);
@@ -1303,30 +1303,30 @@ void GLFWComponentNative::handleResized (int width, int height)
triggerRenderingUpdate();
}
-void GLFWComponentNative::handleFocusChanged (bool gotFocus)
+void SDL2ComponentNative::handleFocusChanged (bool gotFocus)
{
//DBG ("handleFocusChanged: " << (gotFocus ? 1 : 0));
}
-void GLFWComponentNative::handleContentScaleChanged (float xscale, float yscale)
+void SDL2ComponentNative::handleContentScaleChanged()
{
int width = screenBounds.getWidth();
int height = screenBounds.getHeight();
if (window != nullptr)
- glfwGetWindowSize (window, &width, &height);
+ SDL_GetWindowSize (window, &width, &height);
handleResized (width, height);
}
-void GLFWComponentNative::handleUserTriedToCloseWindow()
+void SDL2ComponentNative::handleUserTriedToCloseWindow()
{
component.internalUserTriedToCloseWindow();
}
//==============================================================================
-void GLFWComponentNative::updateComponentUnderMouse (const MouseEvent& event)
+void SDL2ComponentNative::updateComponentUnderMouse (const MouseEvent& event)
{
Component* child = component.findComponentAt (event.getPosition());
if (child != nullptr)
@@ -1358,141 +1358,176 @@ std::unique_ptr ComponentNative::createFor (Component& componen
const Options& options,
void* parent)
{
- return std::make_unique (component, options, parent);
+ return std::make_unique (component, options, parent);
}
//==============================================================================
-void GLFWComponentNative::glfwWindowContentScale (GLFWwindow* window, float xscale, float yscale)
+void SDL2ComponentNative::handleWindowEvent (const SDL_WindowEvent& windowEvent)
{
- auto* nativeComponent = static_cast (glfwGetWindowUserPointer (window));
+ switch (windowEvent.event)
+ {
+ case SDL_WINDOWEVENT_RESIZED:
+ case SDL_WINDOWEVENT_SIZE_CHANGED:
+ handleResized (windowEvent.data1, windowEvent.data2);
+ break;
- nativeComponent->handleContentScaleChanged (xscale, yscale);
-}
+ case SDL_WINDOWEVENT_MOVED:
+ handleMoved (windowEvent.data1, windowEvent.data2);
+ break;
-void GLFWComponentNative::glfwWindowClose (GLFWwindow* window)
-{
- auto* nativeComponent = static_cast (glfwGetWindowUserPointer (window));
+ case SDL_WINDOWEVENT_MINIMIZED:
+ break;
- nativeComponent->handleUserTriedToCloseWindow();
-}
+ case SDL_WINDOWEVENT_MAXIMIZED:
+ break;
-void GLFWComponentNative::glfwWindowPos (GLFWwindow* window, int xpos, int ypos)
-{
- auto* nativeComponent = static_cast (glfwGetWindowUserPointer (window));
+ case SDL_WINDOWEVENT_RESTORED:
+ break;
- nativeComponent->handleMoved (xpos, ypos);
-}
+ case SDL_WINDOWEVENT_FOCUS_GAINED:
+ handleFocusChanged (true);
+ break;
-void GLFWComponentNative::glfwWindowSize (GLFWwindow* window, int width, int height)
-{
- auto* nativeComponent = static_cast (glfwGetWindowUserPointer (window));
+ case SDL_WINDOWEVENT_FOCUS_LOST:
+ handleFocusChanged (false);
+ break;
- nativeComponent->handleResized (width, height);
+ case SDL_WINDOWEVENT_DISPLAY_CHANGED:
+ handleContentScaleChanged();
+ break;
+ }
}
-void GLFWComponentNative::glfwWindowFocus (GLFWwindow* window, int focused)
+//==============================================================================
+
+void SDL2ComponentNative::handleEvent (SDL_Event* event)
{
- auto* nativeComponent = static_cast (glfwGetWindowUserPointer (window));
+ switch (event->type)
+ {
+ case SDL_QUIT:
+ {
+ // component.internalUserTriedToCloseWindow();
+ break;
+ }
- nativeComponent->handleFocusChanged (focused != 0);
-}
+ case SDL_WINDOWEVENT:
+ {
+ handleWindowEvent (event->window);
+ break;
+ }
-void GLFWComponentNative::glfwMouseMove (GLFWwindow* window, double x, double y)
-{
- auto* nativeComponent = static_cast (glfwGetWindowUserPointer (window));
+ case SDL_DISPLAYEVENT:
+ {
+ break;
+ }
- nativeComponent->handleMouseMoveOrDrag ({ static_cast (x), static_cast (y) });
-}
+ case SDL_RENDER_TARGETS_RESET:
+ {
+ break;
+ }
-void GLFWComponentNative::glfwMousePress (GLFWwindow* window, int button, int action, int mods)
-{
- auto* nativeComponent = static_cast (glfwGetWindowUserPointer (window));
+ case SDL_RENDER_DEVICE_RESET:
+ {
+ break;
+ }
- auto cursorPosition = nativeComponent->getCursorPosition();
+ case SDL_MOUSEMOTION:
+ {
+ handleMouseMoveOrDrag ({ static_cast (event->motion.x), static_cast (event->motion.y) });
+ break;
+ }
- if (action == GLFW_PRESS)
- nativeComponent->handleMouseDown (cursorPosition, toMouseButton (button), toKeyModifiers (mods));
- else
- nativeComponent->handleMouseUp (cursorPosition, toMouseButton (button), toKeyModifiers (mods));
-}
+ case SDL_MOUSEBUTTONDOWN:
+ {
+ auto cursorPosition = Point { static_cast (event->button.x), static_cast (event->button.y) };
-void GLFWComponentNative::glfwMouseScroll (GLFWwindow* window, double xoffset, double yoffset)
-{
- auto* nativeComponent = static_cast (glfwGetWindowUserPointer (window));
+ handleMouseDown (cursorPosition, toMouseButton (event->button.button), KeyModifiers());
- auto cursorPosition = nativeComponent->getCursorPosition();
+ break;
+ }
- nativeComponent->handleMouseWheel (cursorPosition, { static_cast (xoffset), static_cast (yoffset) });
-}
+ case SDL_MOUSEBUTTONUP:
+ {
+ auto cursorPosition = Point { static_cast (event->button.x), static_cast (event->button.y) };
-void GLFWComponentNative::glfwKeyPress (GLFWwindow* window, int key, int scancode, int action, int mods)
-{
- auto* nativeComponent = static_cast (glfwGetWindowUserPointer (window));
+ handleMouseUp (cursorPosition, toMouseButton (event->button.button), KeyModifiers());
- auto cursorPosition = nativeComponent->getCursorPosition();
+ break;
+ }
- if (action == GLFW_PRESS)
- {
- mods |= convertKeyToModifier (key);
- nativeComponent->handleKeyDown (toKeyPress (key, scancode, mods), cursorPosition);
- }
- else
- {
- mods &= ~convertKeyToModifier (key);
- nativeComponent->handleKeyUp (toKeyPress (key, scancode, mods), cursorPosition);
+ case SDL_MOUSEWHEEL:
+ {
+ auto cursorPosition = getCursorPosition();
+
+ handleMouseWheel (cursorPosition, { static_cast (event->wheel.x), static_cast (event->wheel.y) });
+
+ break;
+ }
+
+ case SDL_KEYDOWN:
+ {
+ auto cursorPosition = getCursorPosition();
+ auto modifiers = toKeyModifiers (event->key.keysym.mod);
+
+ handleKeyDown (toKeyPress (event->key.keysym.sym, event->key.keysym.scancode, modifiers), cursorPosition);
+
+ break;
+ }
+
+ case SDL_KEYUP:
+ {
+ auto cursorPosition = getCursorPosition();
+ auto modifiers = toKeyModifiers (event->key.keysym.mod);
+
+ handleKeyUp (toKeyPress (event->key.keysym.sym, event->key.keysym.scancode, modifiers), cursorPosition);
+
+ break;
+ }
+
+ default:
+ break;
}
}
//==============================================================================
-void Desktop::updateDisplays()
+int SDL2ComponentNative::eventDispatcher (void* userdata, SDL_Event* event)
{
- int count;
- GLFWmonitor** monitors = glfwGetMonitors (&count);
- auto primaryMonitor = glfwGetPrimaryMonitor();
+ static_cast (userdata)->handleEvent (event);
+ return 0;
+}
- for (int index = 0; index < count; ++index)
+//==============================================================================
+
+void Desktop::updateDisplays()
+{
+ const int numDisplays = SDL_GetNumVideoDisplays();
+ for (int i = 0; i < numDisplays; ++i)
{
- auto monitor = monitors[index];
- if (monitor == nullptr)
+ SDL_Rect bounds;
+ if (SDL_GetDisplayBounds (i, &bounds) != 0)
continue;
auto display = std::make_unique();
-#if ! (JUCE_EMSCRIPTEN && RIVE_WEBGL)
- glfwSetMonitorUserPointer (monitor, display.get());
-#endif
-
- int physicalWidth = 0, physicalHeight = 0;
- glfwGetMonitorPhysicalSize (monitor, &physicalWidth, &physicalHeight);
- display->physicalSizeMillimeters = Size (physicalWidth, physicalHeight);
-
- int posX = 0, posY = 0;
- glfwGetMonitorPos (monitor, &posX, &posY);
- display->virtualPosition = Point (posX, posY);
+ display->virtualPosition = Point (bounds.x, bounds.y);
+ display->workArea = Rectangle (bounds.x, bounds.y, bounds.w, bounds.h);
- int workX = 0, workY = 0, workWidth = 0, workHeight = 0;
- glfwGetMonitorWorkarea (monitor, &workX, &workY, &workWidth, &workHeight);
- display->workArea = Rectangle (workX, workY, workWidth, workHeight);
-
- float scaleX = 1.0f, scaleY = 1.0f;
- glfwGetMonitorContentScale (monitor, &scaleX, &scaleY);
- display->contentScaleX = scaleX;
- display->contentScaleY = scaleY;
+ float ddpi, hdpi, vdpi;
+ if (SDL_GetDisplayDPI (i, &ddpi, &hdpi, &vdpi) == 0)
+ {
+ display->physicalSizeMillimeters = Size (
+ static_cast (bounds.w * 25.4f / hdpi),
+ static_cast (bounds.h * 25.4f / vdpi));
+ }
- if (auto name = glfwGetMonitorName (monitor))
- display->name = String::fromUTF8 (name);
+ display->contentScaleX = hdpi / 96.0f; // Assuming 96 DPI as standard
+ display->contentScaleY = vdpi / 96.0f;
- if (primaryMonitor == monitor)
- {
- display->isPrimary = true;
+ display->name = String (SDL_GetDisplayName (i));
+ display->isPrimary = (i == 0);
- displays.insert (0, display.release());
- }
- else
- {
- displays.add (display.release());
- }
+ displays.add (display.release());
}
}
@@ -1500,50 +1535,36 @@ void Desktop::updateDisplays()
void initialiseYup_Windowing()
{
- // Setup error callback
+ // Initialise SDL2
+ if (SDL_Init (SDL_INIT_VIDEO) != 0)
{
- auto errorCallback = +[] (int code, const char* message)
- {
- DBG ("GLFW Error: " << code << " - " << message);
- };
-
- glfwSetErrorCallback (errorCallback);
+ DBG ("Error initialising SDL");
+ return; // quit !
}
- // Initialise glfw
- glfwInit();
+ // Update available displays
+ Desktop::getInstance()->updateDisplays();
- // Setup monitor callback
+ // Allow SDL to poll events
+ auto loopCallback = []
{
- Desktop::getInstance()->updateDisplays();
-
- auto monitorCallback = +[] (GLFWmonitor* monitor, int event)
- {
- auto desktop = Desktop::getInstance();
-
- if (event == GLFW_CONNECTED)
- {
- }
- else if (event == GLFW_DISCONNECTED)
- {
- }
+ SDL_PumpEvents();
+ };
- desktop->updateDisplays();
- };
+ MessageManager::getInstance()->registerEventLoopCallback (loopCallback);
- glfwSetMonitorCallback (monitorCallback);
- }
-
- GLFWComponentNative::isInitialised.test_and_set();
+ SDL2ComponentNative::isInitialised.test_and_set();
}
void shutdownYup_Windowing()
{
- GLFWComponentNative::isInitialised.clear();
+ SDL2ComponentNative::isInitialised.clear();
+
+ MessageManager::getInstance()->registerEventLoopCallback (nullptr);
Desktop::getInstance()->deleteInstance();
- glfwTerminate();
+ SDL_Quit();
}
} // namespace yup
diff --git a/modules/yup_gui/yup_gui.cpp b/modules/yup_gui/yup_gui.cpp
index 7fc39c4e..5dc26b55 100644
--- a/modules/yup_gui/yup_gui.cpp
+++ b/modules/yup_gui/yup_gui.cpp
@@ -51,49 +51,41 @@
#include "windowing/yup_DocumentWindow.cpp"
//==============================================================================
-#if JUCE_MAC
-#define GLFW_INCLUDE_NONE
-#define GLFW_EXPOSE_NATIVE_COCOA
-#include
-#include
+#include
+#include
+//==============================================================================
+#if JUCE_MAC || JUCE_IOS
#import
#import
+#if JUCE_MAC
+#import
+#else
+#include "native/yup_Windowing_ios.mm"
+#endif
+
+//==============================================================================
#elif JUCE_LINUX
-#define GLFW_INCLUDE_NONE
-#define GLFW_EXPOSE_NATIVE_X11
-#define GLFW_EXPOSE_NATIVE_GLX
-#include
-#include
#undef None
#undef KeyPress
#undef SIZEOF
+//==============================================================================
#elif JUCE_WINDOWS
-#define GLFW_INCLUDE_NONE
-#define GLFW_EXPOSE_NATIVE_WGL
-#define GLFW_EXPOSE_NATIVE_WIN32
-#include
-#include
+//==============================================================================
#elif JUCE_ANDROID
-#define GLFW_INCLUDE_NONE
-#define GLFW_EXPOSE_NATIVE_ANDROID
-#include
-#include
-
-#else
-#define GLFW_INCLUDE_NONE
-#include
-
-#endif
//==============================================================================
-#if JUCE_EMSCRIPTEN
+#elif JUCE_EMSCRIPTEN
#include
#include
+
+//==============================================================================
+#else
+
#endif
//==============================================================================
-#include "native/yup_Windowing_glfw.cpp"
+#include "native/yup_Windowing_sdl2.cpp"
diff --git a/modules/yup_gui/yup_gui.h b/modules/yup_gui/yup_gui.h
index aad22c76..57ca78c0 100644
--- a/modules/yup_gui/yup_gui.h
+++ b/modules/yup_gui/yup_gui.h
@@ -36,7 +36,7 @@
dependencies: juce_events yup_graphics rive
osxFrameworks: Metal
iosFrameworks: Metal
- androidSearchpaths: {ANDROID_NDK}/sources/android/native_app_glue
+ iosSimFrameworks: Metal
enableARC: 1
END_JUCE_MODULE_DECLARATION
diff --git a/thirdparty/glad/glad.h b/thirdparty/glad/glad.h
index 8389e216..7d50ca75 100644
--- a/thirdparty/glad/glad.h
+++ b/thirdparty/glad/glad.h
@@ -32,7 +32,6 @@
website: https://glad.dav1d.de/
license: MIT
- dependencies:
searchpaths: include
END_JUCE_MODULE_DECLARATION
diff --git a/thirdparty/oboe_library/oboe_library.h b/thirdparty/oboe_library/oboe_library.h
index 06506c10..596c1176 100644
--- a/thirdparty/oboe_library/oboe_library.h
+++ b/thirdparty/oboe_library/oboe_library.h
@@ -32,7 +32,6 @@
website: https://developer.android.com/games/sdk/oboe
license: Apache-2.0
- dependencies:
searchpaths: upstream/include upstream/src
androidLibs: OpenSLES
diff --git a/thirdparty/rive_renderer/rive_renderer.h b/thirdparty/rive_renderer/rive_renderer.h
index af59c9e9..3a6b752a 100644
--- a/thirdparty/rive_renderer/rive_renderer.h
+++ b/thirdparty/rive_renderer/rive_renderer.h
@@ -37,6 +37,7 @@
osxFrameworks: Metal QuartzCore
defines: WITH_RIVE_TEXT=1
iosDefines: RIVE_IOS=1
+ iosSimDefines: RIVE_IOS_SIMULATOR=1
linuxDefines: RIVE_DESKTOP_GL=1
wasmDefines: RIVE_WEBGL=1
androidDefines: RIVE_ANDROID=1
diff --git a/thirdparty/sheenbidi/sheenbidi.h b/thirdparty/sheenbidi/sheenbidi.h
index fea034ab..fbf573df 100644
--- a/thirdparty/sheenbidi/sheenbidi.h
+++ b/thirdparty/sheenbidi/sheenbidi.h
@@ -32,7 +32,6 @@
website: https://github.com/Tehreer/SheenBidi
license: Apache-2.0
- dependencies:
searchpaths: include
END_JUCE_MODULE_DECLARATION
diff --git a/thirdparty/yoga_library/yoga_library.h b/thirdparty/yoga_library/yoga_library.h
index b82cf1c3..a1b399e8 100644
--- a/thirdparty/yoga_library/yoga_library.h
+++ b/thirdparty/yoga_library/yoga_library.h
@@ -32,7 +32,6 @@
website: https://www.zlib.net/
license: Public Domain
- dependencies:
searchpaths: upstream
END_JUCE_MODULE_DECLARATION
diff --git a/thirdparty/zlib/zlib.h b/thirdparty/zlib/zlib.h
index c583d716..e704b633 100644
--- a/thirdparty/zlib/zlib.h
+++ b/thirdparty/zlib/zlib.h
@@ -32,8 +32,6 @@
website: https://www.zlib.net/
license: Public Domain
- dependencies:
-
END_JUCE_MODULE_DECLARATION
==============================================================================