summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Cowgill <jcowgill@debian.org>2018-10-16 22:26:31 +0100
committerJames Cowgill <jcowgill@debian.org>2018-10-16 22:26:31 +0100
commitf57a5d96a92d1208d252b7d3f97b3b5c3b69fd12 (patch)
treef2c152c29b5cac3a1b21cbae02c82b006ae7cdb4
parent088cbaedcc0634d0949ca8a92236e62a6d6caf71 (diff)
parent08bb1c372efcc9e2054e64b80959f025c8f43744 (diff)
Update upstream source from tag 'upstream/2.5.1+dfsg'
Update to upstream version '2.5.1+dfsg' with Debian dir 8171c41179aa4509b53f92cff2b893d4ceafc883
-rw-r--r--CMakeLists.txt49
-rw-r--r--changelog.md48
-rw-r--r--cmake/Config.cmake15
-rw-r--r--cmake/Macros.cmake27
-rw-r--r--cmake/SFMLConfigDependencies.cmake.in16
-rw-r--r--cmake/toolchains/iOS.toolchain.cmake101
-rw-r--r--examples/android/app/src/main/jni/main.cpp3
-rw-r--r--examples/cocoa/CMakeLists.txt2
-rw-r--r--examples/iOS/CMakeLists.txt2
-rw-r--r--include/SFML/Config.hpp2
-rw-r--r--include/SFML/System/FileInputStream.hpp4
-rw-r--r--include/SFML/Window/Clipboard.hpp19
-rw-r--r--include/SFML/Window/Cursor.hpp9
-rw-r--r--src/SFML/Audio/SoundFileReaderWav.cpp6
-rw-r--r--src/SFML/Graphics/Font.cpp26
-rw-r--r--src/SFML/Graphics/RenderTarget.cpp8
-rw-r--r--src/SFML/Graphics/RenderTexture.cpp2
-rw-r--r--src/SFML/Graphics/RenderTextureImplFBO.cpp34
-rw-r--r--src/SFML/Graphics/RenderWindow.cpp2
-rw-r--r--src/SFML/Graphics/Text.cpp29
-rw-r--r--src/SFML/Graphics/Texture.cpp15
-rw-r--r--src/SFML/Main/MainAndroid.cpp19
-rw-r--r--src/SFML/Network/TcpSocket.cpp2
-rw-r--r--src/SFML/System/FileInputStream.cpp14
-rw-r--r--src/SFML/Window/CMakeLists.txt14
-rw-r--r--src/SFML/Window/OSX/CursorImpl.mm44
-rw-r--r--src/SFML/Window/Unix/ClipboardImpl.cpp459
-rw-r--r--src/SFML/Window/Unix/ClipboardImpl.hpp78
-rw-r--r--src/SFML/Window/Unix/GlxExtensions.hpp3
-rw-r--r--src/SFML/Window/Unix/WindowImplX11.cpp307
-rw-r--r--src/SFML/Window/Unix/WindowImplX11.hpp34
-rwxr-xr-xsrc/SFML/Window/Win32/CursorImpl.cpp9
-rw-r--r--src/SFML/Window/iOS/SFAppDelegate.mm6
-rw-r--r--src/SFML/Window/iOS/SFView.mm6
-rw-r--r--src/SFML/Window/iOS/SFViewController.hpp8
-rw-r--r--src/SFML/Window/iOS/SFViewController.mm8
36 files changed, 987 insertions, 443 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index bb30b46..e821a49 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -32,9 +32,6 @@ endif()
if(NOT CMAKE_OSX_ARCHITECTURES)
set(CMAKE_OSX_ARCHITECTURES "x86_64" CACHE STRING "macOS architecture to build; 64-bit is expected" FORCE)
endif()
-if(NOT CMAKE_OSX_DEPLOYMENT_TARGET)
- set(CMAKE_OSX_DEPLOYMENT_TARGET "10.7" CACHE STRING "macOS deployement target; 10.7+ is expected" FORCE)
-endif()
if(NOT CMAKE_OSX_SYSROOT)
# query the path to the default SDK, will fail on non-macOS, but it's okay.
execute_process(COMMAND xcodebuild -sdk macosx -version Path
@@ -53,7 +50,7 @@ include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/Config.cmake)
# setup version numbers
set(VERSION_MAJOR 2)
set(VERSION_MINOR 5)
-set(VERSION_PATCH 0)
+set(VERSION_PATCH 1)
# add an option for choosing the build type (shared or static)
if(NOT (SFML_OS_IOS OR SFML_OS_ANDROID))
@@ -260,39 +257,10 @@ if(SFML_OS_MACOSX)
message(FATAL_ERROR "Only 64-bit architecture is supported")
endif()
- # Ensure macOS 10.7+ is used
- if(CMAKE_OSX_DEPLOYMENT_TARGET VERSION_LESS "10.7")
- message(FATAL_ERROR "macOS 10.7 or greater is required for the deployment target.")
- endif()
-
# configure Xcode templates
set(XCODE_TEMPLATES_ARCH "\$(NATIVE_ARCH_ACTUAL)")
endif()
-if(SFML_OS_LINUX OR SFML_OS_FREEBSD OR SFML_OS_OPENBSD)
- set(PKGCONFIG_DIR lib${LIB_SUFFIX}/pkgconfig)
- if(SFML_OS_FREEBSD OR SFML_OS_OPENBSD)
- set(PKGCONFIG_DIR libdata/pkgconfig)
- endif()
- if(BUILD_SHARED_LIBS)
- sfml_set_option(SFML_INSTALL_PKGCONFIG_FILES FALSE BOOL "TRUE to automatically install pkg-config files so other projects can find SFML")
- if(SFML_INSTALL_PKGCONFIG_FILES)
- foreach(sfml_module IN ITEMS all system window graphics audio network)
- CONFIGURE_FILE(
- "tools/pkg-config/sfml-${sfml_module}.pc.in"
- "tools/pkg-config/sfml-${sfml_module}.pc"
- @ONLY)
- INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/tools/pkg-config/sfml-${sfml_module}.pc"
- DESTINATION "${CMAKE_INSTALL_PREFIX}/${PKGCONFIG_DIR}")
- endforeach()
- endif()
- else()
- if(SFML_INSTALL_PKGCONFIG_FILES)
- message(WARNING "No pkg-config files are provided for the static SFML libraries (SFML_INSTALL_PKGCONFIG_FILES will be ignored).")
- endif()
- endif()
-endif()
-
# enable project folders
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set_property(GLOBAL PROPERTY PREDEFINED_TARGETS_FOLDER "CMake")
@@ -306,16 +274,25 @@ if(SFML_BUILD_DOC)
add_subdirectory(doc)
endif()
-sfml_set_option(SFML_INSTALL_PKGCONFIG_FILES FALSE BOOL "TRUE to automatically install pkg-config files so other projects can find SFML")
+# on Linux and BSD-like OS, install pkg-config files by default
+set(SFML_INSTALL_PKGCONFIG_DEFAULT FALSE)
+
+if(SFML_OS_LINUX OR SFML_OS_FREEBSD OR SFML_OS_OPENBSD)
+ set(SFML_INSTALL_PKGCONFIG_DEFAULT TRUE)
+endif()
+
+sfml_set_option(SFML_INSTALL_PKGCONFIG_FILES ${SFML_INSTALL_PKGCONFIG_DEFAULT} BOOL "TRUE to automatically install pkg-config files so other projects can find SFML")
+
+if(SFML_INSTALL_PKGCONFIG_FILES)
+ sfml_set_option(SFML_PKGCONFIG_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}/${SFML_PKGCONFIG_DIR}" PATH "Install directory for SFML's pkg-config .pc files")
-if(SFML_OS_SUPPORTS_PKGCONFIG OR SFML_INSTALL_PKGCONFIG_FILES)
foreach(sfml_module IN ITEMS all system window graphics audio network)
CONFIGURE_FILE(
"tools/pkg-config/sfml-${sfml_module}.pc.in"
"tools/pkg-config/sfml-${sfml_module}.pc"
@ONLY)
INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/tools/pkg-config/sfml-${sfml_module}.pc"
- DESTINATION "${CMAKE_INSTALL_PREFIX}/${SFML_OS_PKGCONFIG_DIR}")
+ DESTINATION "${SFML_PKGCONFIG_INSTALL_PREFIX}")
endforeach()
endif()
diff --git a/changelog.md b/changelog.md
index c51ee3a..6174a84 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,53 @@
# Changelog
+## SFML 2.5.1
+
+Also available on the website: https://www.sfml-dev.org/changelog.php#sfml-2.5.1
+
+### General
+
+ * Various CMake fixes (#1414, #1416, #1436, #1439, #1467, #1470)
+ * Fixed the installation of pkg-config files (#1466)
+ * Fixed two conversion warnings (#1454)
+ * [Android] Fixes all symbols in sfml-main are hidden (#1457, #1460)
+ * [Android] Fixed some `#define` flag problem (#1458)
+ * [Android] Fix deadlock in main cleanup (#1265)
+ * [iOS] Modernized toolchain file (#1411)
+ * [iOS] Check that `<SFML/Main.hpp>` is used (#1412)
+ * [macOS] Add `-ObjC` flag to fix static linking on macOS (#1485)
+
+### Window
+
+**Bugfixes**
+
+ * [iOS] Use default supported rotations when none are specified (#1417)
+ * [iOS] Fixed autocomplete window overlaps keyboard (#1473, #1482)
+ * [Linux] Fixed dual monitor issue (#1226, #1238)
+ * [Linux] Fixed issue where fullscreen window didn't go over task bars on top and left on in Ubuntu (#1224)
+ * [Linux] Fixed the Unix clipboard implementation causing an abort due to internal data races in Xlib (#1437)
+ * [macOS] Added additional system cursors (#1401, #1413, #1425)
+ * [Windows] Fixed swapped colors for custom cursors (#1464, #1465, #1491)
+
+### Graphics
+
+**Bugfixes**
+
+ * Fixed a bug in which a `sf::RenderTexture` would not be re-activated after being re-created (#1438)
+ * Fixed `sf::RenderTextureImplFBO`'s destructor incorrectly triggering deletion of other `sf::RenderTextureImplFBO`'s active FBOs (#1440)
+ * Fix `sf::RenderWindow::setActive` incorrectly trying to unbind an FBO during deactivation (#1442)
+ * Fixed `sf::RenderTexture::display()` dereferencing a NULL pointer when being called before `sf::RenderTexture::create()` (#1446)
+ * Fixed bug in `sf::Text` when applying an outline color/thickness (#1176)
+ * Squash duplicated `sf::Font` glyphs to single chars (#1461)
+ * Fixed two issues with glyph sub-pixel positioning (#1452)
+ * Reduced context locking & unlocking while creating textures (#1459)
+ * Fixed the error message when the wrong bitmap font size is selected (#1456, #1474, #1492)
+
+### Audio
+
+**Bugfixes**
+
+ * Fixed performance issue with reading WAV files (#1450)
+
## SFML 2.5.0
Also available on the website: https://www.sfml-dev.org/changelog.php#sfml-2.5.0
diff --git a/cmake/Config.cmake b/cmake/Config.cmake
index 82a094c..0a28660 100644
--- a/cmake/Config.cmake
+++ b/cmake/Config.cmake
@@ -69,17 +69,12 @@ else()
return()
endif()
-# check if OS or package system supports pkg-config
+# set pkgconfig install directory
# this could be e.g. macports on mac or msys2 on windows etc.
-find_package(PkgConfig QUIET)
-if(PKG_CONFIG_EXECUTABLE)
- if(EXISTS "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}/pkgconfig")
- set(SFML_OS_SUPPORTS_PKGCONFIG ON)
- set(SFML_OS_PKGCONFIG_DIR "/lib${LIB_SUFFIX}/pkgconfig")
- elseif(EXISTS "${CMAKE_INSTALL_PREFIX}/libdata/pkgconfig")
- set(SFML_OS_SUPPORTS_PKGCONFIG ON)
- set(SFML_OS_PKGCONFIG_DIR "/libdata/pkgconfig")
- endif()
+set(SFML_PKGCONFIG_DIR "/lib${LIB_SUFFIX}/pkgconfig")
+
+if(SFML_OS_FREEBSD OR SFML_OS_OPENBSD)
+ set(SFML_PKGCONFIG_DIR "/libdata/pkgconfig")
endif()
# detect the compiler and its version
diff --git a/cmake/Macros.cmake b/cmake/Macros.cmake
index be52345..ecb37c8 100644
--- a/cmake/Macros.cmake
+++ b/cmake/Macros.cmake
@@ -1,7 +1,12 @@
include(CMakeParseArguments)
+# This little macro lets you set any Xcode specific property
+macro (sfml_set_xcode_property TARGET XCODE_PROPERTY XCODE_VALUE)
+ set_property (TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY} ${XCODE_VALUE})
+endmacro ()
+
# set the appropriate standard library on each platform for the given target
-# ex: sfml_set_stdlib(sfml-system)
+# example: sfml_set_stdlib(sfml-system)
function(sfml_set_stdlib target)
# for gcc >= 4.0 on Windows, apply the SFML_USE_STATIC_STD_LIBS option if it is enabled
if(SFML_OS_WINDOWS AND SFML_COMPILER_GCC AND NOT SFML_GCC_VERSION VERSION_LESS "4")
@@ -14,7 +19,7 @@ function(sfml_set_stdlib target)
if (SFML_OS_MACOSX)
if (${CMAKE_GENERATOR} MATCHES "Xcode")
- set_property(TARGET ${target} PROPERTY XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++")
+ sfml_set_xcode_property(${target} CLANG_CXX_LIBRARY "libc++")
else()
target_compile_options(${target} PRIVATE "-stdlib=libc++")
target_link_libraries(${target} PRIVATE "-stdlib=libc++")
@@ -23,9 +28,9 @@ function(sfml_set_stdlib target)
endfunction()
# add a new target which is a SFML library
-# ex: sfml_add_library(sfml-graphics
-# SOURCES sprite.cpp image.cpp ...
-# [STATIC]) # Always create a static library and ignore BUILD_SHARED_LIBS
+# example: sfml_add_library(sfml-graphics
+# SOURCES sprite.cpp image.cpp ...
+# [STATIC]) # Always create a static library and ignore BUILD_SHARED_LIBS
macro(sfml_add_library target)
# parse the arguments
@@ -178,11 +183,11 @@ macro(sfml_add_library target)
endmacro()
# add a new target which is a SFML example
-# ex: sfml_add_example(ftp
-# SOURCES ftp.cpp ...
-# BUNDLE_RESOURCES MainMenu.nib ... # Files to be added in target but not installed next to the executable
-# DEPENDS sfml-network
-# RESOURCES_DIR resources) # A directory to install next to the executable and sources
+# example: sfml_add_example(ftp
+# SOURCES ftp.cpp ...
+# BUNDLE_RESOURCES MainMenu.nib ... # Files to be added in target but not installed next to the executable
+# DEPENDS sfml-network
+# RESOURCES_DIR resources) # A directory to install next to the executable and sources
macro(sfml_add_example target)
# parse the arguments
@@ -320,7 +325,7 @@ function(sfml_export_targets)
if (SFML_BUILD_FRAMEWORKS)
set(config_package_location "SFML.framework/Resources/CMake")
else()
- set(config_package_location lib/cmake/SFML)
+ set(config_package_location lib${LIB_SUFFIX}/cmake/SFML)
endif()
configure_package_config_file("${CURRENT_DIR}/SFMLConfig.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/SFMLConfig.cmake"
INSTALL_DESTINATION "${config_package_location}")
diff --git a/cmake/SFMLConfigDependencies.cmake.in b/cmake/SFMLConfigDependencies.cmake.in
index 2f85b38..1028110 100644
--- a/cmake/SFMLConfigDependencies.cmake.in
+++ b/cmake/SFMLConfigDependencies.cmake.in
@@ -13,7 +13,11 @@ if(SFML_STATIC_LIBRARIES)
elseif(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
set(FIND_SFML_OS_FREEBSD 1)
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
- set(FIND_SFML_OS_MACOSX 1)
+ if (DEFINED IOS)
+ set(FIND_SFML_OS_IOS 1)
+ else()
+ set(FIND_SFML_OS_MACOSX 1)
+ endif()
endif()
# start with an empty list
@@ -51,7 +55,7 @@ if(SFML_STATIC_LIBRARIES)
if (FIND_SFML_OS_WINDOWS)
set_property(TARGET OpenGL APPEND PROPERTY INTERFACE_LINK_LIBRARIES "OpenGL32")
- else()
+ elseif(NOT FIND_SFML_OS_IOS)
sfml_bind_dependency(TARGET OpenGL FRIENDLY_NAME "OpenGL" SEARCH_NAMES "OpenGL" "GL")
endif()
endif()
@@ -66,10 +70,12 @@ if(SFML_STATIC_LIBRARIES)
list(FIND SFML_FIND_COMPONENTS "audio" FIND_SFML_AUDIO_COMPONENT_INDEX)
if(FIND_SFML_AUDIO_COMPONENT_INDEX GREATER -1)
sfml_bind_dependency(TARGET OpenAL FRIENDLY_NAME "OpenAL" SEARCH_NAMES "OpenAL" "openal" "openal32")
- sfml_bind_dependency(TARGET Vorbis FRIENDLY_NAME "Ogg" SEARCH_NAMES "ogg")
+ if (NOT FIND_SFML_OS_IOS)
+ sfml_bind_dependency(TARGET Vorbis FRIENDLY_NAME "VorbisFile" SEARCH_NAMES "vorbisfile")
+ sfml_bind_dependency(TARGET Vorbis FRIENDLY_NAME "VorbisEnc" SEARCH_NAMES "vorbisenc")
+ endif()
sfml_bind_dependency(TARGET Vorbis FRIENDLY_NAME "Vorbis" SEARCH_NAMES "vorbis")
- sfml_bind_dependency(TARGET Vorbis FRIENDLY_NAME "VorbisFile" SEARCH_NAMES "vorbisfile")
- sfml_bind_dependency(TARGET Vorbis FRIENDLY_NAME "VorbisEnc" SEARCH_NAMES "vorbisenc")
+ sfml_bind_dependency(TARGET Vorbis FRIENDLY_NAME "Ogg" SEARCH_NAMES "ogg")
sfml_bind_dependency(TARGET FLAC FRIENDLY_NAME "FLAC" SEARCH_NAMES "FLAC")
endif()
diff --git a/cmake/toolchains/iOS.toolchain.cmake b/cmake/toolchains/iOS.toolchain.cmake
index abbff03..c697857 100644
--- a/cmake/toolchains/iOS.toolchain.cmake
+++ b/cmake/toolchains/iOS.toolchain.cmake
@@ -22,13 +22,13 @@
# OS - the default, used to build for iPhone and iPad physical devices, which have an arm arch.
# SIMULATOR - used to build for the Simulator platforms, which have an x86_64 arch.
#
-# CMAKE_IOS_DEVELOPER_ROOT = automatic(default) or /path/to/platform/Developer folder
+# IOS_DEVELOPER_ROOT = automatic(default) or /path/to/platform/Developer folder
# By default this location is automatcially chosen based on the IOS_PLATFORM value above.
# If set manually, it will override the default location and force the user of a particular Developer Platform
#
-# CMAKE_IOS_SDK_ROOT = automatic(default) or /path/to/platform/Developer/SDKs/SDK folder
-# By default this location is automatcially chosen based on the CMAKE_IOS_DEVELOPER_ROOT value.
-# In this case it will always be the most up-to-date SDK found in the CMAKE_IOS_DEVELOPER_ROOT path.
+# IOS_SDK_ROOT = automatic(default) or /path/to/platform/Developer/SDKs/SDK folder
+# By default this location is automatcially chosen based on the IOS_DEVELOPER_ROOT value.
+# In this case it will always be the most up-to-date SDK found in the IOS_DEVELOPER_ROOT path.
# If set manually, this will force the use of a specific SDK version
# Macros:
@@ -58,8 +58,8 @@ if (CMAKE_UNAME)
string (REGEX REPLACE "^([0-9]+)\\.([0-9]+).*$" "\\1" DARWIN_MAJOR_VERSION "${CMAKE_HOST_SYSTEM_VERSION}")
endif (CMAKE_UNAME)
-set(CMAKE_C_COMPILER /usr/bin/gcc CACHE FILEPATH "" FORCE)
-set(CMAKE_CXX_COMPILER /usr/bin/g++ CACHE FILEPATH "" FORCE)
+set(CMAKE_C_COMPILER /usr/bin/clang CACHE FILEPATH "" FORCE)
+set(CMAKE_CXX_COMPILER /usr/bin/clang++ CACHE FILEPATH "" FORCE)
set(CMAKE_AR ar CACHE FILEPATH "" FORCE)
# Skip the platform compiler checks for cross compiling
@@ -105,64 +105,43 @@ endif (NOT DEFINED CMAKE_INSTALL_NAME_TOOL)
if (NOT DEFINED IOS_PLATFORM)
set (IOS_PLATFORM "OS")
endif (NOT DEFINED IOS_PLATFORM)
-set (IOS_PLATFORM ${IOS_PLATFORM} CACHE STRING "Type of iOS Platform")
-
-# Setup building for arm64 or not
-if (NOT DEFINED BUILD_ARM64)
- set (BUILD_ARM64 true)
-endif (NOT DEFINED BUILD_ARM64)
-set (BUILD_ARM64 ${BUILD_ARM64} CACHE STRING "Build arm64 arch or not")
+set (IOS_PLATFORM ${IOS_PLATFORM} CACHE STRING "Type of iOS Platform: OS or SIMULATOR")
# Check the platform selection and setup for developer root
-if (${IOS_PLATFORM} STREQUAL OS)
- message (STATUS "Targeting iPhone platform")
+if (IOS_PLATFORM STREQUAL OS)
set (IOS_PLATFORM_LOCATION "iPhoneOS.platform")
# This causes the installers to properly locate the output libraries
set (CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphoneos")
-elseif (${IOS_PLATFORM} STREQUAL SIMULATOR)
- message (STATUS "Targeting iPhoneSimulator platform")
- set (SIMULATOR true)
+elseif (IOS_PLATFORM STREQUAL SIMULATOR)
set (IOS_PLATFORM_LOCATION "iPhoneSimulator.platform")
# This causes the installers to properly locate the output libraries
set (CMAKE_XCODE_EFFECTIVE_PLATFORMS "-iphonesimulator")
-
-else (${IOS_PLATFORM} STREQUAL OS)
- message (FATAL_ERROR "Unsupported IOS_PLATFORM value '${IOS_PLATFORM}' selected. Please choose OS or SIMULATOR")
-endif (${IOS_PLATFORM} STREQUAL OS)
-
-# Setup iOS developer location unless specified manually with CMAKE_IOS_DEVELOPER_ROOT
-# Note Xcode 4.3 changed the installation location, choose the most recent one available
-exec_program(/usr/bin/xcode-select ARGS -print-path OUTPUT_VARIABLE CMAKE_XCODE_DEVELOPER_DIR)
-set (XCODE_POST_43_ROOT "${CMAKE_XCODE_DEVELOPER_DIR}/Platforms/${IOS_PLATFORM_LOCATION}/Developer")
-set (XCODE_PRE_43_ROOT "/Developer/Platforms/${IOS_PLATFORM_LOCATION}/Developer")
-if (NOT DEFINED CMAKE_IOS_DEVELOPER_ROOT)
- if (EXISTS ${XCODE_POST_43_ROOT})
- set (CMAKE_IOS_DEVELOPER_ROOT ${XCODE_POST_43_ROOT})
- elseif(EXISTS ${XCODE_PRE_43_ROOT})
- set (CMAKE_IOS_DEVELOPER_ROOT ${XCODE_PRE_43_ROOT})
- endif (EXISTS ${XCODE_POST_43_ROOT})
-endif (NOT DEFINED CMAKE_IOS_DEVELOPER_ROOT)
-set (CMAKE_IOS_DEVELOPER_ROOT ${CMAKE_IOS_DEVELOPER_ROOT} CACHE PATH "Location of iOS Platform")
-
-# Find and use the most recent iOS sdk unless specified manually with CMAKE_IOS_SDK_ROOT
-if (NOT DEFINED CMAKE_IOS_SDK_ROOT)
- file (GLOB _CMAKE_IOS_SDKS "${CMAKE_IOS_DEVELOPER_ROOT}/SDKs/*")
- if (_CMAKE_IOS_SDKS)
- list (SORT _CMAKE_IOS_SDKS)
- list (REVERSE _CMAKE_IOS_SDKS)
- list (GET _CMAKE_IOS_SDKS 0 CMAKE_IOS_SDK_ROOT)
- else (_CMAKE_IOS_SDKS)
- message (FATAL_ERROR "No iOS SDK's found in default search path ${CMAKE_IOS_DEVELOPER_ROOT}. Manually set CMAKE_IOS_SDK_ROOT or install the iOS SDK.")
- endif (_CMAKE_IOS_SDKS)
- message (STATUS "Toolchain using default iOS SDK: ${CMAKE_IOS_SDK_ROOT}")
-endif (NOT DEFINED CMAKE_IOS_SDK_ROOT)
-set (CMAKE_IOS_SDK_ROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Location of the selected iOS SDK")
+else ()
+ message (FATAL_ERROR "Unsupported IOS_PLATFORM value '${IOS_PLATFORM}' selected. Please choose OS or SIMULATOR")
+endif ()
+
+# Setup iOS developer location unless specified manually with IOS_DEVELOPER_ROOT
+exec_program(/usr/bin/xcode-select ARGS -print-path OUTPUT_VARIABLE XCODE_DEVELOPER_DIR)
+set (IOS_DEVELOPER_ROOT "${XCODE_DEVELOPER_DIR}/Platforms/${IOS_PLATFORM_LOCATION}/Developer" CACHE PATH "Location of iOS Platform")
+
+# Find and use the most recent iOS sdk unless specified manually with IOS_SDK_ROOT
+if (NOT DEFINED IOS_SDK_ROOT)
+ file (GLOB _IOS_SDKS "${IOS_DEVELOPER_ROOT}/SDKs/*")
+ if (_IOS_SDKS)
+ list (SORT _IOS_SDKS)
+ list (REVERSE _IOS_SDKS)
+ list (GET _IOS_SDKS 0 IOS_SDK_ROOT)
+ else (_IOS_SDKS)
+ message (FATAL_ERROR "No iOS SDK's found in default search path ${IOS_DEVELOPER_ROOT}. Manually set IOS_SDK_ROOT or install the iOS SDK.")
+ endif (_IOS_SDKS)
+ message (STATUS "Toolchain using default iOS SDK: ${IOS_SDK_ROOT}")
+endif (NOT DEFINED IOS_SDK_ROOT)
+set (IOS_SDK_ROOT ${IOS_SDK_ROOT} CACHE PATH "Location of the selected iOS SDK")
# Set the sysroot default to the most recent SDK
-set (CMAKE_OSX_SYSROOT ${CMAKE_IOS_SDK_ROOT} CACHE PATH "Sysroot used for iOS support")
-message (STATUS "iOS sysroot=${CMAKE_OSX_SYSROOT}")
+set (CMAKE_OSX_SYSROOT ${IOS_SDK_ROOT} CACHE PATH "Sysroot used for iOS support")
# set the architecture for iOS
if (${IOS_PLATFORM} STREQUAL OS)
@@ -172,21 +151,19 @@ elseif (${IOS_PLATFORM} STREQUAL SIMULATOR)
set (IOS_ARCH x86_64)
endif (${IOS_PLATFORM} STREQUAL OS)
-set (CMAKE_OSX_ARCHITECTURES ${IOS_ARCH} CACHE string "Build architecture for iOS" FORCE)
-set (CMAKE_XCODE_ATTRIBUTE_VALID_ARCHS ${IOS_ARCH})
-message (STATUS "iOS architecture=${IOS_ARCH}")
+set (CMAKE_OSX_ARCHITECTURES ${IOS_ARCH} CACHE STRING "Build architecture for iOS" FORCE)
# Set the find root to the iOS developer roots and to user defined paths
-set (CMAKE_FIND_ROOT_PATH ${CMAKE_IOS_DEVELOPER_ROOT} ${CMAKE_IOS_SDK_ROOT} ${CMAKE_PREFIX_PATH} CACHE string "iOS find search path root")
+set (CMAKE_FIND_ROOT_PATH ${IOS_DEVELOPER_ROOT} ${IOS_SDK_ROOT} ${CMAKE_PREFIX_PATH} CACHE STRING "iOS find search path root")
# default to searching for frameworks first
set (CMAKE_FIND_FRAMEWORK FIRST)
# set up the default search directories for frameworks
set (CMAKE_SYSTEM_FRAMEWORK_PATH
- ${CMAKE_IOS_SDK_ROOT}/System/Library/Frameworks
- ${CMAKE_IOS_SDK_ROOT}/System/Library/PrivateFrameworks
- ${CMAKE_IOS_SDK_ROOT}/Developer/Library/Frameworks
+ ${IOS_SDK_ROOT}/System/Library/Frameworks
+ ${IOS_SDK_ROOT}/System/Library/PrivateFrameworks
+ ${IOS_SDK_ROOT}/Developer/Library/Frameworks
)
# only search the iOS sdks, not the remainder of the host filesystem
@@ -195,12 +172,6 @@ set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
-# This little macro lets you set any XCode specific property
-macro (set_xcode_property TARGET XCODE_PROPERTY XCODE_VALUE)
- set_property (TARGET ${TARGET} PROPERTY XCODE_ATTRIBUTE_${XCODE_PROPERTY} ${XCODE_VALUE})
-endmacro (set_xcode_property)
-
-
# This macro lets you find executable programs on the host system
macro (find_host_package)
set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
diff --git a/examples/android/app/src/main/jni/main.cpp b/examples/android/app/src/main/jni/main.cpp
index e5445b5..edf67b4 100644
--- a/examples/android/app/src/main/jni/main.cpp
+++ b/examples/android/app/src/main/jni/main.cpp
@@ -6,7 +6,8 @@
// Do we want to showcase direct JNI/NDK interaction?
// Undefine this to get real cross-platform code.
-#define USE_JNI
+// Uncomment this to try JNI access; this seems to be broken in latest NDKs
+//#define USE_JNI
#if defined(USE_JNI)
// These headers are only needed for direct NDK/JDK interaction
diff --git a/examples/cocoa/CMakeLists.txt b/examples/cocoa/CMakeLists.txt
index ff63cc0..dfa46be 100644
--- a/examples/cocoa/CMakeLists.txt
+++ b/examples/cocoa/CMakeLists.txt
@@ -20,7 +20,7 @@ function(compile_xib)
endif()
# Default args taken from Xcode 9 when it generates a nib from a xib
- set(DEFAULT_ARGS --errors --warnings --notices --module cocoa --auto-activate-custom-fonts --target-device mac --minimum-deployment-target ${CMAKE_OSX_DEPLOYMENT_TARGET} --output-format human-readable-text)
+ set(DEFAULT_ARGS --errors --warnings --notices --module cocoa --auto-activate-custom-fonts --target-device mac --output-format human-readable-text)
add_custom_command(OUTPUT "${THIS_OUTPUT}"
COMMAND "${IBTOOL}" ${DEFAULT_ARGS} "${THIS_INPUT}" --compile "${THIS_OUTPUT}"
diff --git a/examples/iOS/CMakeLists.txt b/examples/iOS/CMakeLists.txt
index 96450f4..24aca5f 100644
--- a/examples/iOS/CMakeLists.txt
+++ b/examples/iOS/CMakeLists.txt
@@ -21,5 +21,5 @@ sfml_add_example(ios_demo GUI_APP
"-framework OpenGLES")
# The app needs an identifier and signing to work correctly
-SET_XCODE_PROPERTY(ios_demo CODE_SIGN_IDENTITY "iPhone Developer")
+sfml_set_xcode_property(ios_demo CODE_SIGN_IDENTITY "iPhone Developer")
set(MACOSX_BUNDLE_GUI_IDENTIFIER "com.sfml.ios_demo")
diff --git a/include/SFML/Config.hpp b/include/SFML/Config.hpp
index aae5f54..40b677e 100644
--- a/include/SFML/Config.hpp
+++ b/include/SFML/Config.hpp
@@ -31,7 +31,7 @@
////////////////////////////////////////////////////////////
#define SFML_VERSION_MAJOR 2
#define SFML_VERSION_MINOR 5
-#define SFML_VERSION_PATCH 0
+#define SFML_VERSION_PATCH 1
////////////////////////////////////////////////////////////
diff --git a/include/SFML/System/FileInputStream.hpp b/include/SFML/System/FileInputStream.hpp
index 43618da..ca26797 100644
--- a/include/SFML/System/FileInputStream.hpp
+++ b/include/SFML/System/FileInputStream.hpp
@@ -35,7 +35,7 @@
#include <cstdio>
#include <string>
-#ifdef ANDROID
+#ifdef SFML_SYSTEM_ANDROID
namespace sf
{
namespace priv
@@ -122,7 +122,7 @@ private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
-#ifdef ANDROID
+#ifdef SFML_SYSTEM_ANDROID
priv::ResourceStream* m_file;
#else
std::FILE* m_file; ///< stdio file stream
diff --git a/include/SFML/Window/Clipboard.hpp b/include/SFML/Window/Clipboard.hpp
index 436da8f..50ea804 100644
--- a/include/SFML/Window/Clipboard.hpp
+++ b/include/SFML/Window/Clipboard.hpp
@@ -60,7 +60,12 @@ public:
/// This function sets the content of the clipboard as a
/// string.
///
- /// \param text sf::String containing the data to be sent
+ /// \warning Due to limitations on some operating systems,
+ /// setting the clipboard contents is only
+ /// guaranteed to work if there is currently an
+ /// open window for which events are being handled.
+ ///
+ /// \param text sf::String containing the data to be sent
/// to the clipboard
///
////////////////////////////////////////////////////////////
@@ -80,6 +85,11 @@ public:
/// sf::Clipboard provides an interface for getting and
/// setting the contents of the system clipboard.
///
+/// It is important to note that due to limitations on some
+/// operating systems, setting the clipboard contents is
+/// only guaranteed to work if there is currently an open
+/// window for which events are being handled.
+///
/// Usage example:
/// \code
/// // get the clipboard content as a string
@@ -96,11 +106,12 @@ public:
/// // Using Ctrl + V to paste a string into SFML
/// if(event.key.control && event.key.code == sf::Keyboard::V)
/// string = sf::Clipboard::getString();
+///
+/// // Using Ctrl + C to copy a string out of SFML
+/// if(event.key.control && event.key.code == sf::Keyboard::C)
+/// sf::Clipboard::setString("Hello World!");
/// }
/// }
-///
-/// // set the clipboard to a string
-/// sf::Clipboard::setString("Hello World!");
/// \endcode
///
/// \see sf::String, sf::Event
diff --git a/include/SFML/Window/Cursor.hpp b/include/SFML/Window/Cursor.hpp
index 30aebd4..9daa13b 100644
--- a/include/SFML/Window/Cursor.hpp
+++ b/include/SFML/Window/Cursor.hpp
@@ -62,13 +62,16 @@ public:
/// sf::Cursor::Hand | yes | yes | yes |
/// sf::Cursor::SizeHorizontal | yes | yes | yes |
/// sf::Cursor::SizeVertical | yes | yes | yes |
- /// sf::Cursor::SizeTopLeftBottomRight | no | no | yes |
- /// sf::Cursor::SizeBottomLeftTopRight | no | no | yes |
+ /// sf::Cursor::SizeTopLeftBottomRight | no | yes* | yes |
+ /// sf::Cursor::SizeBottomLeftTopRight | no | yes* | yes |
/// sf::Cursor::SizeAll | yes | no | yes |
/// sf::Cursor::Cross | yes | yes | yes |
- /// sf::Cursor::Help | yes | no | yes |
+ /// sf::Cursor::Help | yes | yes* | yes |
/// sf::Cursor::NotAllowed | yes | yes | yes |
///
+ /// * These cursor types are undocumented so may not
+ /// be available on all versions, but have been tested on 10.13
+ ///
////////////////////////////////////////////////////////////
enum Type
{
diff --git a/src/SFML/Audio/SoundFileReaderWav.cpp b/src/SFML/Audio/SoundFileReaderWav.cpp
index dc1dc52..84d92c1 100644
--- a/src/SFML/Audio/SoundFileReaderWav.cpp
+++ b/src/SFML/Audio/SoundFileReaderWav.cpp
@@ -155,7 +155,11 @@ Uint64 SoundFileReaderWav::read(Int16* samples, Uint64 maxCount)
assert(m_stream);
Uint64 count = 0;
- while ((count < maxCount) && (static_cast<Uint64>(m_stream->tell()) < m_dataEnd))
+ Uint64 startPos = m_stream->tell();
+
+ // Tracking of m_dataEnd is important to prevent sf::Music from reading
+ // data until EOF, as WAV files may have metadata at the end.
+ while ((count < maxCount) && (startPos + count * m_bytesPerSample < m_dataEnd))
{
switch (m_bytesPerSample)
{
diff --git a/src/SFML/Graphics/Font.cpp b/src/SFML/Graphics/Font.cpp
index 45f6baf..308070a 100644
--- a/src/SFML/Graphics/Font.cpp
+++ b/src/SFML/Graphics/Font.cpp
@@ -71,10 +71,10 @@ namespace
return output;
}
- // Combine outline thickness, boldness and codepoint into a single 64-bit key
- sf::Uint64 combine(float outlineThickness, bool bold, sf::Uint32 codePoint)
+ // Combine outline thickness, boldness and font glyph index into a single 64-bit key
+ sf::Uint64 combine(float outlineThickness, bool bold, sf::Uint32 index)
{
- return (static_cast<sf::Uint64>(reinterpret<sf::Uint32>(outlineThickness)) << 32) | (static_cast<sf::Uint64>(bold) << 31) | codePoint;
+ return (static_cast<sf::Uint64>(reinterpret<sf::Uint32>(outlineThickness)) << 32) | (static_cast<sf::Uint64>(bold) << 31) | index;
}
}
@@ -346,8 +346,8 @@ const Glyph& Font::getGlyph(Uint32 codePoint, unsigned int characterSize, bool b
// Get the page corresponding to the character size
GlyphTable& glyphs = m_pages[characterSize].glyphs;
- // Build the key by combining the code point, bold flag, and outline thickness
- Uint64 key = combine(outlineThickness, bold, codePoint);
+ // Build the key by combining the glyph index (based on code point), bold flag, and outline thickness
+ Uint64 key = combine(outlineThickness, bold, FT_Get_Char_Index(static_cast<FT_Face>(m_face), codePoint));
// Search the glyph into the cache
GlyphTable::const_iterator it = glyphs.find(key);
@@ -727,6 +727,7 @@ IntRect Font::findGlyphRect(Page& page, unsigned int width, unsigned int height)
// Make the texture 2 times bigger
Texture newTexture;
newTexture.create(textureWidth * 2, textureHeight * 2);
+ newTexture.setSmooth(true);
newTexture.update(page.texture);
page.texture.swap(newTexture);
}
@@ -776,17 +777,22 @@ bool Font::setCurrentSize(unsigned int characterSize) const
err() << "Failed to set bitmap font size to " << characterSize << std::endl;
err() << "Available sizes are: ";
for (int i = 0; i < face->num_fixed_sizes; ++i)
- err() << face->available_sizes[i].height << " ";
+ {
+ const unsigned int size = (face->available_sizes[i].y_ppem + 32) >> 6;
+ err() << size << " ";
+ }
err() << std::endl;
}
+ else
+ {
+ err() << "Failed to set font size to " << characterSize << std::endl;
+ }
}
return result == FT_Err_Ok;
}
- else
- {
- return true;
- }
+
+ return true;
}
diff --git a/src/SFML/Graphics/RenderTarget.cpp b/src/SFML/Graphics/RenderTarget.cpp
index 7eccf82..9a6e301 100644
--- a/src/SFML/Graphics/RenderTarget.cpp
+++ b/src/SFML/Graphics/RenderTarget.cpp
@@ -129,7 +129,7 @@ RenderTarget::RenderTarget() :
m_defaultView(),
m_view (),
m_cache (),
-m_id (getUniqueId())
+m_id (0)
{
m_cache.glStatesSet = false;
}
@@ -547,6 +547,10 @@ void RenderTarget::initialize()
// Set GL states only on first draw, so that we don't pollute user's states
m_cache.glStatesSet = false;
+
+ // Generate a unique ID for this RenderTarget to track
+ // whether it is active within a specific context
+ m_id = getUniqueId();
}
@@ -704,7 +708,7 @@ void RenderTarget::drawPrimitives(PrimitiveType type, std::size_t firstVertex, s
GLenum mode = modes[type];
// Draw the primitives
- glCheck(glDrawArrays(mode, firstVertex, static_cast<GLsizei>(vertexCount)));
+ glCheck(glDrawArrays(mode, static_cast<GLint>(firstVertex), static_cast<GLsizei>(vertexCount)));
}
diff --git a/src/SFML/Graphics/RenderTexture.cpp b/src/SFML/Graphics/RenderTexture.cpp
index 0805627..51abee9 100644
--- a/src/SFML/Graphics/RenderTexture.cpp
+++ b/src/SFML/Graphics/RenderTexture.cpp
@@ -161,7 +161,7 @@ bool RenderTexture::setActive(bool active)
void RenderTexture::display()
{
// Update the target texture
- if (priv::RenderTextureImplFBO::isAvailable() || setActive(true))
+ if (m_impl && (priv::RenderTextureImplFBO::isAvailable() || setActive(true)))
{
m_impl->updateTexture(m_texture.m_texture);
m_texture.m_pixelsFlipped = true;
diff --git a/src/SFML/Graphics/RenderTextureImplFBO.cpp b/src/SFML/Graphics/RenderTextureImplFBO.cpp
index 301aa04..c0debd7 100644
--- a/src/SFML/Graphics/RenderTextureImplFBO.cpp
+++ b/src/SFML/Graphics/RenderTextureImplFBO.cpp
@@ -53,6 +53,29 @@ namespace
// Mutex to protect both active and stale frame buffer sets
sf::Mutex mutex;
+ // This function is called either when a RenderTextureImplFBO is
+ // destroyed or via contextDestroyCallback when context destruction
+ // might trigger deletion of its contained stale FBOs
+ void destroyStaleFBOs()
+ {
+ sf::Uint64 contextId = sf::Context::getActiveContextId();
+
+ for (std::set<std::pair<sf::Uint64, unsigned int> >::iterator iter = staleFrameBuffers.begin(); iter != staleFrameBuffers.end();)
+ {
+ if (iter->first == contextId)
+ {
+ GLuint frameBuffer = static_cast<GLuint>(iter->second);
+ glCheck(GLEXT_glDeleteFramebuffers(1, &frameBuffer));
+
+ staleFrameBuffers.erase(iter++);
+ }
+ else
+ {
+ ++iter;
+ }
+ }
+ }
+
// Callback that is called every time a context is destroyed
void contextDestroyCallback(void* arg)
{
@@ -79,14 +102,7 @@ namespace
}
// Destroy stale frame buffer objects
- for (std::set<std::pair<sf::Uint64, unsigned int> >::iterator iter = staleFrameBuffers.begin(); iter != staleFrameBuffers.end(); ++iter)
- {
- if (iter->first == contextId)
- {
- GLuint frameBuffer = static_cast<GLuint>(iter->second);
- glCheck(GLEXT_glDeleteFramebuffers(1, &frameBuffer));
- }
- }
+ destroyStaleFBOs();
}
}
@@ -150,7 +166,7 @@ RenderTextureImplFBO::~RenderTextureImplFBO()
staleFrameBuffers.insert(std::make_pair(iter->first, iter->second));
// Clean up FBOs
- contextDestroyCallback(0);
+ destroyStaleFBOs();
// Delete the backup context if we had to create one
delete m_context;
diff --git a/src/SFML/Graphics/RenderWindow.cpp b/src/SFML/Graphics/RenderWindow.cpp
index 906363b..446e906 100644
--- a/src/SFML/Graphics/RenderWindow.cpp
+++ b/src/SFML/Graphics/RenderWindow.cpp
@@ -81,7 +81,7 @@ bool RenderWindow::setActive(bool active)
// If FBOs are available, make sure none are bound when we
// try to draw to the default framebuffer of the RenderWindow
- if (result && priv::RenderTextureImplFBO::isAvailable())
+ if (active && result && priv::RenderTextureImplFBO::isAvailable())
{
priv::RenderTextureImplFBO::unbind();
diff --git a/src/SFML/Graphics/Text.cpp b/src/SFML/Graphics/Text.cpp
index 3773616..6687551 100644
--- a/src/SFML/Graphics/Text.cpp
+++ b/src/SFML/Graphics/Text.cpp
@@ -50,15 +50,17 @@ namespace
// Add a glyph quad to the vertex array
void addGlyphQuad(sf::VertexArray& vertices, sf::Vector2f position, const sf::Color& color, const sf::Glyph& glyph, float italicShear, float outlineThickness = 0)
{
- float left = glyph.bounds.left;
- float top = glyph.bounds.top;
- float right = glyph.bounds.left + glyph.bounds.width;
- float bottom = glyph.bounds.top + glyph.bounds.height;
+ float padding = 1.0;
- float u1 = static_cast<float>(glyph.textureRect.left);
- float v1 = static_cast<float>(glyph.textureRect.top);
- float u2 = static_cast<float>(glyph.textureRect.left + glyph.textureRect.width);
- float v2 = static_cast<float>(glyph.textureRect.top + glyph.textureRect.height);
+ float left = glyph.bounds.left - padding;
+ float top = glyph.bounds.top - padding;
+ float right = glyph.bounds.left + glyph.bounds.width + padding;
+ float bottom = glyph.bounds.top + glyph.bounds.height + padding;
+
+ float u1 = static_cast<float>(glyph.textureRect.left) - padding;
+ float v1 = static_cast<float>(glyph.textureRect.top) - padding;
+ float u2 = static_cast<float>(glyph.textureRect.left + glyph.textureRect.width) + padding;
+ float v2 = static_cast<float>(glyph.textureRect.top + glyph.textureRect.height) + padding;
vertices.append(sf::Vertex(sf::Vector2f(position.x + left - italicShear * top - outlineThickness, position.y + top - outlineThickness), color, sf::Vector2f(u1, v1)));
vertices.append(sf::Vertex(sf::Vector2f(position.x + right - italicShear * top - outlineThickness, position.y + top - outlineThickness), color, sf::Vector2f(u2, v1)));
@@ -444,12 +446,15 @@ void Text::ensureGeometryUpdate() const
{
Uint32 curChar = m_string[i];
+ // Skip the \r char to avoid weird graphical issues
+ if (curChar == '\r')
+ continue;
+
// Apply the kerning offset
x += m_font->getKerning(prevChar, curChar, m_characterSize);
- prevChar = curChar;
// If we're using the underlined style and there's a new line, draw a line
- if (isUnderlined && (curChar == L'\n'))
+ if (isUnderlined && (curChar == L'\n' && prevChar != L'\n'))
{
addLine(m_vertices, x, y, m_fillColor, underlineOffset, underlineThickness);
@@ -458,7 +463,7 @@ void Text::ensureGeometryUpdate() const
}
// If we're using the strike through style and there's a new line, draw a line across all characters
- if (isStrikeThrough && (curChar == L'\n'))
+ if (isStrikeThrough && (curChar == L'\n' && prevChar != L'\n'))
{
addLine(m_vertices, x, y, m_fillColor, strikeThroughOffset, underlineThickness);
@@ -466,6 +471,8 @@ void Text::ensureGeometryUpdate() const
addLine(m_outlineVertices, x, y, m_outlineColor, strikeThroughOffset, underlineThickness, m_outlineThickness);
}
+ prevChar = curChar;
+
// Handle special characters
if ((curChar == L' ') || (curChar == L'\n') || (curChar == L'\t'))
{
diff --git a/src/SFML/Graphics/Texture.cpp b/src/SFML/Graphics/Texture.cpp
index faeef7d..fd94acf 100644
--- a/src/SFML/Graphics/Texture.cpp
+++ b/src/SFML/Graphics/Texture.cpp
@@ -129,6 +129,11 @@ bool Texture::create(unsigned int width, unsigned int height)
return false;
}
+ TransientContextLock lock;
+
+ // Make sure that extensions are initialized
+ priv::ensureExtensionsInit();
+
// Compute the internal texture dimensions depending on NPOT textures support
Vector2u actualSize(getValidSize(width), getValidSize(height));
@@ -150,8 +155,6 @@ bool Texture::create(unsigned int width, unsigned int height)
m_pixelsFlipped = false;
m_fboAttachment = false;
- TransientContextLock lock;
-
// Create the OpenGL texture if it doesn't exist yet
if (!m_texture)
{
@@ -160,9 +163,6 @@ bool Texture::create(unsigned int width, unsigned int height)
m_texture = static_cast<unsigned int>(texture);
}
- // Make sure that extensions are initialized
- priv::ensureExtensionsInit();
-
// Make sure that the current texture binding will be preserved
priv::TextureSaver save;
@@ -851,11 +851,6 @@ unsigned int Texture::getNativeHandle() const
////////////////////////////////////////////////////////////
unsigned int Texture::getValidSize(unsigned int size)
{
- TransientContextLock lock;
-
- // Make sure that extensions are initialized
- priv::ensureExtensionsInit();
-
if (GLEXT_texture_non_power_of_two)
{
// If hardware supports NPOT textures, then just return the unmodified size
diff --git a/src/SFML/Main/MainAndroid.cpp b/src/SFML/Main/MainAndroid.cpp
index fcb8500..5e62133 100644
--- a/src/SFML/Main/MainAndroid.cpp
+++ b/src/SFML/Main/MainAndroid.cpp
@@ -93,6 +93,13 @@ static void initializeMain(ActivityStates* states)
ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
states->looper = looper;
+ /**
+ * Acquire increments a reference counter on the looper. This keeps android
+ * from collecting it before the activity thread has a chance to detach its
+ * input queue.
+ */
+ ALooper_acquire(states->looper);
+
// Get the default configuration
states->config = AConfiguration_new();
AConfiguration_fromAssetManager(states->config, states->activity->assetManager);
@@ -338,7 +345,7 @@ static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* wind
// Wait for the event to be taken into account by SFML
states->updated = false;
- while(!states->updated)
+ while(!(states->updated | states->terminated))
{
states->mutex.unlock();
sf::sleep(sf::milliseconds(10));
@@ -363,7 +370,7 @@ static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* wi
// Wait for the event to be taken into account by SFML
states->updated = false;
- while(!states->updated)
+ while(!(states->updated | states->terminated))
{
states->mutex.unlock();
sf::sleep(sf::milliseconds(10));
@@ -410,8 +417,10 @@ static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue)
{
sf::Lock lock(states->mutex);
- states->inputQueue = NULL;
AInputQueue_detachLooper(queue);
+ states->inputQueue = NULL;
+
+ ALooper_release(states->looper);
}
}
@@ -464,7 +473,7 @@ static void onLowMemory(ANativeActivity* activity)
////////////////////////////////////////////////////////////
-void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_t savedStateSize)
+JNIEXPORT void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_t savedStateSize)
{
// Create an activity states (will keep us in the know, about events we care)
sf::priv::ActivityStates* states = NULL;
@@ -542,7 +551,7 @@ void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_
// Wait for the main thread to be initialized
states->mutex.lock();
- while (!states->initialized)
+ while (!(states->initialized | states->terminated))
{
states->mutex.unlock();
sf::sleep(sf::milliseconds(20));
diff --git a/src/SFML/Network/TcpSocket.cpp b/src/SFML/Network/TcpSocket.cpp
index e11f76b..d8effa1 100644
--- a/src/SFML/Network/TcpSocket.cpp
+++ b/src/SFML/Network/TcpSocket.cpp
@@ -246,7 +246,7 @@ Socket::Status TcpSocket::send(const void* data, std::size_t size, std::size_t&
for (sent = 0; sent < size; sent += result)
{
// Send a chunk of data
- result = ::send(getHandle(), static_cast<const char*>(data) + sent, size - sent, flags);
+ result = ::send(getHandle(), static_cast<const char*>(data) + sent, static_cast<int>(size - sent), flags);
// Check for errors
if (result < 0)
diff --git a/src/SFML/System/FileInputStream.cpp b/src/SFML/System/FileInputStream.cpp
index 852470d..89e77c4 100644
--- a/src/SFML/System/FileInputStream.cpp
+++ b/src/SFML/System/FileInputStream.cpp
@@ -26,7 +26,7 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/FileInputStream.hpp>
-#ifdef ANDROID
+#ifdef SFML_SYSTEM_ANDROID
#include <SFML/System/Android/ResourceStream.hpp>
#endif
@@ -44,7 +44,7 @@ FileInputStream::FileInputStream()
////////////////////////////////////////////////////////////
FileInputStream::~FileInputStream()
{
-#ifdef ANDROID
+#ifdef SFML_SYSTEM_ANDROID
if (m_file)
delete m_file;
#else
@@ -57,7 +57,7 @@ FileInputStream::~FileInputStream()
////////////////////////////////////////////////////////////
bool FileInputStream::open(const std::string& filename)
{
-#ifdef ANDROID
+#ifdef SFML_SYSTEM_ANDROID
if (m_file)
delete m_file;
m_file = new priv::ResourceStream(filename);
@@ -76,7 +76,7 @@ bool FileInputStream::open(const std::string& filename)
////////////////////////////////////////////////////////////
Int64 FileInputStream::read(void* data, Int64 size)
{
-#ifdef ANDROID
+#ifdef SFML_SYSTEM_ANDROID
return m_file->read(data, size);
#else
if (m_file)
@@ -90,7 +90,7 @@ Int64 FileInputStream::read(void* data, Int64 size)
////////////////////////////////////////////////////////////
Int64 FileInputStream::seek(Int64 position)
{
-#ifdef ANDROID
+#ifdef SFML_SYSTEM_ANDROID
return m_file->seek(position);
#else
if (m_file)
@@ -111,7 +111,7 @@ Int64 FileInputStream::seek(Int64 position)
////////////////////////////////////////////////////////////
Int64 FileInputStream::tell()
{
-#ifdef ANDROID
+#ifdef SFML_SYSTEM_ANDROID
return m_file->tell();
#else
if (m_file)
@@ -125,7 +125,7 @@ Int64 FileInputStream::tell()
////////////////////////////////////////////////////////////
Int64 FileInputStream::getSize()
{
-#ifdef ANDROID
+#ifdef SFML_SYSTEM_ANDROID
return m_file->getSize();
#else
if (m_file)
diff --git a/src/SFML/Window/CMakeLists.txt b/src/SFML/Window/CMakeLists.txt
index 916c1dc..98ea439 100644
--- a/src/SFML/Window/CMakeLists.txt
+++ b/src/SFML/Window/CMakeLists.txt
@@ -229,12 +229,24 @@ sfml_add_library(sfml-window
SOURCES ${SRC} ${PLATFORM_SRC})
target_link_libraries(sfml-window PUBLIC sfml-system)
+# When static linking on macOS, we need to add this flag for objective C to work
+if ((NOT BUILD_SHARED_LIBS) AND SFML_OS_MACOSX)
+ target_link_libraries(sfml-window PRIVATE -ObjC)
+endif()
+
# find and setup usage for external libraries
if(SFML_OS_LINUX OR SFML_OS_FREEBSD OR SFML_OPENBSD)
sfml_find_package(X11 INCLUDE "X11_INCLUDE_DIR" LINK "X11_X11_LIB" "X11_Xrandr_LIB")
target_link_libraries(sfml-window PRIVATE X11)
endif()
+# CMake 3.11 and later prefer to choose GLVND, but we choose legacy OpenGL for backward compability
+# (unless the OpenGL_GL_PREFERENCE was explicitly set)
+# See CMP0072 for more details (cmake --help-policy CMP0072)
+if ((NOT ${CMAKE_VERSION} VERSION_LESS 3.11) AND (NOT OpenGL_GL_PREFERENCE))
+ set(OpenGL_GL_PREFERENCE "LEGACY")
+endif()
+
if(SFML_OPENGL_ES)
if(SFML_OS_IOS)
target_link_libraries(sfml-window PRIVATE "-framework OpenGLES")
@@ -242,7 +254,7 @@ if(SFML_OPENGL_ES)
target_link_libraries(sfml-window PRIVATE EGL GLESv1_CM)
endif()
else()
- sfml_find_package(OpenGL INCLUDE "OPENGL_INCLUDE_DIR" LINK "OPENGL_gl_LIBRARY")
+ sfml_find_package(OpenGL INCLUDE "OPENGL_INCLUDE_DIR" LINK "OPENGL_LIBRARIES")
target_link_libraries(sfml-window PRIVATE OpenGL)
endif()
diff --git a/src/SFML/Window/OSX/CursorImpl.mm b/src/SFML/Window/OSX/CursorImpl.mm
index 5f41376..ed905ef 100644
--- a/src/SFML/Window/OSX/CursorImpl.mm
+++ b/src/SFML/Window/OSX/CursorImpl.mm
@@ -32,6 +32,21 @@
#import <SFML/Window/OSX/NSImage+raw.h>
#import <AppKit/AppKit.h>
+namespace
+{
+
+////////////////////////////////////////////////////////////
+NSCursor* loadFromSelector(SEL selector)
+{
+ // The caller is responsible for retaining the cursor.
+ if ([NSCursor respondsToSelector:selector])
+ return [NSCursor performSelector:selector];
+ else
+ return nil;
+}
+
+}
+
namespace sf
{
namespace priv
@@ -56,6 +71,8 @@ CursorImpl::~CursorImpl()
////////////////////////////////////////////////////////////
bool CursorImpl::loadFromPixels(const Uint8* pixels, Vector2u size, Vector2u hotspot)
{
+ [m_cursor release];
+
NSSize nssize = NSMakeSize(size.x, size.y);
NSImage* image = [NSImage imageWithRawData:pixels andSize:nssize];
NSPoint nshotspot = NSMakePoint(hotspot.x, hotspot.y);
@@ -65,10 +82,11 @@ bool CursorImpl::loadFromPixels(const Uint8* pixels, Vector2u size, Vector2u hot
return m_cursor != nil;
}
-
////////////////////////////////////////////////////////////
bool CursorImpl::loadFromSystem(Cursor::Type type)
{
+ [m_cursor release];
+
switch (type)
{
default: return false;
@@ -80,14 +98,28 @@ bool CursorImpl::loadFromSystem(Cursor::Type type)
case Cursor::SizeVertical: m_cursor = [NSCursor resizeUpDownCursor]; break;
case Cursor::Cross: m_cursor = [NSCursor crosshairCursor]; break;
case Cursor::NotAllowed: m_cursor = [NSCursor operationNotAllowedCursor]; break;
+
+ // These cursor types are undocumented, may not be available on some platforms
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wundeclared-selector"
+ case Cursor::SizeBottomLeftTopRight:
+ m_cursor = loadFromSelector(@selector(_windowResizeNorthEastSouthWestCursor));
+ break;
+
+ case Cursor::SizeTopLeftBottomRight:
+ m_cursor = loadFromSelector(@selector(_windowResizeNorthWestSouthEastCursor));
+ break;
+
+ case Cursor::Help:
+ m_cursor = loadFromSelector(@selector(_helpCursor));
+ break;
+#pragma clang diagnostic pop
}
- // Since we didn't allocate the cursor ourself, we have to retain it
- // in order to not break the retain count.
- [m_cursor retain];
+ if (m_cursor)
+ [m_cursor retain];
- // For all non-default cases, it was a success.
- return true;
+ return m_cursor != nil;
}
diff --git a/src/SFML/Window/Unix/ClipboardImpl.cpp b/src/SFML/Window/Unix/ClipboardImpl.cpp
index 32ef21b..df2fd95 100644
--- a/src/SFML/Window/Unix/ClipboardImpl.cpp
+++ b/src/SFML/Window/Unix/ClipboardImpl.cpp
@@ -27,233 +27,356 @@
////////////////////////////////////////////////////////////
#include <SFML/Window/Unix/ClipboardImpl.hpp>
#include <SFML/Window/Unix/Display.hpp>
-#include <SFML/System/String.hpp>
-#include <SFML/System/Sleep.hpp>
-#include <iostream>
-#include <string>
-#include <X11/Xlib.h>
+#include <SFML/System/Clock.hpp>
+#include <SFML/System/Err.hpp>
+#include <X11/Xatom.h>
+#include <vector>
namespace
{
+ // Filter the events received by windows (only allow those matching a specific window)
+ Bool checkEvent(::Display*, XEvent* event, XPointer userData)
+ {
+ // Just check if the event matches the window
+ return event->xany.window == reinterpret_cast< ::Window >(userData);
+ }
+}
+
+namespace sf
+{
+namespace priv
+{
+
////////////////////////////////////////////////////////////
-void initClipboard();
-void* hostSelection(void*);
+String ClipboardImpl::getString()
+{
+ return getInstance().getStringImpl();
+}
-sf::String string;
-pthread_mutex_t mutex;
-pthread_t host_thread;
+////////////////////////////////////////////////////////////
+void ClipboardImpl::setString(const String& text)
+{
+ getInstance().setStringImpl(text);
+}
-bool is_fail = false;
-bool is_init = false;
-bool is_host = false;
-Display* display = NULL;
-Window window = 0;
+////////////////////////////////////////////////////////////
+void ClipboardImpl::processEvents()
+{
+ getInstance().processEventsImpl();
+}
-Atom selection = 0;
-Atom atom_targ = 0;
-Atom atom_text = 0;
-Atom utf8_text = 0;
-int xa_string = 31;
-int xa_atom = 4;
////////////////////////////////////////////////////////////
-void initClipboard()
+ClipboardImpl::ClipboardImpl() :
+m_window (0),
+m_requestResponded(false)
{
- is_init = true;
+ // Open a connection with the X server
+ m_display = OpenDisplay();
- display = XOpenDisplay(NULL);
- int screen = DefaultScreen(display);
- window = XCreateSimpleWindow(display, RootWindow(display, screen),
- 0, 0, 1, 1, 0, BlackPixel(display, screen), WhitePixel(display, screen));
+ // Get the atoms we need to make use of the clipboard
+ m_clipboard = getAtom("CLIPBOARD", false);
+ m_targets = getAtom("TARGETS", false);
+ m_text = getAtom("TEXT", false);
+ m_utf8String = getAtom("UTF8_STRING", true );
+ m_targetProperty = getAtom("SFML_CLIPBOARD_TARGET_PROPERTY", false);
- selection = XInternAtom(display, "CLIPBOARD", false);
- atom_targ = XInternAtom(display, "TARGETS", false);
- atom_text = XInternAtom(display, "TEXT", false);
- utf8_text = XInternAtom(display, "UTF8_STRING", true);
+ // Create a hidden window that will broker our clipboard interactions with X
+ m_window = XCreateSimpleWindow(m_display, DefaultRootWindow(m_display), 0, 0, 1, 1, 0, 0, 0);
- if(utf8_text == None)
- {
- std::cerr << "UTF-8 format unavailable on clipboard." << std::endl;
- utf8_text = xa_string;
- }
+ // Register the events we are interested in
+ XSelectInput(m_display, m_window, SelectionNotify | SelectionClear | SelectionRequest);
+}
- if(pthread_mutex_init(&mutex, NULL))
- {
- is_fail = true;
- std::cerr << "Unable to initialize mutex. Failed to initialize clipboard." << std::endl;
- return;
- }
- if(pthread_create(&host_thread, NULL, hostSelection, NULL))
+////////////////////////////////////////////////////////////
+ClipboardImpl::~ClipboardImpl()
+{
+ // Destroy the window
+ if (m_window)
{
- is_fail = true;
- std::cerr << "Unable to create host thread. Failed to initialize clipboard." << std::endl;
- return;
+ XDestroyWindow(m_display, m_window);
+ XFlush(m_display);
}
+
+ // Close the connection with the X server
+ CloseDisplay(m_display);
}
+
////////////////////////////////////////////////////////////
-void* hostSelection(void*)
+ClipboardImpl& ClipboardImpl::getInstance()
{
- while(true)
- {
- if(XPending(display) && is_host)
- {
- XEvent event;
+ static ClipboardImpl instance;
- pthread_mutex_lock(&mutex);
- XNextEvent(display, &event);
- pthread_mutex_unlock(&mutex);
+ return instance;
+}
- switch(event.type)
- {
- case SelectionClear:
- {
- pthread_mutex_lock(&mutex);
- is_host = false;
- pthread_mutex_unlock(&mutex);
- break;
- }
- case SelectionRequest:
- {
- if(event.xselectionrequest.selection == selection)
- {
- XSelectionRequestEvent* sel_req_event = &event.xselectionrequest;
- XSelectionEvent sel_event = {0};
-
- int result = 0;
- sel_event.type = SelectionNotify,
- sel_event.display = sel_req_event->display,
- sel_event.requestor = sel_req_event->requestor,
- sel_event.selection = sel_req_event->selection,
- sel_event.time = sel_req_event->time,
- sel_event.target = sel_req_event->target,
- sel_event.property = sel_req_event->property;
-
- std::basic_string<unsigned char> str = string.toUtf8();
-
- if(sel_event.target == atom_targ)
- result = XChangeProperty(sel_event.display, sel_event.requestor,
- sel_event.property, xa_atom, 32, PropModeReplace,
- reinterpret_cast<unsigned char*>(&utf8_text), 1);
- else if(sel_event.target == xa_string || sel_event.target == atom_text)
- result = XChangeProperty(sel_event.display, sel_event.requestor,
- sel_event.property, xa_string, 8, PropModeReplace,
- reinterpret_cast<unsigned char*>(&str[0]), str.size());
- else if(sel_event.target == utf8_text)
- result = XChangeProperty(sel_event.display, sel_event.requestor,
- sel_event.property, utf8_text, 8, PropModeReplace,
- reinterpret_cast<unsigned char*>(&str[0]), str.size());
- else
- sel_event.property = None;
-
- if((result & 2) == 0)
- XSendEvent(display, sel_event.requestor, 0, 0,
- reinterpret_cast<XEvent*>(&sel_event));
- }
- break;
- }
- default: break;
- }
- }
- else
- sf::sleep(sf::milliseconds(20));
+////////////////////////////////////////////////////////////
+String ClipboardImpl::getStringImpl()
+{
+ // Check if anybody owns the current selection
+ if (XGetSelectionOwner(m_display, m_clipboard) == None)
+ {
+ m_clipboardContents.clear();
+
+ return m_clipboardContents;
}
-}
+
+ // Process any already pending events
+ processEvents();
+
+ m_requestResponded = false;
+
+ // Request the current selection to be converted to UTF-8 (or STRING
+ // if UTF-8 is not available) and written to our window property
+ XConvertSelection(
+ m_display,
+ m_clipboard,
+ (m_utf8String != None) ? m_utf8String : XA_STRING,
+ m_targetProperty,
+ m_window,
+ CurrentTime
+ );
+
+ Clock clock;
+
+ // Wait for a response for up to 1000ms
+ while (!m_requestResponded && (clock.getElapsedTime().asMilliseconds() < 1000))
+ processEvents();
+
+ // If no response was received within the time period, clear our clipboard contents
+ if (!m_requestResponded)
+ m_clipboardContents.clear();
+
+ return m_clipboardContents;
}
-namespace sf
-{
-namespace priv
-{
////////////////////////////////////////////////////////////
-String ClipboardImpl::getString()
+void ClipboardImpl::setStringImpl(const String& text)
{
- if(!is_init)
- initClipboard();
+ m_clipboardContents = text;
+
+ // Set our window as the current owner of the selection
+ XSetSelectionOwner(m_display, m_clipboard, m_window, CurrentTime);
- if(is_fail || is_host)
- return string;
+ // Check if setting the selection owner was successful
+ if (XGetSelectionOwner(m_display, m_clipboard) != m_window)
+ err() << "Cannot set clipboard string: Unable to get ownership of X selection" << std::endl;
+}
- // Dangerous! Wipes all previous events!
- XSync(display, true);
- XConvertSelection(display, selection, utf8_text, atom_text, window, CurrentTime);
+////////////////////////////////////////////////////////////
+void ClipboardImpl::processEventsImpl()
+{
XEvent event;
- pthread_mutex_lock(&mutex);
- XNextEvent(display, &event);
- pthread_mutex_unlock(&mutex);
+ // Pick out the events that are interesting for this window
+ while (XCheckIfEvent(m_display, &event, &checkEvent, reinterpret_cast<XPointer>(m_window)))
+ m_events.push_back(event);
- if(event.type == SelectionNotify)
+ // Handle the events for this window that we just picked out
+ while (!m_events.empty())
{
- if(event.xselection.selection != selection || event.xselection.target != utf8_text)
+ event = m_events.front();
+ m_events.pop_front();
+ processEvent(event);
+ }
+}
+
+
+////////////////////////////////////////////////////////////
+void ClipboardImpl::processEvent(XEvent& windowEvent)
+{
+ switch (windowEvent.type)
+ {
+ case SelectionClear:
{
- std::cerr << "Failed to convert selection." << std::endl;
- return string;
+ // We don't have any resources we need to clean up
+ // when losing selection ownership so we don't do
+ // anything when we receive SelectionClear
+ // We will still respond to any future SelectionRequest
+ // events since doing so doesn't really do any harm
+ break;
}
-
- if(event.xselection.property)
+ case SelectionNotify:
{
- Atom target;
- int format;
- unsigned long size;
- unsigned long byte_left;
- unsigned char* data;
+ // Notification that the current selection owner
+ // has responded to our request
+
+ XSelectionEvent& selectionEvent = *reinterpret_cast<XSelectionEvent*>(&windowEvent.xselection);
- XGetWindowProperty(event.xselection.display,
- event.xselection.requestor, event.xselection.property,
- 0L, (~0L), false, AnyPropertyType,
- &target, &format, &size, &byte_left, &data);
+ m_clipboardContents.clear();
- if(target == utf8_text)
+ // If retrieving the selection fails or conversion is unsuccessful
+ // we leave the contents of the clipboard empty since we don't
+ // own it and we don't know what it could currently be
+ if ((selectionEvent.property == None) || (selectionEvent.selection != m_clipboard))
+ break;
+
+ Atom type;
+ int format;
+ unsigned long items;
+ unsigned long remainingBytes;
+ unsigned char* data = 0;
+
+ // The selection owner should have wrote the selection
+ // data to the specified window property
+ int result = XGetWindowProperty(
+ m_display,
+ m_window,
+ m_targetProperty,
+ 0,
+ 0x7fffffff,
+ False,
+ AnyPropertyType,
+ &type,
+ &format,
+ &items,
+ &remainingBytes,
+ &data
+ );
+
+ if (result == Success)
{
- std::basic_string<unsigned char> str(data, size);
- string = sf::String::fromUtf8(str.begin(), str.end());
+ // We don't support INCR for now
+ // It is very unlikely that this will be returned
+ // for purely text data transfer anyway
+ if (type != getAtom("INCR", false))
+ {
+ // Only copy the data if the format is what we expect
+ if ((type == m_utf8String) && (format == 8))
+ {
+ m_clipboardContents = String::fromUtf8(data, data + items);
+ }
+ else if ((type == XA_STRING) && (format == 8))
+ {
+ // Convert from ANSI std::string to sf::String
+ m_clipboardContents = std::string(data, data + items);
+ }
+ }
XFree(data);
+
+ // The selection requestor must always delete the property themselves
+ XDeleteProperty(m_display, m_window, m_targetProperty);
}
- XDeleteProperty(event.xselection.display, event.xselection.requestor, event.xselection.property);
+ m_requestResponded = true;
+
+ break;
}
- }
+ case SelectionRequest:
+ {
+ // Respond to a request for our clipboard contents
+ XSelectionRequestEvent& selectionRequestEvent = *reinterpret_cast<XSelectionRequestEvent*>(&windowEvent.xselectionrequest);
- return string;
-}
+ // Our reply
+ XSelectionEvent selectionEvent;
+ selectionEvent.type = SelectionNotify;
+ selectionEvent.requestor = selectionRequestEvent.requestor;
+ selectionEvent.selection = selectionRequestEvent.selection;
+ selectionEvent.property = selectionRequestEvent.property;
+ selectionEvent.time = selectionRequestEvent.time;
-////////////////////////////////////////////////////////////
-void ClipboardImpl::setString(const String& text)
-{
- if(!is_init)
- initClipboard();
+ if (selectionRequestEvent.selection == m_clipboard)
+ {
+ if (selectionRequestEvent.target == m_targets)
+ {
+ // Respond to a request for our valid conversion targets
+ std::vector<Atom> targets;
- if(is_fail)
- return;
+ targets.push_back(m_targets);
+ targets.push_back(m_text);
+ targets.push_back(XA_STRING);
- if(!is_host)
- {
- XSetSelectionOwner(display, selection, window, CurrentTime);
+ if (m_utf8String != None)
+ targets.push_back(m_utf8String);
- if(XGetSelectionOwner(display, selection) != window)
- {
- std::cerr << "Unable to get ownership of selection." << std::endl;
- return;
- }
+ XChangeProperty(
+ m_display,
+ selectionRequestEvent.requestor,
+ selectionRequestEvent.property,
+ XA_ATOM,
+ 32,
+ PropModeReplace,
+ reinterpret_cast<unsigned char*>(&targets[0]),
+ targets.size()
+ );
- pthread_mutex_lock(&mutex);
- is_host = true;
- pthread_mutex_unlock(&mutex);
- }
+ // Notify the requestor that they can read the targets from their window property
+ selectionEvent.target = m_targets;
+
+ XSendEvent(m_display, selectionRequestEvent.requestor, True, NoEventMask, reinterpret_cast<XEvent*>(&selectionEvent));
+
+ break;
+ }
+ else if ((selectionRequestEvent.target == XA_STRING) || ((m_utf8String == None) && (selectionRequestEvent.target == m_text)))
+ {
+ // Respond to a request for conversion to a Latin-1 string
+ std::string data = m_clipboardContents.toAnsiString();
+
+ XChangeProperty(
+ m_display,
+ selectionRequestEvent.requestor,
+ selectionRequestEvent.property,
+ XA_STRING,
+ 8,
+ PropModeReplace,
+ reinterpret_cast<const unsigned char*>(data.c_str()),
+ data.size()
+ );
- pthread_mutex_lock(&mutex);
- string = text;
- pthread_mutex_unlock(&mutex);
+ // Notify the requestor that they can read the data from their window property
+ selectionEvent.target = XA_STRING;
+
+ XSendEvent(m_display, selectionRequestEvent.requestor, True, NoEventMask, reinterpret_cast<XEvent*>(&selectionEvent));
+
+ break;
+ }
+ else if ((m_utf8String != None) && ((selectionRequestEvent.target == m_utf8String) || (selectionRequestEvent.target == m_text)))
+ {
+ // Respond to a request for conversion to a UTF-8 string
+ // or an encoding of our choosing (we always choose UTF-8)
+ std::basic_string<Uint8> data = m_clipboardContents.toUtf8();
+
+ XChangeProperty(
+ m_display,
+ selectionRequestEvent.requestor,
+ selectionRequestEvent.property,
+ m_utf8String,
+ 8,
+ PropModeReplace,
+ reinterpret_cast<const unsigned char*>(data.c_str()),
+ data.size()
+ );
+
+ // Notify the requestor that they can read the data from their window property
+ selectionEvent.target = m_utf8String;
+
+ XSendEvent(m_display, selectionRequestEvent.requestor, True, NoEventMask, reinterpret_cast<XEvent*>(&selectionEvent));
+
+ break;
+ }
+ }
+
+ // Notify the requestor that we could not respond to their request
+ selectionEvent.target = selectionRequestEvent.target;
+ selectionEvent.property = None;
+
+ XSendEvent(m_display, selectionRequestEvent.requestor, True, NoEventMask, reinterpret_cast<XEvent*>(&selectionEvent));
+
+ break;
+ }
+ default:
+ break;
+ }
}
} // namespace priv
diff --git a/src/SFML/Window/Unix/ClipboardImpl.hpp b/src/SFML/Window/Unix/ClipboardImpl.hpp
index f4aca98..48ec787 100644
--- a/src/SFML/Window/Unix/ClipboardImpl.hpp
+++ b/src/SFML/Window/Unix/ClipboardImpl.hpp
@@ -29,6 +29,8 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/String.hpp>
+#include <X11/Xlib.h>
+#include <deque>
namespace sf
@@ -67,6 +69,82 @@ public:
///
////////////////////////////////////////////////////////////
static void setString(const String& text);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Process pending events for the hidden clipboard window
+ ///
+ /// This function has to be called as part of normal window
+ /// event processing in order for our application to respond
+ /// to selection requests from other applications.
+ ///
+ ////////////////////////////////////////////////////////////
+ static void processEvents();
+
+private:
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Constructor
+ ///
+ ////////////////////////////////////////////////////////////
+ ClipboardImpl();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Destructor
+ ///
+ ////////////////////////////////////////////////////////////
+ ~ClipboardImpl();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Get singleton instance
+ ///
+ /// \return Singleton instance
+ ///
+ ////////////////////////////////////////////////////////////
+ static ClipboardImpl& getInstance();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief getString implementation
+ ///
+ /// \return Current content of the clipboard
+ ///
+ ////////////////////////////////////////////////////////////
+ String getStringImpl();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief setString implementation
+ ///
+ /// \param text sf::String object containing the data to be sent to the clipboard
+ ///
+ ////////////////////////////////////////////////////////////
+ void setStringImpl(const String& text);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief processEvents implementation
+ ///
+ ////////////////////////////////////////////////////////////
+ void processEventsImpl();
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Process an incoming event from the window
+ ///
+ /// \param windowEvent Event which has been received
+ ///
+ ////////////////////////////////////////////////////////////
+ void processEvent(XEvent& windowEvent);
+
+ ////////////////////////////////////////////////////////////
+ // Member data
+ ////////////////////////////////////////////////////////////
+ ::Window m_window; ///< X identifier defining our window
+ ::Display* m_display; ///< Pointer to the display
+ Atom m_clipboard; ///< X Atom identifying the CLIPBOARD selection
+ Atom m_targets; ///< X Atom identifying TARGETS
+ Atom m_text; ///< X Atom identifying TEXT
+ Atom m_utf8String; ///< X Atom identifying UTF8_STRING
+ Atom m_targetProperty; ///< X Atom identifying our destination window property
+ String m_clipboardContents; ///< Our clipboard contents
+ std::deque<XEvent> m_events; ///< Queue we use to store pending events for this window
+ bool m_requestResponded; ///< Holds whether our selection request has been responded to or not
};
} // namespace priv
diff --git a/src/SFML/Window/Unix/GlxExtensions.hpp b/src/SFML/Window/Unix/GlxExtensions.hpp
index abbb132..fb2c7da 100644
--- a/src/SFML/Window/Unix/GlxExtensions.hpp
+++ b/src/SFML/Window/Unix/GlxExtensions.hpp
@@ -25,11 +25,12 @@
#ifndef SF_POINTER_C_GENERATED_HEADER_GLXWIN_HPP
#define SF_POINTER_C_GENERATED_HEADER_GLXWIN_HPP
-#ifdef __glxext_h_
+#if defined(__glxext_h_) || defined(__glx_glxext_h_)
#error Attempt to include glx_exts after including glxext.h
#endif
#define __glxext_h_
+#define __glx_glxext_h_
#include <X11/Xlib.h>
#include <X11/Xutil.h>
diff --git a/src/SFML/Window/Unix/WindowImplX11.cpp b/src/SFML/Window/Unix/WindowImplX11.cpp
index e2c8d29..da69750 100644
--- a/src/SFML/Window/Unix/WindowImplX11.cpp
+++ b/src/SFML/Window/Unix/WindowImplX11.cpp
@@ -26,6 +26,7 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Window/Unix/WindowImplX11.hpp>
+#include <SFML/Window/Unix/ClipboardImpl.hpp>
#include <SFML/Window/Unix/Display.hpp>
#include <SFML/Window/Unix/InputImpl.hpp>
#include <SFML/System/Utf.hpp>
@@ -173,7 +174,7 @@ namespace
if (result != Success || actualType != XA_WINDOW || numItems != 1)
{
- if(result == Success)
+ if (result == Success)
XFree(data);
sf::priv::CloseDisplay(display);
@@ -205,7 +206,7 @@ namespace
if (result != Success || actualType != XA_WINDOW || numItems != 1)
{
- if(result == Success)
+ if (result == Success)
XFree(data);
sf::priv::CloseDisplay(display);
@@ -269,7 +270,7 @@ namespace
windowManagerName = sf::String::fromUtf8(begin, end);
}
- if(result == Success)
+ if (result == Success)
XFree(data);
sf::priv::CloseDisplay(display);
@@ -486,6 +487,7 @@ m_inputMethod (NULL),
m_inputContext (NULL),
m_isExternal (true),
m_oldVideoMode (0),
+m_oldRRCrtc (0),
m_hiddenCursor (0),
m_lastCursor (None),
m_keyRepeat (true),
@@ -534,6 +536,7 @@ m_inputMethod (NULL),
m_inputContext (NULL),
m_isExternal (false),
m_oldVideoMode (0),
+m_oldRRCrtc (0),
m_hiddenCursor (0),
m_lastCursor (None),
m_keyRepeat (true),
@@ -555,8 +558,17 @@ m_lastInputTime (0)
m_screen = DefaultScreen(m_display);
// Compute position and size
- int left = m_fullscreen ? 0 : (DisplayWidth(m_display, m_screen) - mode.width) / 2;
- int top = m_fullscreen ? 0 : (DisplayHeight(m_display, m_screen) - mode.height) / 2;
+ Vector2i windowPosition;
+ if(m_fullscreen)
+ {
+ windowPosition = getPrimaryMonitorPosition();
+ }
+ else
+ {
+ windowPosition.x = (DisplayWidth(m_display, m_screen) - mode.width) / 2;
+ windowPosition.y = (DisplayWidth(m_display, m_screen) - mode.height) / 2;
+ }
+
int width = mode.width;
int height = mode.height;
@@ -571,7 +583,7 @@ m_lastInputTime (0)
m_window = XCreateWindow(m_display,
DefaultRootWindow(m_display),
- left, top,
+ windowPosition.x, windowPosition.y,
width, height,
0,
visualInfo.depth,
@@ -668,9 +680,11 @@ m_lastInputTime (0)
{
m_useSizeHints = true;
XSizeHints* sizeHints = XAllocSizeHints();
- sizeHints->flags = PMinSize | PMaxSize;
+ sizeHints->flags = PMinSize | PMaxSize | USPosition;
sizeHints->min_width = sizeHints->max_width = width;
sizeHints->min_height = sizeHints->max_height = height;
+ sizeHints->x = windowPosition.x;
+ sizeHints->y = windowPosition.y;
XSetWMNormalHints(m_display, m_window, sizeHints);
XFree(sizeHints);
}
@@ -707,7 +721,15 @@ m_lastInputTime (0)
// Set fullscreen video mode and switch to fullscreen if necessary
if (m_fullscreen)
{
- setPosition(Vector2i(0, 0));
+ // Disable hint for min and max size,
+ // otherwise some windows managers will not remove window decorations
+ XSizeHints *sizeHints = XAllocSizeHints();
+ long flags = 0;
+ XGetWMNormalHints(m_display, m_window, sizeHints, &flags);
+ sizeHints->flags &= ~(PMinSize | PMaxSize);
+ XSetWMNormalHints(m_display, m_window, sizeHints);
+ XFree(sizeHints);
+
setVideoMode(mode);
switchToFullscreen();
}
@@ -721,11 +743,11 @@ WindowImplX11::~WindowImplX11()
cleanup();
// Destroy icon pixmap
- if(m_iconPixmap)
+ if (m_iconPixmap)
XFreePixmap(m_display, m_iconPixmap);
// Destroy icon mask pixmap
- if(m_iconMaskPixmap)
+ if (m_iconMaskPixmap)
XFreePixmap(m_display, m_iconMaskPixmap);
// Destroy the cursor
@@ -779,6 +801,9 @@ void WindowImplX11::processEvents()
m_events.pop_front();
processEvent(event);
}
+
+ // Process clipboard window events
+ priv::ClipboardImpl::processEvents();
}
@@ -956,10 +981,10 @@ void WindowImplX11::setIcon(unsigned int width, unsigned int height, const Uint8
return;
}
- if(m_iconPixmap)
+ if (m_iconPixmap)
XFreePixmap(m_display, m_iconPixmap);
- if(m_iconMaskPixmap)
+ if (m_iconMaskPixmap)
XFreePixmap(m_display, m_iconMaskPixmap);
m_iconPixmap = XCreatePixmap(m_display, RootWindow(m_display, m_screen), width, height, defDepth);
@@ -1236,53 +1261,99 @@ void WindowImplX11::setVideoMode(const VideoMode& mode)
return;
// Check if the XRandR extension is present
- int version;
- if (!XQueryExtension(m_display, "RANDR", &version, &version, &version))
+ int xRandRMajor, xRandRMinor;
+ if (!checkXRandR(xRandRMajor, xRandRMinor))
{
// XRandR extension is not supported: we cannot use fullscreen mode
err() << "Fullscreen is not supported, switching to window mode" << std::endl;
return;
}
- // Get the current configuration
- XRRScreenConfiguration* config = XRRGetScreenInfo(m_display, RootWindow(m_display, m_screen));
+ // Get root window
+ ::Window rootWindow = RootWindow(m_display, m_screen);
- if (!config)
+ // Get the screen resources
+ XRRScreenResources* res = XRRGetScreenResources(m_display, rootWindow);
+ if (!res)
{
- // Failed to get the screen configuration
- err() << "Failed to get the current screen configuration for fullscreen mode, switching to window mode" << std::endl;
+ err() << "Failed to get the current screen resources for fullscreen mode, switching to window mode" << std::endl;
return;
}
- // Save the current video mode before we switch to fullscreen
- Rotation currentRotation;
- m_oldVideoMode = XRRConfigCurrentConfiguration(config, &currentRotation);
+ RROutput output = getOutputPrimary(rootWindow, res, xRandRMajor, xRandRMinor);
+
+ // Get output info from output
+ XRROutputInfo* outputInfo = XRRGetOutputInfo(m_display, res, output);
+ if (!outputInfo || outputInfo->connection == RR_Disconnected)
+ {
+ XRRFreeScreenResources(res);
- // Get the available screen sizes
- int nbSizes;
- XRRScreenSize* sizes = XRRConfigSizes(config, &nbSizes);
+ // If outputInfo->connection == RR_Disconnected, free output info
+ if (outputInfo)
+ XRRFreeOutputInfo(outputInfo);
- // Search for a matching size
- for (int i = 0; (sizes && i < nbSizes); ++i)
+ err() << "Failed to get output info for fullscreen mode, switching to window mode" << std::endl;
+ return;
+ }
+
+ // Retreive current RRMode, screen position and rotation
+ XRRCrtcInfo* crtcInfo = XRRGetCrtcInfo(m_display, res, outputInfo->crtc);
+ if (!crtcInfo)
{
- XRRConfigRotations(config, &currentRotation);
+ XRRFreeScreenResources(res);
+ XRRFreeOutputInfo(outputInfo);
+ err() << "Failed to get crtc info for fullscreen mode, switching to window mode" << std::endl;
+ return;
+ }
- if (currentRotation == RR_Rotate_90 || currentRotation == RR_Rotate_270)
- std::swap(sizes[i].height, sizes[i].width);
+ // Find RRMode to set
+ bool modeFound = false;
+ RRMode xRandMode;
- if ((sizes[i].width == static_cast<int>(mode.width)) && (sizes[i].height == static_cast<int>(mode.height)))
- {
- // Switch to fullscreen mode
- XRRSetScreenConfig(m_display, config, RootWindow(m_display, m_screen), i, currentRotation, CurrentTime);
+ for (int i = 0; (i < res->nmode) && !modeFound; i++)
+ {
+ if (crtcInfo->rotation == RR_Rotate_90 || crtcInfo->rotation == RR_Rotate_270)
+ std::swap(res->modes[i].height, res->modes[i].width);
- // Set "this" as the current fullscreen window
- fullscreenWindow = this;
- break;
+ // Check if screen size match
+ if (res->modes[i].width == static_cast<int>(mode.width) &&
+ res->modes[i].height == static_cast<int>(mode.height))
+ {
+ xRandMode = res->modes[i].id;
+ modeFound = true;
}
}
- // Free the configuration instance
- XRRFreeScreenConfigInfo(config);
+ if (!modeFound)
+ {
+ XRRFreeScreenResources(res);
+ XRRFreeOutputInfo(outputInfo);
+ err() << "Failed to find a matching RRMode for fullscreen mode, switching to window mode" << std::endl;
+ return;
+ }
+
+ // Save the current video mode before we switch to fullscreen
+ m_oldVideoMode = crtcInfo->mode;
+ m_oldRRCrtc = outputInfo->crtc;
+
+ // Switch to fullscreen mode
+ XRRSetCrtcConfig(m_display,
+ res,
+ outputInfo->crtc,
+ CurrentTime,
+ crtcInfo->x,
+ crtcInfo->y,
+ xRandMode,
+ crtcInfo->rotation,
+ &output,
+ 1);
+
+ // Set "this" as the current fullscreen window
+ fullscreenWindow = this;
+
+ XRRFreeScreenResources(res);
+ XRRFreeOutputInfo(outputInfo);
+ XRRFreeCrtcInfo(crtcInfo);
}
@@ -1291,19 +1362,55 @@ void WindowImplX11::resetVideoMode()
{
if (fullscreenWindow == this)
{
- // Get current screen info
- XRRScreenConfiguration* config = XRRGetScreenInfo(m_display, RootWindow(m_display, m_screen));
- if (config)
+ // Try to set old configuration
+ // Check if the XRandR extension
+ int xRandRMajor, xRandRMinor;
+ if (checkXRandR(xRandRMajor, xRandRMinor))
{
- // Get the current rotation
- Rotation currentRotation;
- XRRConfigCurrentConfiguration(config, &currentRotation);
+ XRRScreenResources* res = XRRGetScreenResources(m_display, DefaultRootWindow(m_display));
+ if (!res)
+ {
+ err() << "Failed to get the current screen resources to reset the video mode" << std::endl;
+ return;
+ }
+
+ // Retreive current screen position and rotation
+ XRRCrtcInfo* crtcInfo = XRRGetCrtcInfo(m_display, res, m_oldRRCrtc);
+ if (!crtcInfo)
+ {
+ XRRFreeScreenResources(res);
+ err() << "Failed to get crtc info to reset the video mode" << std::endl;
+ return;
+ }
+
+ RROutput output;
+
+ // if version >= 1.3 get the primary screen else take the first screen
+ if ((xRandRMajor == 1 && xRandRMinor >= 3) || xRandRMajor > 1)
+ {
+ output = XRRGetOutputPrimary(m_display, DefaultRootWindow(m_display));
- // Reset the video mode
- XRRSetScreenConfig(m_display, config, RootWindow(m_display, m_screen), m_oldVideoMode, currentRotation, CurrentTime);
+ // Check if returned output is valid, otherwise use the first screen
+ if (output == None)
+ output = res->outputs[0];
+ }
+ else{
+ output = res->outputs[0];
+ }
- // Free the configuration instance
- XRRFreeScreenConfigInfo(config);
+ XRRSetCrtcConfig(m_display,
+ res,
+ m_oldRRCrtc,
+ CurrentTime,
+ crtcInfo->x,
+ crtcInfo->y,
+ m_oldVideoMode,
+ crtcInfo->rotation,
+ &output,
+ 1);
+
+ XRRFreeCrtcInfo(crtcInfo);
+ XRRFreeScreenResources(res);
}
// Reset the fullscreen window
@@ -1499,7 +1606,7 @@ void WindowImplX11::updateLastInputTime(::Time time)
{
Atom netWmUserTime = getAtom("_NET_WM_USER_TIME", true);
- if(netWmUserTime)
+ if (netWmUserTime)
{
XChangeProperty(m_display,
m_window,
@@ -1969,6 +2076,106 @@ bool WindowImplX11::processEvent(XEvent& windowEvent)
return true;
}
+
+////////////////////////////////////////////////////////////
+bool WindowImplX11::checkXRandR(int& xRandRMajor, int& xRandRMinor)
+{
+ // Check if the XRandR extension is present
+ int version;
+ if (!XQueryExtension(m_display, "RANDR", &version, &version, &version))
+ {
+ err() << "XRandR extension is not supported" << std::endl;
+ return false;
+ }
+
+ // Check XRandR version, 1.2 required
+ if (!XRRQueryVersion(m_display, &xRandRMajor, &xRandRMinor) || xRandRMajor < 1 || (xRandRMajor == 1 && xRandRMinor < 2 ))
+ {
+ err() << "XRandR is too old" << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
+
+////////////////////////////////////////////////////////////
+RROutput WindowImplX11::getOutputPrimary(::Window& rootWindow, XRRScreenResources* res, int xRandRMajor, int xRandRMinor)
+{
+ // if xRandR version >= 1.3 get the primary screen else take the first screen
+ if ((xRandRMajor == 1 && xRandRMinor >= 3) || xRandRMajor > 1)
+ {
+ RROutput output = XRRGetOutputPrimary(m_display, rootWindow);
+
+ // Check if returned output is valid, otherwise use the first screen
+ if (output == None)
+ return res->outputs[0];
+ else
+ return output;
+ }
+
+ // xRandr version can't get the primary screen, use the first screen
+ return res->outputs[0];
+}
+
+
+////////////////////////////////////////////////////////////
+Vector2i WindowImplX11::getPrimaryMonitorPosition()
+{
+ Vector2i monitorPosition;
+
+ // Get root window
+ ::Window rootWindow = RootWindow(m_display, m_screen);
+
+ // Get the screen resources
+ XRRScreenResources* res = XRRGetScreenResources(m_display, rootWindow);
+ if (!res)
+ {
+ err() << "Failed to get the current screen resources for.primary monitor position" << std::endl;
+ return monitorPosition;
+ }
+
+ // Get xRandr version
+ int xRandRMajor, xRandRMinor;
+ if (!checkXRandR(xRandRMajor, xRandRMinor))
+ xRandRMajor = xRandRMinor = 0;
+
+ RROutput output = getOutputPrimary(rootWindow, res, xRandRMajor, xRandRMinor);
+
+ // Get output info from output
+ XRROutputInfo* outputInfo = XRRGetOutputInfo(m_display, res, output);
+ if (!outputInfo || outputInfo->connection == RR_Disconnected)
+ {
+ XRRFreeScreenResources(res);
+
+ // If outputInfo->connection == RR_Disconnected, free output info
+ if (outputInfo)
+ XRRFreeOutputInfo(outputInfo);
+
+ err() << "Failed to get output info for.primary monitor position" << std::endl;
+ return monitorPosition;
+ }
+
+ // Retreive current RRMode, screen position and rotation
+ XRRCrtcInfo* crtcInfo = XRRGetCrtcInfo(m_display, res, outputInfo->crtc);
+ if (!crtcInfo)
+ {
+ XRRFreeScreenResources(res);
+ XRRFreeOutputInfo(outputInfo);
+ err() << "Failed to get crtc info for.primary monitor position" << std::endl;
+ return monitorPosition;
+ }
+
+ monitorPosition.x = crtcInfo->x;
+ monitorPosition.y = crtcInfo->y;
+
+ XRRFreeCrtcInfo(crtcInfo);
+ XRRFreeOutputInfo(outputInfo);
+ XRRFreeScreenResources(res);
+
+ return monitorPosition;
+}
+
} // namespace priv
} // namespace sf
diff --git a/src/SFML/Window/Unix/WindowImplX11.hpp b/src/SFML/Window/Unix/WindowImplX11.hpp
index 0ff694b..a025a1a 100644
--- a/src/SFML/Window/Unix/WindowImplX11.hpp
+++ b/src/SFML/Window/Unix/WindowImplX11.hpp
@@ -34,6 +34,7 @@
#include <SFML/Window/WindowStyle.hpp> // Prevent conflict with macro None from Xlib
#include <X11/Xlib.h>
#include <deque>
+#include <X11/extensions/Xrandr.h>
namespace sf
@@ -265,6 +266,38 @@ private:
bool processEvent(XEvent& windowEvent);
////////////////////////////////////////////////////////////
+ /// \brief Check if a valid version of XRandR extension is present
+ ///
+ /// \param xRandRMajor XRandR major version
+ /// \param xRandRMinor XRandR minor version
+ ///
+ /// \return True if a valid XRandR version found, false otherwise
+ ///
+ ////////////////////////////////////////////////////////////
+ bool checkXRandR(int& xRandRMajor, int& xRandRMinor);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Get the RROutput of the primary monitor
+ ///
+ /// \param rootWindow the root window
+ /// \param res screen resources
+ /// \param xRandRMajor XRandR major version
+ /// \param xRandRMinor XRandR minor version
+ ///
+ /// \return RROutput of the primary monitor
+ ///
+ ////////////////////////////////////////////////////////////
+ RROutput getOutputPrimary(::Window& rootWindow, XRRScreenResources* res, int xRandRMajor, int xRandRMinor);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Get coordinates of the primary monitor
+ ///
+ /// \return Position of the primary monitor
+ ///
+ ////////////////////////////////////////////////////////////
+ Vector2i getPrimaryMonitorPosition();
+
+ ////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
::Window m_window; ///< X identifier defining our window
@@ -275,6 +308,7 @@ private:
std::deque<XEvent> m_events; ///< Queue we use to store pending events for this window
bool m_isExternal; ///< Tell whether the window has been created externally or by SFML
int m_oldVideoMode; ///< Video mode in use before we switch to fullscreen
+ RRCrtc m_oldRRCrtc; ///< RRCrtc in use before we switch to fullscreen
::Cursor m_hiddenCursor; ///< As X11 doesn't provide cursor hiding, we must create a transparent one
::Cursor m_lastCursor; ///< Last cursor used -- this data is not owned by the window and is required to be always valid
bool m_keyRepeat; ///< Is the KeyRepeat feature enabled?
diff --git a/src/SFML/Window/Win32/CursorImpl.cpp b/src/SFML/Window/Win32/CursorImpl.cpp
index 28f4274..d1913d6 100755
--- a/src/SFML/Window/Win32/CursorImpl.cpp
+++ b/src/SFML/Window/Win32/CursorImpl.cpp
@@ -69,7 +69,7 @@ bool CursorImpl::loadFromPixels(const Uint8* pixels, Vector2u size, Vector2u hot
bitmapHeader.bV5BlueMask = 0x000000ff;
bitmapHeader.bV5AlphaMask = 0xff000000;
- Uint8* bitmapData = NULL;
+ Uint32* bitmapData = NULL;
HDC screenDC = GetDC(NULL);
HBITMAP color = CreateDIBSection(
@@ -89,7 +89,12 @@ bool CursorImpl::loadFromPixels(const Uint8* pixels, Vector2u size, Vector2u hot
}
// Fill our bitmap with the cursor color data
- std::memcpy(bitmapData, pixels, size.x * size.y * 4);
+ // We'll have to swap the red and blue channels here
+ Uint32* bitmapOffset = bitmapData;
+ for (std::size_t remaining = size.x * size.y; remaining > 0; --remaining, pixels += 4)
+ {
+ *bitmapOffset++ = (pixels[3] << 24) | (pixels[0] << 16) | (pixels[1] << 8) | pixels[2];
+ }
// Create a dummy mask bitmap (it won't be used)
HBITMAP mask = CreateBitmap(size.x, size.y, 1, 1, NULL);
diff --git a/src/SFML/Window/iOS/SFAppDelegate.mm b/src/SFML/Window/iOS/SFAppDelegate.mm
index 6b17384..ea69f41 100644
--- a/src/SFML/Window/iOS/SFAppDelegate.mm
+++ b/src/SFML/Window/iOS/SFAppDelegate.mm
@@ -56,6 +56,10 @@ namespace
////////////////////////////////////////////////////////////
+ (SFAppDelegate*)getInstance
{
+ NSAssert(delegateInstance,
+ @"SFAppDelegate instance is nil, this means SFML was not properly initialized. "
+ "Make sure that the file defining your main() function includes <SFML/Main.hpp>");
+
return delegateInstance;
}
@@ -173,7 +177,7 @@ namespace
NSArray *supportedOrientations = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UISupportedInterfaceOrientations"];
if (!supportedOrientations)
- return false;
+ return (1 << orientation) & [rootViewController supportedInterfaceOrientations];
int appFlags = 0;
if ([supportedOrientations containsObject:@"UIInterfaceOrientationPortrait"])
diff --git a/src/SFML/Window/iOS/SFView.mm b/src/SFML/Window/iOS/SFView.mm
index 063c61a..940d0a8 100644
--- a/src/SFML/Window/iOS/SFView.mm
+++ b/src/SFML/Window/iOS/SFView.mm
@@ -202,5 +202,11 @@
return self;
}
+////////////////////////////////////////////////////////////
+- (UITextAutocorrectionType) autocorrectionType
+{
+ return UITextAutocorrectionTypeNo;
+}
+
@end
diff --git a/src/SFML/Window/iOS/SFViewController.hpp b/src/SFML/Window/iOS/SFViewController.hpp
index b8a77aa..2b65d35 100644
--- a/src/SFML/Window/iOS/SFViewController.hpp
+++ b/src/SFML/Window/iOS/SFViewController.hpp
@@ -56,14 +56,6 @@
- (BOOL)shouldAutorotate;
////////////////////////////////////////////////////////////
-/// \brief Returns the supported orientations (iOS >= 6)
-///
-/// \return A combination of all the supported orientations
-///
-////////////////////////////////////////////////////////////
-- (NSUInteger)supportedInterfaceOrientations;
-
-////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
@property (nonatomic) bool orientationCanChange; ///< Tells whether the controller's view can rotate or not
diff --git a/src/SFML/Window/iOS/SFViewController.mm b/src/SFML/Window/iOS/SFViewController.mm
index d8be047..8c23cdc 100644
--- a/src/SFML/Window/iOS/SFViewController.mm
+++ b/src/SFML/Window/iOS/SFViewController.mm
@@ -46,12 +46,4 @@
return self.orientationCanChange;
}
-
-////////////////////////////////////////////////////////////
-- (NSUInteger)supportedInterfaceOrientations
-{
- return UIInterfaceOrientationMaskAll;
-}
-
-
@end