diff --git a/Engine/lib/sdl/Android.mk b/Engine/lib/sdl/Android.mk
old mode 100644
new mode 100755
diff --git a/Engine/lib/sdl/BUGS.txt b/Engine/lib/sdl/BUGS.txt
index c5ed3af23..6a4cbb7ad 100644
--- a/Engine/lib/sdl/BUGS.txt
+++ b/Engine/lib/sdl/BUGS.txt
@@ -1,7 +1,7 @@
Bugs are now managed in the SDL bug tracker, here:
- http://bugzilla.libsdl.org/
+ https://bugzilla.libsdl.org/
You may report bugs there, and search to see if a given issue has already
been reported, discussed, and maybe even fixed.
diff --git a/Engine/lib/sdl/CMakeLists.txt b/Engine/lib/sdl/CMakeLists.txt
index 63244a9e2..54a23f0c7 100644
--- a/Engine/lib/sdl/CMakeLists.txt
+++ b/Engine/lib/sdl/CMakeLists.txt
@@ -2,8 +2,19 @@ if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_BINARY_DIR})
message(FATAL_ERROR "Prevented in-tree built. Please create a build directory outside of the SDL source code and call cmake from there")
endif()
-cmake_minimum_required(VERSION 2.8)
+cmake_minimum_required(VERSION 2.8.5)
project(SDL2 C)
+
+# !!! FIXME: this should probably do "MACOSX_RPATH ON" as a target property
+# !!! FIXME: for the SDL2 shared library (so you get an
+# !!! FIXME: install_name ("soname") of "@rpath/libSDL-whatever.dylib"
+# !!! FIXME: instead of "/usr/local/lib/libSDL-whatever.dylib"), but I'm
+# !!! FIXME: punting for now and leaving the existing behavior. Until this
+# !!! FIXME: properly resolved, this line silences a warning in CMake 3.0+.
+# !!! FIXME: remove it and this comment entirely once the problem is
+# !!! FIXME: properly resolved.
+#cmake_policy(SET CMP0042 OLD)
+
include(CheckFunctionExists)
include(CheckLibraryExists)
include(CheckIncludeFiles)
@@ -15,6 +26,7 @@ include(CheckTypeSize)
include(CheckStructHasMember)
include(CMakeDependentOption)
include(FindPkgConfig)
+include(GNUInstallDirs)
set(CMAKE_MODULE_PATH "${SDL2_SOURCE_DIR}/cmake")
include(${SDL2_SOURCE_DIR}/cmake/macros.cmake)
include(${SDL2_SOURCE_DIR}/cmake/sdlchecks.cmake)
@@ -29,9 +41,9 @@ include(${SDL2_SOURCE_DIR}/cmake/sdlchecks.cmake)
# set SDL_BINARY_AGE and SDL_INTERFACE_AGE to 0.
set(SDL_MAJOR_VERSION 2)
set(SDL_MINOR_VERSION 0)
-set(SDL_MICRO_VERSION 4)
-set(SDL_INTERFACE_AGE 0)
-set(SDL_BINARY_AGE 4)
+set(SDL_MICRO_VERSION 5)
+set(SDL_INTERFACE_AGE 1)
+set(SDL_BINARY_AGE 5)
set(SDL_VERSION "${SDL_MAJOR_VERSION}.${SDL_MINOR_VERSION}.${SDL_MICRO_VERSION}")
# Calculate a libtool-like version number
@@ -147,8 +159,10 @@ endif()
# Default flags, if not set otherwise
if("$ENV{CFLAGS}" STREQUAL "")
- if(USE_GCC OR USE_CLANG)
- set(CMAKE_C_FLAGS "-g -O3")
+ if(CMAKE_BUILD_TYPE STREQUAL "")
+ if(USE_GCC OR USE_CLANG)
+ set(CMAKE_C_FLAGS "-g -O3")
+ endif()
endif()
else()
set(CMAKE_C_FLAGS "$ENV{CFLAGS}")
@@ -183,8 +197,8 @@ endif()
set(SDL_LIBS "-lSDL2")
set(SDL_CFLAGS "")
-# Emscripten toolchain has a nonempty default value for this, and the checks
-# in this file need to change that, so remember the original value, and
+# Emscripten toolchain has a nonempty default value for this, and the checks
+# in this file need to change that, so remember the original value, and
# restore back to that afterwards. For check_function_exists() to work in
# Emscripten, this value must be at its default value.
set(ORIG_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
@@ -192,7 +206,7 @@ set(ORIG_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
if(CYGWIN)
# We build SDL on cygwin without the UNIX emulation layer
include_directories("-I/usr/include/mingw")
- set(CMAKE_REQUIRED_FLAGS "-mno-cygwin")
+ set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -mno-cygwin")
check_c_source_compiles("int main(int argc, char **argv) {}"
HAVE_GCC_NO_CYGWIN)
set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
@@ -212,7 +226,7 @@ include_directories(${SDL2_BINARY_DIR}/include ${SDL2_SOURCE_DIR}/include)
set(OPT_DEF_ASM TRUE)
if(EMSCRIPTEN)
# Set up default values for the currently supported set of subsystems:
- # Emscripten/Javascript does not have assembly support, a dynamic library
+ # Emscripten/Javascript does not have assembly support, a dynamic library
# loading architecture, low-level CPU inspection or multithreading.
set(OPT_DEF_ASM FALSE)
set(SDL_SHARED_ENABLED_BY_DEFAULT OFF)
@@ -299,6 +313,8 @@ set_option(VIDEO_VIVANTE "Use Vivante EGL video driver" ${UNIX_SYS})
set(SDL_SHARED ${SDL_SHARED_ENABLED_BY_DEFAULT} CACHE BOOL "Build a shared version of the library")
set(SDL_STATIC ON CACHE BOOL "Build a static version of the library")
+dep_option(SDL_STATIC_PIC "Static version of the library should be built with Position Independent Code" OFF "SDL_STATIC" OFF)
+
# General source files
file(GLOB SOURCE_FILES
${SDL2_SOURCE_DIR}/src/*.c
@@ -334,6 +350,24 @@ set(HAVE_ASSERTIONS ${ASSERTIONS})
# Compiler option evaluation
if(USE_GCC OR USE_CLANG)
+ # Check for -Wall first, so later things can override pieces of it.
+ check_c_compiler_flag(-Wall HAVE_GCC_WALL)
+ if(HAVE_GCC_WALL)
+ list(APPEND EXTRA_CFLAGS "-Wall")
+ if(HAIKU)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-multichar")
+ endif()
+ endif()
+
+ check_c_compiler_flag(-Wdeclaration-after-statement HAVE_GCC_WDECLARATION_AFTER_STATEMENT)
+ if(HAVE_GCC_WDECLARATION_AFTER_STATEMENT)
+ check_c_compiler_flag(-Werror=declaration-after-statement HAVE_GCC_WERROR_DECLARATION_AFTER_STATEMENT)
+ if(HAVE_GCC_WERROR_DECLARATION_AFTER_STATEMENT)
+ list(APPEND EXTRA_CFLAGS "-Werror=declaration-after-statement")
+ endif()
+ list(APPEND EXTRA_CFLAGS "-Wdeclaration-after-statement")
+ endif()
+
if(DEPENDENCY_TRACKING)
check_c_source_compiles("
#if !defined(__GNUC__) || __GNUC__ < 3
@@ -375,26 +409,16 @@ if(USE_GCC OR USE_CLANG)
endif()
set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
- check_c_compiler_flag(-Wall HAVE_GCC_WALL)
- if(HAVE_GCC_WALL)
- list(APPEND EXTRA_CFLAGS "-Wall")
- if(HAIKU)
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-multichar")
- endif()
- endif()
check_c_compiler_flag(-Wshadow HAVE_GCC_WSHADOW)
if(HAVE_GCC_WSHADOW)
list(APPEND EXTRA_CFLAGS "-Wshadow")
endif()
- # --no-undefined is unsupported with clang
- if(NOT USE_CLANG)
- set(CMAKE_REQUIRED_FLAGS "-Wl,--no-undefined")
- check_c_compiler_flag("" HAVE_NO_UNDEFINED)
- set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
- if(HAVE_NO_UNDEFINED)
- list(APPEND EXTRA_LDFLAGS "-Wl,--no-undefined")
- endif()
+ set(CMAKE_REQUIRED_FLAGS "-Wl,--no-undefined")
+ check_c_compiler_flag("" HAVE_NO_UNDEFINED)
+ set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
+ if(HAVE_NO_UNDEFINED)
+ list(APPEND EXTRA_LDFLAGS "-Wl,--no-undefined")
endif()
endif()
@@ -773,6 +797,16 @@ if(EMSCRIPTEN)
set(SOURCE_FILES ${SOURCE_FILES} ${EM_POWER_SOURCES})
set(HAVE_SDL_POWER TRUE)
endif()
+ if(SDL_TIMERS)
+ set(SDL_TIMER_UNIX 1)
+ file(GLOB TIMER_SOURCES ${SDL2_SOURCE_DIR}/src/timer/unix/*.c)
+ set(SOURCE_FILES ${SOURCE_FILES} ${TIMER_SOURCES})
+ set(HAVE_SDL_TIMERS TRUE)
+
+ if(CLOCK_GETTIME)
+ set(HAVE_CLOCK_GETTIME 1)
+ endif()
+ endif()
if(SDL_VIDEO)
set(SDL_VIDEO_DRIVER_EMSCRIPTEN 1)
file(GLOB EM_VIDEO_SOURCES ${SDL2_SOURCE_DIR}/src/video/emscripten/*.c)
@@ -839,7 +873,7 @@ elseif(UNIX AND NOT APPLE)
#include
#include
- int main(int argc, char **argv)
+ int main(int argc, char **argv)
{
struct kbentry kbe;
kbe.kb_table = KG_CTRL;
@@ -866,8 +900,24 @@ elseif(UNIX AND NOT APPLE)
check_include_file("libudev.h" HAVE_LIBUDEV_H)
- # !!! FIXME: this needs pkg-config to find the include path, I think.
- check_include_file("dbus/dbus.h" HAVE_DBUS_DBUS_H)
+ if(PKG_CONFIG_FOUND)
+ pkg_search_module(DBUS dbus-1 dbus)
+ if(DBUS_FOUND)
+ set(HAVE_DBUS_DBUS_H TRUE)
+ include_directories(${DBUS_INCLUDE_DIRS})
+ list(APPEND EXTRA_LIBS ${DBUS_LIBRARIES})
+ endif()
+
+ pkg_search_module(IBUS ibus-1.0 ibus)
+ if(IBUS_FOUND)
+ set(HAVE_IBUS_IBUS_H TRUE)
+ include_directories(${IBUS_INCLUDE_DIRS})
+ list(APPEND EXTRA_LIBS ${IBUS_LIBRARIES})
+ endif()
+ endif()
+
+ check_include_file("fcitx/frontend.h" HAVE_FCITX_FRONTEND_H)
+
endif()
if(INPUT_TSLIB)
@@ -936,7 +986,14 @@ elseif(UNIX AND NOT APPLE)
if(RPATH)
set(SDL_RLD_FLAGS "")
if(BSDI OR FREEBSD OR LINUX OR NETBSD)
- set(SDL_RLD_FLAGS "-Wl,-rpath,\${libdir}")
+ set(CMAKE_REQUIRED_FLAGS "-Wl,--enable-new-dtags")
+ check_c_compiler_flag("" HAVE_ENABLE_NEW_DTAGS)
+ set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
+ if(HAVE_ENABLE_NEW_DTAGS)
+ set(SDL_RLD_FLAGS "-Wl,-rpath,\${libdir} -Wl,--enable-new-dtags")
+ else()
+ set(SDL_RLD_FLAGS "-Wl,-rpath,\${libdir}")
+ endif()
elseif(SOLARIS)
set(SDL_RLD_FLAGS "-R\${libdir}")
endif()
@@ -1108,7 +1165,7 @@ elseif(WINDOWS)
set(SOURCE_FILES ${SOURCE_FILES} ${JOYSTICK_SOURCES})
if(HAVE_DINPUT_H)
set(SDL_JOYSTICK_DINPUT 1)
- list(APPEND EXTRA_LIBS dinput8 dxguid)
+ list(APPEND EXTRA_LIBS dinput8)
if(CMAKE_COMPILER_IS_MINGW)
list(APPEND EXTRA_LIBS dxerr8)
elseif (NOT USE_WINSDK_DIRECTX)
@@ -1166,16 +1223,20 @@ elseif(APPLE)
if(SDL_AUDIO)
set(SDL_AUDIO_DRIVER_COREAUDIO 1)
- file(GLOB AUDIO_SOURCES ${SDL2_SOURCE_DIR}/src/audio/coreaudio/*.c)
+ file(GLOB AUDIO_SOURCES ${SDL2_SOURCE_DIR}/src/audio/coreaudio/*.m)
set(SOURCE_FILES ${SOURCE_FILES} ${AUDIO_SOURCES})
set(HAVE_SDL_AUDIO TRUE)
set(SDL_FRAMEWORK_COREAUDIO 1)
- set(SDL_FRAMEWORK_AUDIOUNIT 1)
+ set(SDL_FRAMEWORK_AUDIOTOOLBOX 1)
endif()
if(SDL_JOYSTICK)
set(SDL_JOYSTICK_IOKIT 1)
- file(GLOB JOYSTICK_SOURCES ${SDL2_SOURCE_DIR}/src/joystick/darwin/*.c)
+ if (IOS)
+ file(GLOB JOYSTICK_SOURCES ${SDL2_SOURCE_DIR}/src/joystick/iphoneos/*.m)
+ else()
+ file(GLOB JOYSTICK_SOURCES ${SDL2_SOURCE_DIR}/src/joystick/darwin/*.c)
+ endif()
set(SOURCE_FILES ${SOURCE_FILES} ${JOYSTICK_SOURCES})
set(HAVE_SDL_JOYSTICK TRUE)
set(SDL_FRAMEWORK_IOKIT 1)
@@ -1184,7 +1245,12 @@ elseif(APPLE)
if(SDL_HAPTIC)
set(SDL_HAPTIC_IOKIT 1)
- file(GLOB HAPTIC_SOURCES ${SDL2_SOURCE_DIR}/src/haptic/darwin/*.c)
+ if (IOS)
+ file(GLOB POWER_SOURCES ${SDL2_SOURCE_DIR}/src/power/dummy/*.c)
+ set(SDL_HAPTIC_DUMMY 1)
+ else()
+ file(GLOB HAPTIC_SOURCES ${SDL2_SOURCE_DIR}/src/haptic/darwin/*.c)
+ endif()
set(SOURCE_FILES ${SOURCE_FILES} ${HAPTIC_SOURCES})
set(HAVE_SDL_HAPTIC TRUE)
set(SDL_FRAMEWORK_IOKIT 1)
@@ -1196,7 +1262,11 @@ elseif(APPLE)
if(SDL_POWER)
set(SDL_POWER_MACOSX 1)
- file(GLOB POWER_SOURCES ${SDL2_SOURCE_DIR}/src/power/macosx/*.c)
+ if (IOS)
+ file(GLOB POWER_SOURCES ${SDL2_SOURCE_DIR}/src/power/uikit/*.m)
+ else()
+ file(GLOB POWER_SOURCES ${SDL2_SOURCE_DIR}/src/power/macosx/*.c)
+ endif()
set(SOURCE_FILES ${SOURCE_FILES} ${POWER_SOURCES})
set(HAVE_SDL_POWER TRUE)
set(SDL_FRAMEWORK_CARBON 1)
@@ -1243,19 +1313,25 @@ elseif(APPLE)
find_library(COREAUDIO CoreAudio)
list(APPEND EXTRA_LIBS ${COREAUDIO})
endif()
- if(SDL_FRAMEWORK_AUDIOUNIT)
- find_library(AUDIOUNIT AudioUnit)
- list(APPEND EXTRA_LIBS ${AUDIOUNIT})
+ if(SDL_FRAMEWORK_AUDIOTOOLBOX)
+ find_library(AUDIOTOOLBOX AudioToolbox)
+ list(APPEND EXTRA_LIBS ${AUDIOTOOLBOX})
endif()
# iOS hack needed - http://code.google.com/p/ios-cmake/ ?
if(SDL_VIDEO)
- CheckCOCOA()
- if(VIDEO_OPENGL)
- set(SDL_VIDEO_OPENGL 1)
- set(SDL_VIDEO_OPENGL_CGL 1)
- set(SDL_VIDEO_RENDER_OGL 1)
- set(HAVE_VIDEO_OPENGL TRUE)
+ if (IOS)
+ set(SDL_VIDEO_DRIVER_UIKIT 1)
+ file(GLOB UIKITVIDEO_SOURCES ${SDL2_SOURCE_DIR}/src/video/uikit/*.m)
+ set(SOURCE_FILES ${SOURCE_FILES} ${UIKITVIDEO_SOURCES})
+ else()
+ CheckCOCOA()
+ if(VIDEO_OPENGL)
+ set(SDL_VIDEO_OPENGL 1)
+ set(SDL_VIDEO_OPENGL_CGL 1)
+ set(SDL_VIDEO_RENDER_OGL 1)
+ set(HAVE_VIDEO_OPENGL TRUE)
+ endif()
endif()
endif()
@@ -1442,6 +1518,9 @@ message(STATUS " EXTRA_LIBS: ${EXTRA_LIBS}")
message(STATUS "")
message(STATUS " Build Shared Library: ${SDL_SHARED}")
message(STATUS " Build Static Library: ${SDL_STATIC}")
+if(SDL_STATIC)
+ message(STATUS " Build Static Library with Position Independent Code: ${SDL_STATIC_PIC}")
+endif()
message(STATUS "")
if(UNIX)
message(STATUS "If something was not detected, although the libraries")
@@ -1458,7 +1537,7 @@ add_library(SDL2main STATIC ${SDLMAIN_SOURCES})
set(_INSTALL_LIBS "SDL2main")
if(SDL_SHARED)
- add_library(SDL2 SHARED ${SOURCE_FILES})
+ add_library(SDL2 SHARED ${SOURCE_FILES} ${VERSION_SOURCES})
if(UNIX)
set_target_properties(SDL2 PROPERTIES
VERSION ${LT_VERSION}
@@ -1484,6 +1563,7 @@ if(SDL_STATIC)
set (BUILD_SHARED_LIBS FALSE)
add_library(SDL2-static STATIC ${SOURCE_FILES})
set_target_properties(SDL2-static PROPERTIES OUTPUT_NAME "SDL2")
+ set_target_properties(SDL2-static PROPERTIES POSITION_INDEPENDENT_CODE ${SDL_STATIC_PIC})
if(MSVC)
set_target_properties(SDL2-static PROPERTIES LINK_FLAGS_RELEASE "/NODEFAULTLIB")
set_target_properties(SDL2-static PROPERTIES LINK_FLAGS_DEBUG "/NODEFAULTLIB")
@@ -1510,12 +1590,17 @@ endforeach()
list(APPEND INCLUDE_FILES ${BIN_INCLUDE_FILES})
install(FILES ${INCLUDE_FILES} DESTINATION include/SDL2)
-if(NOT WINDOWS OR CYGWIN)
+if(NOT (WINDOWS OR CYGWIN))
if(SDL_SHARED)
+ if (APPLE)
+ set(SOEXT "dylib")
+ else()
+ set(SOEXT "so")
+ endif()
install(CODE "
execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink
- \"libSDL2-2.0.so\" \"libSDL2.so\")")
- install(FILES ${SDL2_BINARY_DIR}/libSDL2.so DESTINATION "lib${LIB_SUFFIX}")
+ \"libSDL2-2.0.${SOEXT}\" \"libSDL2.${SOEXT}\")")
+ install(FILES ${SDL2_BINARY_DIR}/libSDL2.${SOEXT} DESTINATION "lib${LIB_SUFFIX}")
endif()
if(FREEBSD)
# FreeBSD uses ${PREFIX}/libdata/pkgconfig
@@ -1526,7 +1611,7 @@ if(NOT WINDOWS OR CYGWIN)
endif()
install(PROGRAMS ${SDL2_BINARY_DIR}/sdl2-config DESTINATION bin)
# TODO: what about the .spec file? Is it only needed for RPM creation?
- install(FILES "${SDL2_SOURCE_DIR}/sdl2.m4" DESTINATION "share/aclocal")
+ install(FILES "${SDL2_SOURCE_DIR}/sdl2.m4" DESTINATION "${CMAKE_INSTALL_FULL_DATAROOTDIR}/aclocal")
endif()
##### Uninstall target #####
diff --git a/Engine/lib/sdl/Makefile.in b/Engine/lib/sdl/Makefile.in
index b66e0f5e2..a7cbddf26 100644
--- a/Engine/lib/sdl/Makefile.in
+++ b/Engine/lib/sdl/Makefile.in
@@ -3,6 +3,7 @@
top_builddir = .
srcdir = @srcdir@
objects = build
+gen = gen
prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
@@ -31,6 +32,8 @@ WINDRES = @WINDRES@
TARGET = libSDL2.la
OBJECTS = @OBJECTS@
+GEN_HEADERS = @GEN_HEADERS@
+GEN_OBJECTS = @GEN_OBJECTS@
VERSION_OBJECTS = @VERSION_OBJECTS@
SDLMAIN_TARGET = libSDL2main.a
@@ -39,6 +42,8 @@ SDLMAIN_OBJECTS = @SDLMAIN_OBJECTS@
SDLTEST_TARGET = libSDL2_test.a
SDLTEST_OBJECTS = @SDLTEST_OBJECTS@
+WAYLAND_SCANNER = @WAYLAND_SCANNER@
+
SRC_DIST = *.txt acinclude Android.mk autogen.sh android-project build-scripts cmake cmake_uninstall.cmake.in configure configure.in debian docs include Makefile.* sdl2-config.cmake.in sdl2-config.in sdl2.m4 sdl2.pc.in SDL2.spec.in src test VisualC.html VisualC VisualC-WinRT Xcode Xcode-iOS
GEN_DIST = SDL2.spec
@@ -48,6 +53,7 @@ RUN_CMD_CC = @echo " CC " $@;
RUN_CMD_CXX = @echo " CXX " $@;
RUN_CMD_LTLINK = @echo " LTLINK" $@;
RUN_CMD_RANLIB = @echo " RANLIB" $@;
+RUN_CMD_GEN = @echo " GEN " $@;
LIBTOOL += --quiet
endif
@@ -137,8 +143,8 @@ update-revision:
.PHONY: all update-revision install install-bin install-hdrs install-lib install-data uninstall uninstall-bin uninstall-hdrs uninstall-lib uninstall-data clean distclean dist $(OBJECTS:.lo=.d)
-$(objects)/$(TARGET): $(OBJECTS) $(VERSION_OBJECTS)
- $(RUN_CMD_LTLINK)$(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ $(OBJECTS) $(VERSION_OBJECTS) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LT_LDFLAGS)
+$(objects)/$(TARGET): $(GEN_HEADERS) $(GEN_OBJECTS) $(OBJECTS) $(VERSION_OBJECTS)
+ $(RUN_CMD_LTLINK)$(LIBTOOL) --tag=CC --mode=link $(CC) -o $@ $(OBJECTS) $(GEN_OBJECTS) $(VERSION_OBJECTS) $(LDFLAGS) $(EXTRA_LDFLAGS) $(LT_LDFLAGS)
$(objects)/$(SDLMAIN_TARGET): $(SDLMAIN_OBJECTS)
$(RUN_CMD_AR)$(AR) cru $@ $(SDLMAIN_OBJECTS)
@@ -200,6 +206,7 @@ uninstall-data:
clean:
rm -rf $(objects)
+ rm -rf $(gen)
if test -f test/Makefile; then (cd test; $(MAKE) $@); fi
distclean: clean
diff --git a/Engine/lib/sdl/Makefile.pandora b/Engine/lib/sdl/Makefile.pandora
index bb89d52a6..8b78f2734 100644
--- a/Engine/lib/sdl/Makefile.pandora
+++ b/Engine/lib/sdl/Makefile.pandora
@@ -19,7 +19,7 @@ SOURCES = ./src/*.c ./src/audio/*.c ./src/cpuinfo/*.c ./src/events/*.c \
./src/thread/pthread/SDL_systhread.c ./src/thread/pthread/SDL_syssem.c \
./src/thread/pthread/SDL_sysmutex.c ./src/thread/pthread/SDL_syscond.c \
./src/joystick/linux/*.c ./src/haptic/linux/*.c ./src/timer/unix/*.c \
- ./src/atomic/linux/*.c ./src/filesystem/unix/*.c \
+ ./src/atomic/*.c ./src/filesystem/unix/*.c \
./src/video/pandora/SDL_pandora.o ./src/video/pandora/SDL_pandora_events.o ./src/video/x11/*.c
diff --git a/Engine/lib/sdl/Makefile.psp b/Engine/lib/sdl/Makefile.psp
index 5e7dcd29a..93fb9e447 100644
--- a/Engine/lib/sdl/Makefile.psp
+++ b/Engine/lib/sdl/Makefile.psp
@@ -49,6 +49,7 @@ OBJS= src/SDL.o \
src/stdlib/SDL_stdlib.o \
src/stdlib/SDL_string.o \
src/thread/SDL_thread.o \
+ src/thread/generic/SDL_systls.o \
src/thread/psp/SDL_syssem.o \
src/thread/psp/SDL_systhread.o \
src/thread/psp/SDL_sysmutex.o \
diff --git a/Engine/lib/sdl/Makefile.wiz b/Engine/lib/sdl/Makefile.wiz
index bb7705789..0981be853 100644
--- a/Engine/lib/sdl/Makefile.wiz
+++ b/Engine/lib/sdl/Makefile.wiz
@@ -9,8 +9,8 @@ STRIP = $(WIZSDK)/bin/arm-openwiz-linux-gnu-strip
CFLAGS = -Wall -fPIC -I./include -I$(WIZSDK)/include -DWIZ_GLES_LITE
-TARGET_STATIC = libSDL13.a
-TARGET_SHARED = libSDL13.so
+TARGET_STATIC = libSDL2.a
+TARGET_SHARED = libSDL2.so
SOURCES = ./src/*.c ./src/audio/*.c ./src/cpuinfo/*.c ./src/events/*.c \
./src/file/*.c ./src/stdlib/*.c ./src/thread/*.c ./src/timer/*.c ./src/video/*.c \
@@ -43,7 +43,7 @@ clean:
install:
mkdir -p $(WIZSDK)/lib
- mkdir -p $(WIZSDK)/include/SDL13
+ mkdir -p $(WIZSDK)/include/SDL2
cp -f $(TARGET_STATIC) $(WIZSDK)/lib
cp -f $(TARGET_SHARED).0.0.1 $(WIZSDK)/lib
rm -f $(WIZSDK)/lib/$(TARGET_SHARED).0 $(WIZSDK)/lib/$(TARGET_SHARED)
@@ -57,5 +57,5 @@ install:
ln -s ../../toolchain/libs/$(TARGET_SHARED).0 ../../toolchain/libs/$(TARGET_SHARED)
cp $(TARGET_SHARED).0.0.1 ../nehe_demos/build/$(TARGET_SHARED).0
- cp -f include/*.h $(WIZSDK)/include/SDL13/
- cp -f include/*.h ../../toolchain/include/SDL13/
+ cp -f include/*.h $(WIZSDK)/include/SDL2/
+ cp -f include/*.h ../../toolchain/include/SDL2/
diff --git a/Engine/lib/sdl/README-SDL.txt b/Engine/lib/sdl/README-SDL.txt
index fade0b958..8eaf051f7 100644
--- a/Engine/lib/sdl/README-SDL.txt
+++ b/Engine/lib/sdl/README-SDL.txt
@@ -2,8 +2,8 @@
Please distribute this file with the SDL runtime environment:
The Simple DirectMedia Layer (SDL for short) is a cross-platform library
-designed to make it easy to write multi-media software, such as games and
-emulators.
+designed to make it easy to write multi-media software, such as games
+and emulators.
The Simple DirectMedia Layer library source code is available from:
http://www.libsdl.org/
diff --git a/Engine/lib/sdl/SDL2.spec b/Engine/lib/sdl/SDL2.spec
index 0fe57540f..5dfda5802 100644
--- a/Engine/lib/sdl/SDL2.spec
+++ b/Engine/lib/sdl/SDL2.spec
@@ -1,6 +1,6 @@
Summary: Simple DirectMedia Layer
Name: SDL2
-Version: 2.0.4
+Version: 2.0.5
Release: 2
Source: http://www.libsdl.org/release/%{name}-%{version}.tar.gz
URL: http://www.libsdl.org/
diff --git a/Engine/lib/sdl/VisualC.html b/Engine/lib/sdl/VisualC.html
index 89035d677..0631832e8 100644
--- a/Engine/lib/sdl/VisualC.html
+++ b/Engine/lib/sdl/VisualC.html
@@ -21,7 +21,7 @@
There are different solution files for the various
- versions of the IDE. Please use the appropiate version
+ versions of the IDE. Please use the appropriate version
2008, 2010, 2012 or 2013.
@@ -101,7 +101,7 @@
files to project")
Instead of adding the files to your project it is more
- desireable to add them to the linker options: Project|Properties|Linker|Command
+ desirable to add them to the linker options: Project|Properties|Linker|Command
Line and type the names of the libraries to link with in the "Additional
Options:" box. Note: This must be done for each build
configuration (e.g. Release,Debug).
diff --git a/Engine/lib/sdl/VisualC/clean.sh b/Engine/lib/sdl/VisualC/clean.sh
deleted file mode 100644
index fd16f9a12..000000000
--- a/Engine/lib/sdl/VisualC/clean.sh
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/sh
-find . -type f \( -name '*.user' -o -name '*.sdf' -o -name '*.ncb' -o -name '*.suo' \) -print -delete
-find . -type f \( -name '*.bmp' -o -name '*.wav' -o -name '*.dat' \) -print -delete
-find . -depth -type d \( -name Win32 -o -name x64 \) -exec rm -rv {} \;
diff --git a/Engine/lib/sdl/WhatsNew.txt b/Engine/lib/sdl/WhatsNew.txt
index 9b7139f5d..1979ac2b3 100644
--- a/Engine/lib/sdl/WhatsNew.txt
+++ b/Engine/lib/sdl/WhatsNew.txt
@@ -1,6 +1,69 @@
This is a list of major changes in SDL's version history.
+---------------------------------------------------------------------------
+2.0.5:
+---------------------------------------------------------------------------
+
+General:
+* Implemented audio capture support for some platforms
+* Added SDL_DequeueAudio() to retrieve audio when buffer queuing is turned on for audio capture
+* Added events for dragging and dropping text
+* Added events for dragging and dropping multiple items
+* By default the click raising a window will not be delivered to the SDL application. You can set the hint SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH to "1" to allow that click through to the window.
+* Saving a surface with an alpha channel as a BMP will use a newer BMP format that supports alpha information. You can set the hint SDL_HINT_BMP_SAVE_LEGACY_FORMAT to "1" to use the old format.
+* Added SDL_GetHintBoolean() to get the boolean value of a hint
+* Added SDL_RenderSetIntegerScale() to set whether to smoothly scale or use integral multiples of the viewport size when scaling the rendering output
+* Added SDL_CreateRGBSurfaceWithFormat() and SDL_CreateRGBSurfaceWithFormatFrom() to create an SDL surface with a specific pixel format
+* Added SDL_GetDisplayUsableBounds() which returns the area usable for windows. For example, on Mac OS X, this subtracts the area occupied by the menu bar and dock.
+* Added SDL_GetWindowBordersSize() which returns the size of the window's borders around the client area
+* Added a window event SDL_WINDOWEVENT_HIT_TEST when a window had a hit test that wasn't SDL_HITTEST_NORMAL (e.g. in the title bar or window frame)
+* Added SDL_SetWindowResizable() to change whether a window is resizable
+* Added SDL_SetWindowOpacity() and SDL_GetWindowOpacity() to affect the window transparency
+* Added SDL_SetWindowModalFor() to set a window as modal for another window
+* Added support for AUDIO_U16LSB and AUDIO_U16MSB to SDL_MixAudioFormat()
+* Fixed flipped images when reading back from target textures when using the OpenGL renderer
+* Fixed texture color modulation with SDL_BLENDMODE_NONE when using the OpenGL renderer
+* Fixed bug where the alpha value of colorkeys was ignored when blitting in some cases
+
+Windows:
+* Added a hint SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING to prevent SDL from raising a debugger exception to name threads. This exception can cause problems with .NET applications when running under a debugger.
+* The hint SDL_HINT_THREAD_STACK_SIZE is now supported on Windows
+* Fixed XBox controller triggers automatically being pulled at startup
+* The first icon from the executable is used as the default window icon at runtime
+* Fixed SDL log messages being printed twice if SDL was built with C library support
+* Reset dead keys when the SDL window loses focus, so dead keys pressed in SDL applications don't affect text input into other applications.
+
+Mac OS X:
+* Fixed selecting the dummy video driver
+* The caps lock key now generates a pressed event when pressed and a released event when released, instead of a press/release event pair when pressed.
+* Fixed mouse wheel events on Mac OS X 10.12
+* The audio driver has been updated to use AVFoundation for better compatibility with newer versions of Mac OS X
+
+Linux:
+* Added support for the Fcitx IME
+* Added a window event SDL_WINDOWEVENT_TAKE_FOCUS when a window manager asks the SDL window whether it wants to take focus.
+* Refresh rates are now rounded instead of truncated, e.g. 59.94 Hz is rounded up to 60 Hz instead of 59.
+* Added initial support for touchscreens on Raspberry Pi
+
+OpenBSD:
+* SDL_GetBasePath() is now implemented on OpenBSD
+
+iOS:
+* Added support for dynamically loaded objects on iOS 8 and newer
+
+tvOS:
+* Added support for Apple TV
+* Added a hint SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION to control whether he Apple TV remote's joystick axes will automatically match the rotation of the remote.
+
+Android:
+* Fixed SDL not resizing window when Android screen resolution changes
+* Corrected the joystick Z axis reporting for the accelerometer
+
+Emscripten (running in a web browser):
+* Many bug fixes and improvements
+
+
---------------------------------------------------------------------------
2.0.4:
---------------------------------------------------------------------------
diff --git a/Engine/lib/sdl/Xcode/SDL/Info-Framework.plist b/Engine/lib/sdl/Xcode/SDL/Info-Framework.plist
index bccaa8afc..da4183466 100644
--- a/Engine/lib/sdl/Xcode/SDL/Info-Framework.plist
+++ b/Engine/lib/sdl/Xcode/SDL/Info-Framework.plist
@@ -11,7 +11,7 @@
CFBundleIconFile
CFBundleIdentifier
- org.libsdl.SDL2
+ $(PRODUCT_BUNDLE_IDENTIFIER)
CFBundleInfoDictionaryVersion
6.0
CFBundleName
@@ -19,10 +19,10 @@
CFBundlePackageType
FMWK
CFBundleShortVersionString
- 2.0.4
+ 2.0.5
CFBundleSignature
SDLX
CFBundleVersion
- 2.0.4
+ 2.0.5
diff --git a/Engine/lib/sdl/Xcode/SDL/SDL.xcodeproj/project.pbxproj b/Engine/lib/sdl/Xcode/SDL/SDL.xcodeproj/project.pbxproj
old mode 100644
new mode 100755
index 9fc2a5019..1f16953cf
--- a/Engine/lib/sdl/Xcode/SDL/SDL.xcodeproj/project.pbxproj
+++ b/Engine/lib/sdl/Xcode/SDL/SDL.xcodeproj/project.pbxproj
@@ -7,15 +7,9 @@
objects = {
/* Begin PBXBuildFile section */
- 007317A20858DECD00B2BC32 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179B0858DECD00B2BC32 /* AudioToolbox.framework */; };
- 007317A30858DECD00B2BC32 /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179C0858DECD00B2BC32 /* AudioUnit.framework */; };
007317A40858DECD00B2BC32 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179D0858DECD00B2BC32 /* Cocoa.framework */; };
- 007317A50858DECD00B2BC32 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179E0858DECD00B2BC32 /* CoreAudio.framework */; };
007317A60858DECD00B2BC32 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179F0858DECD00B2BC32 /* IOKit.framework */; };
- 007317A90858DECD00B2BC32 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179B0858DECD00B2BC32 /* AudioToolbox.framework */; };
- 007317AA0858DECD00B2BC32 /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179C0858DECD00B2BC32 /* AudioUnit.framework */; };
007317AB0858DECD00B2BC32 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179D0858DECD00B2BC32 /* Cocoa.framework */; };
- 007317AC0858DECD00B2BC32 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179E0858DECD00B2BC32 /* CoreAudio.framework */; };
007317AD0858DECD00B2BC32 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179F0858DECD00B2BC32 /* IOKit.framework */; };
007317C30858E15000B2BC32 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 007317C10858E15000B2BC32 /* Carbon.framework */; };
00CFA89D106B4BA100758660 /* ForceFeedback.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00CFA89C106B4BA100758660 /* ForceFeedback.framework */; };
@@ -57,14 +51,12 @@
04BD000912E6671800899322 /* SDL_diskaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFD8912E6671700899322 /* SDL_diskaudio.h */; };
04BD001012E6671800899322 /* SDL_dummyaudio.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFD9412E6671700899322 /* SDL_dummyaudio.c */; };
04BD001112E6671800899322 /* SDL_dummyaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFD9512E6671700899322 /* SDL_dummyaudio.h */; };
- 04BD001812E6671800899322 /* SDL_coreaudio.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDA012E6671700899322 /* SDL_coreaudio.c */; };
04BD001912E6671800899322 /* SDL_coreaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDA112E6671700899322 /* SDL_coreaudio.h */; };
04BD002612E6671800899322 /* SDL_audio.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDB412E6671700899322 /* SDL_audio.c */; };
04BD002712E6671800899322 /* SDL_audio_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDB512E6671700899322 /* SDL_audio_c.h */; };
04BD002812E6671800899322 /* SDL_audiocvt.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDB612E6671700899322 /* SDL_audiocvt.c */; };
04BD002912E6671800899322 /* SDL_audiodev.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDB712E6671700899322 /* SDL_audiodev.c */; };
04BD002A12E6671800899322 /* SDL_audiodev_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDB812E6671700899322 /* SDL_audiodev_c.h */; };
- 04BD002B12E6671800899322 /* SDL_audiomem.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDB912E6671700899322 /* SDL_audiomem.h */; };
04BD002C12E6671800899322 /* SDL_audiotypecvt.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDBA12E6671700899322 /* SDL_audiotypecvt.c */; };
04BD002D12E6671800899322 /* SDL_mixer.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDBB12E6671700899322 /* SDL_mixer.c */; };
04BD003412E6671800899322 /* SDL_sysaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDC212E6671700899322 /* SDL_sysaudio.h */; };
@@ -211,14 +203,12 @@
04BD022512E6671800899322 /* SDL_diskaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFD8912E6671700899322 /* SDL_diskaudio.h */; };
04BD022C12E6671800899322 /* SDL_dummyaudio.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFD9412E6671700899322 /* SDL_dummyaudio.c */; };
04BD022D12E6671800899322 /* SDL_dummyaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFD9512E6671700899322 /* SDL_dummyaudio.h */; };
- 04BD023412E6671800899322 /* SDL_coreaudio.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDA012E6671700899322 /* SDL_coreaudio.c */; };
04BD023512E6671800899322 /* SDL_coreaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDA112E6671700899322 /* SDL_coreaudio.h */; };
04BD024212E6671800899322 /* SDL_audio.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDB412E6671700899322 /* SDL_audio.c */; };
04BD024312E6671800899322 /* SDL_audio_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDB512E6671700899322 /* SDL_audio_c.h */; };
04BD024412E6671800899322 /* SDL_audiocvt.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDB612E6671700899322 /* SDL_audiocvt.c */; };
04BD024512E6671800899322 /* SDL_audiodev.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDB712E6671700899322 /* SDL_audiodev.c */; };
04BD024612E6671800899322 /* SDL_audiodev_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDB812E6671700899322 /* SDL_audiodev_c.h */; };
- 04BD024712E6671800899322 /* SDL_audiomem.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDB912E6671700899322 /* SDL_audiomem.h */; };
04BD024812E6671800899322 /* SDL_audiotypecvt.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDBA12E6671700899322 /* SDL_audiotypecvt.c */; };
04BD024912E6671800899322 /* SDL_mixer.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDBB12E6671700899322 /* SDL_mixer.c */; };
04BD025012E6671800899322 /* SDL_sysaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDC212E6671700899322 /* SDL_sysaudio.h */; };
@@ -387,6 +377,10 @@
04F7805D12FB74A200FC43C0 /* SDL_drawline.h in Headers */ = {isa = PBXBuildFile; fileRef = 04F7804512FB74A200FC43C0 /* SDL_drawline.h */; };
04F7805E12FB74A200FC43C0 /* SDL_drawpoint.c in Sources */ = {isa = PBXBuildFile; fileRef = 04F7804612FB74A200FC43C0 /* SDL_drawpoint.c */; };
04F7805F12FB74A200FC43C0 /* SDL_drawpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 04F7804712FB74A200FC43C0 /* SDL_drawpoint.h */; };
+ 562C4AE91D8F496200AF9EBE /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A7381E931D8B69C300B177DD /* AudioToolbox.framework */; };
+ 562C4AEA1D8F496300AF9EBE /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A7381E931D8B69C300B177DD /* AudioToolbox.framework */; };
+ 562D3C7C1D8F4933003FEEE6 /* SDL_coreaudio.m in Sources */ = {isa = PBXBuildFile; fileRef = FABA34C61D8B5DB100915323 /* SDL_coreaudio.m */; };
+ 562D3C7D1D8F4933003FEEE6 /* SDL_coreaudio.m in Sources */ = {isa = PBXBuildFile; fileRef = FABA34C61D8B5DB100915323 /* SDL_coreaudio.m */; };
566CDE8F148F0AC200C5A9BB /* SDL_dropevents_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 566CDE8D148F0AC200C5A9BB /* SDL_dropevents_c.h */; };
566CDE90148F0AC200C5A9BB /* SDL_dropevents.c in Sources */ = {isa = PBXBuildFile; fileRef = 566CDE8E148F0AC200C5A9BB /* SDL_dropevents.c */; };
567E2F1C17C44BB2005F1892 /* SDL_sysfilesystem.m in Sources */ = {isa = PBXBuildFile; fileRef = 567E2F1B17C44BB2005F1892 /* SDL_sysfilesystem.m */; };
@@ -406,6 +400,12 @@
56A6702A185654B40007D20F /* SDL_dynapi_overrides.h in Headers */ = {isa = PBXBuildFile; fileRef = 56A67020185654B40007D20F /* SDL_dynapi_overrides.h */; };
56A6702B185654B40007D20F /* SDL_dynapi_overrides.h in Headers */ = {isa = PBXBuildFile; fileRef = 56A67020185654B40007D20F /* SDL_dynapi_overrides.h */; };
56A6702C185654B40007D20F /* SDL_dynapi_overrides.h in Headers */ = {isa = PBXBuildFile; fileRef = 56A67020185654B40007D20F /* SDL_dynapi_overrides.h */; };
+ 56C5237E1D8F4985001F2F30 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A7381E951D8B69D600B177DD /* CoreAudio.framework */; };
+ 56C5237F1D8F4985001F2F30 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A7381E951D8B69D600B177DD /* CoreAudio.framework */; };
+ 56C523801D8F498B001F2F30 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00D0D08310675DD9004B05EF /* CoreFoundation.framework */; };
+ 56C523811D8F498C001F2F30 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00D0D08310675DD9004B05EF /* CoreFoundation.framework */; };
+ A7381E961D8B69D600B177DD /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A7381E951D8B69D600B177DD /* CoreAudio.framework */; };
+ A7381E971D8B6A0300B177DD /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A7381E931D8B69C300B177DD /* AudioToolbox.framework */; };
A77E6EB4167AB0A90010E40B /* SDL_gamecontroller.h in Headers */ = {isa = PBXBuildFile; fileRef = A77E6EB3167AB0A90010E40B /* SDL_gamecontroller.h */; settings = {ATTRIBUTES = (Public, ); }; };
A77E6EB5167AB0A90010E40B /* SDL_gamecontroller.h in Headers */ = {isa = PBXBuildFile; fileRef = A77E6EB3167AB0A90010E40B /* SDL_gamecontroller.h */; settings = {ATTRIBUTES = (Public, ); }; };
AA0AD09D16648D1700CE5896 /* SDL_gamecontroller.c in Sources */ = {isa = PBXBuildFile; fileRef = BBFC088A164C6514003E6A99 /* SDL_gamecontroller.c */; };
@@ -563,7 +563,6 @@
DB313F7617554B71006C0E22 /* SDL_coreaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDA112E6671700899322 /* SDL_coreaudio.h */; };
DB313F7717554B71006C0E22 /* SDL_audio_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDB512E6671700899322 /* SDL_audio_c.h */; };
DB313F7817554B71006C0E22 /* SDL_audiodev_c.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDB812E6671700899322 /* SDL_audiodev_c.h */; };
- DB313F7917554B71006C0E22 /* SDL_audiomem.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDB912E6671700899322 /* SDL_audiomem.h */; };
DB313F7A17554B71006C0E22 /* SDL_sysaudio.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDC212E6671700899322 /* SDL_sysaudio.h */; };
DB313F7B17554B71006C0E22 /* SDL_wave.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDC412E6671700899322 /* SDL_wave.h */; };
DB313F7C17554B71006C0E22 /* blank_cursor.h in Headers */ = {isa = PBXBuildFile; fileRef = 04BDFDD612E6671700899322 /* blank_cursor.h */; };
@@ -698,7 +697,6 @@
DB313FFF17554B71006C0E22 /* SDL_spinlock.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFD7512E6671700899322 /* SDL_spinlock.c */; };
DB31400017554B71006C0E22 /* SDL_diskaudio.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFD8812E6671700899322 /* SDL_diskaudio.c */; };
DB31400117554B71006C0E22 /* SDL_dummyaudio.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFD9412E6671700899322 /* SDL_dummyaudio.c */; };
- DB31400217554B71006C0E22 /* SDL_coreaudio.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDA012E6671700899322 /* SDL_coreaudio.c */; };
DB31400317554B71006C0E22 /* SDL_audio.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDB412E6671700899322 /* SDL_audio.c */; };
DB31400417554B71006C0E22 /* SDL_audiocvt.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDB612E6671700899322 /* SDL_audiocvt.c */; };
DB31400517554B71006C0E22 /* SDL_audiodev.c in Sources */ = {isa = PBXBuildFile; fileRef = 04BDFDB712E6671700899322 /* SDL_audiodev.c */; };
@@ -802,10 +800,7 @@
DB31406817554B71006C0E22 /* SDL_x11xinput2.c in Sources */ = {isa = PBXBuildFile; fileRef = AA628ACF159367F2005138DD /* SDL_x11xinput2.c */; };
DB31406917554B71006C0E22 /* SDL_x11messagebox.c in Sources */ = {isa = PBXBuildFile; fileRef = AA9E4092163BE51E007A2AD0 /* SDL_x11messagebox.c */; };
DB31406A17554B71006C0E22 /* SDL_cocoamessagebox.m in Sources */ = {isa = PBXBuildFile; fileRef = AABCC38C164063D200AB8930 /* SDL_cocoamessagebox.m */; };
- DB31406C17554B71006C0E22 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179B0858DECD00B2BC32 /* AudioToolbox.framework */; };
- DB31406D17554B71006C0E22 /* AudioUnit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179C0858DECD00B2BC32 /* AudioUnit.framework */; };
DB31406E17554B71006C0E22 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179D0858DECD00B2BC32 /* Cocoa.framework */; };
- DB31406F17554B71006C0E22 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179E0858DECD00B2BC32 /* CoreAudio.framework */; };
DB31407017554B71006C0E22 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0073179F0858DECD00B2BC32 /* IOKit.framework */; };
DB31407217554B71006C0E22 /* Carbon.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 007317C10858E15000B2BC32 /* Carbon.framework */; };
DB31408B17554D37006C0E22 /* ForceFeedback.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 00CFA89C106B4BA100758660 /* ForceFeedback.framework */; };
@@ -813,6 +808,7 @@
FA73671D19A540EF004122E4 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA73671C19A540EF004122E4 /* CoreVideo.framework */; };
FA73671E19A54140004122E4 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA73671C19A540EF004122E4 /* CoreVideo.framework */; };
FA73671F19A54144004122E4 /* CoreVideo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA73671C19A540EF004122E4 /* CoreVideo.framework */; };
+ FABA34C71D8B5DB100915323 /* SDL_coreaudio.m in Sources */ = {isa = PBXBuildFile; fileRef = FABA34C61D8B5DB100915323 /* SDL_coreaudio.m */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -826,10 +822,7 @@
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
- 0073179B0858DECD00B2BC32 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = /System/Library/Frameworks/AudioToolbox.framework; sourceTree = ""; };
- 0073179C0858DECD00B2BC32 /* AudioUnit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioUnit.framework; path = /System/Library/Frameworks/AudioUnit.framework; sourceTree = ""; };
0073179D0858DECD00B2BC32 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework; sourceTree = ""; };
- 0073179E0858DECD00B2BC32 /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = /System/Library/Frameworks/CoreAudio.framework; sourceTree = ""; };
0073179F0858DECD00B2BC32 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = /System/Library/Frameworks/IOKit.framework; sourceTree = ""; };
007317C10858E15000B2BC32 /* Carbon.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Carbon.framework; path = /System/Library/Frameworks/Carbon.framework; sourceTree = ""; };
00794D3F09D0C461003FC8A1 /* License.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = License.txt; sourceTree = ""; };
@@ -857,14 +850,12 @@
04BDFD8912E6671700899322 /* SDL_diskaudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_diskaudio.h; sourceTree = ""; };
04BDFD9412E6671700899322 /* SDL_dummyaudio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_dummyaudio.c; sourceTree = ""; };
04BDFD9512E6671700899322 /* SDL_dummyaudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_dummyaudio.h; sourceTree = ""; };
- 04BDFDA012E6671700899322 /* SDL_coreaudio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_coreaudio.c; sourceTree = ""; };
04BDFDA112E6671700899322 /* SDL_coreaudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_coreaudio.h; sourceTree = ""; };
04BDFDB412E6671700899322 /* SDL_audio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_audio.c; sourceTree = ""; };
04BDFDB512E6671700899322 /* SDL_audio_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_audio_c.h; sourceTree = ""; };
04BDFDB612E6671700899322 /* SDL_audiocvt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_audiocvt.c; sourceTree = ""; };
04BDFDB712E6671700899322 /* SDL_audiodev.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_audiodev.c; sourceTree = ""; };
04BDFDB812E6671700899322 /* SDL_audiodev_c.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_audiodev_c.h; sourceTree = ""; };
- 04BDFDB912E6671700899322 /* SDL_audiomem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_audiomem.h; sourceTree = ""; };
04BDFDBA12E6671700899322 /* SDL_audiotypecvt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_audiotypecvt.c; sourceTree = ""; };
04BDFDBB12E6671700899322 /* SDL_mixer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_mixer.c; sourceTree = ""; };
04BDFDC212E6671700899322 /* SDL_sysaudio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_sysaudio.h; sourceTree = ""; };
@@ -1027,6 +1018,8 @@
56A6701E185654B40007D20F /* SDL_dynapi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = SDL_dynapi.c; path = ../../src/dynapi/SDL_dynapi.c; sourceTree = ""; };
56A6701F185654B40007D20F /* SDL_dynapi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_dynapi.h; path = ../../src/dynapi/SDL_dynapi.h; sourceTree = ""; };
56A67020185654B40007D20F /* SDL_dynapi_overrides.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDL_dynapi_overrides.h; path = ../../src/dynapi/SDL_dynapi_overrides.h; sourceTree = ""; };
+ A7381E931D8B69C300B177DD /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
+ A7381E951D8B69D600B177DD /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; };
A77E6EB3167AB0A90010E40B /* SDL_gamecontroller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_gamecontroller.h; sourceTree = ""; };
AA0F8490178D5ECC00823F9D /* SDL_systls.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_systls.c; sourceTree = ""; };
AA628AC8159367B7005138DD /* SDL_rotate.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_rotate.c; sourceTree = ""; };
@@ -1106,6 +1099,7 @@
F59C710600D5CB5801000001 /* SDL.info */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; path = SDL.info; sourceTree = ""; };
F5A2EF3900C6A39A01000001 /* BUGS.txt */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = text; name = BUGS.txt; path = ../../BUGS.txt; sourceTree = SOURCE_ROOT; };
FA73671C19A540EF004122E4 /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = /System/Library/Frameworks/CoreVideo.framework; sourceTree = ""; };
+ FABA34C61D8B5DB100915323 /* SDL_coreaudio.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_coreaudio.m; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -1113,11 +1107,10 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ A7381E971D8B6A0300B177DD /* AudioToolbox.framework in Frameworks */,
+ A7381E961D8B69D600B177DD /* CoreAudio.framework in Frameworks */,
FA73671D19A540EF004122E4 /* CoreVideo.framework in Frameworks */,
- 007317A20858DECD00B2BC32 /* AudioToolbox.framework in Frameworks */,
- 007317A30858DECD00B2BC32 /* AudioUnit.framework in Frameworks */,
007317A40858DECD00B2BC32 /* Cocoa.framework in Frameworks */,
- 007317A50858DECD00B2BC32 /* CoreAudio.framework in Frameworks */,
007317A60858DECD00B2BC32 /* IOKit.framework in Frameworks */,
00D0D08410675DD9004B05EF /* CoreFoundation.framework in Frameworks */,
00D0D0D810675E46004B05EF /* Carbon.framework in Frameworks */,
@@ -1129,14 +1122,14 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ 56C5237E1D8F4985001F2F30 /* CoreAudio.framework in Frameworks */,
FA73671E19A54140004122E4 /* CoreVideo.framework in Frameworks */,
- 007317A90858DECD00B2BC32 /* AudioToolbox.framework in Frameworks */,
- 007317AA0858DECD00B2BC32 /* AudioUnit.framework in Frameworks */,
007317AB0858DECD00B2BC32 /* Cocoa.framework in Frameworks */,
- 007317AC0858DECD00B2BC32 /* CoreAudio.framework in Frameworks */,
007317AD0858DECD00B2BC32 /* IOKit.framework in Frameworks */,
+ 56C523801D8F498B001F2F30 /* CoreFoundation.framework in Frameworks */,
007317C30858E15000B2BC32 /* Carbon.framework in Frameworks */,
DB31408B17554D37006C0E22 /* ForceFeedback.framework in Frameworks */,
+ 562C4AE91D8F496200AF9EBE /* AudioToolbox.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1144,14 +1137,14 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ 56C5237F1D8F4985001F2F30 /* CoreAudio.framework in Frameworks */,
FA73671F19A54144004122E4 /* CoreVideo.framework in Frameworks */,
- DB31406C17554B71006C0E22 /* AudioToolbox.framework in Frameworks */,
- DB31406D17554B71006C0E22 /* AudioUnit.framework in Frameworks */,
DB31406E17554B71006C0E22 /* Cocoa.framework in Frameworks */,
- DB31406F17554B71006C0E22 /* CoreAudio.framework in Frameworks */,
DB31407017554B71006C0E22 /* IOKit.framework in Frameworks */,
+ 56C523811D8F498C001F2F30 /* CoreFoundation.framework in Frameworks */,
DB31407217554B71006C0E22 /* Carbon.framework in Frameworks */,
DB31408D17554D3C006C0E22 /* ForceFeedback.framework in Frameworks */,
+ 562C4AEA1D8F496300AF9EBE /* AudioToolbox.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1307,7 +1300,6 @@
04BDFDB612E6671700899322 /* SDL_audiocvt.c */,
04BDFDB712E6671700899322 /* SDL_audiodev.c */,
04BDFDB812E6671700899322 /* SDL_audiodev_c.h */,
- 04BDFDB912E6671700899322 /* SDL_audiomem.h */,
04BDFDBA12E6671700899322 /* SDL_audiotypecvt.c */,
04BDFDBB12E6671700899322 /* SDL_mixer.c */,
04BDFDC212E6671700899322 /* SDL_sysaudio.h */,
@@ -1339,8 +1331,8 @@
04BDFD9F12E6671700899322 /* coreaudio */ = {
isa = PBXGroup;
children = (
- 04BDFDA012E6671700899322 /* SDL_coreaudio.c */,
04BDFDA112E6671700899322 /* SDL_coreaudio.h */,
+ FABA34C61D8B5DB100915323 /* SDL_coreaudio.m */,
);
path = coreaudio;
sourceTree = "";
@@ -1737,13 +1729,12 @@
BEC562FE0761C0E800A33029 /* Linked Frameworks */ = {
isa = PBXGroup;
children = (
+ A7381E931D8B69C300B177DD /* AudioToolbox.framework */,
+ A7381E951D8B69D600B177DD /* CoreAudio.framework */,
FA73671C19A540EF004122E4 /* CoreVideo.framework */,
00D0D08310675DD9004B05EF /* CoreFoundation.framework */,
007317C10858E15000B2BC32 /* Carbon.framework */,
- 0073179B0858DECD00B2BC32 /* AudioToolbox.framework */,
- 0073179C0858DECD00B2BC32 /* AudioUnit.framework */,
0073179D0858DECD00B2BC32 /* Cocoa.framework */,
- 0073179E0858DECD00B2BC32 /* CoreAudio.framework */,
0073179F0858DECD00B2BC32 /* IOKit.framework */,
00CFA89C106B4BA100758660 /* ForceFeedback.framework */,
);
@@ -1840,7 +1831,6 @@
04BD001912E6671800899322 /* SDL_coreaudio.h in Headers */,
04BD002712E6671800899322 /* SDL_audio_c.h in Headers */,
04BD002A12E6671800899322 /* SDL_audiodev_c.h in Headers */,
- 04BD002B12E6671800899322 /* SDL_audiomem.h in Headers */,
04BD003412E6671800899322 /* SDL_sysaudio.h in Headers */,
04BD003612E6671800899322 /* SDL_wave.h in Headers */,
04BD004212E6671800899322 /* blank_cursor.h in Headers */,
@@ -1996,7 +1986,6 @@
04BD024312E6671800899322 /* SDL_audio_c.h in Headers */,
04BD024612E6671800899322 /* SDL_audiodev_c.h in Headers */,
AAC070FD195606770073DCDF /* SDL_opengles2_gl2.h in Headers */,
- 04BD024712E6671800899322 /* SDL_audiomem.h in Headers */,
04BD025012E6671800899322 /* SDL_sysaudio.h in Headers */,
04BD025212E6671800899322 /* SDL_wave.h in Headers */,
04BD025D12E6671800899322 /* blank_cursor.h in Headers */,
@@ -2151,7 +2140,6 @@
DB313F7717554B71006C0E22 /* SDL_audio_c.h in Headers */,
DB313F7817554B71006C0E22 /* SDL_audiodev_c.h in Headers */,
AAC070FE195606770073DCDF /* SDL_opengles2_gl2.h in Headers */,
- DB313F7917554B71006C0E22 /* SDL_audiomem.h in Headers */,
DB313F7A17554B71006C0E22 /* SDL_sysaudio.h in Headers */,
DB313F7B17554B71006C0E22 /* SDL_wave.h in Headers */,
DB313F7C17554B71006C0E22 /* blank_cursor.h in Headers */,
@@ -2323,7 +2311,7 @@
0867D690FE84028FC02AAC07 /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 0630;
+ LastUpgradeCheck = 0730;
TargetAttributes = {
BECDF5FE0761BA81005FE872 = {
DevelopmentTeam = EH385AYQ6F;
@@ -2404,7 +2392,6 @@
04BDFFFC12E6671800899322 /* SDL_spinlock.c in Sources */,
04BD000812E6671800899322 /* SDL_diskaudio.c in Sources */,
04BD001012E6671800899322 /* SDL_dummyaudio.c in Sources */,
- 04BD001812E6671800899322 /* SDL_coreaudio.c in Sources */,
04BD002612E6671800899322 /* SDL_audio.c in Sources */,
04BD002812E6671800899322 /* SDL_audiocvt.c in Sources */,
04BD002912E6671800899322 /* SDL_audiodev.c in Sources */,
@@ -2440,6 +2427,7 @@
04BD00A812E6671800899322 /* SDL_string.c in Sources */,
04BD00BD12E6671800899322 /* SDL_syscond.c in Sources */,
04BD00BE12E6671800899322 /* SDL_sysmutex.c in Sources */,
+ FABA34C71D8B5DB100915323 /* SDL_coreaudio.m in Sources */,
04BD00C012E6671800899322 /* SDL_syssem.c in Sources */,
04BD00C112E6671800899322 /* SDL_systhread.c in Sources */,
04BD00CA12E6671800899322 /* SDL_thread.c in Sources */,
@@ -2523,7 +2511,6 @@
04BD021812E6671800899322 /* SDL_spinlock.c in Sources */,
04BD022412E6671800899322 /* SDL_diskaudio.c in Sources */,
04BD022C12E6671800899322 /* SDL_dummyaudio.c in Sources */,
- 04BD023412E6671800899322 /* SDL_coreaudio.c in Sources */,
04BD024212E6671800899322 /* SDL_audio.c in Sources */,
04BD024412E6671800899322 /* SDL_audiocvt.c in Sources */,
04BD024512E6671800899322 /* SDL_audiodev.c in Sources */,
@@ -2559,6 +2546,7 @@
04BD02C012E6671800899322 /* SDL_qsort.c in Sources */,
04BD02C112E6671800899322 /* SDL_stdlib.c in Sources */,
04BD02C212E6671800899322 /* SDL_string.c in Sources */,
+ 562D3C7C1D8F4933003FEEE6 /* SDL_coreaudio.m in Sources */,
04BD02D712E6671800899322 /* SDL_syscond.c in Sources */,
04BD02D812E6671800899322 /* SDL_sysmutex.c in Sources */,
04BD02DA12E6671800899322 /* SDL_syssem.c in Sources */,
@@ -2642,7 +2630,6 @@
DB313FFF17554B71006C0E22 /* SDL_spinlock.c in Sources */,
DB31400017554B71006C0E22 /* SDL_diskaudio.c in Sources */,
DB31400117554B71006C0E22 /* SDL_dummyaudio.c in Sources */,
- DB31400217554B71006C0E22 /* SDL_coreaudio.c in Sources */,
DB31400317554B71006C0E22 /* SDL_audio.c in Sources */,
DB31400417554B71006C0E22 /* SDL_audiocvt.c in Sources */,
DB31400517554B71006C0E22 /* SDL_audiodev.c in Sources */,
@@ -2678,6 +2665,7 @@
DB31402417554B71006C0E22 /* SDL_qsort.c in Sources */,
DB31402517554B71006C0E22 /* SDL_stdlib.c in Sources */,
DB31402617554B71006C0E22 /* SDL_string.c in Sources */,
+ 562D3C7D1D8F4933003FEEE6 /* SDL_coreaudio.m in Sources */,
DB31402717554B71006C0E22 /* SDL_syscond.c in Sources */,
DB31402817554B71006C0E22 /* SDL_sysmutex.c in Sources */,
DB31402917554B71006C0E22 /* SDL_syssem.c in Sources */,
@@ -2767,14 +2755,31 @@
00CFA621106A567900758660 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
DEPLOYMENT_POSTPROCESSING = YES;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_ALTIVEC_EXTENSIONS = YES;
GCC_AUTO_VECTORIZATION = YES;
GCC_ENABLE_SSE3_EXTENSIONS = YES;
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 3;
GCC_SYMBOLS_PRIVATE_EXTERN = YES;
- MACOSX_DEPLOYMENT_TARGET = 10.5;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.6;
SDKROOT = macosx;
STRIP_STYLE = "non-global";
};
@@ -2783,15 +2788,17 @@
00CFA622106A567900758660 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
CLANG_LINK_OBJC_RUNTIME = NO;
COMBINE_HIDPI_IMAGES = YES;
DYLIB_COMPATIBILITY_VERSION = 1.0.0;
- DYLIB_CURRENT_VERSION = 5.0.0;
+ DYLIB_CURRENT_VERSION = 5.1.0;
FRAMEWORK_VERSION = A;
HEADER_SEARCH_PATHS = /usr/X11R6/include;
INFOPLIST_FILE = "Info-Framework.plist";
INSTALL_PATH = "@rpath";
OTHER_LDFLAGS = "-liconv";
+ PRODUCT_BUNDLE_IDENTIFIER = org.libsdl.SDL2;
PRODUCT_NAME = SDL2;
PROVISIONING_PROFILE = "";
WRAPPER_EXTENSION = framework;
@@ -2827,12 +2834,30 @@
00CFA627106A568900758660 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
GCC_ALTIVEC_EXTENSIONS = YES;
GCC_AUTO_VECTORIZATION = YES;
GCC_ENABLE_SSE3_EXTENSIONS = YES;
+ GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_SYMBOLS_PRIVATE_EXTERN = YES;
- MACOSX_DEPLOYMENT_TARGET = 10.5;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MACOSX_DEPLOYMENT_TARGET = 10.6;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
STRIP_INSTALLED_PRODUCT = NO;
@@ -2842,15 +2867,17 @@
00CFA628106A568900758660 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
CLANG_LINK_OBJC_RUNTIME = NO;
COMBINE_HIDPI_IMAGES = YES;
DYLIB_COMPATIBILITY_VERSION = 1.0.0;
- DYLIB_CURRENT_VERSION = 5.0.0;
+ DYLIB_CURRENT_VERSION = 5.1.0;
FRAMEWORK_VERSION = A;
HEADER_SEARCH_PATHS = /usr/X11R6/include;
INFOPLIST_FILE = "Info-Framework.plist";
INSTALL_PATH = "@rpath";
OTHER_LDFLAGS = "-liconv";
+ PRODUCT_BUNDLE_IDENTIFIER = org.libsdl.SDL2;
PRODUCT_NAME = SDL2;
PROVISIONING_PROFILE = "";
WRAPPER_EXTENSION = framework;
diff --git a/Engine/lib/sdl/Xcode/SDL/pkg-support/SDL.info b/Engine/lib/sdl/Xcode/SDL/pkg-support/SDL.info
old mode 100644
new mode 100755
diff --git a/Engine/lib/sdl/Xcode/SDL/pkg-support/resources/ReadMe.txt b/Engine/lib/sdl/Xcode/SDL/pkg-support/resources/ReadMe.txt
old mode 100644
new mode 100755
diff --git a/Engine/lib/sdl/Xcode/SDLTest/SDLTest.xcodeproj/project.pbxproj b/Engine/lib/sdl/Xcode/SDLTest/SDLTest.xcodeproj/project.pbxproj
old mode 100644
new mode 100755
index 59cdd631b..144d24ca5
--- a/Engine/lib/sdl/Xcode/SDLTest/SDLTest.xcodeproj/project.pbxproj
+++ b/Engine/lib/sdl/Xcode/SDLTest/SDLTest.xcodeproj/project.pbxproj
@@ -3934,7 +3934,7 @@
);
GCC_OPTIMIZATION_LEVEL = 0;
HEADER_SEARCH_PATHS = ../../include;
- MACOSX_DEPLOYMENT_TARGET = 10.5;
+ MACOSX_DEPLOYMENT_TARGET = 10.6;
};
name = Debug;
};
@@ -4060,7 +4060,7 @@
);
GCC_GENERATE_DEBUGGING_SYMBOLS = NO;
HEADER_SEARCH_PATHS = ../../include;
- MACOSX_DEPLOYMENT_TARGET = 10.5;
+ MACOSX_DEPLOYMENT_TARGET = 10.6;
};
name = Release;
};
diff --git a/Engine/lib/sdl/autogen.sh b/Engine/lib/sdl/autogen.sh
old mode 100644
new mode 100755
index 649d7b31e..3e958e195
--- a/Engine/lib/sdl/autogen.sh
+++ b/Engine/lib/sdl/autogen.sh
@@ -3,6 +3,10 @@
echo "Generating build information using autoconf"
echo "This may take a while ..."
+srcdir=`dirname $0`
+test -z "$srcdir" && srcdir=.
+pushd $srcdir
+
# Regenerate configuration files
cat acinclude/* >aclocal.m4
found=false
@@ -15,5 +19,7 @@ if test x$found = xfalse; then
fi
(cd test; sh autogen.sh)
+popd
+
# Run configure for this platform
echo "Now you are ready to run ./configure"
diff --git a/Engine/lib/sdl/build-scripts/androidbuild.sh b/Engine/lib/sdl/build-scripts/androidbuild.sh
old mode 100644
new mode 100755
index 8ca3c916d..fb48e2e5b
--- a/Engine/lib/sdl/build-scripts/androidbuild.sh
+++ b/Engine/lib/sdl/build-scripts/androidbuild.sh
@@ -87,8 +87,8 @@ else
fi
cp -r $SDLPATH/Android.mk $BUILDPATH/jni/SDL
-sed -i "s|YourSourceHere.c|$MKSOURCES|g" $BUILDPATH/jni/src/Android.mk
-sed -i "s|org\.libsdl\.app|$APP|g" $BUILDPATH/AndroidManifest.xml
+sed -i -e "s|YourSourceHere.c|$MKSOURCES|g" $BUILDPATH/jni/src/Android.mk
+sed -i -e "s|org\.libsdl\.app|$APP|g" $BUILDPATH/AndroidManifest.xml
# Copy user sources
for src in "${SOURCES[@]}"
@@ -105,8 +105,8 @@ do
done
ACTIVITY="${folder}Activity"
-sed -i "s|SDLActivity|$ACTIVITY|g" $BUILDPATH/AndroidManifest.xml
-sed -i "s|SDLActivity|$APP|g" $BUILDPATH/build.xml
+sed -i -e "s|SDLActivity|$ACTIVITY|g" $BUILDPATH/AndroidManifest.xml
+sed -i -e "s|SDLActivity|$APP|g" $BUILDPATH/build.xml
# Fill in a default Activity
echo "package $APP;" > "$ACTIVITY.java"
diff --git a/Engine/lib/sdl/build-scripts/checker-buildbot.sh b/Engine/lib/sdl/build-scripts/checker-buildbot.sh
old mode 100644
new mode 100755
index 682e7fbbb..eb014311a
--- a/Engine/lib/sdl/build-scripts/checker-buildbot.sh
+++ b/Engine/lib/sdl/build-scripts/checker-buildbot.sh
@@ -61,13 +61,13 @@ mkdir checker-buildbot
cd checker-buildbot
# You might want to do this for CMake-backed builds instead...
-PATH="$CHECKERDIR:$PATH" scan-build -o analysis cmake -DCMAKE_BUILD_TYPE=Debug ..
+PATH="$CHECKERDIR:$PATH" scan-build -o analysis cmake -DCMAKE_BUILD_TYPE=Debug -DASSERTIONS=enabled ..
# ...or run configure without the scan-build wrapper...
-#CC="$CHECKERDIR/libexec/ccc-analyzer" CFLAGS="-O0" ../configure
+#CC="$CHECKERDIR/libexec/ccc-analyzer" CFLAGS="-O0" ../configure --enable-assertions=enabled
# ...but this works for our buildbots just fine (EXCEPT ON LATEST MAC OS X).
-#CFLAGS="-O0" PATH="$CHECKERDIR:$PATH" scan-build -o analysis ../configure
+#CFLAGS="-O0" PATH="$CHECKERDIR:$PATH" scan-build -o analysis ../configure --enable-assertions=enabled
rm -rf analysis
PATH="$CHECKERDIR:$PATH" scan-build -o analysis $MAKE
diff --git a/Engine/lib/sdl/build-scripts/emscripten-buildbot.sh b/Engine/lib/sdl/build-scripts/emscripten-buildbot.sh
old mode 100644
new mode 100755
index db5fb8184..42eebb697
--- a/Engine/lib/sdl/build-scripts/emscripten-buildbot.sh
+++ b/Engine/lib/sdl/build-scripts/emscripten-buildbot.sh
@@ -51,13 +51,14 @@ mkdir buildbot
pushd buildbot
echo "Configuring..."
-emconfigure ../configure --host=asmjs-unknown-emscripten --disable-assembly --disable-threads --enable-cpuinfo=false CFLAGS="-O2 -Wno-warn-absolute-paths -Wdeclaration-after-statement -Werror=declaration-after-statement" --prefix="$PWD/emscripten-sdl2-installed"
+emconfigure ../configure --host=asmjs-unknown-emscripten --disable-assembly --disable-threads --enable-cpuinfo=false CFLAGS="-O2 -Wno-warn-absolute-paths -Wdeclaration-after-statement -Werror=declaration-after-statement" --prefix="$PWD/emscripten-sdl2-installed" || exit $?
echo "Building..."
-emmake $MAKE
+emmake $MAKE || exit $?
echo "Moving things around..."
-emmake $MAKE install
+emmake $MAKE install || exit $?
+
# Fix up a few things to a real install path
perl -w -pi -e "s#$PWD/emscripten-sdl2-installed#/usr/local#g;" ./emscripten-sdl2-installed/lib/libSDL2.la ./emscripten-sdl2-installed/lib/pkgconfig/sdl2.pc ./emscripten-sdl2-installed/bin/sdl2-config
mkdir -p ./usr
diff --git a/Engine/lib/sdl/build-scripts/g++-fat.sh b/Engine/lib/sdl/build-scripts/g++-fat.sh
old mode 100644
new mode 100755
index 29b04302f..0dbe99039
--- a/Engine/lib/sdl/build-scripts/g++-fat.sh
+++ b/Engine/lib/sdl/build-scripts/g++-fat.sh
@@ -6,11 +6,11 @@
DEVELOPER="`xcode-select -print-path`/Platforms/MacOSX.platform/Developer"
-# Intel 32-bit compiler flags (10.5 runtime compatibility)
-GCC_COMPILE_X86="g++ -arch i386 -mmacosx-version-min=10.5 \
+# Intel 32-bit compiler flags (10.6 runtime compatibility)
+GCC_COMPILE_X86="g++ -arch i386 -mmacosx-version-min=10.6 \
-I/usr/local/include"
-GCC_LINK_X86="-mmacosx-version-min=10.5"
+GCC_LINK_X86="-mmacosx-version-min=10.6"
# Intel 64-bit compiler flags (10.6 runtime compatibility)
GCC_COMPILE_X64="g++ -arch x86_64 -mmacosx-version-min=10.6 \
diff --git a/Engine/lib/sdl/build-scripts/gcc-fat.sh b/Engine/lib/sdl/build-scripts/gcc-fat.sh
old mode 100644
new mode 100755
index e556c1dd1..65f759d4a
--- a/Engine/lib/sdl/build-scripts/gcc-fat.sh
+++ b/Engine/lib/sdl/build-scripts/gcc-fat.sh
@@ -6,15 +6,15 @@
DEVELOPER="`xcode-select -print-path`/Platforms/MacOSX.platform/Developer"
-# Intel 32-bit compiler flags (10.5 runtime compatibility)
-GCC_COMPILE_X86="gcc -arch i386 -mmacosx-version-min=10.5 \
+# Intel 32-bit compiler flags (10.6 runtime compatibility)
+GCC_COMPILE_X86="gcc -arch i386 -mmacosx-version-min=10.6 \
-I/usr/local/include"
-GCC_LINK_X86="-mmacosx-version-min=10.5"
+GCC_LINK_X86="-mmacosx-version-min=10.6"
# Intel 64-bit compiler flags (10.6 runtime compatibility)
GCC_COMPILE_X64="gcc -arch x86_64 -mmacosx-version-min=10.6 \
--DMAC_OS_X_VERSION_MIN_REQUIRED=1050 \
+-DMAC_OS_X_VERSION_MIN_REQUIRED=1060 \
-I/usr/local/include"
GCC_LINK_X64="-mmacosx-version-min=10.6"
diff --git a/Engine/lib/sdl/build-scripts/install-sh b/Engine/lib/sdl/build-scripts/install-sh
old mode 100644
new mode 100755
diff --git a/Engine/lib/sdl/build-scripts/iosbuild.sh b/Engine/lib/sdl/build-scripts/iosbuild.sh
old mode 100644
new mode 100755
diff --git a/Engine/lib/sdl/build-scripts/ltmain.sh b/Engine/lib/sdl/build-scripts/ltmain.sh
old mode 100644
new mode 100755
diff --git a/Engine/lib/sdl/build-scripts/mkinstalldirs b/Engine/lib/sdl/build-scripts/mkinstalldirs
old mode 100644
new mode 100755
diff --git a/Engine/lib/sdl/build-scripts/nacl-buildbot.sh b/Engine/lib/sdl/build-scripts/nacl-buildbot.sh
old mode 100644
new mode 100755
diff --git a/Engine/lib/sdl/build-scripts/naclbuild.sh b/Engine/lib/sdl/build-scripts/naclbuild.sh
old mode 100644
new mode 100755
diff --git a/Engine/lib/sdl/build-scripts/raspberrypi-buildbot.sh b/Engine/lib/sdl/build-scripts/raspberrypi-buildbot.sh
old mode 100644
new mode 100755
diff --git a/Engine/lib/sdl/build-scripts/showrev.sh b/Engine/lib/sdl/build-scripts/showrev.sh
old mode 100644
new mode 100755
index 2a68fe694..517992d9c
--- a/Engine/lib/sdl/build-scripts/showrev.sh
+++ b/Engine/lib/sdl/build-scripts/showrev.sh
@@ -2,6 +2,4 @@
#
# Print the current source revision, if available
-# FIXME: this prints the tip, which isn't useful if you're on a different
-# branch, or just not sync'd to the tip.
-hg tip --template 'hg-{rev}:{node|short}' || (echo "hg-0:baadf00d"; exit 1)
+hg parents --template 'hg-{rev}:{node|short}' || (echo "hg-0:baadf00d"; exit 1)
diff --git a/Engine/lib/sdl/build-scripts/strip_fPIC.sh b/Engine/lib/sdl/build-scripts/strip_fPIC.sh
old mode 100644
new mode 100755
diff --git a/Engine/lib/sdl/build-scripts/update-copyright.sh b/Engine/lib/sdl/build-scripts/update-copyright.sh
old mode 100644
new mode 100755
diff --git a/Engine/lib/sdl/build-scripts/updaterev.sh b/Engine/lib/sdl/build-scripts/updaterev.sh
old mode 100644
new mode 100755
diff --git a/Engine/lib/sdl/cmake/sdlchecks.cmake b/Engine/lib/sdl/cmake/sdlchecks.cmake
index 7ff0985fd..b10078192 100644
--- a/Engine/lib/sdl/cmake/sdlchecks.cmake
+++ b/Engine/lib/sdl/cmake/sdlchecks.cmake
@@ -105,7 +105,9 @@ macro(CheckALSA)
if(ALSA)
CHECK_INCLUDE_FILE(alsa/asoundlib.h HAVE_ASOUNDLIB_H)
if(HAVE_ASOUNDLIB_H)
- CHECK_LIBRARY_EXISTS(asound snd_pcm_open "" HAVE_LIBASOUND)
+ CHECK_LIBRARY_EXISTS(asound snd_pcm_recover "" HAVE_LIBASOUND)
+ endif()
+ if(HAVE_LIBASOUND)
set(HAVE_ALSA TRUE)
file(GLOB ALSA_SOURCES ${SDL2_SOURCE_DIR}/src/audio/alsa/*.c)
set(SOURCE_FILES ${SOURCE_FILES} ${ALSA_SOURCES})
@@ -537,6 +539,27 @@ macro(CheckMir)
endif()
endmacro()
+macro(WaylandProtocolGen _SCANNER _XML _PROTL)
+ set(_WAYLAND_PROT_C_CODE "${CMAKE_CURRENT_BINARY_DIR}/wayland-generated-protocols/${_PROTL}-protocol.c")
+ set(_WAYLAND_PROT_H_CODE "${CMAKE_CURRENT_BINARY_DIR}/wayland-generated-protocols/${_PROTL}-client-protocol.h")
+
+ add_custom_command(
+ OUTPUT "${_WAYLAND_PROT_H_CODE}"
+ DEPENDS "${_XML}"
+ COMMAND "${_SCANNER}"
+ ARGS client-header "${_XML}" "${_WAYLAND_PROT_H_CODE}"
+ )
+
+ add_custom_command(
+ OUTPUT "${_WAYLAND_PROT_C_CODE}"
+ DEPENDS "${_WAYLAND_PROT_H_CODE}"
+ COMMAND "${_SCANNER}"
+ ARGS code "${_XML}" "${_WAYLAND_PROT_C_CODE}"
+ )
+
+ set(SOURCE_FILES ${SOURCE_FILES} "${CMAKE_CURRENT_BINARY_DIR}/wayland-generated-protocols/${_PROTL}-protocol.c")
+endmacro()
+
# Requires:
# - EGL
# - PkgCheckModules
@@ -545,7 +568,51 @@ endmacro()
# - HAVE_DLOPEN opt
macro(CheckWayland)
if(VIDEO_WAYLAND)
- pkg_check_modules(WAYLAND wayland-client wayland-cursor wayland-egl egl xkbcommon)
+ pkg_check_modules(WAYLAND wayland-client wayland-scanner wayland-protocols wayland-egl wayland-cursor egl xkbcommon)
+
+ # We have to generate some protocol interface code for some various Wayland features.
+ if(WAYLAND_FOUND)
+ execute_process(
+ COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=pkgdatadir wayland-client
+ WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
+ RESULT_VARIABLE WAYLAND_CORE_PROTOCOL_DIR_RC
+ OUTPUT_VARIABLE WAYLAND_CORE_PROTOCOL_DIR
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+ if(NOT WAYLAND_CORE_PROTOCOL_DIR_RC EQUAL 0)
+ set(WAYLAND_FOUND FALSE)
+ endif()
+ endif()
+
+ if(WAYLAND_FOUND)
+ execute_process(
+ COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=pkgdatadir wayland-protocols
+ WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
+ RESULT_VARIABLE WAYLAND_PROTOCOLS_DIR_RC
+ OUTPUT_VARIABLE WAYLAND_PROTOCOLS_DIR
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+ if(NOT WAYLAND_PROTOCOLS_DIR_RC EQUAL 0)
+ set(WAYLAND_FOUND FALSE)
+ endif()
+ endif()
+
+ if(WAYLAND_FOUND)
+ execute_process(
+ COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=wayland_scanner wayland-scanner
+ WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
+ RESULT_VARIABLE WAYLAND_SCANNER_RC
+ OUTPUT_VARIABLE WAYLAND_SCANNER
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+ if(NOT WAYLAND_SCANNER_RC EQUAL 0)
+ set(WAYLAND_FOUND FALSE)
+ endif()
+ endif()
+
if(WAYLAND_FOUND)
link_directories(
${WAYLAND_LIBRARY_DIRS}
@@ -559,6 +626,17 @@ macro(CheckWayland)
file(GLOB WAYLAND_SOURCES ${SDL2_SOURCE_DIR}/src/video/wayland/*.c)
set(SOURCE_FILES ${SOURCE_FILES} ${WAYLAND_SOURCES})
+ # We have to generate some protocol interface code for some unstable Wayland features.
+ file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/wayland-generated-protocols")
+ include_directories("${CMAKE_CURRENT_BINARY_DIR}/wayland-generated-protocols")
+
+ WaylandProtocolGen("${WAYLAND_SCANNER}" "${WAYLAND_CORE_PROTOCOL_DIR}/wayland.xml" "wayland")
+
+ foreach(_PROTL relative-pointer-unstable-v1 pointer-constraints-unstable-v1)
+ string(REGEX REPLACE "\\-unstable\\-.*$" "" PROTSUBDIR ${_PROTL})
+ WaylandProtocolGen("${WAYLAND_SCANNER}" "${WAYLAND_PROTOCOLS_DIR}/unstable/${PROTSUBDIR}/${_PROTL}.xml" "${_PROTL}")
+ endforeach()
+
if(VIDEO_WAYLAND_QT_TOUCH)
set(SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH 1)
endif()
@@ -679,7 +757,6 @@ macro(CheckOpenGLX11)
set(SDL_VIDEO_OPENGL 1)
set(SDL_VIDEO_OPENGL_GLX 1)
set(SDL_VIDEO_RENDER_OGL 1)
- list(APPEND EXTRA_LIBS GL)
endif()
endif()
endmacro()
@@ -767,7 +844,8 @@ macro(CheckPTHREAD)
endif()
# Run some tests
- set(CMAKE_REQUIRED_FLAGS "${PTHREAD_CFLAGS} ${PTHREAD_LDFLAGS}")
+ set(ORIG_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
+ set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${PTHREAD_CFLAGS} ${PTHREAD_LDFLAGS}")
if(CMAKE_CROSSCOMPILING)
set(HAVE_PTHREADS 1)
else()
@@ -829,7 +907,7 @@ macro(CheckPTHREAD)
int main(int argc, char** argv) { return 0; }" HAVE_PTHREAD_NP_H)
check_function_exists(pthread_setname_np HAVE_PTHREAD_SETNAME_NP)
check_function_exists(pthread_set_name_np HAVE_PTHREAD_SET_NAME_NP)
- set(CMAKE_REQUIRED_FLAGS)
+ set(CMAKE_REQUIRED_FLAGS "${ORIG_CMAKE_REQUIRED_FLAGS}")
set(SOURCE_FILES ${SOURCE_FILES}
${SDL2_SOURCE_DIR}/src/thread/pthread/SDL_systhread.c
@@ -883,7 +961,8 @@ macro(CheckUSBHID)
endif()
endif()
- set(CMAKE_REQUIRED_FLAGS "${USB_CFLAGS}")
+ set(ORIG_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
+ set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${USB_CFLAGS}")
set(CMAKE_REQUIRED_LIBRARIES "${USB_LIBS}")
check_c_source_compiles("
#include
@@ -984,7 +1063,7 @@ macro(CheckUSBHID)
set(HAVE_SDL_JOYSTICK TRUE)
set(CMAKE_REQUIRED_LIBRARIES)
- set(CMAKE_REQUIRED_FLAGS)
+ set(CMAKE_REQUIRED_FLAGS "${ORIG_CMAKE_REQUIRED_FLAGS}")
endif()
endmacro()
@@ -998,12 +1077,13 @@ macro(CheckRPI)
listtostr(VIDEO_RPI_INCLUDE_DIRS VIDEO_RPI_INCLUDE_FLAGS "-I")
listtostr(VIDEO_RPI_LIBRARY_DIRS VIDEO_RPI_LIBRARY_FLAGS "-L")
- set(CMAKE_REQUIRED_FLAGS "${VIDEO_RPI_INCLUDE_FLAGS} ${VIDEO_RPI_LIBRARY_FLAGS}")
+ set(ORIG_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}")
+ set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${VIDEO_RPI_INCLUDE_FLAGS} ${VIDEO_RPI_LIBRARY_FLAGS}")
set(CMAKE_REQUIRED_LIBRARIES "${VIDEO_RPI_LIBS}")
check_c_source_compiles("
#include
int main(int argc, char **argv) {}" HAVE_VIDEO_RPI)
- set(CMAKE_REQUIRED_FLAGS)
+ set(CMAKE_REQUIRED_FLAGS "${ORIG_CMAKE_REQUIRED_FLAGS}")
set(CMAKE_REQUIRED_LIBRARIES)
if(SDL_VIDEO AND HAVE_VIDEO_RPI)
diff --git a/Engine/lib/sdl/configure b/Engine/lib/sdl/configure
old mode 100644
new mode 100755
index a41f02595..5070f6e6a
--- a/Engine/lib/sdl/configure
+++ b/Engine/lib/sdl/configure
@@ -630,6 +630,7 @@ ac_includes_default="\
#endif"
ac_subst_vars='LTLIBOBJS
+WAYLAND_SCANNER
EXTRA_LDFLAGS
BUILD_LDFLAGS
EXTRA_CFLAGS
@@ -637,6 +638,8 @@ BUILD_CFLAGS
SDLTEST_OBJECTS
SDLMAIN_OBJECTS
VERSION_OBJECTS
+GEN_OBJECTS
+GEN_HEADERS
OBJECTS
INCLUDE
ac_aux_dir
@@ -846,7 +849,9 @@ enable_video_opengles1
enable_video_opengles2
enable_libudev
enable_dbus
+enable_ime
enable_ibus
+enable_fcitx
enable_input_tslib
enable_pthreads
enable_pthread_sem
@@ -1584,7 +1589,9 @@ Optional Features:
include OpenGL ES 2.0 support [[default=yes]]
--enable-libudev enable libudev support [[default=yes]]
--enable-dbus enable D-Bus support [[default=yes]]
+ --enable-ime enable IME support [[default=yes]]
--enable-ibus enable IBus support [[default=yes]]
+ --enable-fcitx enable fcitx support [[default=yes]]
--enable-input-tslib use the Touchscreen library for input
[[default=yes]]
--enable-pthreads use POSIX threads for multi-threading
@@ -2683,9 +2690,9 @@ orig_CFLAGS="$CFLAGS"
#
SDL_MAJOR_VERSION=2
SDL_MINOR_VERSION=0
-SDL_MICRO_VERSION=4
-SDL_INTERFACE_AGE=0
-SDL_BINARY_AGE=4
+SDL_MICRO_VERSION=5
+SDL_INTERFACE_AGE=1
+SDL_BINARY_AGE=5
SDL_VERSION=$SDL_MAJOR_VERSION.$SDL_MINOR_VERSION.$SDL_MICRO_VERSION
@@ -17601,7 +17608,7 @@ LIBS="$ALSA_LIBS $LIBS"
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ALSA_LIBS" >&5
$as_echo "$ALSA_LIBS" >&6; }
-min_alsa_version=0.9.0
+min_alsa_version=1.0.11
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for libasound headers version >= $min_alsa_version" >&5
$as_echo_n "checking for libasound headers version >= $min_alsa_version... " >&6; }
no_alsa=""
@@ -18650,6 +18657,43 @@ $as_echo "$have_gcc_preferred_stack_boundary" >&6; }
fi
}
+CheckDeclarationAfterStatement()
+{
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GCC -Wdeclaration-after-statement option" >&5
+$as_echo_n "checking for GCC -Wdeclaration-after-statement option... " >&6; }
+ have_gcc_declaration_after_statement=no
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$save_CFLAGS -Wdeclaration-after-statement -Werror=declaration-after-statement"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ int x = 0;
+
+int
+main ()
+{
+
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ have_gcc_declaration_after_statement=yes
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_gcc_declaration_after_statement" >&5
+$as_echo "$have_gcc_declaration_after_statement" >&6; }
+ CFLAGS="$save_CFLAGS"
+
+ if test x$have_gcc_declaration_after_statement = xyes; then
+ EXTRA_CFLAGS="$EXTRA_CFLAGS -Wdeclaration-after-statement -Werror=declaration-after-statement"
+ fi
+}
+
CheckWarnAll()
{
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GCC -Wall option" >&5
@@ -18767,9 +18811,12 @@ $as_echo_n "checking for Wayland support... " >&6; }
if test x$PKG_CONFIG != xno && \
test x$video_opengl_egl = xyes && \
test x$video_opengles_v2 = xyes; then
- if $PKG_CONFIG --exists wayland-client wayland-egl wayland-cursor egl xkbcommon ; then
+ if $PKG_CONFIG --exists wayland-client wayland-scanner wayland-protocols wayland-egl wayland-cursor egl xkbcommon ; then
WAYLAND_CFLAGS=`$PKG_CONFIG --cflags wayland-client wayland-egl wayland-cursor xkbcommon`
WAYLAND_LIBS=`$PKG_CONFIG --libs wayland-client wayland-egl wayland-cursor xkbcommon`
+ WAYLAND_SCANNER=`$PKG_CONFIG --variable=wayland_scanner wayland-scanner`
+ WAYLAND_CORE_PROTOCOL_DIR=`$PKG_CONFIG --variable=pkgdatadir wayland-client`
+ WAYLAND_PROTOCOLS_DIR=`$PKG_CONFIG --variable=pkgdatadir wayland-protocols`
video_wayland=yes
fi
fi
@@ -18785,8 +18832,11 @@ $as_echo "#define SDL_VIDEO_DRIVER_WAYLAND 1" >>confdefs.h
$as_echo "#define SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH 1" >>confdefs.h
fi
+
+ WAYLAND_PROTOCOLS_UNSTABLE="relative-pointer-unstable-v1 pointer-constraints-unstable-v1"
+
SOURCES="$SOURCES $srcdir/src/video/wayland/*.c"
- EXTRA_CFLAGS="$EXTRA_CFLAGS $WAYLAND_CFLAGS"
+ EXTRA_CFLAGS="$EXTRA_CFLAGS $WAYLAND_CFLAGS -I\$(gen)"
# Check whether --enable-wayland-shared was given.
if test "${enable_wayland_shared+set}" = set; then :
enableval=$enable_wayland_shared;
@@ -18928,7 +18978,7 @@ int
main ()
{
- MirMotionToolType tool = mir_motion_tool_type_mouse;
+ MirTouchAction actions = mir_touch_actions
;
return 0;
@@ -21604,6 +21654,23 @@ $as_echo "#define HAVE_DBUS_DBUS_H 1" >>confdefs.h
fi
}
+CheckIME()
+{
+ # Check whether --enable-ime was given.
+if test "${enable_ime+set}" = set; then :
+ enableval=$enable_ime;
+else
+ enable_ime=yes
+fi
+
+ if test x$enable_ime = xyes; then
+
+$as_echo "#define SDL_USE_IME 1" >>confdefs.h
+
+ SOURCES="$SOURCES $srcdir/src/core/linux/SDL_ime.c"
+ fi
+}
+
CheckIBus()
{
# Check whether --enable-ibus was given.
@@ -21677,7 +21744,11 @@ fi
CFLAGS="$save_CFLAGS"
if test x$have_ibus_ibus_h_hdr = xyes; then
- if test x$enable_dbus != xyes; then
+ if test x$enable_ime != xyes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: IME support is required for IBus." >&5
+$as_echo "$as_me: WARNING: IME support is required for IBus." >&2;}
+ have_ibus_ibus_h_hdr=no
+ elif test x$enable_dbus != xyes; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: DBus support is required for IBus." >&5
$as_echo "$as_me: WARNING: DBus support is required for IBus." >&2;}
have_ibus_ibus_h_hdr=no
@@ -21697,6 +21768,90 @@ $as_echo "#define HAVE_IBUS_IBUS_H 1" >>confdefs.h
fi
}
+CheckFcitx()
+{
+ # Check whether --enable-fcitx was given.
+if test "${enable_fcitx+set}" = set; then :
+ enableval=$enable_fcitx;
+else
+ enable_fcitx=yes
+fi
+
+ if test x$enable_fcitx = xyes; then
+ # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PKG_CONFIG+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $PKG_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_PKG_CONFIG" && ac_cv_path_PKG_CONFIG="no"
+ ;;
+esac
+fi
+PKG_CONFIG=$ac_cv_path_PKG_CONFIG
+if test -n "$PKG_CONFIG"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
+$as_echo "$PKG_CONFIG" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ if test x$PKG_CONFIG != xno; then
+ FCITX_CFLAGS=`$PKG_CONFIG --cflags fcitx`
+ CFLAGS="$CFLAGS $FCITX_CFLAGS"
+ ac_fn_c_check_header_mongrel "$LINENO" "fcitx/frontend.h" "ac_cv_header_fcitx_frontend_h" "$ac_includes_default"
+if test "x$ac_cv_header_fcitx_frontend_h" = xyes; then :
+ have_fcitx_frontend_h_hdr=yes
+else
+ have_fcitx_frontend_h_hdr=no
+fi
+
+
+ CFLAGS="$save_CFLAGS"
+ if test x$have_fcitx_frontend_h_hdr = xyes; then
+ if test x$enable_ime != xyes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: IME support is required for fcitx." >&5
+$as_echo "$as_me: WARNING: IME support is required for fcitx." >&2;}
+ have_fcitx_frontend_h_hdr=no
+ elif test x$enable_dbus != xyes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: DBus support is required for fcitx." >&5
+$as_echo "$as_me: WARNING: DBus support is required for fcitx." >&2;}
+ have_fcitx_frontend_h_hdr=no
+ else
+
+$as_echo "#define HAVE_FCITX_FRONTEND_H 1" >>confdefs.h
+
+ EXTRA_CFLAGS="$EXTRA_CFLAGS $FCITX_CFLAGS"
+ SOURCES="$SOURCES $srcdir/src/core/linux/SDL_fcitx.c"
+ fi
+ fi
+ fi
+ fi
+}
+
CheckTslib()
{
# Check whether --enable-input-tslib was given.
@@ -22894,6 +23049,8 @@ fi
}
+CheckWarnAll
+
case "$host" in
*-*-linux*|*-*-uclinux*|*-*-gnu*|*-*-k*bsd*-gnu|*-*-bsdi*|*-*-freebsd*|*-*-dragonfly*|*-*-netbsd*|*-*-openbsd*|*-*-sysv5*|*-*-solaris*|*-*-hpux*|*-*-aix*|*-*-minix*)
case "$host" in
@@ -22962,6 +23119,7 @@ case "$host" in
*-*-minix*) ARCH=minix ;;
esac
CheckVisibilityHidden
+ CheckDeclarationAfterStatement
CheckDummyVideo
CheckDiskAudio
CheckDummyAudio
@@ -22982,7 +23140,9 @@ case "$host" in
CheckWayland
CheckLibUDev
CheckDBus
+ CheckIME
CheckIBus
+ CheckFcitx
case $ARCH in
linux)
CheckInputEvents
@@ -23392,6 +23552,7 @@ $as_echo "#define SDL_FILESYSTEM_HAIKU 1" >>confdefs.h
ARCH=ios
CheckVisibilityHidden
+ CheckDeclarationAfterStatement
CheckDummyVideo
CheckDiskAudio
CheckDummyAudio
@@ -23402,7 +23563,7 @@ $as_echo "#define SDL_FILESYSTEM_HAIKU 1" >>confdefs.h
# Set up files for the audio library
if test x$enable_audio = xyes; then
- SOURCES="$SOURCES $srcdir/src/audio/coreaudio/*.c"
+ SOURCES="$SOURCES $srcdir/src/audio/coreaudio/*.m"
SUMMARY_audio="${SUMMARY_audio} coreaudio"
have_audio=yes
fi
@@ -23461,6 +23622,7 @@ $as_echo "#define SDL_FILESYSTEM_HAIKU 1" >>confdefs.h
EXTRA_CFLAGS="$EXTRA_CFLAGS -DTARGET_API_MAC_OSX"
CheckVisibilityHidden
+ CheckDeclarationAfterStatement
CheckDummyVideo
CheckDiskAudio
CheckDummyAudio
@@ -23476,7 +23638,8 @@ $as_echo "#define SDL_FILESYSTEM_HAIKU 1" >>confdefs.h
$as_echo "#define SDL_AUDIO_DRIVER_COREAUDIO 1" >>confdefs.h
- SOURCES="$SOURCES $srcdir/src/audio/coreaudio/*.c"
+ SOURCES="$SOURCES $srcdir/src/audio/coreaudio/*.m"
+ EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox"
SUMMARY_audio="${SUMMARY_audio} coreaudio"
have_audio=yes
fi
@@ -23494,8 +23657,8 @@ $as_echo "#define SDL_JOYSTICK_IOKIT 1" >>confdefs.h
$as_echo "#define SDL_HAPTIC_IOKIT 1" >>confdefs.h
SOURCES="$SOURCES $srcdir/src/haptic/darwin/*.c"
- have_haptic=yes
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,ForceFeedback"
+ have_haptic=yes
fi
# Set up files for the power library
if test x$enable_power = xyes; then
@@ -23532,10 +23695,6 @@ $as_echo "#define SDL_TIMER_UNIX 1" >>confdefs.h
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,Cocoa"
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,Carbon"
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,IOKit"
- # If audio is used, add the AudioUnit framework
- if test x$enable_audio = xyes; then
- EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,AudioUnit"
- fi
;;
*-nacl|*-pnacl)
ARCH=nacl
@@ -23581,6 +23740,7 @@ $as_echo "#define SDL_AUDIO_DRIVER_EMSCRIPTEN 1" >>confdefs.h
fi
CheckVisibilityHidden
+ CheckDeclarationAfterStatement
CheckDummyVideo
CheckDiskAudio
CheckDummyAudio
@@ -23630,8 +23790,6 @@ $as_echo "#define SDL_TIMER_UNIX 1" >>confdefs.h
;;
esac
-CheckWarnAll
-
# Verify that we have all the platform specific files we need
if test x$have_joystick != xyes; then
@@ -23687,6 +23845,57 @@ if test x$SDLMAIN_SOURCES = x; then
fi
SDLTEST_SOURCES="$srcdir/src/test/*.c"
+if test x$video_wayland = xyes; then
+ WAYLAND_CORE_PROTOCOL_SOURCE='$(gen)/wayland-protocol.c'
+ WAYLAND_CORE_PROTOCOL_HEADER='$(gen)/wayland-client-protocol.h'
+ WAYLAND_PROTOCOLS_UNSTABLE_SOURCES=`echo $WAYLAND_PROTOCOLS_UNSTABLE |\
+ sed 's,[^ ]\+,\\$(gen)/&-protocol.c,g'`
+ WAYLAND_PROTOCOLS_UNSTABLE_HEADERS=`echo $WAYLAND_PROTOCOLS_UNSTABLE |\
+ sed 's,[^ ]\+,\\$(gen)/&-client-protocol.h,g'`
+ GEN_SOURCES="$GEN_SOURCES $WAYLAND_CORE_PROTOCOL_SOURCE $WAYLAND_PROTOCOLS_UNSTABLE_SOURCES"
+ GEN_HEADERS="$GEN_HEADERS $WAYLAND_CORE_PROTOCOL_HEADER $WAYLAND_PROTOCOLS_UNSTABLE_HEADERS"
+
+ WAYLAND_CORE_PROTOCOL_SOURCE_DEPENDS="
+$WAYLAND_CORE_PROTOCOL_SOURCE: $WAYLAND_CORE_PROTOCOL_DIR/wayland.xml
+ \$(SHELL) \$(auxdir)/mkinstalldirs \$(gen)
+ \$(RUN_CMD_GEN)\$(WAYLAND_SCANNER) code \$< \$@"
+
+ WAYLAND_CORE_PROTOCOL_HEADER_DEPENDS="
+$WAYLAND_CORE_PROTOCOL_HEADER: $WAYLAND_CORE_PROTOCOL_DIR/wayland.xml
+ \$(SHELL) \$(auxdir)/mkinstalldirs \$(gen)
+ \$(RUN_CMD_GEN)\$(WAYLAND_SCANNER) client-header \$< \$@"
+
+ WAYLAND_CORE_PROTOCOL_OBJECT="
+\$(objects)/`echo $WAYLAND_CORE_PROTOCOL_SOURCE | sed 's/\$(gen)\/\(.*\).c$/\1.lo/'`: $WAYLAND_CORE_PROTOCOL_SOURCE
+ \$(RUN_CMD_CC)\$(LIBTOOL) --tag=CC --mode=compile \$(CC) \$(CFLAGS) \$(EXTRA_CFLAGS) $DEPENDENCY_TRACKING_OPTIONS -c \$< -o \$@"
+
+ WAYLAND_PROTOCOLS_CLIENT_HEADER_UNSTABLE_DEPENDS=`for p in $WAYLAND_PROTOCOLS_UNSTABLE;\
+ do echo ; echo \$p | sed\
+ "s,^\\([a-z\\-]\\+\\)-unstable-\\(v[0-9]\+\\)\$,\\$(gen)/&-client-protocol.h: $WAYLAND_PROTOCOLS_DIR/unstable/\1/&.xml\\\\
+ \\$(SHELL) \\$(auxdir)/mkinstalldirs \\$(gen)\\\\
+ \\$(RUN_CMD_GEN)\\$(WAYLAND_SCANNER) client-header \\$< \\$@," ; done`
+
+ WAYLAND_PROTOCOLS_CODE_UNSTABLE_DEPENDS=`for p in $WAYLAND_PROTOCOLS_UNSTABLE;\
+ do echo ; echo \$p | sed\
+ "s,^\\([a-z\\-]\\+\\)-unstable-\\(v[0-9]\+\\)\$,\\$(gen)/&-protocol.c: $WAYLAND_PROTOCOLS_DIR/unstable/\1/&.xml\\\\
+ \\$(SHELL) \\$(auxdir)/mkinstalldirs \\$(gen)\\\\
+ \\$(RUN_CMD_GEN)\\$(WAYLAND_SCANNER) code \\$< \\$@," ; done`
+
+ WAYLAND_PROTOCOLS_OBJECTS_UNSTABLE=`for p in $WAYLAND_PROTOCOLS_UNSTABLE;\
+ do echo ; echo \$p | sed\
+ "s,^\\([a-z\\-]\\+\\)-unstable-\\(v[0-9]\+\\)\$,\\\$(objects)/&-protocol.lo: \\$(gen)/&-protocol.c \\$(gen)/&-client-protocol.h\\\\
+ \\$(RUN_CMD_CC)\\$(LIBTOOL) --tag=CC --mode=compile \\$(CC) \\$(CFLAGS) \\$(EXTRA_CFLAGS) $DEPENDENCY_TRACKING_OPTIONS -c \\$< -o \\$@," ; done`
+
+ WAYLAND_PROTOCOLS_DEPENDS="
+$WAYLAND_CORE_PROTOCOL_SOURCE_DEPENDS
+$WAYLAND_CORE_PROTOCOL_HEADER_DEPENDS
+$WAYLAND_CORE_PROTOCOL_OBJECT
+$WAYLAND_PROTOCOLS_CLIENT_HEADER_UNSTABLE_DEPENDS
+$WAYLAND_PROTOCOLS_CODE_UNSTABLE_DEPENDS
+$WAYLAND_PROTOCOLS_OBJECTS_UNSTABLE
+"
+fi
+
OBJECTS=`echo $SOURCES`
DEPENDS=`echo $SOURCES | tr ' ' '\n'`
for EXT in asm cc m c S; do
@@ -23696,6 +23905,8 @@ for EXT in asm cc m c S; do
\\$(RUN_CMD_CC)\\$(LIBTOOL) --tag=CC --mode=compile \\$(CC) \\$(CFLAGS) \\$(EXTRA_CFLAGS) $DEPENDENCY_TRACKING_OPTIONS -c \\$< -o \\$@,g"`
done
+GEN_OBJECTS=`echo "$GEN_SOURCES" | sed 's,[^ ]*/\([^ ]*\)\.c,$(objects)/\1.lo,g'`
+
VERSION_OBJECTS=`echo $VERSION_SOURCES`
VERSION_DEPENDS=`echo $VERSION_SOURCES`
VERSION_OBJECTS=`echo "$VERSION_OBJECTS" | sed 's,[^ ]*/\([^ ]*\)\.rc,$(objects)/\1.o,g'`
@@ -23722,6 +23933,36 @@ SDLTEST_DEPENDS=`echo "$SDLTEST_DEPENDS" | sed "s,\\([^ ]*\\)/\\([^ ]*\\)\\.c,\\
if test "x$enable_rpath" = "xyes"; then
if test $ARCH = bsdi -o $ARCH = freebsd -o $ARCH = linux -o $ARCH = netbsd; then
SDL_RLD_FLAGS="-Wl,-rpath,\${libdir}"
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker option --enable-new-dtags" >&5
+$as_echo_n "checking for linker option --enable-new-dtags... " >&6; }
+ have_enable_new_dtags=no
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS -Wl,--enable-new-dtags"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+
+int
+main ()
+{
+
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+ have_enable_new_dtags=yes
+ SDL_RLD_FLAGS="$SDL_RLD_FLAGS -Wl,--enable-new-dtags"
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LDFLAGS="$save_LDFLAGS"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_enable_new_dtags" >&5
+$as_echo "$have_enable_new_dtags" >&6; }
fi
if test $ARCH = solaris; then
SDL_RLD_FLAGS="-R\${libdir}"
@@ -23767,6 +24008,9 @@ fi
+
+
+
cat >Makefile.rules <<__EOF__
# Build rules for objects
@@ -23778,6 +24022,7 @@ $DEPENDS
$VERSION_DEPENDS
$SDLMAIN_DEPENDS
$SDLTEST_DEPENDS
+$WAYLAND_PROTOCOLS_DEPENDS
__EOF__
ac_config_files="$ac_config_files Makefile:Makefile.in:Makefile.rules sdl2-config sdl2-config.cmake SDL2.spec sdl2.pc"
@@ -23810,11 +24055,21 @@ if test x$have_dbus_dbus_h_hdr = xyes; then
else
SUMMARY="${SUMMARY}Using dbus : NO\n"
fi
+if test x$enable_ime = xyes; then
+ SUMMARY="${SUMMARY}Using ime : YES\n"
+else
+ SUMMARY="${SUMMARY}Using ime : NO\n"
+fi
if test x$have_ibus_ibus_h_hdr = xyes; then
SUMMARY="${SUMMARY}Using ibus : YES\n"
else
SUMMARY="${SUMMARY}Using ibus : NO\n"
fi
+if test x$have_fcitx_frontend_h_hdr = xyes; then
+ SUMMARY="${SUMMARY}Using fcitx : YES\n"
+else
+ SUMMARY="${SUMMARY}Using fcitx : NO\n"
+fi
ac_config_commands="$ac_config_commands summary"
diff --git a/Engine/lib/sdl/configure.in b/Engine/lib/sdl/configure.in
index f585d01af..37c57e288 100644
--- a/Engine/lib/sdl/configure.in
+++ b/Engine/lib/sdl/configure.in
@@ -20,9 +20,9 @@ dnl Set various version strings - taken gratefully from the GTk sources
#
SDL_MAJOR_VERSION=2
SDL_MINOR_VERSION=0
-SDL_MICRO_VERSION=4
-SDL_INTERFACE_AGE=0
-SDL_BINARY_AGE=4
+SDL_MICRO_VERSION=5
+SDL_INTERFACE_AGE=1
+SDL_BINARY_AGE=5
SDL_VERSION=$SDL_MAJOR_VERSION.$SDL_MINOR_VERSION.$SDL_MICRO_VERSION
AC_SUBST(SDL_MAJOR_VERSION)
@@ -770,7 +770,7 @@ CheckALSA()
AC_HELP_STRING([--enable-alsa], [support the ALSA audio API [[default=yes]]]),
, enable_alsa=yes)
if test x$enable_audio = xyes -a x$enable_alsa = xyes; then
- AM_PATH_ALSA(0.9.0, have_alsa=yes, have_alsa=no)
+ AM_PATH_ALSA(1.0.11, have_alsa=yes, have_alsa=no)
# Restore all flags from before the ALSA detection runs
CFLAGS="$alsa_save_CFLAGS"
LDFLAGS="$alsa_save_LDFLAGS"
@@ -1124,6 +1124,30 @@ CheckStackBoundary()
fi
}
+dnl See if GCC's -Wdeclaration-after-statement is supported.
+dnl This lets us catch things that would fail on a C89 compiler when using
+dnl a modern GCC.
+CheckDeclarationAfterStatement()
+{
+ AC_MSG_CHECKING(for GCC -Wdeclaration-after-statement option)
+ have_gcc_declaration_after_statement=no
+
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$save_CFLAGS -Wdeclaration-after-statement -Werror=declaration-after-statement"
+ AC_TRY_COMPILE([
+ int x = 0;
+ ],[
+ ],[
+ have_gcc_declaration_after_statement=yes
+ ])
+ AC_MSG_RESULT($have_gcc_declaration_after_statement)
+ CFLAGS="$save_CFLAGS"
+
+ if test x$have_gcc_declaration_after_statement = xyes; then
+ EXTRA_CFLAGS="$EXTRA_CFLAGS -Wdeclaration-after-statement -Werror=declaration-after-statement"
+ fi
+}
+
dnl See if GCC's -Wall is supported.
CheckWarnAll()
{
@@ -1177,9 +1201,12 @@ AC_HELP_STRING([--enable-video-wayland-qt-touch], [QtWayland server support for
if test x$PKG_CONFIG != xno && \
test x$video_opengl_egl = xyes && \
test x$video_opengles_v2 = xyes; then
- if $PKG_CONFIG --exists wayland-client wayland-egl wayland-cursor egl xkbcommon ; then
+ if $PKG_CONFIG --exists wayland-client wayland-scanner wayland-protocols wayland-egl wayland-cursor egl xkbcommon ; then
WAYLAND_CFLAGS=`$PKG_CONFIG --cflags wayland-client wayland-egl wayland-cursor xkbcommon`
WAYLAND_LIBS=`$PKG_CONFIG --libs wayland-client wayland-egl wayland-cursor xkbcommon`
+ WAYLAND_SCANNER=`$PKG_CONFIG --variable=wayland_scanner wayland-scanner`
+ WAYLAND_CORE_PROTOCOL_DIR=`$PKG_CONFIG --variable=pkgdatadir wayland-client`
+ WAYLAND_PROTOCOLS_DIR=`$PKG_CONFIG --variable=pkgdatadir wayland-protocols`
video_wayland=yes
fi
fi
@@ -1190,8 +1217,11 @@ AC_HELP_STRING([--enable-video-wayland-qt-touch], [QtWayland server support for
if test x$enable_video_wayland_qt_touch = xyes; then
AC_DEFINE(SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH, 1, [ ])
fi
+
+ WAYLAND_PROTOCOLS_UNSTABLE="relative-pointer-unstable-v1 pointer-constraints-unstable-v1"
+
SOURCES="$SOURCES $srcdir/src/video/wayland/*.c"
- EXTRA_CFLAGS="$EXTRA_CFLAGS $WAYLAND_CFLAGS"
+ EXTRA_CFLAGS="$EXTRA_CFLAGS $WAYLAND_CFLAGS -I\$(gen)"
AC_ARG_ENABLE(wayland-shared,
AC_HELP_STRING([--enable-wayland-shared], [dynamically load Wayland support [[default=maybe]]]),
, enable_wayland_shared=maybe)
@@ -1260,12 +1290,12 @@ AC_HELP_STRING([--enable-video-mir], [use Mir video driver [[default=yes]]]),
MIR_LIBS=`$PKG_CONFIG --libs mirclient egl xkbcommon`
save_CFLAGS="$CFLAGS"
CFLAGS="$save_CFLAGS $MIR_CFLAGS"
-
- dnl This will disable Mir on Ubuntu < 14.04
+
+ dnl This will disable Mir if >= v0.25 is not available
AC_TRY_COMPILE([
#include
],[
- MirMotionToolType tool = mir_motion_tool_type_mouse;
+ MirTouchAction actions = mir_touch_actions
],[
video_mir=yes
])
@@ -2230,6 +2260,18 @@ AC_HELP_STRING([--enable-dbus], [enable D-Bus support [[default=yes]]]),
fi
}
+dnl See if the platform wanna IME support.
+CheckIME()
+{
+ AC_ARG_ENABLE(ime,
+AC_HELP_STRING([--enable-ime], [enable IME support [[default=yes]]]),
+ , enable_ime=yes)
+ if test x$enable_ime = xyes; then
+ AC_DEFINE(SDL_USE_IME, 1, [ ])
+ SOURCES="$SOURCES $srcdir/src/core/linux/SDL_ime.c"
+ fi
+}
+
dnl See if the platform has libibus IME support.
CheckIBus()
{
@@ -2250,7 +2292,10 @@ AC_HELP_STRING([--enable-ibus], [enable IBus support [[default=yes]]]),
have_inotify_inotify_h_hdr=no)
CFLAGS="$save_CFLAGS"
if test x$have_ibus_ibus_h_hdr = xyes; then
- if test x$enable_dbus != xyes; then
+ if test x$enable_ime != xyes; then
+ AC_MSG_WARN([IME support is required for IBus.])
+ have_ibus_ibus_h_hdr=no
+ elif test x$enable_dbus != xyes; then
AC_MSG_WARN([DBus support is required for IBus.])
have_ibus_ibus_h_hdr=no
elif test x$have_inotify_inotify_h_hdr != xyes; then
@@ -2266,6 +2311,38 @@ AC_HELP_STRING([--enable-ibus], [enable IBus support [[default=yes]]]),
fi
}
+dnl See if the platform has fcitx IME support.
+CheckFcitx()
+{
+ AC_ARG_ENABLE(fcitx,
+AC_HELP_STRING([--enable-fcitx], [enable fcitx support [[default=yes]]]),
+ , enable_fcitx=yes)
+ if test x$enable_fcitx = xyes; then
+ AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
+ if test x$PKG_CONFIG != xno; then
+ FCITX_CFLAGS=`$PKG_CONFIG --cflags fcitx`
+ CFLAGS="$CFLAGS $FCITX_CFLAGS"
+ AC_CHECK_HEADER(fcitx/frontend.h,
+ have_fcitx_frontend_h_hdr=yes,
+ have_fcitx_frontend_h_hdr=no)
+ CFLAGS="$save_CFLAGS"
+ if test x$have_fcitx_frontend_h_hdr = xyes; then
+ if test x$enable_ime != xyes; then
+ AC_MSG_WARN([IME support is required for fcitx.])
+ have_fcitx_frontend_h_hdr=no
+ elif test x$enable_dbus != xyes; then
+ AC_MSG_WARN([DBus support is required for fcitx.])
+ have_fcitx_frontend_h_hdr=no
+ else
+ AC_DEFINE(HAVE_FCITX_FRONTEND_H, 1, [ ])
+ EXTRA_CFLAGS="$EXTRA_CFLAGS $FCITX_CFLAGS"
+ SOURCES="$SOURCES $srcdir/src/core/linux/SDL_fcitx.c"
+ fi
+ fi
+ fi
+ fi
+}
+
dnl See if we can use the Touchscreen input library
CheckTslib()
{
@@ -2801,6 +2878,9 @@ AC_HELP_STRING([--enable-rpath], [use an rpath when linking SDL [[default=yes]]]
, enable_rpath=yes)
}
+dnl Do this on all platforms, before everything else (other things might want to override it).
+CheckWarnAll
+
dnl Set up the configuration based on the host platform!
case "$host" in
*-*-linux*|*-*-uclinux*|*-*-gnu*|*-*-k*bsd*-gnu|*-*-bsdi*|*-*-freebsd*|*-*-dragonfly*|*-*-netbsd*|*-*-openbsd*|*-*-sysv5*|*-*-solaris*|*-*-hpux*|*-*-aix*|*-*-minix*)
@@ -2870,6 +2950,7 @@ case "$host" in
*-*-minix*) ARCH=minix ;;
esac
CheckVisibilityHidden
+ CheckDeclarationAfterStatement
CheckDummyVideo
CheckDiskAudio
CheckDummyAudio
@@ -2890,7 +2971,9 @@ case "$host" in
CheckWayland
CheckLibUDev
CheckDBus
+ CheckIME
CheckIBus
+ CheckFcitx
case $ARCH in
linux)
CheckInputEvents
@@ -3196,6 +3279,7 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
ARCH=ios
CheckVisibilityHidden
+ CheckDeclarationAfterStatement
CheckDummyVideo
CheckDiskAudio
CheckDummyAudio
@@ -3206,7 +3290,7 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
# Set up files for the audio library
if test x$enable_audio = xyes; then
- SOURCES="$SOURCES $srcdir/src/audio/coreaudio/*.c"
+ SOURCES="$SOURCES $srcdir/src/audio/coreaudio/*.m"
SUMMARY_audio="${SUMMARY_audio} coreaudio"
have_audio=yes
fi
@@ -3265,6 +3349,7 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
EXTRA_CFLAGS="$EXTRA_CFLAGS -DTARGET_API_MAC_OSX"
CheckVisibilityHidden
+ CheckDeclarationAfterStatement
CheckDummyVideo
CheckDiskAudio
CheckDummyAudio
@@ -3278,7 +3363,8 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
# Set up files for the audio library
if test x$enable_audio = xyes; then
AC_DEFINE(SDL_AUDIO_DRIVER_COREAUDIO, 1, [ ])
- SOURCES="$SOURCES $srcdir/src/audio/coreaudio/*.c"
+ SOURCES="$SOURCES $srcdir/src/audio/coreaudio/*.m"
+ EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox"
SUMMARY_audio="${SUMMARY_audio} coreaudio"
have_audio=yes
fi
@@ -3292,8 +3378,8 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
if test x$enable_haptic = xyes; then
AC_DEFINE(SDL_HAPTIC_IOKIT, 1, [ ])
SOURCES="$SOURCES $srcdir/src/haptic/darwin/*.c"
- have_haptic=yes
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,ForceFeedback"
+ have_haptic=yes
fi
# Set up files for the power library
if test x$enable_power = xyes; then
@@ -3324,10 +3410,6 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,Cocoa"
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,Carbon"
EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,IOKit"
- # If audio is used, add the AudioUnit framework
- if test x$enable_audio = xyes; then
- EXTRA_LDFLAGS="$EXTRA_LDFLAGS -Wl,-framework,CoreAudio -Wl,-framework,AudioToolbox -Wl,-framework,AudioUnit"
- fi
;;
*-nacl|*-pnacl)
ARCH=nacl
@@ -3366,6 +3448,7 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
fi
CheckVisibilityHidden
+ CheckDeclarationAfterStatement
CheckDummyVideo
CheckDiskAudio
CheckDummyAudio
@@ -3407,9 +3490,6 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau
;;
esac
-dnl Do this on all platforms, after everything else.
-CheckWarnAll
-
# Verify that we have all the platform specific files we need
if test x$have_joystick != xyes; then
@@ -3453,6 +3533,57 @@ if test x$SDLMAIN_SOURCES = x; then
fi
SDLTEST_SOURCES="$srcdir/src/test/*.c"
+if test x$video_wayland = xyes; then
+ WAYLAND_CORE_PROTOCOL_SOURCE='$(gen)/wayland-protocol.c'
+ WAYLAND_CORE_PROTOCOL_HEADER='$(gen)/wayland-client-protocol.h'
+ WAYLAND_PROTOCOLS_UNSTABLE_SOURCES=`echo $WAYLAND_PROTOCOLS_UNSTABLE |\
+ sed 's,[[^ ]]\+,\\$(gen)/&-protocol.c,g'`
+ WAYLAND_PROTOCOLS_UNSTABLE_HEADERS=`echo $WAYLAND_PROTOCOLS_UNSTABLE |\
+ sed 's,[[^ ]]\+,\\$(gen)/&-client-protocol.h,g'`
+ GEN_SOURCES="$GEN_SOURCES $WAYLAND_CORE_PROTOCOL_SOURCE $WAYLAND_PROTOCOLS_UNSTABLE_SOURCES"
+ GEN_HEADERS="$GEN_HEADERS $WAYLAND_CORE_PROTOCOL_HEADER $WAYLAND_PROTOCOLS_UNSTABLE_HEADERS"
+
+ WAYLAND_CORE_PROTOCOL_SOURCE_DEPENDS="
+$WAYLAND_CORE_PROTOCOL_SOURCE: $WAYLAND_CORE_PROTOCOL_DIR/wayland.xml
+ \$(SHELL) \$(auxdir)/mkinstalldirs \$(gen)
+ \$(RUN_CMD_GEN)\$(WAYLAND_SCANNER) code \$< \$@"
+
+ WAYLAND_CORE_PROTOCOL_HEADER_DEPENDS="
+$WAYLAND_CORE_PROTOCOL_HEADER: $WAYLAND_CORE_PROTOCOL_DIR/wayland.xml
+ \$(SHELL) \$(auxdir)/mkinstalldirs \$(gen)
+ \$(RUN_CMD_GEN)\$(WAYLAND_SCANNER) client-header \$< \$@"
+
+ WAYLAND_CORE_PROTOCOL_OBJECT="
+\$(objects)/`echo $WAYLAND_CORE_PROTOCOL_SOURCE | sed 's/\$(gen)\/\(.*\).c$/\1.lo/'`: $WAYLAND_CORE_PROTOCOL_SOURCE
+ \$(RUN_CMD_CC)\$(LIBTOOL) --tag=CC --mode=compile \$(CC) \$(CFLAGS) \$(EXTRA_CFLAGS) $DEPENDENCY_TRACKING_OPTIONS -c \$< -o \$@"
+
+ WAYLAND_PROTOCOLS_CLIENT_HEADER_UNSTABLE_DEPENDS=`for p in $WAYLAND_PROTOCOLS_UNSTABLE;\
+ do echo ; echo \$p | sed\
+ "s,^\\([[a-z\\-]]\\+\\)-unstable-\\(v[[0-9]]\+\\)\$,\\$(gen)/&-client-protocol.h: $WAYLAND_PROTOCOLS_DIR/unstable/\1/&.xml\\\\
+ \\$(SHELL) \\$(auxdir)/mkinstalldirs \\$(gen)\\\\
+ \\$(RUN_CMD_GEN)\\$(WAYLAND_SCANNER) client-header \\$< \\$@," ; done`
+
+ WAYLAND_PROTOCOLS_CODE_UNSTABLE_DEPENDS=`for p in $WAYLAND_PROTOCOLS_UNSTABLE;\
+ do echo ; echo \$p | sed\
+ "s,^\\([[a-z\\-]]\\+\\)-unstable-\\(v[[0-9]]\+\\)\$,\\$(gen)/&-protocol.c: $WAYLAND_PROTOCOLS_DIR/unstable/\1/&.xml\\\\
+ \\$(SHELL) \\$(auxdir)/mkinstalldirs \\$(gen)\\\\
+ \\$(RUN_CMD_GEN)\\$(WAYLAND_SCANNER) code \\$< \\$@," ; done`
+
+ WAYLAND_PROTOCOLS_OBJECTS_UNSTABLE=`for p in $WAYLAND_PROTOCOLS_UNSTABLE;\
+ do echo ; echo \$p | sed\
+ "s,^\\([[a-z\\-]]\\+\\)-unstable-\\(v[[0-9]]\+\\)\$,\\\$(objects)/&-protocol.lo: \\$(gen)/&-protocol.c \\$(gen)/&-client-protocol.h\\\\
+ \\$(RUN_CMD_CC)\\$(LIBTOOL) --tag=CC --mode=compile \\$(CC) \\$(CFLAGS) \\$(EXTRA_CFLAGS) $DEPENDENCY_TRACKING_OPTIONS -c \\$< -o \\$@," ; done`
+
+ WAYLAND_PROTOCOLS_DEPENDS="
+$WAYLAND_CORE_PROTOCOL_SOURCE_DEPENDS
+$WAYLAND_CORE_PROTOCOL_HEADER_DEPENDS
+$WAYLAND_CORE_PROTOCOL_OBJECT
+$WAYLAND_PROTOCOLS_CLIENT_HEADER_UNSTABLE_DEPENDS
+$WAYLAND_PROTOCOLS_CODE_UNSTABLE_DEPENDS
+$WAYLAND_PROTOCOLS_OBJECTS_UNSTABLE
+"
+fi
+
OBJECTS=`echo $SOURCES`
DEPENDS=`echo $SOURCES | tr ' ' '\n'`
for EXT in asm cc m c S; do
@@ -3462,6 +3593,8 @@ for EXT in asm cc m c S; do
\\$(RUN_CMD_CC)\\$(LIBTOOL) --tag=CC --mode=compile \\$(CC) \\$(CFLAGS) \\$(EXTRA_CFLAGS) $DEPENDENCY_TRACKING_OPTIONS -c \\$< -o \\$@,g"`
done
+GEN_OBJECTS=`echo "$GEN_SOURCES" | sed 's,[[^ ]]*/\([[^ ]]*\)\.c,$(objects)/\1.lo,g'`
+
VERSION_OBJECTS=`echo $VERSION_SOURCES`
VERSION_DEPENDS=`echo $VERSION_SOURCES`
VERSION_OBJECTS=`echo "$VERSION_OBJECTS" | sed 's,[[^ ]]*/\([[^ ]]*\)\.rc,$(objects)/\1.o,g'`
@@ -3488,6 +3621,19 @@ SDLTEST_DEPENDS=`echo "$SDLTEST_DEPENDS" | sed "s,\\([[^ ]]*\\)/\\([[^ ]]*\\)\\.
if test "x$enable_rpath" = "xyes"; then
if test $ARCH = bsdi -o $ARCH = freebsd -o $ARCH = linux -o $ARCH = netbsd; then
SDL_RLD_FLAGS="-Wl,-rpath,\${libdir}"
+
+ AC_MSG_CHECKING(for linker option --enable-new-dtags)
+ have_enable_new_dtags=no
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS -Wl,--enable-new-dtags"
+ AC_TRY_LINK([
+ ],[
+ ],[
+ have_enable_new_dtags=yes
+ SDL_RLD_FLAGS="$SDL_RLD_FLAGS -Wl,--enable-new-dtags"
+ ])
+ LDFLAGS="$save_LDFLAGS"
+ AC_MSG_RESULT($have_enable_new_dtags)
fi
if test $ARCH = solaris; then
SDL_RLD_FLAGS="-R\${libdir}"
@@ -3526,6 +3672,8 @@ dnl Expand the sources and objects needed to build the library
AC_SUBST(ac_aux_dir)
AC_SUBST(INCLUDE)
AC_SUBST(OBJECTS)
+AC_SUBST(GEN_HEADERS)
+AC_SUBST(GEN_OBJECTS)
AC_SUBST(VERSION_OBJECTS)
AC_SUBST(SDLMAIN_OBJECTS)
AC_SUBST(SDLTEST_OBJECTS)
@@ -3534,6 +3682,7 @@ AC_SUBST(EXTRA_CFLAGS)
AC_SUBST(BUILD_LDFLAGS)
AC_SUBST(EXTRA_LDFLAGS)
AC_SUBST(WINDRES)
+AC_SUBST(WAYLAND_SCANNER)
cat >Makefile.rules <<__EOF__
@@ -3546,6 +3695,7 @@ $DEPENDS
$VERSION_DEPENDS
$SDLMAIN_DEPENDS
$SDLTEST_DEPENDS
+$WAYLAND_PROTOCOLS_DEPENDS
__EOF__
AC_CONFIG_FILES([
@@ -3578,11 +3728,21 @@ if test x$have_dbus_dbus_h_hdr = xyes; then
else
SUMMARY="${SUMMARY}Using dbus : NO\n"
fi
+if test x$enable_ime = xyes; then
+ SUMMARY="${SUMMARY}Using ime : YES\n"
+else
+ SUMMARY="${SUMMARY}Using ime : NO\n"
+fi
if test x$have_ibus_ibus_h_hdr = xyes; then
SUMMARY="${SUMMARY}Using ibus : YES\n"
else
SUMMARY="${SUMMARY}Using ibus : NO\n"
fi
+if test x$have_fcitx_frontend_h_hdr = xyes; then
+ SUMMARY="${SUMMARY}Using fcitx : YES\n"
+else
+ SUMMARY="${SUMMARY}Using fcitx : NO\n"
+fi
AC_CONFIG_COMMANDS([summary], [echo -en "$SUMMARY"], [SUMMARY="$SUMMARY"])
AC_OUTPUT
diff --git a/Engine/lib/sdl/debian/changelog b/Engine/lib/sdl/debian/changelog
index 84d1b878b..6a88d2473 100644
--- a/Engine/lib/sdl/debian/changelog
+++ b/Engine/lib/sdl/debian/changelog
@@ -1,3 +1,9 @@
+libsdl2 (2.0.4) UNRELEASED; urgency=low
+
+ * Updated SDL to version 2.0.4
+
+ -- Sam Lantinga Thu, 07 Jan 2016 11:02:39 -0800
+
libsdl2 (2.0.3) UNRELEASED; urgency=low
* Updated SDL to version 2.0.3
diff --git a/Engine/lib/sdl/debian/copyright b/Engine/lib/sdl/debian/copyright
index 8ce26d1c5..99c3d4496 100644
--- a/Engine/lib/sdl/debian/copyright
+++ b/Engine/lib/sdl/debian/copyright
@@ -31,10 +31,6 @@ Copyright: 1995 Erik Corry
1995 Brown University
License: BrownUn_UnCalifornia_ErikCorry
-Files: src/stdlib/SDL_qsort.c
-Copyright: 1998 Gareth McCaughan
-License: Gareth_McCaughan
-
Files: src/test/SDL_test_md5.c
Copyright: 1997-2016 Sam Lantinga
1990 RSA Data Security, Inc.
@@ -270,13 +266,6 @@ License: BrownUn_UnCalifornia_ErikCorry
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*/
-License: Gareth_McCaughan
- You may use it in anything you like; you may make money
- out of it; you may distribute it in object form or as
- part of an executable without including source code;
- you don't have to credit me. (But it would be nice if
- you did.)
-
License: Johnson_M._Hart
Permission is granted for any and all use providing that this
copyright is properly acknowledged.
diff --git a/Engine/lib/sdl/debian/libsdl2-dev.install b/Engine/lib/sdl/debian/libsdl2-dev.install
index 7f99ff427..af2c5b19d 100644
--- a/Engine/lib/sdl/debian/libsdl2-dev.install
+++ b/Engine/lib/sdl/debian/libsdl2-dev.install
@@ -5,4 +5,5 @@ usr/lib/*/libSDL2.a
usr/lib/*/libSDL2main.a
usr/lib/*/libSDL2_test.a
usr/lib/*/pkgconfig/sdl2.pc
+usr/lib/*/cmake/SDL2/sdl2-config.cmake
usr/share/aclocal/sdl2.m4
diff --git a/Engine/lib/sdl/debian/rules b/Engine/lib/sdl/debian/rules
old mode 100644
new mode 100755
diff --git a/Engine/lib/sdl/include/SDL.h b/Engine/lib/sdl/include/SDL.h
index 7647b5111..1a3fa285c 100644
--- a/Engine/lib/sdl/include/SDL.h
+++ b/Engine/lib/sdl/include/SDL.h
@@ -72,14 +72,14 @@ extern "C" {
* specify the subsystems which you will be using in your application.
*/
/* @{ */
-#define SDL_INIT_TIMER 0x00000001
-#define SDL_INIT_AUDIO 0x00000010
-#define SDL_INIT_VIDEO 0x00000020 /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
-#define SDL_INIT_JOYSTICK 0x00000200 /**< SDL_INIT_JOYSTICK implies SDL_INIT_EVENTS */
-#define SDL_INIT_HAPTIC 0x00001000
-#define SDL_INIT_GAMECONTROLLER 0x00002000 /**< SDL_INIT_GAMECONTROLLER implies SDL_INIT_JOYSTICK */
-#define SDL_INIT_EVENTS 0x00004000
-#define SDL_INIT_NOPARACHUTE 0x00100000 /**< compatibility; this flag is ignored. */
+#define SDL_INIT_TIMER 0x00000001u
+#define SDL_INIT_AUDIO 0x00000010u
+#define SDL_INIT_VIDEO 0x00000020u /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
+#define SDL_INIT_JOYSTICK 0x00000200u /**< SDL_INIT_JOYSTICK implies SDL_INIT_EVENTS */
+#define SDL_INIT_HAPTIC 0x00001000u
+#define SDL_INIT_GAMECONTROLLER 0x00002000u /**< SDL_INIT_GAMECONTROLLER implies SDL_INIT_JOYSTICK */
+#define SDL_INIT_EVENTS 0x00004000u
+#define SDL_INIT_NOPARACHUTE 0x00100000u /**< compatibility; this flag is ignored. */
#define SDL_INIT_EVERYTHING ( \
SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_EVENTS | \
SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER \
@@ -95,8 +95,8 @@ extern DECLSPEC int SDLCALL SDL_Init(Uint32 flags);
* This function initializes specific SDL subsystems
*
* Subsystem initialization is ref-counted, you must call
- * SDL_QuitSubSystem for each SDL_InitSubSystem to correctly
- * shutdown a subsystem manually (or call SDL_Quit to force shutdown).
+ * SDL_QuitSubSystem() for each SDL_InitSubSystem() to correctly
+ * shutdown a subsystem manually (or call SDL_Quit() to force shutdown).
* If a subsystem is already loaded then this call will
* increase the ref-count and return.
*/
diff --git a/Engine/lib/sdl/include/SDL_audio.h b/Engine/lib/sdl/include/SDL_audio.h
index 4f6552146..d51f0d1ce 100644
--- a/Engine/lib/sdl/include/SDL_audio.h
+++ b/Engine/lib/sdl/include/SDL_audio.h
@@ -278,7 +278,8 @@ extern DECLSPEC const char *SDLCALL SDL_GetCurrentAudioDriver(void);
* protect data structures that it accesses by calling SDL_LockAudio()
* and SDL_UnlockAudio() in your code. Alternately, you may pass a NULL
* pointer here, and call SDL_QueueAudio() with some frequency, to queue
- * more audio samples to be played.
+ * more audio samples to be played (or for capture devices, call
+ * SDL_DequeueAudio() with some frequency, to obtain audio samples).
* - \c desired->userdata is passed as the first parameter to your callback
* function. If you passed a NULL callback, this value is ignored.
*
@@ -482,6 +483,10 @@ extern DECLSPEC void SDLCALL SDL_MixAudioFormat(Uint8 * dst,
/**
* Queue more audio on non-callback devices.
*
+ * (If you are looking to retrieve queued audio from a non-callback capture
+ * device, you want SDL_DequeueAudio() instead. This will return -1 to
+ * signify an error if you use it with capture devices.)
+ *
* SDL offers two ways to feed audio to the device: you can either supply a
* callback that SDL triggers with some frequency to obtain more audio
* (pull method), or you can supply no callback, and then SDL will expect
@@ -516,21 +521,76 @@ extern DECLSPEC void SDLCALL SDL_MixAudioFormat(Uint8 * dst,
*/
extern DECLSPEC int SDLCALL SDL_QueueAudio(SDL_AudioDeviceID dev, const void *data, Uint32 len);
+/**
+ * Dequeue more audio on non-callback devices.
+ *
+ * (If you are looking to queue audio for output on a non-callback playback
+ * device, you want SDL_QueueAudio() instead. This will always return 0
+ * if you use it with playback devices.)
+ *
+ * SDL offers two ways to retrieve audio from a capture device: you can
+ * either supply a callback that SDL triggers with some frequency as the
+ * device records more audio data, (push method), or you can supply no
+ * callback, and then SDL will expect you to retrieve data at regular
+ * intervals (pull method) with this function.
+ *
+ * There are no limits on the amount of data you can queue, short of
+ * exhaustion of address space. Data from the device will keep queuing as
+ * necessary without further intervention from you. This means you will
+ * eventually run out of memory if you aren't routinely dequeueing data.
+ *
+ * Capture devices will not queue data when paused; if you are expecting
+ * to not need captured audio for some length of time, use
+ * SDL_PauseAudioDevice() to stop the capture device from queueing more
+ * data. This can be useful during, say, level loading times. When
+ * unpaused, capture devices will start queueing data from that point,
+ * having flushed any capturable data available while paused.
+ *
+ * This function is thread-safe, but dequeueing from the same device from
+ * two threads at once does not promise which thread will dequeued data
+ * first.
+ *
+ * You may not dequeue audio from a device that is using an
+ * application-supplied callback; doing so returns an error. You have to use
+ * the audio callback, or dequeue audio with this function, but not both.
+ *
+ * You should not call SDL_LockAudio() on the device before queueing; SDL
+ * handles locking internally for this function.
+ *
+ * \param dev The device ID from which we will dequeue audio.
+ * \param data A pointer into where audio data should be copied.
+ * \param len The number of bytes (not samples!) to which (data) points.
+ * \return number of bytes dequeued, which could be less than requested.
+ *
+ * \sa SDL_GetQueuedAudioSize
+ * \sa SDL_ClearQueuedAudio
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_DequeueAudio(SDL_AudioDeviceID dev, void *data, Uint32 len);
+
/**
* Get the number of bytes of still-queued audio.
*
- * This is the number of bytes that have been queued for playback with
- * SDL_QueueAudio(), but have not yet been sent to the hardware.
+ * For playback device:
*
- * Once we've sent it to the hardware, this function can not decide the exact
- * byte boundary of what has been played. It's possible that we just gave the
- * hardware several kilobytes right before you called this function, but it
- * hasn't played any of it yet, or maybe half of it, etc.
+ * This is the number of bytes that have been queued for playback with
+ * SDL_QueueAudio(), but have not yet been sent to the hardware. This
+ * number may shrink at any time, so this only informs of pending data.
+ *
+ * Once we've sent it to the hardware, this function can not decide the
+ * exact byte boundary of what has been played. It's possible that we just
+ * gave the hardware several kilobytes right before you called this
+ * function, but it hasn't played any of it yet, or maybe half of it, etc.
+ *
+ * For capture devices:
+ *
+ * This is the number of bytes that have been captured by the device and
+ * are waiting for you to dequeue. This number may grow at any time, so
+ * this only informs of the lower-bound of available data.
*
* You may not queue audio on a device that is using an application-supplied
* callback; calling this function on such a device always returns 0.
- * You have to use the audio callback or queue audio with SDL_QueueAudio(),
- * but not both.
+ * You have to queue audio with SDL_QueueAudio()/SDL_DequeueAudio(), or use
+ * the audio callback, but not both.
*
* You should not call SDL_LockAudio() on the device before querying; SDL
* handles locking internally for this function.
@@ -544,10 +604,17 @@ extern DECLSPEC int SDLCALL SDL_QueueAudio(SDL_AudioDeviceID dev, const void *da
extern DECLSPEC Uint32 SDLCALL SDL_GetQueuedAudioSize(SDL_AudioDeviceID dev);
/**
- * Drop any queued audio data waiting to be sent to the hardware.
+ * Drop any queued audio data. For playback devices, this is any queued data
+ * still waiting to be submitted to the hardware. For capture devices, this
+ * is any data that was queued by the device that hasn't yet been dequeued by
+ * the application.
*
- * Immediately after this call, SDL_GetQueuedAudioSize() will return 0 and
- * the hardware will start playing silence if more audio isn't queued.
+ * Immediately after this call, SDL_GetQueuedAudioSize() will return 0. For
+ * playback devices, the hardware will start playing silence if more audio
+ * isn't queued. Unpaused capture devices will start filling the queue again
+ * as soon as they have more data available (which, depending on the state
+ * of the hardware and the thread, could be before this function call
+ * returns!).
*
* This will not prevent playback of queued audio that's already been sent
* to the hardware, as we can not undo that, so expect there to be some
@@ -557,8 +624,8 @@ extern DECLSPEC Uint32 SDLCALL SDL_GetQueuedAudioSize(SDL_AudioDeviceID dev);
*
* You may not queue audio on a device that is using an application-supplied
* callback; calling this function on such a device is always a no-op.
- * You have to use the audio callback or queue audio with SDL_QueueAudio(),
- * but not both.
+ * You have to queue audio with SDL_QueueAudio()/SDL_DequeueAudio(), or use
+ * the audio callback, but not both.
*
* You should not call SDL_LockAudio() on the device before clearing the
* queue; SDL handles locking internally for this function.
diff --git a/Engine/lib/sdl/include/SDL_config.h.cmake b/Engine/lib/sdl/include/SDL_config.h.cmake
index 44173a053..98c62a994 100644
--- a/Engine/lib/sdl/include/SDL_config.h.cmake
+++ b/Engine/lib/sdl/include/SDL_config.h.cmake
@@ -81,6 +81,8 @@
#cmakedefine HAVE_PTHREAD_NP_H 1
#cmakedefine HAVE_LIBUDEV_H 1
#cmakedefine HAVE_DBUS_DBUS_H 1
+#cmakedefine HAVE_IBUS_IBUS_H 1
+#cmakedefine HAVE_FCITX_FRONTEND_H 1
/* C library functions */
#cmakedefine HAVE_MALLOC 1
diff --git a/Engine/lib/sdl/include/SDL_config.h.in b/Engine/lib/sdl/include/SDL_config.h.in
index 2071be4e5..d610cd6ba 100644
--- a/Engine/lib/sdl/include/SDL_config.h.in
+++ b/Engine/lib/sdl/include/SDL_config.h.in
@@ -82,6 +82,7 @@
#undef HAVE_LIBUDEV_H
#undef HAVE_DBUS_DBUS_H
#undef HAVE_IBUS_IBUS_H
+#undef HAVE_FCITX_FRONTEND_H
/* C library functions */
#undef HAVE_MALLOC
@@ -356,4 +357,7 @@
#undef SDL_ASSEMBLY_ROUTINES
#undef SDL_ALTIVEC_BLITTERS
+/* Enable ime support */
+#undef SDL_USE_IME
+
#endif /* _SDL_config_h */
diff --git a/Engine/lib/sdl/include/SDL_config_android.h b/Engine/lib/sdl/include/SDL_config_android.h
index a388ba8de..996cf76c9 100644
--- a/Engine/lib/sdl/include/SDL_config_android.h
+++ b/Engine/lib/sdl/include/SDL_config_android.h
@@ -43,6 +43,7 @@
#define HAVE_STDINT_H 1
#define HAVE_CTYPE_H 1
#define HAVE_MATH_H 1
+#define HAVE_SIGNAL_H 1
/* C library functions */
#define HAVE_MALLOC 1
@@ -75,6 +76,7 @@
#define HAVE_STRTOULL 1
#define HAVE_STRTOD 1
#define HAVE_ATOI 1
+#define HAVE_ATOF 1
#define HAVE_STRCMP 1
#define HAVE_STRNCMP 1
#define HAVE_STRCASECMP 1
@@ -101,6 +103,7 @@
#define HAVE_SQRTF 1
#define HAVE_TAN 1
#define HAVE_TANF 1
+#define HAVE_SIGACTION 1
#define HAVE_SETJMP 1
#define HAVE_NANOSLEEP 1
#define HAVE_SYSCONF 1
diff --git a/Engine/lib/sdl/include/SDL_config_iphoneos.h b/Engine/lib/sdl/include/SDL_config_iphoneos.h
index 304c89201..470985f80 100644
--- a/Engine/lib/sdl/include/SDL_config_iphoneos.h
+++ b/Engine/lib/sdl/include/SDL_config_iphoneos.h
@@ -119,11 +119,7 @@
#define SDL_JOYSTICK_MFI 1
/* Enable Unix style SO loading */
-/* Technically this works, but violates the iOS dev agreement prior to iOS 8 */
-/* #define SDL_LOADSO_DLOPEN 1 */
-
-/* Enable the stub shared object loader (src/loadso/dummy/\*.c) */
-#define SDL_LOADSO_DISABLED 1
+#define SDL_LOADSO_DLOPEN 1
/* Enable various threading systems */
#define SDL_THREAD_PTHREAD 1
diff --git a/Engine/lib/sdl/include/SDL_events.h b/Engine/lib/sdl/include/SDL_events.h
index 1437f4c70..edb89ef49 100644
--- a/Engine/lib/sdl/include/SDL_events.h
+++ b/Engine/lib/sdl/include/SDL_events.h
@@ -136,6 +136,9 @@ typedef enum
/* Drag and drop events */
SDL_DROPFILE = 0x1000, /**< The system requests a file open */
+ SDL_DROPTEXT, /**< text/plain drag-and-drop event */
+ SDL_DROPBEGIN, /**< A new set of drops is beginning (NULL filename) */
+ SDL_DROPCOMPLETE, /**< Current set of drops is now complete (NULL filename) */
/* Audio hotplug events */
SDL_AUDIODEVICEADDED = 0x1100, /**< A new audio device is available */
@@ -461,9 +464,10 @@ typedef struct SDL_DollarGestureEvent
*/
typedef struct SDL_DropEvent
{
- Uint32 type; /**< ::SDL_DROPFILE */
+ Uint32 type; /**< ::SDL_DROPBEGIN or ::SDL_DROPFILE or ::SDL_DROPTEXT or ::SDL_DROPCOMPLETE */
Uint32 timestamp;
- char *file; /**< The file name, which should be freed with SDL_free() */
+ char *file; /**< The file name, which should be freed with SDL_free(), is NULL on begin/complete */
+ Uint32 windowID; /**< The window that was dropped on, if any */
} SDL_DropEvent;
diff --git a/Engine/lib/sdl/include/SDL_gamecontroller.h b/Engine/lib/sdl/include/SDL_gamecontroller.h
index 42087eea1..e67fd9fd0 100644
--- a/Engine/lib/sdl/include/SDL_gamecontroller.h
+++ b/Engine/lib/sdl/include/SDL_gamecontroller.h
@@ -93,7 +93,7 @@ typedef struct SDL_GameControllerButtonBind
* }
* }
*
- * Using the SDL_HINT_GAMECONTROLLERCONFIG hint or the SDL_GameControllerAddMapping you can add support for controllers SDL is unaware of or cause an existing controller to have a different binding. The format is:
+ * Using the SDL_HINT_GAMECONTROLLERCONFIG hint or the SDL_GameControllerAddMapping() you can add support for controllers SDL is unaware of or cause an existing controller to have a different binding. The format is:
* guid,name,mappings
*
* Where GUID is the string value from SDL_JoystickGetGUIDString(), name is the human readable string for the device and mappings are controller mappings to joystick ones.
@@ -136,14 +136,14 @@ extern DECLSPEC int SDLCALL SDL_GameControllerAddMapping( const char* mappingStr
/**
* Get a mapping string for a GUID
*
- * \return the mapping string. Must be freed with SDL_free. Returns NULL if no mapping is available
+ * \return the mapping string. Must be freed with SDL_free(). Returns NULL if no mapping is available
*/
extern DECLSPEC char * SDLCALL SDL_GameControllerMappingForGUID( SDL_JoystickGUID guid );
/**
* Get a mapping string for an open GameController
*
- * \return the mapping string. Must be freed with SDL_free. Returns NULL if no mapping is available
+ * \return the mapping string. Must be freed with SDL_free(). Returns NULL if no mapping is available
*/
extern DECLSPEC char * SDLCALL SDL_GameControllerMapping( SDL_GameController * gamecontroller );
diff --git a/Engine/lib/sdl/include/SDL_haptic.h b/Engine/lib/sdl/include/SDL_haptic.h
index b36d78b12..9421c8f17 100644
--- a/Engine/lib/sdl/include/SDL_haptic.h
+++ b/Engine/lib/sdl/include/SDL_haptic.h
@@ -149,7 +149,7 @@ typedef struct _SDL_Haptic SDL_Haptic;
*
* \sa SDL_HapticCondition
*/
-#define SDL_HAPTIC_CONSTANT (1<<0)
+#define SDL_HAPTIC_CONSTANT (1u<<0)
/**
* \brief Sine wave effect supported.
@@ -158,7 +158,7 @@ typedef struct _SDL_Haptic SDL_Haptic;
*
* \sa SDL_HapticPeriodic
*/
-#define SDL_HAPTIC_SINE (1<<1)
+#define SDL_HAPTIC_SINE (1u<<1)
/**
* \brief Left/Right effect supported.
@@ -169,7 +169,7 @@ typedef struct _SDL_Haptic SDL_Haptic;
* \warning this value was SDL_HAPTIC_SQUARE right before 2.0.0 shipped. Sorry,
* we ran out of bits, and this is important for XInput devices.
*/
-#define SDL_HAPTIC_LEFTRIGHT (1<<2)
+#define SDL_HAPTIC_LEFTRIGHT (1u<<2)
/* !!! FIXME: put this back when we have more bits in 2.1 */
/* #define SDL_HAPTIC_SQUARE (1<<2) */
@@ -181,7 +181,7 @@ typedef struct _SDL_Haptic SDL_Haptic;
*
* \sa SDL_HapticPeriodic
*/
-#define SDL_HAPTIC_TRIANGLE (1<<3)
+#define SDL_HAPTIC_TRIANGLE (1u<<3)
/**
* \brief Sawtoothup wave effect supported.
@@ -190,7 +190,7 @@ typedef struct _SDL_Haptic SDL_Haptic;
*
* \sa SDL_HapticPeriodic
*/
-#define SDL_HAPTIC_SAWTOOTHUP (1<<4)
+#define SDL_HAPTIC_SAWTOOTHUP (1u<<4)
/**
* \brief Sawtoothdown wave effect supported.
@@ -199,7 +199,7 @@ typedef struct _SDL_Haptic SDL_Haptic;
*
* \sa SDL_HapticPeriodic
*/
-#define SDL_HAPTIC_SAWTOOTHDOWN (1<<5)
+#define SDL_HAPTIC_SAWTOOTHDOWN (1u<<5)
/**
* \brief Ramp effect supported.
@@ -208,7 +208,7 @@ typedef struct _SDL_Haptic SDL_Haptic;
*
* \sa SDL_HapticRamp
*/
-#define SDL_HAPTIC_RAMP (1<<6)
+#define SDL_HAPTIC_RAMP (1u<<6)
/**
* \brief Spring effect supported - uses axes position.
@@ -218,7 +218,7 @@ typedef struct _SDL_Haptic SDL_Haptic;
*
* \sa SDL_HapticCondition
*/
-#define SDL_HAPTIC_SPRING (1<<7)
+#define SDL_HAPTIC_SPRING (1u<<7)
/**
* \brief Damper effect supported - uses axes velocity.
@@ -228,7 +228,7 @@ typedef struct _SDL_Haptic SDL_Haptic;
*
* \sa SDL_HapticCondition
*/
-#define SDL_HAPTIC_DAMPER (1<<8)
+#define SDL_HAPTIC_DAMPER (1u<<8)
/**
* \brief Inertia effect supported - uses axes acceleration.
@@ -238,7 +238,7 @@ typedef struct _SDL_Haptic SDL_Haptic;
*
* \sa SDL_HapticCondition
*/
-#define SDL_HAPTIC_INERTIA (1<<9)
+#define SDL_HAPTIC_INERTIA (1u<<9)
/**
* \brief Friction effect supported - uses axes movement.
@@ -248,14 +248,14 @@ typedef struct _SDL_Haptic SDL_Haptic;
*
* \sa SDL_HapticCondition
*/
-#define SDL_HAPTIC_FRICTION (1<<10)
+#define SDL_HAPTIC_FRICTION (1u<<10)
/**
* \brief Custom effect is supported.
*
* User defined custom haptic effect.
*/
-#define SDL_HAPTIC_CUSTOM (1<<11)
+#define SDL_HAPTIC_CUSTOM (1u<<11)
/* @} *//* Haptic effects */
@@ -268,7 +268,7 @@ typedef struct _SDL_Haptic SDL_Haptic;
*
* \sa SDL_HapticSetGain
*/
-#define SDL_HAPTIC_GAIN (1<<12)
+#define SDL_HAPTIC_GAIN (1u<<12)
/**
* \brief Device can set autocenter.
@@ -277,7 +277,7 @@ typedef struct _SDL_Haptic SDL_Haptic;
*
* \sa SDL_HapticSetAutocenter
*/
-#define SDL_HAPTIC_AUTOCENTER (1<<13)
+#define SDL_HAPTIC_AUTOCENTER (1u<<13)
/**
* \brief Device can be queried for effect status.
@@ -286,7 +286,7 @@ typedef struct _SDL_Haptic SDL_Haptic;
*
* \sa SDL_HapticGetEffectStatus
*/
-#define SDL_HAPTIC_STATUS (1<<14)
+#define SDL_HAPTIC_STATUS (1u<<14)
/**
* \brief Device can be paused.
@@ -294,7 +294,7 @@ typedef struct _SDL_Haptic SDL_Haptic;
* \sa SDL_HapticPause
* \sa SDL_HapticUnpause
*/
-#define SDL_HAPTIC_PAUSE (1<<15)
+#define SDL_HAPTIC_PAUSE (1u<<15)
/**
diff --git a/Engine/lib/sdl/include/SDL_hints.h b/Engine/lib/sdl/include/SDL_hints.h
index 3bd5435fb..dd1546431 100644
--- a/Engine/lib/sdl/include/SDL_hints.h
+++ b/Engine/lib/sdl/include/SDL_hints.h
@@ -233,16 +233,27 @@ extern "C" {
#define SDL_HINT_GRAB_KEYBOARD "SDL_GRAB_KEYBOARD"
/**
-* \brief A variable controlling whether relative mouse mode is implemented using mouse warping
-*
-* This variable can be set to the following values:
-* "0" - Relative mouse mode uses raw input
-* "1" - Relative mouse mode uses mouse warping
-*
-* By default SDL will use raw input for relative mouse mode
-*/
+ * \brief A variable controlling whether relative mouse mode is implemented using mouse warping
+ *
+ * This variable can be set to the following values:
+ * "0" - Relative mouse mode uses raw input
+ * "1" - Relative mouse mode uses mouse warping
+ *
+ * By default SDL will use raw input for relative mouse mode
+ */
#define SDL_HINT_MOUSE_RELATIVE_MODE_WARP "SDL_MOUSE_RELATIVE_MODE_WARP"
+/**
+ * \brief Allow mouse click events when clicking to focus an SDL window
+ *
+ * This variable can be set to the following values:
+ * "0" - Ignore mouse clicks that activate a window
+ * "1" - Generate events for mouse clicks that activate a window
+ *
+ * By default SDL will ignore mouse clicks that activate a window
+ */
+#define SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH "SDL_MOUSE_FOCUS_CLICKTHROUGH"
+
/**
* \brief Minimize your SDL_Window if it loses key focus when in fullscreen mode. Defaults to true.
*
@@ -257,8 +268,8 @@ extern "C" {
* this is problematic. This functionality can be disabled by setting this
* hint.
*
- * As of SDL 2.0.4, SDL_EnableScreenSaver and SDL_DisableScreenSaver accomplish
- * the same thing on iOS. They should be preferred over this hint.
+ * As of SDL 2.0.4, SDL_EnableScreenSaver() and SDL_DisableScreenSaver()
+ * accomplish the same thing on iOS. They should be preferred over this hint.
*
* This variable can be set to the following values:
* "0" - Enable idle timer
@@ -276,7 +287,35 @@ extern "C" {
* "LandscapeLeft", "LandscapeRight", "Portrait" "PortraitUpsideDown"
*/
#define SDL_HINT_ORIENTATIONS "SDL_IOS_ORIENTATIONS"
-
+
+/**
+ * \brief A variable controlling whether controllers used with the Apple TV
+ * generate UI events.
+ *
+ * When UI events are generated by controller input, the app will be
+ * backgrounded when the Apple TV remote's menu button is pressed, and when the
+ * pause or B buttons on gamepads are pressed.
+ *
+ * More information about properly making use of controllers for the Apple TV
+ * can be found here:
+ * https://developer.apple.com/tvos/human-interface-guidelines/remote-and-controllers/
+ *
+ * This variable can be set to the following values:
+ * "0" - Controller input does not generate UI events (the default).
+ * "1" - Controller input generates UI events.
+ */
+#define SDL_HINT_APPLE_TV_CONTROLLER_UI_EVENTS "SDL_APPLE_TV_CONTROLLER_UI_EVENTS"
+
+/**
+ * \brief A variable controlling whether the Apple TV remote's joystick axes
+ * will automatically match the rotation of the remote.
+ *
+ * This variable can be set to the following values:
+ * "0" - Remote orientation does not affect joystick axes (the default).
+ * "1" - Joystick axes are based on the orientation of the remote.
+ */
+#define SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION "SDL_APPLE_TV_REMOTE_ALLOW_ROTATION"
+
/**
* \brief A variable controlling whether the Android / iOS built-in
* accelerometer should be listed as a joystick device, rather than listing
@@ -369,7 +408,7 @@ extern "C" {
* Use this hint in case you need to set SDL's threads stack size to other than the default.
* This is specially useful if you build SDL against a non glibc libc library (such as musl) which
* provides a relatively small default thread stack size (a few kilobytes versus the default 8MB glibc uses).
-* Support for this hint is currently available only in the pthread backend.
+* Support for this hint is currently available only in the pthread, Windows, and PSP backend.
*/
#define SDL_HINT_THREAD_STACK_SIZE "SDL_THREAD_STACK_SIZE"
@@ -431,7 +470,7 @@ extern "C" {
* privacy policy.
*
* To setup a URL to an app's privacy policy, set SDL_HINT_WINRT_PRIVACY_POLICY_URL
- * before calling any SDL_Init functions. The contents of the hint should
+ * before calling any SDL_Init() functions. The contents of the hint should
* be a valid URL. For example, "http://www.example.com".
*
* The default value is "", which will prevent SDL from adding a privacy policy
@@ -461,7 +500,7 @@ extern "C" {
* The contents of this hint should be encoded as a UTF8 string.
*
* The default value is "Privacy Policy". This hint should only be set during app
- * initialization, preferably before any calls to SDL_Init.
+ * initialization, preferably before any calls to SDL_Init().
*
* For additional information on linking to a privacy policy, see the documentation for
* SDL_HINT_WINRT_PRIVACY_POLICY_URL.
@@ -630,6 +669,44 @@ extern "C" {
*/
#define SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4 "SDL_WINDOWS_NO_CLOSE_ON_ALT_F4"
+/**
+ * \brief Prevent SDL from using version 4 of the bitmap header when saving BMPs.
+ *
+ * The bitmap header version 4 is required for proper alpha channel support and
+ * SDL will use it when required. Should this not be desired, this hint can
+ * force the use of the 40 byte header version which is supported everywhere.
+ *
+ * The variable can be set to the following values:
+ * "0" - Surfaces with a colorkey or an alpha channel are saved to a
+ * 32-bit BMP file with an alpha mask. SDL will use the bitmap
+ * header version 4 and set the alpha mask accordingly.
+ * "1" - Surfaces with a colorkey or an alpha channel are saved to a
+ * 32-bit BMP file without an alpha mask. The alpha channel data
+ * will be in the file, but applications are going to ignore it.
+ *
+ * The default value is "0".
+ */
+#define SDL_HINT_BMP_SAVE_LEGACY_FORMAT "SDL_BMP_SAVE_LEGACY_FORMAT"
+
+/**
+ * \brief Tell SDL not to name threads on Windows.
+ *
+ * The variable can be set to the following values:
+ * "0" - SDL will raise the 0x406D1388 Exception to name threads.
+ * This is the default behavior of SDL <= 2.0.4. (default)
+ * "1" - SDL will not raise this exception, and threads will be unnamed.
+ * For .NET languages this is required when running under a debugger.
+ */
+#define SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING "SDL_WINDOWS_DISABLE_THREAD_NAMING"
+
+/**
+ * \brief Tell SDL which Dispmanx layer to use on a Raspberry PI
+ *
+ * Also known as Z-order. The variable can take a negative or positive value.
+ * The default is 10000.
+ */
+#define SDL_HINT_RPI_VIDEO_LAYER "SDL_RPI_VIDEO_LAYER"
+
/**
* \brief An enumeration of hint priorities
*/
@@ -669,6 +746,13 @@ extern DECLSPEC SDL_bool SDLCALL SDL_SetHint(const char *name,
*/
extern DECLSPEC const char * SDLCALL SDL_GetHint(const char *name);
+/**
+ * \brief Get a hint
+ *
+ * \return The boolean value of a hint variable.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GetHintBoolean(const char *name, SDL_bool default_value);
+
/**
* \brief Add a function to watch a particular hint
*
diff --git a/Engine/lib/sdl/include/SDL_joystick.h b/Engine/lib/sdl/include/SDL_joystick.h
index 266f3b387..f5dbc9487 100644
--- a/Engine/lib/sdl/include/SDL_joystick.h
+++ b/Engine/lib/sdl/include/SDL_joystick.h
@@ -24,7 +24,7 @@
*
* Include file for SDL joystick event handling
*
- * The term "device_index" identifies currently plugged in joystick devices between 0 and SDL_NumJoysticks, with the exact joystick
+ * The term "device_index" identifies currently plugged in joystick devices between 0 and SDL_NumJoysticks(), with the exact joystick
* behind a device_index changing as joysticks are plugged and unplugged.
*
* The term "instance_id" is the current instantiation of a joystick device in the system, if the joystick is removed and then re-inserted
diff --git a/Engine/lib/sdl/include/SDL_keyboard.h b/Engine/lib/sdl/include/SDL_keyboard.h
index bbba0f07b..f80b6d2de 100644
--- a/Engine/lib/sdl/include/SDL_keyboard.h
+++ b/Engine/lib/sdl/include/SDL_keyboard.h
@@ -136,7 +136,7 @@ extern DECLSPEC SDL_Scancode SDLCALL SDL_GetScancodeFromName(const char *name);
* copy it. If the key doesn't have a name, this function returns an
* empty string ("").
*
- * \sa SDL_Key
+ * \sa SDL_Keycode
*/
extern DECLSPEC const char *SDLCALL SDL_GetKeyName(SDL_Keycode key);
diff --git a/Engine/lib/sdl/include/SDL_main.h b/Engine/lib/sdl/include/SDL_main.h
index 9ce3754e9..67afea5e7 100644
--- a/Engine/lib/sdl/include/SDL_main.h
+++ b/Engine/lib/sdl/include/SDL_main.h
@@ -63,7 +63,7 @@
/* On Android SDL provides a Java class in SDLActivity.java that is the
main activity entry point.
- See README-android.txt for more details on extending that class.
+ See README-android.md for more details on extending that class.
*/
#define SDL_MAIN_NEEDED
diff --git a/Engine/lib/sdl/include/SDL_mouse.h b/Engine/lib/sdl/include/SDL_mouse.h
index ea9622f0f..46f046d0c 100644
--- a/Engine/lib/sdl/include/SDL_mouse.h
+++ b/Engine/lib/sdl/include/SDL_mouse.h
@@ -41,7 +41,7 @@ extern "C" {
typedef struct SDL_Cursor SDL_Cursor; /* Implementation dependent */
/**
- * \brief Cursor types for SDL_CreateSystemCursor.
+ * \brief Cursor types for SDL_CreateSystemCursor().
*/
typedef enum
{
@@ -254,9 +254,11 @@ extern DECLSPEC SDL_Cursor *SDLCALL SDL_GetCursor(void);
extern DECLSPEC SDL_Cursor *SDLCALL SDL_GetDefaultCursor(void);
/**
- * \brief Frees a cursor created with SDL_CreateCursor().
+ * \brief Frees a cursor created with SDL_CreateCursor() or similar functions.
*
* \sa SDL_CreateCursor()
+ * \sa SDL_CreateColorCursor()
+ * \sa SDL_CreateSystemCursor()
*/
extern DECLSPEC void SDLCALL SDL_FreeCursor(SDL_Cursor * cursor);
diff --git a/Engine/lib/sdl/include/SDL_opengles.h b/Engine/lib/sdl/include/SDL_opengles.h
index bcc127779..15abee796 100644
--- a/Engine/lib/sdl/include/SDL_opengles.h
+++ b/Engine/lib/sdl/include/SDL_opengles.h
@@ -24,6 +24,7 @@
*
* This is a simple file to encapsulate the OpenGL ES 1.X API headers.
*/
+#include "SDL_config.h"
#ifdef __IPHONEOS__
#include
diff --git a/Engine/lib/sdl/include/SDL_opengles2.h b/Engine/lib/sdl/include/SDL_opengles2.h
index edcd1a24a..c961f0f7d 100644
--- a/Engine/lib/sdl/include/SDL_opengles2.h
+++ b/Engine/lib/sdl/include/SDL_opengles2.h
@@ -24,6 +24,8 @@
*
* This is a simple file to encapsulate the OpenGL ES 2.0 API headers.
*/
+#include "SDL_config.h"
+
#ifndef _MSC_VER
#ifdef __IPHONEOS__
diff --git a/Engine/lib/sdl/include/SDL_pixels.h b/Engine/lib/sdl/include/SDL_pixels.h
index 8499c3289..cf6a33f08 100644
--- a/Engine/lib/sdl/include/SDL_pixels.h
+++ b/Engine/lib/sdl/include/SDL_pixels.h
@@ -29,6 +29,7 @@
#define _SDL_pixels_h
#include "SDL_stdinc.h"
+#include "SDL_endian.h"
#include "begin_code.h"
/* Set up for C function definitions, even when using C++ */
@@ -260,6 +261,19 @@ enum
SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_ARGB,
SDL_PACKEDLAYOUT_2101010, 32, 4),
+ /* Aliases for RGBA byte arrays of color data, for the current platform */
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+ SDL_PIXELFORMAT_RGBA32 = SDL_PIXELFORMAT_RGBA8888,
+ SDL_PIXELFORMAT_ARGB32 = SDL_PIXELFORMAT_ARGB8888,
+ SDL_PIXELFORMAT_BGRA32 = SDL_PIXELFORMAT_BGRA8888,
+ SDL_PIXELFORMAT_ABGR32 = SDL_PIXELFORMAT_ABGR8888,
+#else
+ SDL_PIXELFORMAT_RGBA32 = SDL_PIXELFORMAT_ABGR8888,
+ SDL_PIXELFORMAT_ARGB32 = SDL_PIXELFORMAT_BGRA8888,
+ SDL_PIXELFORMAT_BGRA32 = SDL_PIXELFORMAT_ARGB8888,
+ SDL_PIXELFORMAT_ABGR32 = SDL_PIXELFORMAT_RGBA8888,
+#endif
+
SDL_PIXELFORMAT_YV12 = /**< Planar mode: Y + V + U (3 planes) */
SDL_DEFINE_PIXELFOURCC('Y', 'V', '1', '2'),
SDL_PIXELFORMAT_IYUV = /**< Planar mode: Y + U + V (3 planes) */
diff --git a/Engine/lib/sdl/include/SDL_platform.h b/Engine/lib/sdl/include/SDL_platform.h
index c6c21398b..03cf17061 100644
--- a/Engine/lib/sdl/include/SDL_platform.h
+++ b/Engine/lib/sdl/include/SDL_platform.h
@@ -70,18 +70,22 @@
/* lets us know what version of Mac OS X we're compiling on */
#include "AvailabilityMacros.h"
#include "TargetConditionals.h"
+#if TARGET_OS_TV
+#undef __TVOS__
+#define __TVOS__ 1
+#endif
#if TARGET_OS_IPHONE
-/* if compiling for iPhone */
+/* if compiling for iOS */
#undef __IPHONEOS__
#define __IPHONEOS__ 1
#undef __MACOSX__
#else
-/* if not compiling for iPhone */
+/* if not compiling for iOS */
#undef __MACOSX__
#define __MACOSX__ 1
-#if MAC_OS_X_VERSION_MIN_REQUIRED < 1050
-# error SDL for Mac OS X only supports deploying on 10.5 and above.
-#endif /* MAC_OS_X_VERSION_MIN_REQUIRED < 1050 */
+#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
+# error SDL for Mac OS X only supports deploying on 10.6 and above.
+#endif /* MAC_OS_X_VERSION_MIN_REQUIRED < 1060 */
#endif /* TARGET_OS_IPHONE */
#endif /* defined(__APPLE__) */
diff --git a/Engine/lib/sdl/include/SDL_render.h b/Engine/lib/sdl/include/SDL_render.h
index e4ed2af69..60c87b66a 100644
--- a/Engine/lib/sdl/include/SDL_render.h
+++ b/Engine/lib/sdl/include/SDL_render.h
@@ -499,6 +499,30 @@ extern DECLSPEC int SDLCALL SDL_RenderSetLogicalSize(SDL_Renderer * renderer, in
*/
extern DECLSPEC void SDLCALL SDL_RenderGetLogicalSize(SDL_Renderer * renderer, int *w, int *h);
+/**
+ * \brief Set whether to force integer scales for resolution-independent rendering
+ *
+ * \param renderer The renderer for which integer scaling should be set.
+ * \param enable Enable or disable integer scaling
+ *
+ * This function restricts the logical viewport to integer values - that is, when
+ * a resolution is between two multiples of a logical size, the viewport size is
+ * rounded down to the lower multiple.
+ *
+ * \sa SDL_RenderSetLogicalSize()
+ */
+extern DECLSPEC int SDLCALL SDL_RenderSetIntegerScale(SDL_Renderer * renderer,
+ SDL_bool enable);
+
+/**
+ * \brief Get whether integer scales are forced for resolution-independent rendering
+ *
+ * \param renderer The renderer from which integer scaling should be queried.
+ *
+ * \sa SDL_RenderSetIntegerScale()
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_RenderGetIntegerScale(SDL_Renderer * renderer);
+
/**
* \brief Set the drawing area for rendering on the current target.
*
@@ -658,7 +682,8 @@ extern DECLSPEC int SDLCALL SDL_GetRenderDrawBlendMode(SDL_Renderer * renderer,
/**
* \brief Clear the current rendering target with the drawing color
*
- * This function clears the entire rendering target, ignoring the viewport.
+ * This function clears the entire rendering target, ignoring the viewport and
+ * the clip rectangle.
*
* \return 0 on success, or -1 on error
*/
diff --git a/Engine/lib/sdl/include/SDL_revision.h b/Engine/lib/sdl/include/SDL_revision.h
index 6d7163d4d..341dc5cce 100644
--- a/Engine/lib/sdl/include/SDL_revision.h
+++ b/Engine/lib/sdl/include/SDL_revision.h
@@ -1,2 +1,2 @@
-#define SDL_REVISION "hg-10001:e12c38730512"
-#define SDL_REVISION_NUMBER 10001
+#define SDL_REVISION "hg-10556:007dfe83abf8"
+#define SDL_REVISION_NUMBER 10556
diff --git a/Engine/lib/sdl/include/SDL_rwops.h b/Engine/lib/sdl/include/SDL_rwops.h
index f460ae7d4..1ad3ac406 100644
--- a/Engine/lib/sdl/include/SDL_rwops.h
+++ b/Engine/lib/sdl/include/SDL_rwops.h
@@ -39,12 +39,12 @@ extern "C" {
#endif
/* RWops Types */
-#define SDL_RWOPS_UNKNOWN 0 /* Unknown stream type */
-#define SDL_RWOPS_WINFILE 1 /* Win32 file */
-#define SDL_RWOPS_STDFILE 2 /* Stdio file */
-#define SDL_RWOPS_JNIFILE 3 /* Android asset */
-#define SDL_RWOPS_MEMORY 4 /* Memory stream */
-#define SDL_RWOPS_MEMORY_RO 5 /* Read-Only memory stream */
+#define SDL_RWOPS_UNKNOWN 0U /* Unknown stream type */
+#define SDL_RWOPS_WINFILE 1U /* Win32 file */
+#define SDL_RWOPS_STDFILE 2U /* Stdio file */
+#define SDL_RWOPS_JNIFILE 3U /* Android asset */
+#define SDL_RWOPS_MEMORY 4U /* Memory stream */
+#define SDL_RWOPS_MEMORY_RO 5U /* Read-Only memory stream */
/**
* This is the read/write operation structure -- very basic.
diff --git a/Engine/lib/sdl/include/SDL_stdinc.h b/Engine/lib/sdl/include/SDL_stdinc.h
index 887bcd2d4..fdf96415f 100644
--- a/Engine/lib/sdl/include/SDL_stdinc.h
+++ b/Engine/lib/sdl/include/SDL_stdinc.h
@@ -83,9 +83,6 @@
#ifdef HAVE_FLOAT_H
# include
#endif
-#if defined(HAVE_ICONV) && defined(HAVE_ICONV_H)
-# include
-#endif
/**
* The number of elements in an array.
@@ -93,6 +90,13 @@
#define SDL_arraysize(array) (sizeof(array)/sizeof(array[0]))
#define SDL_TABLESIZE(table) SDL_arraysize(table)
+/**
+ * Macro useful for building other macros with strings in them
+ *
+ * e.g. #define LOG_ERROR(X) OutputDebugString(SDL_STRINGIFY_ARG(__FUNCTION__) ": " X "\n")
+ */
+#define SDL_STRINGIFY_ARG(arg) #arg
+
/**
* \name Cast operators
*
diff --git a/Engine/lib/sdl/include/SDL_surface.h b/Engine/lib/sdl/include/SDL_surface.h
index e63ca8903..e4a06a204 100644
--- a/Engine/lib/sdl/include/SDL_surface.h
+++ b/Engine/lib/sdl/include/SDL_surface.h
@@ -118,6 +118,8 @@ typedef int (*SDL_blit) (struct SDL_Surface * src, SDL_Rect * srcrect,
extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateRGBSurface
(Uint32 flags, int width, int height, int depth,
Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask);
+extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateRGBSurfaceWithFormat
+ (Uint32 flags, int width, int height, int depth, Uint32 format);
extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateRGBSurfaceFrom(void *pixels,
int width,
int height,
@@ -127,6 +129,8 @@ extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateRGBSurfaceFrom(void *pixels,
Uint32 Gmask,
Uint32 Bmask,
Uint32 Amask);
+extern DECLSPEC SDL_Surface *SDLCALL SDL_CreateRGBSurfaceWithFormatFrom
+ (void *pixels, int width, int height, int depth, int pitch, Uint32 format);
extern DECLSPEC void SDLCALL SDL_FreeSurface(SDL_Surface * surface);
/**
@@ -184,6 +188,12 @@ extern DECLSPEC SDL_Surface *SDLCALL SDL_LoadBMP_RW(SDL_RWops * src,
/**
* Save a surface to a seekable SDL data stream (memory or file).
*
+ * Surfaces with a 24-bit, 32-bit and paletted 8-bit format get saved in the
+ * BMP directly. Other RGB formats with 8-bit or higher get converted to a
+ * 24-bit surface or, if they have an alpha mask or a colorkey, to a 32-bit
+ * surface before they are saved. YUV and paletted 1-bit and 4-bit formats are
+ * not supported.
+ *
* If \c freedst is non-zero, the stream will be closed after being written.
*
* \return 0 if successful or -1 if there was an error.
diff --git a/Engine/lib/sdl/include/SDL_syswm.h b/Engine/lib/sdl/include/SDL_syswm.h
index 1056e526b..71ba5f1f3 100644
--- a/Engine/lib/sdl/include/SDL_syswm.h
+++ b/Engine/lib/sdl/include/SDL_syswm.h
@@ -106,6 +106,10 @@ typedef struct ANativeWindow ANativeWindow;
typedef void *EGLSurface;
#endif
+#if defined(SDL_VIDEO_DRIVER_VIVANTE)
+#include "SDL_egl.h"
+#endif
+
/**
* These are the various supported windowing subsystems
*/
@@ -120,7 +124,8 @@ typedef enum
SDL_SYSWM_WAYLAND,
SDL_SYSWM_MIR,
SDL_SYSWM_WINRT,
- SDL_SYSWM_ANDROID
+ SDL_SYSWM_ANDROID,
+ SDL_SYSWM_VIVANTE
} SDL_SYSWM_TYPE;
/**
@@ -166,6 +171,13 @@ struct SDL_SysWMmsg
int dummy;
/* No UIKit window events yet */
} uikit;
+#endif
+#if defined(SDL_VIDEO_DRIVER_VIVANTE)
+ struct
+ {
+ int dummy;
+ /* No Vivante window events yet */
+ } vivante;
#endif
/* Can't have an empty union */
int dummy;
@@ -259,6 +271,14 @@ struct SDL_SysWMinfo
} android;
#endif
+#if defined(SDL_VIDEO_DRIVER_VIVANTE)
+ struct
+ {
+ EGLNativeDisplayType display;
+ EGLNativeWindowType window;
+ } vivante;
+#endif
+
/* Can't have an empty union */
int dummy;
} info;
diff --git a/Engine/lib/sdl/include/SDL_version.h b/Engine/lib/sdl/include/SDL_version.h
index de1f16056..1700efdd1 100644
--- a/Engine/lib/sdl/include/SDL_version.h
+++ b/Engine/lib/sdl/include/SDL_version.h
@@ -59,7 +59,7 @@ typedef struct SDL_version
*/
#define SDL_MAJOR_VERSION 2
#define SDL_MINOR_VERSION 0
-#define SDL_PATCHLEVEL 4
+#define SDL_PATCHLEVEL 5
/**
* \brief Macro to determine SDL version program was compiled against.
diff --git a/Engine/lib/sdl/include/SDL_video.h b/Engine/lib/sdl/include/SDL_video.h
index 52dbbc765..73c33eb32 100644
--- a/Engine/lib/sdl/include/SDL_video.h
+++ b/Engine/lib/sdl/include/SDL_video.h
@@ -83,6 +83,7 @@ typedef struct
* \sa SDL_SetWindowPosition()
* \sa SDL_SetWindowSize()
* \sa SDL_SetWindowBordered()
+ * \sa SDL_SetWindowResizable()
* \sa SDL_SetWindowTitle()
* \sa SDL_ShowWindow()
*/
@@ -95,6 +96,7 @@ typedef struct SDL_Window SDL_Window;
*/
typedef enum
{
+ /* !!! FIXME: change this to name = (1<= $min_sdl_version)
no_sdl=""
- if test "$SDL2_CONFIG" = "no" ; then
- no_sdl=yes
- else
- SDL_CFLAGS=`$SDL2_CONFIG $sdl_config_args --cflags`
- SDL_LIBS=`$SDL2_CONFIG $sdl_config_args --libs`
+ if test "$SDL2_CONFIG" = "no" -a "x$search_sdl_framework" = "xyes"; then
+ AC_MSG_CHECKING(for SDL2.framework)
+ if test "x$SDL2_FRAMEWORK" != x; then
+ sdl_framework=$SDL2_FRAMEWORK
+ else
+ for d in / ~/ /System/; do
+ if test -d "$dLibrary/Frameworks/SDL2.framework"; then
+ sdl_framework="$dLibrary/Frameworks/SDL2.framework"
+ fi
+ done
+ fi
+
+ if test -d $sdl_framework; then
+ AC_MSG_RESULT($sdl_framework)
+ sdl_framework_dir=`dirname $sdl_framework`
+ SDL_CFLAGS="-F$sdl_framework_dir -Wl,-framework,SDL2 -I$sdl_framework/include"
+ SDL_LIBS="-F$sdl_framework_dir -Wl,-framework,SDL2"
+ else
+ no_sdl=yes
+ fi
+ fi
+
+ if test "$SDL2_CONFIG" != "no"; then
+ if test "x$sdl_pc" = "xno"; then
+ AC_MSG_CHECKING(for SDL - version >= $min_sdl_version)
+ SDL_CFLAGS=`$SDL2_CONFIG $sdl_config_args --cflags`
+ SDL_LIBS=`$SDL2_CONFIG $sdl_config_args --libs`
+ fi
sdl_major_version=`$SDL2_CONFIG $sdl_config_args --version | \
sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
@@ -141,12 +170,15 @@ int main (int argc, char *argv[])
CFLAGS="$ac_save_CFLAGS"
CXXFLAGS="$ac_save_CXXFLAGS"
LIBS="$ac_save_LIBS"
+
+ fi
+ if test "x$sdl_pc" = "xno"; then
+ if test "x$no_sdl" = "xyes"; then
+ AC_MSG_RESULT(no)
+ else
+ AC_MSG_RESULT(yes)
+ fi
fi
- fi
- if test "x$no_sdl" = x ; then
- AC_MSG_RESULT(yes)
- else
- AC_MSG_RESULT(no)
fi
fi
if test "x$no_sdl" = x ; then
diff --git a/Engine/lib/sdl/src/SDL.c b/Engine/lib/sdl/src/SDL.c
index 5d310021a..9eef00cd3 100644
--- a/Engine/lib/sdl/src/SDL.c
+++ b/Engine/lib/sdl/src/SDL.c
@@ -115,6 +115,16 @@ SDL_InitSubSystem(Uint32 flags)
/* Clear the error message */
SDL_ClearError();
+ if ((flags & SDL_INIT_GAMECONTROLLER)) {
+ /* game controller implies joystick */
+ flags |= SDL_INIT_JOYSTICK;
+ }
+
+ if ((flags & (SDL_INIT_VIDEO|SDL_INIT_JOYSTICK))) {
+ /* video or joystick implies events */
+ flags |= SDL_INIT_EVENTS;
+ }
+
#if SDL_VIDEO_DRIVER_WINDOWS
if ((flags & (SDL_INIT_HAPTIC|SDL_INIT_JOYSTICK))) {
if (SDL_HelperWindowCreate() < 0) {
@@ -127,16 +137,6 @@ SDL_InitSubSystem(Uint32 flags)
SDL_TicksInit();
#endif
- if ((flags & SDL_INIT_GAMECONTROLLER)) {
- /* game controller implies joystick */
- flags |= SDL_INIT_JOYSTICK;
- }
-
- if ((flags & (SDL_INIT_VIDEO|SDL_INIT_JOYSTICK))) {
- /* video or joystick implies events */
- flags |= SDL_INIT_EVENTS;
- }
-
/* Initialize the event subsystem */
if ((flags & SDL_INIT_EVENTS)) {
#if !SDL_EVENTS_DISABLED
@@ -443,6 +443,8 @@ SDL_GetPlatform()
return "Windows";
#elif __WINRT__
return "WinRT";
+#elif __TVOS__
+ return "tvOS";
#elif __IPHONEOS__
return "iOS";
#elif __PSP__
diff --git a/Engine/lib/sdl/src/SDL_error.c b/Engine/lib/sdl/src/SDL_error.c
index ace5cc397..804a1eb38 100644
--- a/Engine/lib/sdl/src/SDL_error.c
+++ b/Engine/lib/sdl/src/SDL_error.c
@@ -116,6 +116,10 @@ SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...)
return -1;
}
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+#endif
/* This function has a bit more overhead than most error functions
so that it supports internationalization and thread-safe errors.
*/
@@ -216,6 +220,9 @@ SDL_GetErrorMsg(char *errstr, int maxlen)
}
return (errstr);
}
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
/* Available for backwards compatibility */
const char *
diff --git a/Engine/lib/sdl/src/SDL_hints.c b/Engine/lib/sdl/src/SDL_hints.c
index 04523327a..390d94f9f 100644
--- a/Engine/lib/sdl/src/SDL_hints.c
+++ b/Engine/lib/sdl/src/SDL_hints.c
@@ -118,6 +118,19 @@ SDL_GetHint(const char *name)
return env;
}
+SDL_bool
+SDL_GetHintBoolean(const char *name, SDL_bool default_value)
+{
+ const char *hint = SDL_GetHint(name);
+ if (!hint) {
+ return default_value;
+ }
+ if (*hint == '0' || SDL_strcasecmp(hint, "false") == 0) {
+ return SDL_FALSE;
+ }
+ return SDL_TRUE;
+}
+
void
SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
{
diff --git a/Engine/lib/sdl/src/SDL_log.c b/Engine/lib/sdl/src/SDL_log.c
index 60bac9f65..760cb13de 100644
--- a/Engine/lib/sdl/src/SDL_log.c
+++ b/Engine/lib/sdl/src/SDL_log.c
@@ -324,7 +324,7 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
size_t length;
LPTSTR tstr;
-#ifndef __WINRT__
+#if !defined(HAVE_STDIO_H) && !defined(__WINRT__)
BOOL attachResult;
DWORD attachError;
unsigned long charsWritten;
@@ -356,7 +356,7 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
stderrHandle = GetStdHandle(STD_ERROR_HANDLE);
}
}
-#endif /* ifndef __WINRT__ */
+#endif /* !defined(HAVE_STDIO_H) && !defined(__WINRT__) */
length = SDL_strlen(SDL_priority_prefixes[priority]) + 2 + SDL_strlen(message) + 1 + 1 + 1;
output = SDL_stack_alloc(char, length);
@@ -366,7 +366,7 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
/* Output to debugger */
OutputDebugString(tstr);
-#ifndef __WINRT__
+#if !defined(HAVE_STDIO_H) && !defined(__WINRT__)
/* Screen output to stderr, if console was attached. */
if (consoleAttached == 1) {
if (!WriteConsole(stderrHandle, tstr, lstrlen(tstr), &charsWritten, NULL)) {
@@ -376,7 +376,7 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
}
}
}
-#endif /* ifndef __WINRT__ */
+#endif /* !defined(HAVE_STDIO_H) && !defined(__WINRT__) */
SDL_free(tstr);
SDL_stack_free(output);
diff --git a/Engine/lib/sdl/src/audio/SDL_audio.c b/Engine/lib/sdl/src/audio/SDL_audio.c
index 2ffd216c0..460852d7f 100644
--- a/Engine/lib/sdl/src/audio/SDL_audio.c
+++ b/Engine/lib/sdl/src/audio/SDL_audio.c
@@ -25,33 +25,29 @@
#include "SDL.h"
#include "SDL_audio.h"
#include "SDL_audio_c.h"
-#include "SDL_audiomem.h"
#include "SDL_sysaudio.h"
+#include "../thread/SDL_systhread.h"
#define _THIS SDL_AudioDevice *_this
static SDL_AudioDriver current_audio;
static SDL_AudioDevice *open_devices[16];
-/* !!! FIXME: These are wordy and unlocalized... */
-#define DEFAULT_OUTPUT_DEVNAME "System audio output device"
-#define DEFAULT_INPUT_DEVNAME "System audio capture device"
-
-
/*
* Not all of these will be compiled and linked in, but it's convenient
* to have a complete list here and saves yet-another block of #ifdefs...
* Please see bootstrap[], below, for the actual #ifdef mess.
*/
+extern AudioBootStrap PULSEAUDIO_bootstrap;
+extern AudioBootStrap ALSA_bootstrap;
+extern AudioBootStrap SNDIO_bootstrap;
extern AudioBootStrap BSD_AUDIO_bootstrap;
extern AudioBootStrap DSP_bootstrap;
-extern AudioBootStrap ALSA_bootstrap;
-extern AudioBootStrap PULSEAUDIO_bootstrap;
extern AudioBootStrap QSAAUDIO_bootstrap;
extern AudioBootStrap SUNAUDIO_bootstrap;
extern AudioBootStrap ARTS_bootstrap;
extern AudioBootStrap ESD_bootstrap;
-extern AudioBootStrap NACLAUD_bootstrap;
+extern AudioBootStrap NACLAUDIO_bootstrap;
extern AudioBootStrap NAS_bootstrap;
extern AudioBootStrap XAUDIO2_bootstrap;
extern AudioBootStrap DSOUND_bootstrap;
@@ -59,18 +55,13 @@ extern AudioBootStrap WINMM_bootstrap;
extern AudioBootStrap PAUDIO_bootstrap;
extern AudioBootStrap HAIKUAUDIO_bootstrap;
extern AudioBootStrap COREAUDIO_bootstrap;
-extern AudioBootStrap SNDMGR_bootstrap;
-extern AudioBootStrap DISKAUD_bootstrap;
-extern AudioBootStrap DUMMYAUD_bootstrap;
-extern AudioBootStrap DCAUD_bootstrap;
-extern AudioBootStrap DART_bootstrap;
-extern AudioBootStrap NDSAUD_bootstrap;
+extern AudioBootStrap DISKAUDIO_bootstrap;
+extern AudioBootStrap DUMMYAUDIO_bootstrap;
extern AudioBootStrap FUSIONSOUND_bootstrap;
-extern AudioBootStrap ANDROIDAUD_bootstrap;
-extern AudioBootStrap PSPAUD_bootstrap;
+extern AudioBootStrap ANDROIDAUDIO_bootstrap;
+extern AudioBootStrap PSPAUDIO_bootstrap;
extern AudioBootStrap SNDIO_bootstrap;
-extern AudioBootStrap EmscriptenAudio_bootstrap;
-
+extern AudioBootStrap EMSCRIPTENAUDIO_bootstrap;
/* Available audio drivers */
static const AudioBootStrap *const bootstrap[] = {
@@ -102,7 +93,7 @@ static const AudioBootStrap *const bootstrap[] = {
&ESD_bootstrap,
#endif
#if SDL_AUDIO_DRIVER_NACL
- &NACLAUD_bootstrap,
+ &NACLAUDIO_bootstrap,
#endif
#if SDL_AUDIO_DRIVER_NAS
&NAS_bootstrap,
@@ -126,22 +117,22 @@ static const AudioBootStrap *const bootstrap[] = {
&COREAUDIO_bootstrap,
#endif
#if SDL_AUDIO_DRIVER_DISK
- &DISKAUD_bootstrap,
+ &DISKAUDIO_bootstrap,
#endif
#if SDL_AUDIO_DRIVER_DUMMY
- &DUMMYAUD_bootstrap,
+ &DUMMYAUDIO_bootstrap,
#endif
#if SDL_AUDIO_DRIVER_FUSIONSOUND
&FUSIONSOUND_bootstrap,
#endif
#if SDL_AUDIO_DRIVER_ANDROID
- &ANDROIDAUD_bootstrap,
+ &ANDROIDAUDIO_bootstrap,
#endif
#if SDL_AUDIO_DRIVER_PSP
- &PSPAUD_bootstrap,
+ &PSPAUDIO_bootstrap,
#endif
#if SDL_AUDIO_DRIVER_EMSCRIPTEN
- &EmscriptenAudio_bootstrap,
+ &EMSCRIPTENAUDIO_bootstrap,
#endif
NULL
};
@@ -165,7 +156,7 @@ SDL_AudioDetectDevices_Default(void)
{
/* you have to write your own implementation if these assertions fail. */
SDL_assert(current_audio.impl.OnlyHasDefaultOutputDevice);
- SDL_assert(current_audio.impl.OnlyHasDefaultInputDevice || !current_audio.impl.HasCaptureSupport);
+ SDL_assert(current_audio.impl.OnlyHasDefaultCaptureDevice || !current_audio.impl.HasCaptureSupport);
SDL_AddAudioDevice(SDL_FALSE, DEFAULT_OUTPUT_DEVNAME, (void *) ((size_t) 0x1));
if (current_audio.impl.HasCaptureSupport) {
@@ -200,8 +191,19 @@ SDL_AudioGetDeviceBuf_Default(_THIS)
return NULL;
}
+static int
+SDL_AudioCaptureFromDevice_Default(_THIS, void *buffer, int buflen)
+{
+ return -1; /* just fail immediately. */
+}
+
static void
-SDL_AudioWaitDone_Default(_THIS)
+SDL_AudioFlushCapture_Default(_THIS)
+{ /* no-op. */
+}
+
+static void
+SDL_AudioPrepareToClose_Default(_THIS)
{ /* no-op. */
}
@@ -257,15 +259,28 @@ SDL_AudioUnlockDevice_Default(SDL_AudioDevice * device)
}
}
+static void
+SDL_AudioLockOrUnlockDeviceWithNoMixerLock(SDL_AudioDevice * device)
+{
+}
static void
-finalize_audio_entry_points(void)
+finish_audio_entry_points_init(void)
{
/*
* Fill in stub functions for unused driver entry points. This lets us
* blindly call them without having to check for validity first.
*/
+ if (current_audio.impl.SkipMixerLock) {
+ if (current_audio.impl.LockDevice == NULL) {
+ current_audio.impl.LockDevice = SDL_AudioLockOrUnlockDeviceWithNoMixerLock;
+ }
+ if (current_audio.impl.UnlockDevice == NULL) {
+ current_audio.impl.UnlockDevice = SDL_AudioLockOrUnlockDeviceWithNoMixerLock;
+ }
+ }
+
#define FILL_STUB(x) \
if (current_audio.impl.x == NULL) { \
current_audio.impl.x = SDL_Audio##x##_Default; \
@@ -277,7 +292,9 @@ finalize_audio_entry_points(void)
FILL_STUB(PlayDevice);
FILL_STUB(GetPendingBytes);
FILL_STUB(GetDeviceBuf);
- FILL_STUB(WaitDone);
+ FILL_STUB(CaptureFromDevice);
+ FILL_STUB(FlushCapture);
+ FILL_STUB(PrepareToClose);
FILL_STUB(CloseDevice);
FILL_STUB(LockDevice);
FILL_STUB(UnlockDevice);
@@ -316,7 +333,7 @@ add_audio_device(const char *name, void *handle, SDL_AudioDeviceItem **devices,
static SDL_INLINE int
add_capture_device(const char *name, void *handle)
{
- /* !!! FIXME: add this later. SDL_assert(current_audio.impl.HasCaptureSupport);*/
+ SDL_assert(current_audio.impl.HasCaptureSupport);
return add_audio_device(name, handle, ¤t_audio.inputDevices, ¤t_audio.inputDeviceCount);
}
@@ -365,14 +382,14 @@ void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device)
{
SDL_assert(get_audio_device(device->id) == device);
- if (!device->enabled) {
+ if (!SDL_AtomicGet(&device->enabled)) {
return;
}
/* Ends the audio callback and mark the device as STOPPED, but the
app still needs to close the device to free resources. */
current_audio.impl.LockDevice(device);
- device->enabled = 0;
+ SDL_AtomicSet(&device->enabled, 0);
current_audio.impl.UnlockDevice(device);
/* Post the event, if desired */
@@ -404,13 +421,26 @@ mark_device_removed(void *handle, SDL_AudioDeviceItem *devices, SDL_bool *remove
void
SDL_RemoveAudioDevice(const int iscapture, void *handle)
{
+ int device_index;
+ SDL_AudioDevice *device = NULL;
+
SDL_LockMutex(current_audio.detectionLock);
if (iscapture) {
mark_device_removed(handle, current_audio.inputDevices, ¤t_audio.captureDevicesRemoved);
} else {
mark_device_removed(handle, current_audio.outputDevices, ¤t_audio.outputDevicesRemoved);
}
+ for (device_index = 0; device_index < SDL_arraysize(open_devices); device_index++)
+ {
+ device = open_devices[device_index];
+ if (device != NULL && device->handle == handle)
+ {
+ SDL_OpenedAudioDeviceDisconnected(device);
+ break;
+ }
+ }
SDL_UnlockMutex(current_audio.detectionLock);
+
current_audio.impl.FreeDeviceHandle(handle);
}
@@ -420,77 +450,24 @@ SDL_RemoveAudioDevice(const int iscapture, void *handle)
/* this expects that you managed thread safety elsewhere. */
static void
-free_audio_queue(SDL_AudioBufferQueue *buffer)
+free_audio_queue(SDL_AudioBufferQueue *packet)
{
- while (buffer) {
- SDL_AudioBufferQueue *next = buffer->next;
- SDL_free(buffer);
- buffer = next;
+ while (packet) {
+ SDL_AudioBufferQueue *next = packet->next;
+ SDL_free(packet);
+ packet = next;
}
}
-static void SDLCALL
-SDL_BufferQueueDrainCallback(void *userdata, Uint8 *stream, int _len)
+/* NOTE: This assumes you'll hold the mixer lock before calling! */
+static int
+queue_audio_to_device(SDL_AudioDevice *device, const Uint8 *data, Uint32 len)
{
- /* this function always holds the mixer lock before being called. */
- Uint32 len = (Uint32) _len;
- SDL_AudioDevice *device = (SDL_AudioDevice *) userdata;
- SDL_AudioBufferQueue *buffer;
-
- SDL_assert(device != NULL); /* this shouldn't ever happen, right?! */
- SDL_assert(_len >= 0); /* this shouldn't ever happen, right?! */
-
- while ((len > 0) && ((buffer = device->buffer_queue_head) != NULL)) {
- const Uint32 avail = buffer->datalen - buffer->startpos;
- const Uint32 cpy = SDL_min(len, avail);
- SDL_assert(device->queued_bytes >= avail);
-
- SDL_memcpy(stream, buffer->data + buffer->startpos, cpy);
- buffer->startpos += cpy;
- stream += cpy;
- device->queued_bytes -= cpy;
- len -= cpy;
-
- if (buffer->startpos == buffer->datalen) { /* packet is done, put it in the pool. */
- device->buffer_queue_head = buffer->next;
- SDL_assert((buffer->next != NULL) || (buffer == device->buffer_queue_tail));
- buffer->next = device->buffer_queue_pool;
- device->buffer_queue_pool = buffer;
- }
- }
-
- SDL_assert((device->buffer_queue_head != NULL) == (device->queued_bytes != 0));
-
- if (len > 0) { /* fill any remaining space in the stream with silence. */
- SDL_assert(device->buffer_queue_head == NULL);
- SDL_memset(stream, device->spec.silence, len);
- }
-
- if (device->buffer_queue_head == NULL) {
- device->buffer_queue_tail = NULL; /* in case we drained the queue entirely. */
- }
-}
-
-int
-SDL_QueueAudio(SDL_AudioDeviceID devid, const void *_data, Uint32 len)
-{
- SDL_AudioDevice *device = get_audio_device(devid);
- const Uint8 *data = (const Uint8 *) _data;
SDL_AudioBufferQueue *orighead;
SDL_AudioBufferQueue *origtail;
Uint32 origlen;
Uint32 datalen;
- if (!device) {
- return -1; /* get_audio_device() will have set the error state */
- }
-
- if (device->spec.callback != SDL_BufferQueueDrainCallback) {
- return SDL_SetError("Audio device has a callback, queueing not allowed");
- }
-
- current_audio.impl.LockDevice(device);
-
orighead = device->buffer_queue_head;
origtail = device->buffer_queue_tail;
origlen = origtail ? origtail->datalen : 0;
@@ -520,8 +497,6 @@ SDL_QueueAudio(SDL_AudioDeviceID devid, const void *_data, Uint32 len)
device->buffer_queue_tail = origtail;
device->buffer_queue_pool = NULL;
- current_audio.impl.UnlockDevice(device);
-
free_audio_queue(packet); /* give back what we can. */
return SDL_OutOfMemory();
@@ -548,22 +523,142 @@ SDL_QueueAudio(SDL_AudioDeviceID devid, const void *_data, Uint32 len)
device->queued_bytes += datalen;
}
- current_audio.impl.UnlockDevice(device);
-
return 0;
}
+/* NOTE: This assumes you'll hold the mixer lock before calling! */
+static Uint32
+dequeue_audio_from_device(SDL_AudioDevice *device, Uint8 *stream, Uint32 len)
+{
+ SDL_AudioBufferQueue *packet;
+ Uint8 *ptr = stream;
+
+ while ((len > 0) && ((packet = device->buffer_queue_head) != NULL)) {
+ const Uint32 avail = packet->datalen - packet->startpos;
+ const Uint32 cpy = SDL_min(len, avail);
+ SDL_assert(device->queued_bytes >= avail);
+
+ SDL_memcpy(ptr, packet->data + packet->startpos, cpy);
+ packet->startpos += cpy;
+ ptr += cpy;
+ device->queued_bytes -= cpy;
+ len -= cpy;
+
+ if (packet->startpos == packet->datalen) { /* packet is done, put it in the pool. */
+ device->buffer_queue_head = packet->next;
+ SDL_assert((packet->next != NULL) || (packet == device->buffer_queue_tail));
+ packet->next = device->buffer_queue_pool;
+ device->buffer_queue_pool = packet;
+ }
+ }
+
+ SDL_assert((device->buffer_queue_head != NULL) == (device->queued_bytes != 0));
+
+ if (device->buffer_queue_head == NULL) {
+ device->buffer_queue_tail = NULL; /* in case we drained the queue entirely. */
+ }
+
+ return (Uint32) (ptr - stream);
+}
+
+static void SDLCALL
+SDL_BufferQueueDrainCallback(void *userdata, Uint8 *stream, int len)
+{
+ /* this function always holds the mixer lock before being called. */
+ SDL_AudioDevice *device = (SDL_AudioDevice *) userdata;
+ Uint32 written;
+
+ SDL_assert(device != NULL); /* this shouldn't ever happen, right?! */
+ SDL_assert(!device->iscapture); /* this shouldn't ever happen, right?! */
+ SDL_assert(len >= 0); /* this shouldn't ever happen, right?! */
+
+ written = dequeue_audio_from_device(device, stream, (Uint32) len);
+ stream += written;
+ len -= (int) written;
+
+ if (len > 0) { /* fill any remaining space in the stream with silence. */
+ SDL_assert(device->buffer_queue_head == NULL);
+ SDL_memset(stream, device->spec.silence, len);
+ }
+}
+
+static void SDLCALL
+SDL_BufferQueueFillCallback(void *userdata, Uint8 *stream, int len)
+{
+ /* this function always holds the mixer lock before being called. */
+ SDL_AudioDevice *device = (SDL_AudioDevice *) userdata;
+
+ SDL_assert(device != NULL); /* this shouldn't ever happen, right?! */
+ SDL_assert(device->iscapture); /* this shouldn't ever happen, right?! */
+ SDL_assert(len >= 0); /* this shouldn't ever happen, right?! */
+
+ /* note that if this needs to allocate more space and run out of memory,
+ we have no choice but to quietly drop the data and hope it works out
+ later, but you probably have bigger problems in this case anyhow. */
+ queue_audio_to_device(device, stream, (Uint32) len);
+}
+
+int
+SDL_QueueAudio(SDL_AudioDeviceID devid, const void *data, Uint32 len)
+{
+ SDL_AudioDevice *device = get_audio_device(devid);
+ int rc = 0;
+
+ if (!device) {
+ return -1; /* get_audio_device() will have set the error state */
+ } else if (device->iscapture) {
+ return SDL_SetError("This is a capture device, queueing not allowed");
+ } else if (device->spec.callback != SDL_BufferQueueDrainCallback) {
+ return SDL_SetError("Audio device has a callback, queueing not allowed");
+ }
+
+ if (len > 0) {
+ current_audio.impl.LockDevice(device);
+ rc = queue_audio_to_device(device, data, len);
+ current_audio.impl.UnlockDevice(device);
+ }
+
+ return rc;
+}
+
+Uint32
+SDL_DequeueAudio(SDL_AudioDeviceID devid, void *data, Uint32 len)
+{
+ SDL_AudioDevice *device = get_audio_device(devid);
+ Uint32 rc;
+
+ if ( (len == 0) || /* nothing to do? */
+ (!device) || /* called with bogus device id */
+ (!device->iscapture) || /* playback devices can't dequeue */
+ (device->spec.callback != SDL_BufferQueueFillCallback) ) { /* not set for queueing */
+ return 0; /* just report zero bytes dequeued. */
+ }
+
+ current_audio.impl.LockDevice(device);
+ rc = dequeue_audio_from_device(device, data, len);
+ current_audio.impl.UnlockDevice(device);
+ return rc;
+}
+
Uint32
SDL_GetQueuedAudioSize(SDL_AudioDeviceID devid)
{
Uint32 retval = 0;
SDL_AudioDevice *device = get_audio_device(devid);
+ if (!device) {
+ return 0;
+ }
+
/* Nothing to do unless we're set up for queueing. */
- if (device && (device->spec.callback == SDL_BufferQueueDrainCallback)) {
+ if (device->spec.callback == SDL_BufferQueueDrainCallback) {
current_audio.impl.LockDevice(device);
retval = device->queued_bytes + current_audio.impl.GetPendingBytes(device);
current_audio.impl.UnlockDevice(device);
+ } else if (device->spec.callback == SDL_BufferQueueFillCallback) {
+ current_audio.impl.LockDevice(device);
+ retval = device->queued_bytes;
+ current_audio.impl.UnlockDevice(device);
}
return retval;
@@ -573,25 +668,49 @@ void
SDL_ClearQueuedAudio(SDL_AudioDeviceID devid)
{
SDL_AudioDevice *device = get_audio_device(devid);
- SDL_AudioBufferQueue *buffer = NULL;
+ SDL_AudioBufferQueue *packet;
+
if (!device) {
return; /* nothing to do. */
}
/* Blank out the device and release the mutex. Free it afterwards. */
current_audio.impl.LockDevice(device);
- buffer = device->buffer_queue_head;
+
+ /* merge the available pool and the current queue into one list. */
+ packet = device->buffer_queue_head;
+ if (packet) {
+ device->buffer_queue_tail->next = device->buffer_queue_pool;
+ } else {
+ packet = device->buffer_queue_pool;
+ }
+
+ /* Remove the queued packets from the device. */
device->buffer_queue_tail = NULL;
device->buffer_queue_head = NULL;
device->queued_bytes = 0;
+ device->buffer_queue_pool = packet;
+
+ /* Keep up to two packets in the pool to reduce future malloc pressure. */
+ if (packet) {
+ if (!packet->next) {
+ packet = NULL; /* one packet (the only one) for the pool. */
+ } else {
+ SDL_AudioBufferQueue *next = packet->next->next;
+ packet->next->next = NULL; /* two packets for the pool. */
+ packet = next; /* rest will be freed. */
+ }
+ }
+
current_audio.impl.UnlockDevice(device);
- free_audio_queue(buffer);
+ /* free any extra packets we didn't keep in the pool. */
+ free_audio_queue(packet);
}
/* The general mixing thread function */
-int SDLCALL
+static int SDLCALL
SDL_RunAudio(void *devicep)
{
SDL_AudioDevice *device = (SDL_AudioDevice *) devicep;
@@ -600,7 +719,9 @@ SDL_RunAudio(void *devicep)
const int stream_len = (device->convert.needed) ? device->convert.len : device->spec.size;
Uint8 *stream;
void *udata = device->spec.userdata;
- void (SDLCALL *fill) (void *, Uint8 *, int) = device->spec.callback;
+ void (SDLCALL *callback) (void *, Uint8 *, int) = device->spec.callback;
+
+ SDL_assert(!device->iscapture);
/* The audio mixing is always a high priority thread */
SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
@@ -610,11 +731,11 @@ SDL_RunAudio(void *devicep)
current_audio.impl.ThreadInit(device);
/* Loop, filling the audio buffers */
- while (!device->shutdown) {
+ while (!SDL_AtomicGet(&device->shutdown)) {
/* Fill the current buffer with sound */
if (device->convert.needed) {
stream = device->convert.buf;
- } else if (device->enabled) {
+ } else if (SDL_AtomicGet(&device->enabled)) {
stream = current_audio.impl.GetDeviceBuf(device);
} else {
/* if the device isn't enabled, we still write to the
@@ -630,16 +751,18 @@ SDL_RunAudio(void *devicep)
}
/* !!! FIXME: this should be LockDevice. */
- SDL_LockMutex(device->mixer_lock);
- if (device->paused) {
- SDL_memset(stream, silence, stream_len);
- } else {
- (*fill) (udata, stream, stream_len);
+ if ( SDL_AtomicGet(&device->enabled) ) {
+ SDL_LockMutex(device->mixer_lock);
+ if (SDL_AtomicGet(&device->paused)) {
+ SDL_memset(stream, silence, stream_len);
+ } else {
+ (*callback) (udata, stream, stream_len);
+ }
+ SDL_UnlockMutex(device->mixer_lock);
}
- SDL_UnlockMutex(device->mixer_lock);
/* Convert the audio if necessary */
- if (device->enabled && device->convert.needed) {
+ if (device->convert.needed && SDL_AtomicGet(&device->enabled)) {
SDL_ConvertAudio(&device->convert);
stream = current_audio.impl.GetDeviceBuf(device);
if (stream == NULL) {
@@ -659,8 +782,91 @@ SDL_RunAudio(void *devicep)
}
}
+ current_audio.impl.PrepareToClose(device);
+
/* Wait for the audio to drain. */
- current_audio.impl.WaitDone(device);
+ SDL_Delay(((device->spec.samples * 1000) / device->spec.freq) * 2);
+
+ return 0;
+}
+
+/* The general capture thread function */
+static int SDLCALL
+SDL_CaptureAudio(void *devicep)
+{
+ SDL_AudioDevice *device = (SDL_AudioDevice *) devicep;
+ const int silence = (int) device->spec.silence;
+ const Uint32 delay = ((device->spec.samples * 1000) / device->spec.freq);
+ const int stream_len = (device->convert.needed) ? device->convert.len : device->spec.size;
+ Uint8 *stream;
+ void *udata = device->spec.userdata;
+ void (SDLCALL *callback) (void *, Uint8 *, int) = device->spec.callback;
+
+ SDL_assert(device->iscapture);
+
+ /* The audio mixing is always a high priority thread */
+ SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
+
+ /* Perform any thread setup */
+ device->threadid = SDL_ThreadID();
+ current_audio.impl.ThreadInit(device);
+
+ /* Loop, filling the audio buffers */
+ while (!SDL_AtomicGet(&device->shutdown)) {
+ int still_need;
+ Uint8 *ptr;
+
+ if (!SDL_AtomicGet(&device->enabled) || SDL_AtomicGet(&device->paused)) {
+ SDL_Delay(delay); /* just so we don't cook the CPU. */
+ current_audio.impl.FlushCapture(device); /* dump anything pending. */
+ continue;
+ }
+
+ /* Fill the current buffer with sound */
+ still_need = stream_len;
+ if (device->convert.needed) {
+ ptr = stream = device->convert.buf;
+ } else {
+ /* just use the "fake" stream to hold data read from the device. */
+ ptr = stream = device->fake_stream;
+ }
+
+ /* We still read from the device when "paused" to keep the state sane,
+ and block when there isn't data so this thread isn't eating CPU.
+ But we don't process it further or call the app's callback. */
+
+ while (still_need > 0) {
+ const int rc = current_audio.impl.CaptureFromDevice(device, ptr, still_need);
+ SDL_assert(rc <= still_need); /* device should not overflow buffer. :) */
+ if (rc > 0) {
+ still_need -= rc;
+ ptr += rc;
+ } else { /* uhoh, device failed for some reason! */
+ SDL_OpenedAudioDeviceDisconnected(device);
+ break;
+ }
+ }
+
+ if (still_need > 0) {
+ /* Keep any data we already read, silence the rest. */
+ SDL_memset(ptr, silence, still_need);
+ }
+
+ if (device->convert.needed) {
+ SDL_ConvertAudio(&device->convert);
+ }
+
+ /* !!! FIXME: this should be LockDevice. */
+ SDL_LockMutex(device->mixer_lock);
+ if (SDL_AtomicGet(&device->paused)) {
+ current_audio.impl.FlushCapture(device); /* one snuck in! */
+ } else {
+ (*callback)(udata, stream, stream_len);
+ }
+ SDL_UnlockMutex(device->mixer_lock);
+ }
+
+ current_audio.impl.FlushCapture(device);
return 0;
}
@@ -757,7 +963,7 @@ SDL_AudioInit(const char *driver_name)
current_audio.detectionLock = SDL_CreateMutex();
- finalize_audio_entry_points();
+ finish_audio_entry_points_init();
/* Make sure we have a list of devices available at startup. */
current_audio.impl.DetectDevices();
@@ -872,27 +1078,38 @@ SDL_GetAudioDeviceName(int index, int iscapture)
static void
close_audio_device(SDL_AudioDevice * device)
{
- device->enabled = 0;
- device->shutdown = 1;
+ if (!device) {
+ return;
+ }
+
+ if (device->id > 0) {
+ SDL_AudioDevice *opendev = open_devices[device->id - 1];
+ SDL_assert((opendev == device) || (opendev == NULL));
+ if (opendev == device) {
+ open_devices[device->id - 1] = NULL;
+ }
+ }
+
+ SDL_AtomicSet(&device->shutdown, 1);
+ SDL_AtomicSet(&device->enabled, 0);
if (device->thread != NULL) {
SDL_WaitThread(device->thread, NULL);
}
if (device->mixer_lock != NULL) {
SDL_DestroyMutex(device->mixer_lock);
}
- SDL_FreeAudioMem(device->fake_stream);
+ SDL_free(device->fake_stream);
if (device->convert.needed) {
- SDL_FreeAudioMem(device->convert.buf);
+ SDL_free(device->convert.buf);
}
- if (device->opened) {
+ if (device->hidden != NULL) {
current_audio.impl.CloseDevice(device);
- device->opened = 0;
}
free_audio_queue(device->buffer_queue_head);
free_audio_queue(device->buffer_queue_pool);
- SDL_FreeAudioMem(device);
+ SDL_free(device);
}
@@ -963,12 +1180,12 @@ open_audio_device(const char *devname, int iscapture,
const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
int allowed_changes, int min_id)
{
+ const SDL_bool is_internal_thread = (desired->callback != NULL);
SDL_AudioDeviceID id = 0;
SDL_AudioSpec _obtained;
SDL_AudioDevice *device;
SDL_bool build_cvt;
void *handle = NULL;
- Uint32 stream_len;
int i = 0;
if (!SDL_WasInit(SDL_INIT_AUDIO)) {
@@ -981,6 +1198,7 @@ open_audio_device(const char *devname, int iscapture,
return 0;
}
+ /* !!! FIXME: there is a race condition here if two devices open from two threads at once. */
/* Find an available device ID... */
for (id = min_id - 1; id < SDL_arraysize(open_devices); id++) {
if (open_devices[id] == NULL) {
@@ -1015,7 +1233,7 @@ open_audio_device(const char *devname, int iscapture,
* opens of the default system device.
*/
- if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
+ if ((iscapture) && (current_audio.impl.OnlyHasDefaultCaptureDevice)) {
if ((devname) && (SDL_strcmp(devname, DEFAULT_INPUT_DEVNAME) != 0)) {
SDL_SetError("No such device");
return 0;
@@ -1067,17 +1285,19 @@ open_audio_device(const char *devname, int iscapture,
}
}
- device = (SDL_AudioDevice *) SDL_AllocAudioMem(sizeof(SDL_AudioDevice));
+ device = (SDL_AudioDevice *) SDL_calloc(1, sizeof (SDL_AudioDevice));
if (device == NULL) {
SDL_OutOfMemory();
return 0;
}
- SDL_zerop(device);
device->id = id + 1;
device->spec = *obtained;
- device->enabled = 1;
- device->paused = 1;
- device->iscapture = iscapture;
+ device->iscapture = iscapture ? SDL_TRUE : SDL_FALSE;
+ device->handle = handle;
+
+ SDL_AtomicSet(&device->shutdown, 0); /* just in case. */
+ SDL_AtomicSet(&device->paused, 1);
+ SDL_AtomicSet(&device->enabled, 1);
/* Create a mutex for locking the sound buffers */
if (!current_audio.impl.SkipMixerLock) {
@@ -1093,7 +1313,10 @@ open_audio_device(const char *devname, int iscapture,
close_audio_device(device);
return 0;
}
- device->opened = 1;
+
+ /* if your target really doesn't need it, set it to 0x1 or something. */
+ /* otherwise, close_audio_device() won't call impl.CloseDevice(). */
+ SDL_assert(device->hidden != NULL);
/* See if we need to do any conversion */
build_cvt = SDL_FALSE;
@@ -1143,7 +1366,7 @@ open_audio_device(const char *devname, int iscapture,
device->convert.len_ratio);
device->convert.buf =
- (Uint8 *) SDL_AllocAudioMem(device->convert.len *
+ (Uint8 *) SDL_malloc(device->convert.len *
device->convert.len_mult);
if (device->convert.buf == NULL) {
close_audio_device(device);
@@ -1153,19 +1376,6 @@ open_audio_device(const char *devname, int iscapture,
}
}
- /* Allocate a fake audio memory buffer */
- stream_len = (device->convert.needed) ? device->convert.len_cvt : 0;
- if (device->spec.size > stream_len) {
- stream_len = device->spec.size;
- }
- SDL_assert(stream_len > 0);
- device->fake_stream = (Uint8 *)SDL_AllocAudioMem(stream_len);
- if (device->fake_stream == NULL) {
- close_audio_device(device);
- SDL_OutOfMemory();
- return 0;
- }
-
if (device->spec.callback == NULL) { /* use buffer queueing? */
/* pool a few packets to start. Enough for two callbacks. */
const int packetlen = SDL_AUDIOBUFFERQUEUE_PACKETLEN;
@@ -1181,7 +1391,7 @@ open_audio_device(const char *devname, int iscapture,
}
}
- device->spec.callback = SDL_BufferQueueDrainCallback;
+ device->spec.callback = iscapture ? SDL_BufferQueueFillCallback : SDL_BufferQueueDrainCallback;
device->spec.userdata = device;
}
@@ -1191,21 +1401,30 @@ open_audio_device(const char *devname, int iscapture,
/* Start the audio thread if necessary */
if (!current_audio.impl.ProvidesOwnCallbackThread) {
/* Start the audio thread */
- char name[64];
- SDL_snprintf(name, sizeof (name), "SDLAudioDev%d", (int) device->id);
-/* !!! FIXME: this is nasty. */
-#if defined(__WIN32__) && !defined(HAVE_LIBC)
-#undef SDL_CreateThread
-#if SDL_DYNAMIC_API
- device->thread = SDL_CreateThread_REAL(SDL_RunAudio, name, device, NULL, NULL);
-#else
- device->thread = SDL_CreateThread(SDL_RunAudio, name, device, NULL, NULL);
-#endif
-#else
- device->thread = SDL_CreateThread(SDL_RunAudio, name, device);
-#endif
+ /* !!! FIXME: we don't force the audio thread stack size here if it calls into user code, but maybe we should? */
+ /* buffer queueing callback only needs a few bytes, so make the stack tiny. */
+ const size_t stacksize = is_internal_thread ? 64 * 1024 : 0;
+ char threadname[64];
+
+ /* Allocate a fake audio buffer; only used by our internal threads. */
+ Uint32 stream_len = (device->convert.needed) ? device->convert.len_cvt : 0;
+ if (device->spec.size > stream_len) {
+ stream_len = device->spec.size;
+ }
+ SDL_assert(stream_len > 0);
+
+ device->fake_stream = (Uint8 *) SDL_malloc(stream_len);
+ if (device->fake_stream == NULL) {
+ close_audio_device(device);
+ SDL_OutOfMemory();
+ return 0;
+ }
+
+ SDL_snprintf(threadname, sizeof (threadname), "SDLAudioDev%d", (int) device->id);
+ device->thread = SDL_CreateThreadInternal(iscapture ? SDL_CaptureAudio : SDL_RunAudio, threadname, stacksize, device);
+
if (device->thread == NULL) {
- SDL_CloseAudioDevice(device->id);
+ close_audio_device(device);
SDL_SetError("Couldn't create audio thread");
return 0;
}
@@ -1258,8 +1477,8 @@ SDL_GetAudioDeviceStatus(SDL_AudioDeviceID devid)
{
SDL_AudioDevice *device = get_audio_device(devid);
SDL_AudioStatus status = SDL_AUDIO_STOPPED;
- if (device && device->enabled) {
- if (device->paused) {
+ if (device && SDL_AtomicGet(&device->enabled)) {
+ if (SDL_AtomicGet(&device->paused)) {
status = SDL_AUDIO_PAUSED;
} else {
status = SDL_AUDIO_PLAYING;
@@ -1281,7 +1500,7 @@ SDL_PauseAudioDevice(SDL_AudioDeviceID devid, int pause_on)
SDL_AudioDevice *device = get_audio_device(devid);
if (device) {
current_audio.impl.LockDevice(device);
- device->paused = pause_on;
+ SDL_AtomicSet(&device->paused, pause_on ? 1 : 0);
current_audio.impl.UnlockDevice(device);
}
}
@@ -1328,11 +1547,7 @@ SDL_UnlockAudio(void)
void
SDL_CloseAudioDevice(SDL_AudioDeviceID devid)
{
- SDL_AudioDevice *device = get_audio_device(devid);
- if (device) {
- close_audio_device(device);
- open_devices[devid - 1] = NULL;
- }
+ close_audio_device(get_audio_device(devid));
}
void
@@ -1351,9 +1566,7 @@ SDL_AudioQuit(void)
}
for (i = 0; i < SDL_arraysize(open_devices); i++) {
- if (open_devices[i] != NULL) {
- SDL_CloseAudioDevice(i+1);
- }
+ close_audio_device(open_devices[i]);
}
free_device_list(¤t_audio.outputDevices, ¤t_audio.outputDeviceCount);
diff --git a/Engine/lib/sdl/src/audio/SDL_audio_c.h b/Engine/lib/sdl/src/audio/SDL_audio_c.h
index b03a9156f..7cde3a662 100644
--- a/Engine/lib/sdl/src/audio/SDL_audio_c.h
+++ b/Engine/lib/sdl/src/audio/SDL_audio_c.h
@@ -29,9 +29,6 @@ extern SDL_AudioFormat SDL_NextAudioFormat(void);
/* Function to calculate the size and silence for a SDL_AudioSpec */
extern void SDL_CalculateAudioSpec(SDL_AudioSpec * spec);
-/* The actual mixing thread function */
-extern int SDLCALL SDL_RunAudio(void *audiop);
-
/* this is used internally to access some autogenerated code. */
typedef struct
{
diff --git a/Engine/lib/sdl/src/audio/SDL_mixer.c b/Engine/lib/sdl/src/audio/SDL_mixer.c
index b49c73dab..e0219392d 100644
--- a/Engine/lib/sdl/src/audio/SDL_mixer.c
+++ b/Engine/lib/sdl/src/audio/SDL_mixer.c
@@ -202,6 +202,54 @@ SDL_MixAudioFormat(Uint8 * dst, const Uint8 * src, SDL_AudioFormat format,
}
break;
+ case AUDIO_U16LSB:
+ {
+ Uint16 src1, src2;
+ int dst_sample;
+ const int max_audioval = 0xFFFF;
+
+ len /= 2;
+ while (len--) {
+ src1 = ((src[1]) << 8 | src[0]);
+ ADJUST_VOLUME(src1, volume);
+ src2 = ((dst[1]) << 8 | dst[0]);
+ src += 2;
+ dst_sample = src1 + src2;
+ if (dst_sample > max_audioval) {
+ dst_sample = max_audioval;
+ }
+ dst[0] = dst_sample & 0xFF;
+ dst_sample >>= 8;
+ dst[1] = dst_sample & 0xFF;
+ dst += 2;
+ }
+ }
+ break;
+
+ case AUDIO_U16MSB:
+ {
+ Uint16 src1, src2;
+ int dst_sample;
+ const int max_audioval = 0xFFFF;
+
+ len /= 2;
+ while (len--) {
+ src1 = ((src[0]) << 8 | src[1]);
+ ADJUST_VOLUME(src1, volume);
+ src2 = ((dst[0]) << 8 | dst[1]);
+ src += 2;
+ dst_sample = src1 + src2;
+ if (dst_sample > max_audioval) {
+ dst_sample = max_audioval;
+ }
+ dst[1] = dst_sample & 0xFF;
+ dst_sample >>= 8;
+ dst[0] = dst_sample & 0xFF;
+ dst += 2;
+ }
+ }
+ break;
+
case AUDIO_S32LSB:
{
const Uint32 *src32 = (Uint32 *) src;
@@ -313,7 +361,7 @@ SDL_MixAudioFormat(Uint8 * dst, const Uint8 * src, SDL_AudioFormat format,
break;
default: /* If this happens... FIXME! */
- SDL_SetError("SDL_MixAudio(): unknown audio format");
+ SDL_SetError("SDL_MixAudioFormat(): unknown audio format");
return;
}
}
diff --git a/Engine/lib/sdl/src/audio/SDL_sysaudio.h b/Engine/lib/sdl/src/audio/SDL_sysaudio.h
index 426a190f1..943169bf7 100644
--- a/Engine/lib/sdl/src/audio/SDL_sysaudio.h
+++ b/Engine/lib/sdl/src/audio/SDL_sysaudio.h
@@ -26,6 +26,10 @@
#include "SDL_mutex.h"
#include "SDL_thread.h"
+/* !!! FIXME: These are wordy and unlocalized... */
+#define DEFAULT_OUTPUT_DEVNAME "System audio output device"
+#define DEFAULT_INPUT_DEVNAME "System audio capture device"
+
/* The SDL audio driver */
typedef struct SDL_AudioDevice SDL_AudioDevice;
#define _THIS SDL_AudioDevice *_this
@@ -75,7 +79,9 @@ typedef struct SDL_AudioDriverImpl
void (*PlayDevice) (_THIS);
int (*GetPendingBytes) (_THIS);
Uint8 *(*GetDeviceBuf) (_THIS);
- void (*WaitDone) (_THIS);
+ int (*CaptureFromDevice) (_THIS, void *buffer, int buflen);
+ void (*FlushCapture) (_THIS);
+ void (*PrepareToClose) (_THIS); /**< Called between run and draining wait for playback devices */
void (*CloseDevice) (_THIS);
void (*LockDevice) (_THIS);
void (*UnlockDevice) (_THIS);
@@ -87,10 +93,10 @@ typedef struct SDL_AudioDriverImpl
/* Some flags to push duplicate code into the core and reduce #ifdefs. */
/* !!! FIXME: these should be SDL_bool */
int ProvidesOwnCallbackThread;
- int SkipMixerLock; /* !!! FIXME: do we need this anymore? */
+ int SkipMixerLock;
int HasCaptureSupport;
int OnlyHasDefaultOutputDevice;
- int OnlyHasDefaultInputDevice;
+ int OnlyHasDefaultCaptureDevice;
int AllowsArbitraryDeviceNames;
} SDL_AudioDriverImpl;
@@ -157,12 +163,10 @@ struct SDL_AudioDevice
SDL_AudioStreamer streamer;
/* Current state flags */
- /* !!! FIXME: should be SDL_bool */
- int iscapture;
- int enabled; /* true if device is functioning and connected. */
- int shutdown; /* true if we are signaling the play thread to end. */
- int paused;
- int opened;
+ SDL_atomic_t shutdown; /* true if we are signaling the play thread to end. */
+ SDL_atomic_t enabled; /* true if device is functioning and connected. */
+ SDL_atomic_t paused;
+ SDL_bool iscapture;
/* Fake audio buffer for when the audio hardware is busy */
Uint8 *fake_stream;
@@ -183,6 +187,8 @@ struct SDL_AudioDevice
/* * * */
/* Data private to this driver */
struct SDL_PrivateAudioData *hidden;
+
+ void *handle;
};
#undef _THIS
diff --git a/Engine/lib/sdl/src/audio/SDL_wave.c b/Engine/lib/sdl/src/audio/SDL_wave.c
index 99daac64b..d173b4a92 100644
--- a/Engine/lib/sdl/src/audio/SDL_wave.c
+++ b/Engine/lib/sdl/src/audio/SDL_wave.c
@@ -504,7 +504,7 @@ SDL_LoadWAV_RW(SDL_RWops * src, int freesrc,
was_error = 1;
goto done;
}
- SDL_memset(spec, 0, (sizeof *spec));
+ SDL_zerop(spec);
spec->freq = SDL_SwapLE32(format->frequency);
if (IEEE_float_encoded) {
diff --git a/Engine/lib/sdl/src/audio/alsa/SDL_alsa_audio.c b/Engine/lib/sdl/src/audio/alsa/SDL_alsa_audio.c
index af952371b..574d51bd5 100644
--- a/Engine/lib/sdl/src/audio/alsa/SDL_alsa_audio.c
+++ b/Engine/lib/sdl/src/audio/alsa/SDL_alsa_audio.c
@@ -29,9 +29,9 @@
#include
#include
+#include "SDL_assert.h"
#include "SDL_timer.h"
#include "SDL_audio.h"
-#include "../SDL_audiomem.h"
#include "../SDL_audio_c.h"
#include "SDL_alsa_audio.h"
@@ -42,8 +42,10 @@
static int (*ALSA_snd_pcm_open)
(snd_pcm_t **, const char *, snd_pcm_stream_t, int);
static int (*ALSA_snd_pcm_close) (snd_pcm_t * pcm);
-static snd_pcm_sframes_t(*ALSA_snd_pcm_writei)
+static snd_pcm_sframes_t (*ALSA_snd_pcm_writei)
(snd_pcm_t *, const void *, snd_pcm_uframes_t);
+static snd_pcm_sframes_t (*ALSA_snd_pcm_readi)
+ (snd_pcm_t *, void *, snd_pcm_uframes_t);
static int (*ALSA_snd_pcm_recover) (snd_pcm_t *, int, int);
static int (*ALSA_snd_pcm_prepare) (snd_pcm_t *);
static int (*ALSA_snd_pcm_drain) (snd_pcm_t *);
@@ -85,6 +87,10 @@ static int (*ALSA_snd_pcm_nonblock) (snd_pcm_t *, int);
static int (*ALSA_snd_pcm_wait)(snd_pcm_t *, int);
static int (*ALSA_snd_pcm_sw_params_set_avail_min)
(snd_pcm_t *, snd_pcm_sw_params_t *, snd_pcm_uframes_t);
+static int (*ALSA_snd_pcm_reset)(snd_pcm_t *);
+static int (*ALSA_snd_device_name_hint) (int, const char *, void ***);
+static char* (*ALSA_snd_device_name_get_hint) (const void *, const char *);
+static int (*ALSA_snd_device_name_free_hint) (void **);
#ifdef SDL_AUDIO_DRIVER_ALSA_DYNAMIC
#define snd_pcm_hw_params_sizeof ALSA_snd_pcm_hw_params_sizeof
@@ -118,6 +124,7 @@ load_alsa_syms(void)
SDL_ALSA_SYM(snd_pcm_open);
SDL_ALSA_SYM(snd_pcm_close);
SDL_ALSA_SYM(snd_pcm_writei);
+ SDL_ALSA_SYM(snd_pcm_readi);
SDL_ALSA_SYM(snd_pcm_recover);
SDL_ALSA_SYM(snd_pcm_prepare);
SDL_ALSA_SYM(snd_pcm_drain);
@@ -144,6 +151,11 @@ load_alsa_syms(void)
SDL_ALSA_SYM(snd_pcm_nonblock);
SDL_ALSA_SYM(snd_pcm_wait);
SDL_ALSA_SYM(snd_pcm_sw_params_set_avail_min);
+ SDL_ALSA_SYM(snd_pcm_reset);
+ SDL_ALSA_SYM(snd_device_name_hint);
+ SDL_ALSA_SYM(snd_device_name_get_hint);
+ SDL_ALSA_SYM(snd_device_name_free_hint);
+
return 0;
}
@@ -196,25 +208,27 @@ LoadALSALibrary(void)
#endif /* SDL_AUDIO_DRIVER_ALSA_DYNAMIC */
static const char *
-get_audio_device(int channels)
+get_audio_device(void *handle, const int channels)
{
const char *device;
- device = SDL_getenv("AUDIODEV"); /* Is there a standard variable name? */
- if (device == NULL) {
- switch (channels) {
- case 6:
- device = "plug:surround51";
- break;
- case 4:
- device = "plug:surround40";
- break;
- default:
- device = "default";
- break;
- }
+ if (handle != NULL) {
+ return (const char *) handle;
}
- return device;
+
+ /* !!! FIXME: we also check "SDL_AUDIO_DEVICE_NAME" at the higher level. */
+ device = SDL_getenv("AUDIODEV"); /* Is there a standard variable name? */
+ if (device != NULL) {
+ return device;
+ }
+
+ if (channels == 6) {
+ return "plug:surround51";
+ } else if (channels == 4) {
+ return "plug:surround40";
+ }
+
+ return "default";
}
@@ -232,37 +246,37 @@ ALSA_WaitDevice(_THIS)
* "For Linux ALSA, this is FL-FR-RL-RR-C-LFE
* and for Windows DirectX [and CoreAudio], this is FL-FR-C-LFE-RL-RR"
*/
-#define SWIZ6(T) \
- T *ptr = (T *) this->hidden->mixbuf; \
+#define SWIZ6(T, buf, numframes) \
+ T *ptr = (T *) buf; \
Uint32 i; \
- for (i = 0; i < this->spec.samples; i++, ptr += 6) { \
+ for (i = 0; i < numframes; i++, ptr += 6) { \
T tmp; \
tmp = ptr[2]; ptr[2] = ptr[4]; ptr[4] = tmp; \
tmp = ptr[3]; ptr[3] = ptr[5]; ptr[5] = tmp; \
}
static SDL_INLINE void
-swizzle_alsa_channels_6_64bit(_THIS)
+swizzle_alsa_channels_6_64bit(void *buffer, Uint32 bufferlen)
{
- SWIZ6(Uint64);
+ SWIZ6(Uint64, buffer, bufferlen);
}
static SDL_INLINE void
-swizzle_alsa_channels_6_32bit(_THIS)
+swizzle_alsa_channels_6_32bit(void *buffer, Uint32 bufferlen)
{
- SWIZ6(Uint32);
+ SWIZ6(Uint32, buffer, bufferlen);
}
static SDL_INLINE void
-swizzle_alsa_channels_6_16bit(_THIS)
+swizzle_alsa_channels_6_16bit(void *buffer, Uint32 bufferlen)
{
- SWIZ6(Uint16);
+ SWIZ6(Uint16, buffer, bufferlen);
}
static SDL_INLINE void
-swizzle_alsa_channels_6_8bit(_THIS)
+swizzle_alsa_channels_6_8bit(void *buffer, Uint32 bufferlen)
{
- SWIZ6(Uint8);
+ SWIZ6(Uint8, buffer, bufferlen);
}
#undef SWIZ6
@@ -273,18 +287,16 @@ swizzle_alsa_channels_6_8bit(_THIS)
* channels from Windows/Mac order to the format alsalib will want.
*/
static SDL_INLINE void
-swizzle_alsa_channels(_THIS)
+swizzle_alsa_channels(_THIS, void *buffer, Uint32 bufferlen)
{
if (this->spec.channels == 6) {
- const Uint16 fmtsize = (this->spec.format & 0xFF); /* bits/channel. */
- if (fmtsize == 16)
- swizzle_alsa_channels_6_16bit(this);
- else if (fmtsize == 8)
- swizzle_alsa_channels_6_8bit(this);
- else if (fmtsize == 32)
- swizzle_alsa_channels_6_32bit(this);
- else if (fmtsize == 64)
- swizzle_alsa_channels_6_64bit(this);
+ switch (SDL_AUDIO_BITSIZE(this->spec.format)) {
+ case 8: swizzle_alsa_channels_6_8bit(buffer, bufferlen); break;
+ case 16: swizzle_alsa_channels_6_16bit(buffer, bufferlen); break;
+ case 32: swizzle_alsa_channels_6_32bit(buffer, bufferlen); break;
+ case 64: swizzle_alsa_channels_6_64bit(buffer, bufferlen); break;
+ default: SDL_assert(!"unhandled bitsize"); break;
+ }
}
/* !!! FIXME: update this for 7.1 if needed, later. */
@@ -294,19 +306,29 @@ swizzle_alsa_channels(_THIS)
static void
ALSA_PlayDevice(_THIS)
{
- int status;
const Uint8 *sample_buf = (const Uint8 *) this->hidden->mixbuf;
- const int frame_size = (((int) (this->spec.format & 0xFF)) / 8) *
+ const int frame_size = (((int) SDL_AUDIO_BITSIZE(this->spec.format)) / 8) *
this->spec.channels;
snd_pcm_uframes_t frames_left = ((snd_pcm_uframes_t) this->spec.samples);
- swizzle_alsa_channels(this);
+ swizzle_alsa_channels(this, this->hidden->mixbuf, frames_left);
+
+ while ( frames_left > 0 && SDL_AtomicGet(&this->enabled) ) {
+ int status;
+
+ /* This wait is a work-around for a hang when USB devices are
+ unplugged. Normally it should not result in any waiting,
+ but in the case of a USB unplug, it serves as a way to
+ join the playback thread after the timeout occurs */
+ status = ALSA_snd_pcm_wait(this->hidden->pcm_handle, 1000);
+ if (status == 0) {
+ /*fprintf(stderr, "ALSA timeout waiting for available buffer space\n");*/
+ SDL_OpenedAudioDeviceDisconnected(this);
+ return;
+ }
- while ( frames_left > 0 && this->enabled ) {
- /* !!! FIXME: This works, but needs more testing before going live */
- /* ALSA_snd_pcm_wait(this->hidden->pcm_handle, -1); */
status = ALSA_snd_pcm_writei(this->hidden->pcm_handle,
- sample_buf, frames_left);
+ sample_buf, frames_left);
if (status < 0) {
if (status == -EAGAIN) {
@@ -336,20 +358,71 @@ ALSA_GetDeviceBuf(_THIS)
return (this->hidden->mixbuf);
}
+static int
+ALSA_CaptureFromDevice(_THIS, void *buffer, int buflen)
+{
+ Uint8 *sample_buf = (Uint8 *) buffer;
+ const int frame_size = (((int) SDL_AUDIO_BITSIZE(this->spec.format)) / 8) *
+ this->spec.channels;
+ const int total_frames = buflen / frame_size;
+ snd_pcm_uframes_t frames_left = total_frames;
+
+ SDL_assert((buflen % frame_size) == 0);
+
+ while ( frames_left > 0 && SDL_AtomicGet(&this->enabled) ) {
+ /* !!! FIXME: This works, but needs more testing before going live */
+ /* ALSA_snd_pcm_wait(this->hidden->pcm_handle, -1); */
+ int status = ALSA_snd_pcm_readi(this->hidden->pcm_handle,
+ sample_buf, frames_left);
+
+ if (status < 0) {
+ /*printf("ALSA: capture error %d\n", status);*/
+ if (status == -EAGAIN) {
+ /* Apparently snd_pcm_recover() doesn't handle this case -
+ does it assume snd_pcm_wait() above? */
+ SDL_Delay(1);
+ continue;
+ }
+ status = ALSA_snd_pcm_recover(this->hidden->pcm_handle, status, 0);
+ if (status < 0) {
+ /* Hmm, not much we can do - abort */
+ fprintf(stderr, "ALSA read failed (unrecoverable): %s\n",
+ ALSA_snd_strerror(status));
+ return -1;
+ }
+ continue;
+ }
+
+ /*printf("ALSA: captured %d bytes\n", status * frame_size);*/
+ sample_buf += status * frame_size;
+ frames_left -= status;
+ }
+
+ swizzle_alsa_channels(this, buffer, total_frames - frames_left);
+
+ return (total_frames - frames_left) * frame_size;
+}
+
+static void
+ALSA_FlushCapture(_THIS)
+{
+ ALSA_snd_pcm_reset(this->hidden->pcm_handle);
+}
+
static void
ALSA_CloseDevice(_THIS)
{
- if (this->hidden != NULL) {
- SDL_FreeAudioMem(this->hidden->mixbuf);
- this->hidden->mixbuf = NULL;
- if (this->hidden->pcm_handle) {
- ALSA_snd_pcm_drain(this->hidden->pcm_handle);
- ALSA_snd_pcm_close(this->hidden->pcm_handle);
- this->hidden->pcm_handle = NULL;
- }
- SDL_free(this->hidden);
- this->hidden = NULL;
+ if (this->hidden->pcm_handle) {
+ /* Wait for the submitted audio to drain
+ ALSA_snd_pcm_drop() can hang, so don't use that.
+ */
+ Uint32 delay = ((this->spec.samples * 1000) / this->spec.freq) * 2;
+ SDL_Delay(delay);
+
+ ALSA_snd_pcm_close(this->hidden->pcm_handle);
}
+ SDL_free(this->hidden->mixbuf);
+ SDL_free(this->hidden);
}
static int
@@ -482,16 +555,16 @@ ALSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
if (this->hidden == NULL) {
return SDL_OutOfMemory();
}
- SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+ SDL_zerop(this->hidden);
/* Open the audio device */
/* Name of device should depend on # channels in spec */
status = ALSA_snd_pcm_open(&pcm_handle,
- get_audio_device(this->spec.channels),
- SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
+ get_audio_device(handle, this->spec.channels),
+ iscapture ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK,
+ SND_PCM_NONBLOCK);
if (status < 0) {
- ALSA_CloseDevice(this);
return SDL_SetError("ALSA: Couldn't open audio device: %s",
ALSA_snd_strerror(status));
}
@@ -502,7 +575,6 @@ ALSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
snd_pcm_hw_params_alloca(&hwparams);
status = ALSA_snd_pcm_hw_params_any(pcm_handle, hwparams);
if (status < 0) {
- ALSA_CloseDevice(this);
return SDL_SetError("ALSA: Couldn't get hardware config: %s",
ALSA_snd_strerror(status));
}
@@ -511,7 +583,6 @@ ALSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
status = ALSA_snd_pcm_hw_params_set_access(pcm_handle, hwparams,
SND_PCM_ACCESS_RW_INTERLEAVED);
if (status < 0) {
- ALSA_CloseDevice(this);
return SDL_SetError("ALSA: Couldn't set interleaved access: %s",
ALSA_snd_strerror(status));
}
@@ -565,7 +636,6 @@ ALSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
}
}
if (status < 0) {
- ALSA_CloseDevice(this);
return SDL_SetError("ALSA: Couldn't find any hardware audio formats");
}
this->spec.format = test_format;
@@ -577,7 +647,6 @@ ALSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
if (status < 0) {
status = ALSA_snd_pcm_hw_params_get_channels(hwparams, &channels);
if (status < 0) {
- ALSA_CloseDevice(this);
return SDL_SetError("ALSA: Couldn't set audio channels");
}
this->spec.channels = channels;
@@ -588,7 +657,6 @@ ALSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
status = ALSA_snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams,
&rate, NULL);
if (status < 0) {
- ALSA_CloseDevice(this);
return SDL_SetError("ALSA: Couldn't set audio frequency: %s",
ALSA_snd_strerror(status));
}
@@ -598,8 +666,8 @@ ALSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
if ( ALSA_set_period_size(this, hwparams, 0) < 0 &&
ALSA_set_buffer_size(this, hwparams, 0) < 0 ) {
/* Failed to set desired buffer size, do the best you can... */
- if ( ALSA_set_period_size(this, hwparams, 1) < 0 ) {
- ALSA_CloseDevice(this);
+ status = ALSA_set_period_size(this, hwparams, 1);
+ if (status < 0) {
return SDL_SetError("Couldn't set hardware audio parameters: %s", ALSA_snd_strerror(status));
}
}
@@ -607,26 +675,22 @@ ALSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
snd_pcm_sw_params_alloca(&swparams);
status = ALSA_snd_pcm_sw_params_current(pcm_handle, swparams);
if (status < 0) {
- ALSA_CloseDevice(this);
return SDL_SetError("ALSA: Couldn't get software config: %s",
ALSA_snd_strerror(status));
}
status = ALSA_snd_pcm_sw_params_set_avail_min(pcm_handle, swparams, this->spec.samples);
if (status < 0) {
- ALSA_CloseDevice(this);
return SDL_SetError("Couldn't set minimum available samples: %s",
ALSA_snd_strerror(status));
}
status =
ALSA_snd_pcm_sw_params_set_start_threshold(pcm_handle, swparams, 1);
if (status < 0) {
- ALSA_CloseDevice(this);
return SDL_SetError("ALSA: Couldn't set start threshold: %s",
ALSA_snd_strerror(status));
}
status = ALSA_snd_pcm_sw_params(pcm_handle, swparams);
if (status < 0) {
- ALSA_CloseDevice(this);
return SDL_SetError("Couldn't set software audio parameters: %s",
ALSA_snd_strerror(status));
}
@@ -635,13 +699,14 @@ ALSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
SDL_CalculateAudioSpec(&this->spec);
/* Allocate mixing buffer */
- this->hidden->mixlen = this->spec.size;
- this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
- if (this->hidden->mixbuf == NULL) {
- ALSA_CloseDevice(this);
- return SDL_OutOfMemory();
+ if (!iscapture) {
+ this->hidden->mixlen = this->spec.size;
+ this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->hidden->mixlen);
+ if (this->hidden->mixbuf == NULL) {
+ return SDL_OutOfMemory();
+ }
+ SDL_memset(this->hidden->mixbuf, this->spec.silence, this->hidden->mixlen);
}
- SDL_memset(this->hidden->mixbuf, this->spec.silence, this->hidden->mixlen);
/* Switch to blocking mode for playback */
ALSA_snd_pcm_nonblock(pcm_handle, 0);
@@ -650,9 +715,238 @@ ALSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
return 0;
}
+typedef struct ALSA_Device
+{
+ char *name;
+ SDL_bool iscapture;
+ struct ALSA_Device *next;
+} ALSA_Device;
+
+static void
+add_device(const int iscapture, const char *name, void *hint, ALSA_Device **pSeen)
+{
+ ALSA_Device *dev = SDL_malloc(sizeof (ALSA_Device));
+ char *desc = ALSA_snd_device_name_get_hint(hint, "DESC");
+ char *handle = NULL;
+ char *ptr;
+
+ if (!desc) {
+ SDL_free(dev);
+ return;
+ } else if (!dev) {
+ free(desc);
+ return;
+ }
+
+ SDL_assert(name != NULL);
+
+ /* some strings have newlines, like "HDA NVidia, HDMI 0\nHDMI Audio Output".
+ just chop the extra lines off, this seems to get a reasonable device
+ name without extra details. */
+ if ((ptr = strchr(desc, '\n')) != NULL) {
+ *ptr = '\0';
+ }
+
+ /*printf("ALSA: adding %s device '%s' (%s)\n", iscapture ? "capture" : "output", name, desc);*/
+
+ handle = SDL_strdup(name);
+ if (!handle) {
+ free(desc);
+ SDL_free(dev);
+ return;
+ }
+
+ SDL_AddAudioDevice(iscapture, desc, handle);
+ free(desc);
+
+ dev->name = handle;
+ dev->iscapture = iscapture;
+ dev->next = *pSeen;
+ *pSeen = dev;
+}
+
+
+static SDL_atomic_t ALSA_hotplug_shutdown;
+static SDL_Thread *ALSA_hotplug_thread;
+
+static int SDLCALL
+ALSA_HotplugThread(void *arg)
+{
+ SDL_sem *first_run_semaphore = (SDL_sem *) arg;
+ ALSA_Device *devices = NULL;
+ ALSA_Device *next;
+ ALSA_Device *dev;
+ Uint32 ticks;
+
+ while (!SDL_AtomicGet(&ALSA_hotplug_shutdown)) {
+ void **hints = NULL;
+ if (ALSA_snd_device_name_hint(-1, "pcm", &hints) != -1) {
+ ALSA_Device *unseen = devices;
+ ALSA_Device *seen = NULL;
+ ALSA_Device *prev;
+ int i, j;
+ const char *match = NULL;
+ int bestmatch = 0xFFFF;
+ size_t match_len = 0;
+ int defaultdev = -1;
+ static const char * const prefixes[] = {
+ "hw:", "sysdefault:", "default:", NULL
+ };
+
+ /* Apparently there are several different ways that ALSA lists
+ actual hardware. It could be prefixed with "hw:" or "default:"
+ or "sysdefault:" and maybe others. Go through the list and see
+ if we can find a preferred prefix for the system. */
+ for (i = 0; hints[i]; i++) {
+ char *name = ALSA_snd_device_name_get_hint(hints[i], "NAME");
+ if (!name) {
+ continue;
+ }
+
+ /* full name, not a prefix */
+ if ((defaultdev == -1) && (SDL_strcmp(name, "default") == 0)) {
+ defaultdev = i;
+ }
+
+ for (j = 0; prefixes[j]; j++) {
+ const char *prefix = prefixes[j];
+ const size_t prefixlen = SDL_strlen(prefix);
+ if (SDL_strncmp(name, prefix, prefixlen) == 0) {
+ if (j < bestmatch) {
+ bestmatch = j;
+ match = prefix;
+ match_len = prefixlen;
+ }
+ }
+ }
+
+ free(name);
+ }
+
+ /* look through the list of device names to find matches */
+ for (i = 0; hints[i]; i++) {
+ char *name;
+
+ /* if we didn't find a device name prefix we like at all... */
+ if ((!match) && (defaultdev != i)) {
+ continue; /* ...skip anything that isn't the default device. */
+ }
+
+ name = ALSA_snd_device_name_get_hint(hints[i], "NAME");
+ if (!name) {
+ continue;
+ }
+
+ /* only want physical hardware interfaces */
+ if (!match || (SDL_strncmp(name, match, match_len) == 0)) {
+ char *ioid = ALSA_snd_device_name_get_hint(hints[i], "IOID");
+ const SDL_bool isoutput = (ioid == NULL) || (SDL_strcmp(ioid, "Output") == 0);
+ const SDL_bool isinput = (ioid == NULL) || (SDL_strcmp(ioid, "Input") == 0);
+ SDL_bool have_output = SDL_FALSE;
+ SDL_bool have_input = SDL_FALSE;
+
+ free(ioid);
+
+ if (!isoutput && !isinput) {
+ free(name);
+ continue;
+ }
+
+ prev = NULL;
+ for (dev = unseen; dev; dev = next) {
+ next = dev->next;
+ if ( (SDL_strcmp(dev->name, name) == 0) && (((isinput) && dev->iscapture) || ((isoutput) && !dev->iscapture)) ) {
+ if (prev) {
+ prev->next = next;
+ } else {
+ unseen = next;
+ }
+ dev->next = seen;
+ seen = dev;
+ if (isinput) have_input = SDL_TRUE;
+ if (isoutput) have_output = SDL_TRUE;
+ } else {
+ prev = dev;
+ }
+ }
+
+ if (isinput && !have_input) {
+ add_device(SDL_TRUE, name, hints[i], &seen);
+ }
+ if (isoutput && !have_output) {
+ add_device(SDL_FALSE, name, hints[i], &seen);
+ }
+ }
+
+ free(name);
+ }
+
+ ALSA_snd_device_name_free_hint(hints);
+
+ devices = seen; /* now we have a known-good list of attached devices. */
+
+ /* report anything still in unseen as removed. */
+ for (dev = unseen; dev; dev = next) {
+ /*printf("ALSA: removing %s device '%s'\n", dev->iscapture ? "capture" : "output", dev->name);*/
+ next = dev->next;
+ SDL_RemoveAudioDevice(dev->iscapture, dev->name);
+ SDL_free(dev->name);
+ SDL_free(dev);
+ }
+ }
+
+ /* On first run, tell ALSA_DetectDevices() that we have a complete device list so it can return. */
+ if (first_run_semaphore) {
+ SDL_SemPost(first_run_semaphore);
+ first_run_semaphore = NULL; /* let other thread clean it up. */
+ }
+
+ /* Block awhile before checking again, unless we're told to stop. */
+ ticks = SDL_GetTicks() + 5000;
+ while (!SDL_AtomicGet(&ALSA_hotplug_shutdown) && !SDL_TICKS_PASSED(SDL_GetTicks(), ticks)) {
+ SDL_Delay(100);
+ }
+ }
+
+ /* Shutting down! Clean up any data we've gathered. */
+ for (dev = devices; dev; dev = next) {
+ /*printf("ALSA: at shutdown, removing %s device '%s'\n", dev->iscapture ? "capture" : "output", dev->name);*/
+ next = dev->next;
+ SDL_free(dev->name);
+ SDL_free(dev);
+ }
+
+ return 0;
+}
+
+static void
+ALSA_DetectDevices(void)
+{
+ /* Start the device detection thread here, wait for an initial iteration to complete. */
+ SDL_sem *semaphore = SDL_CreateSemaphore(0);
+ if (!semaphore) {
+ return; /* oh well. */
+ }
+
+ SDL_AtomicSet(&ALSA_hotplug_shutdown, 0);
+
+ ALSA_hotplug_thread = SDL_CreateThread(ALSA_HotplugThread, "SDLHotplugALSA", semaphore);
+ if (ALSA_hotplug_thread) {
+ SDL_SemWait(semaphore); /* wait for the first iteration to finish. */
+ }
+
+ SDL_DestroySemaphore(semaphore);
+}
+
static void
ALSA_Deinitialize(void)
{
+ if (ALSA_hotplug_thread != NULL) {
+ SDL_AtomicSet(&ALSA_hotplug_shutdown, 1);
+ SDL_WaitThread(ALSA_hotplug_thread, NULL);
+ ALSA_hotplug_thread = NULL;
+ }
+
UnloadALSALibrary();
}
@@ -664,13 +958,17 @@ ALSA_Init(SDL_AudioDriverImpl * impl)
}
/* Set the function pointers */
+ impl->DetectDevices = ALSA_DetectDevices;
impl->OpenDevice = ALSA_OpenDevice;
impl->WaitDevice = ALSA_WaitDevice;
impl->GetDeviceBuf = ALSA_GetDeviceBuf;
impl->PlayDevice = ALSA_PlayDevice;
impl->CloseDevice = ALSA_CloseDevice;
impl->Deinitialize = ALSA_Deinitialize;
- impl->OnlyHasDefaultOutputDevice = 1; /* !!! FIXME: Add device enum! */
+ impl->CaptureFromDevice = ALSA_CaptureFromDevice;
+ impl->FlushCapture = ALSA_FlushCapture;
+
+ impl->HasCaptureSupport = SDL_TRUE;
return 1; /* this audio target is available. */
}
diff --git a/Engine/lib/sdl/src/audio/android/SDL_androidaudio.c b/Engine/lib/sdl/src/audio/android/SDL_androidaudio.c
index 4a4faadcf..96f6d631a 100644
--- a/Engine/lib/sdl/src/audio/android/SDL_androidaudio.c
+++ b/Engine/lib/sdl/src/audio/android/SDL_androidaudio.c
@@ -24,6 +24,7 @@
/* Output audio to Android */
+#include "SDL_assert.h"
#include "SDL_audio.h"
#include "../SDL_audio_c.h"
#include "SDL_androidaudio.h"
@@ -33,23 +34,22 @@
#include
static SDL_AudioDevice* audioDevice = NULL;
+static SDL_AudioDevice* captureDevice = NULL;
static int
-AndroidAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
+ANDROIDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
SDL_AudioFormat test_format;
+ SDL_assert((captureDevice == NULL) || !iscapture);
+ SDL_assert((audioDevice == NULL) || iscapture);
+
if (iscapture) {
- /* TODO: implement capture */
- return SDL_SetError("Capture not supported on Android");
+ captureDevice = this;
+ } else {
+ audioDevice = this;
}
- if (audioDevice != NULL) {
- return SDL_SetError("Only one audio device at a time please!");
- }
-
- audioDevice = this;
-
this->hidden = (struct SDL_PrivateAudioData *) SDL_calloc(1, (sizeof *this->hidden));
if (this->hidden == NULL) {
return SDL_OutOfMemory();
@@ -82,100 +82,137 @@ AndroidAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
this->spec.freq = 48000;
}
- /* TODO: pass in/return a (Java) device ID, also whether we're opening for input or output */
- this->spec.samples = Android_JNI_OpenAudioDevice(this->spec.freq, this->spec.format == AUDIO_U8 ? 0 : 1, this->spec.channels, this->spec.samples);
- SDL_CalculateAudioSpec(&this->spec);
+ /* TODO: pass in/return a (Java) device ID */
+ this->spec.samples = Android_JNI_OpenAudioDevice(iscapture, this->spec.freq, this->spec.format == AUDIO_U8 ? 0 : 1, this->spec.channels, this->spec.samples);
if (this->spec.samples == 0) {
/* Init failed? */
return SDL_SetError("Java-side initialization failed!");
}
+ SDL_CalculateAudioSpec(&this->spec);
+
return 0;
}
static void
-AndroidAUD_PlayDevice(_THIS)
+ANDROIDAUDIO_PlayDevice(_THIS)
{
Android_JNI_WriteAudioBuffer();
}
static Uint8 *
-AndroidAUD_GetDeviceBuf(_THIS)
+ANDROIDAUDIO_GetDeviceBuf(_THIS)
{
return Android_JNI_GetAudioBuffer();
}
+static int
+ANDROIDAUDIO_CaptureFromDevice(_THIS, void *buffer, int buflen)
+{
+ return Android_JNI_CaptureAudioBuffer(buffer, buflen);
+}
+
static void
-AndroidAUD_CloseDevice(_THIS)
+ANDROIDAUDIO_FlushCapture(_THIS)
+{
+ Android_JNI_FlushCapturedAudio();
+}
+
+static void
+ANDROIDAUDIO_CloseDevice(_THIS)
{
/* At this point SDL_CloseAudioDevice via close_audio_device took care of terminating the audio thread
so it's safe to terminate the Java side buffer and AudioTrack
*/
- Android_JNI_CloseAudioDevice();
-
- if (audioDevice == this) {
- if (audioDevice->hidden != NULL) {
- SDL_free(this->hidden);
- this->hidden = NULL;
- }
+ Android_JNI_CloseAudioDevice(this->iscapture);
+ if (this->iscapture) {
+ SDL_assert(captureDevice == this);
+ captureDevice = NULL;
+ } else {
+ SDL_assert(audioDevice == this);
audioDevice = NULL;
}
+ SDL_free(this->hidden);
}
static int
-AndroidAUD_Init(SDL_AudioDriverImpl * impl)
+ANDROIDAUDIO_Init(SDL_AudioDriverImpl * impl)
{
/* Set the function pointers */
- impl->OpenDevice = AndroidAUD_OpenDevice;
- impl->PlayDevice = AndroidAUD_PlayDevice;
- impl->GetDeviceBuf = AndroidAUD_GetDeviceBuf;
- impl->CloseDevice = AndroidAUD_CloseDevice;
+ impl->OpenDevice = ANDROIDAUDIO_OpenDevice;
+ impl->PlayDevice = ANDROIDAUDIO_PlayDevice;
+ impl->GetDeviceBuf = ANDROIDAUDIO_GetDeviceBuf;
+ impl->CloseDevice = ANDROIDAUDIO_CloseDevice;
+ impl->CaptureFromDevice = ANDROIDAUDIO_CaptureFromDevice;
+ impl->FlushCapture = ANDROIDAUDIO_FlushCapture;
/* and the capabilities */
- impl->HasCaptureSupport = 0; /* TODO */
+ impl->HasCaptureSupport = SDL_TRUE;
impl->OnlyHasDefaultOutputDevice = 1;
- impl->OnlyHasDefaultInputDevice = 1;
+ impl->OnlyHasDefaultCaptureDevice = 1;
return 1; /* this audio target is available. */
}
-AudioBootStrap ANDROIDAUD_bootstrap = {
- "android", "SDL Android audio driver", AndroidAUD_Init, 0
+AudioBootStrap ANDROIDAUDIO_bootstrap = {
+ "android", "SDL Android audio driver", ANDROIDAUDIO_Init, 0
};
/* Pause (block) all non already paused audio devices by taking their mixer lock */
-void AndroidAUD_PauseDevices(void)
+void ANDROIDAUDIO_PauseDevices(void)
{
/* TODO: Handle multiple devices? */
struct SDL_PrivateAudioData *private;
if(audioDevice != NULL && audioDevice->hidden != NULL) {
private = (struct SDL_PrivateAudioData *) audioDevice->hidden;
- if (audioDevice->paused) {
+ if (SDL_AtomicGet(&audioDevice->paused)) {
/* The device is already paused, leave it alone */
private->resume = SDL_FALSE;
}
else {
SDL_LockMutex(audioDevice->mixer_lock);
- audioDevice->paused = SDL_TRUE;
+ SDL_AtomicSet(&audioDevice->paused, 1);
+ private->resume = SDL_TRUE;
+ }
+ }
+
+ if(captureDevice != NULL && captureDevice->hidden != NULL) {
+ private = (struct SDL_PrivateAudioData *) captureDevice->hidden;
+ if (SDL_AtomicGet(&captureDevice->paused)) {
+ /* The device is already paused, leave it alone */
+ private->resume = SDL_FALSE;
+ }
+ else {
+ SDL_LockMutex(captureDevice->mixer_lock);
+ SDL_AtomicSet(&captureDevice->paused, 1);
private->resume = SDL_TRUE;
}
}
}
/* Resume (unblock) all non already paused audio devices by releasing their mixer lock */
-void AndroidAUD_ResumeDevices(void)
+void ANDROIDAUDIO_ResumeDevices(void)
{
/* TODO: Handle multiple devices? */
struct SDL_PrivateAudioData *private;
if(audioDevice != NULL && audioDevice->hidden != NULL) {
private = (struct SDL_PrivateAudioData *) audioDevice->hidden;
if (private->resume) {
- audioDevice->paused = SDL_FALSE;
+ SDL_AtomicSet(&audioDevice->paused, 0);
private->resume = SDL_FALSE;
SDL_UnlockMutex(audioDevice->mixer_lock);
}
}
+
+ if(captureDevice != NULL && captureDevice->hidden != NULL) {
+ private = (struct SDL_PrivateAudioData *) captureDevice->hidden;
+ if (private->resume) {
+ SDL_AtomicSet(&captureDevice->paused, 0);
+ private->resume = SDL_FALSE;
+ SDL_UnlockMutex(captureDevice->mixer_lock);
+ }
+ }
}
diff --git a/Engine/lib/sdl/src/audio/android/SDL_androidaudio.h b/Engine/lib/sdl/src/audio/android/SDL_androidaudio.h
index 639be9c08..133615302 100644
--- a/Engine/lib/sdl/src/audio/android/SDL_androidaudio.h
+++ b/Engine/lib/sdl/src/audio/android/SDL_androidaudio.h
@@ -34,8 +34,6 @@ struct SDL_PrivateAudioData
int resume;
};
-static void AndroidAUD_CloseDevice(_THIS);
-
#endif /* _SDL_androidaudio_h */
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/audio/arts/SDL_artsaudio.c b/Engine/lib/sdl/src/audio/arts/SDL_artsaudio.c
index 5d40cd14e..6054e36b6 100644
--- a/Engine/lib/sdl/src/audio/arts/SDL_artsaudio.c
+++ b/Engine/lib/sdl/src/audio/arts/SDL_artsaudio.c
@@ -32,7 +32,6 @@
#include "SDL_timer.h"
#include "SDL_audio.h"
-#include "../SDL_audiomem.h"
#include "../SDL_audio_c.h"
#include "SDL_artsaudio.h"
@@ -186,13 +185,6 @@ ARTS_PlayDevice(_THIS)
#endif
}
-static void
-ARTS_WaitDone(_THIS)
-{
- /* !!! FIXME: camp here until buffer drains... SDL_Delay(???); */
-}
-
-
static Uint8 *
ARTS_GetDeviceBuf(_THIS)
{
@@ -203,17 +195,12 @@ ARTS_GetDeviceBuf(_THIS)
static void
ARTS_CloseDevice(_THIS)
{
- if (this->hidden != NULL) {
- SDL_FreeAudioMem(this->hidden->mixbuf);
- this->hidden->mixbuf = NULL;
- if (this->hidden->stream) {
- SDL_NAME(arts_close_stream) (this->hidden->stream);
- this->hidden->stream = 0;
- }
- SDL_NAME(arts_free) ();
- SDL_free(this->hidden);
- this->hidden = NULL;
+ if (this->hidden->stream) {
+ SDL_NAME(arts_close_stream) (this->hidden->stream);
}
+ SDL_NAME(arts_free) ();
+ SDL_free(this->hidden->mixbuf);
+ SDL_free(this->hidden);
}
static int
@@ -241,7 +228,7 @@ ARTS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
if (this->hidden == NULL) {
return SDL_OutOfMemory();
}
- SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+ SDL_zerop(this->hidden);
/* Try for a closest match on audio format */
for (test_format = SDL_FirstAudioFormat(this->spec.format);
@@ -267,19 +254,16 @@ ARTS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
}
}
if (format == 0) {
- ARTS_CloseDevice(this);
return SDL_SetError("Couldn't find any hardware audio formats");
}
this->spec.format = test_format;
if ((rc = SDL_NAME(arts_init) ()) != 0) {
- ARTS_CloseDevice(this);
return SDL_SetError("Unable to initialize ARTS: %s",
SDL_NAME(arts_error_text) (rc));
}
if (!ARTS_Suspend()) {
- ARTS_CloseDevice(this);
return SDL_SetError("ARTS can not open audio device");
}
@@ -297,7 +281,6 @@ ARTS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
/* Determine the power of two of the fragment size */
for (frag_spec = 0; (0x01 << frag_spec) < this->spec.size; ++frag_spec);
if ((0x01 << frag_spec) != this->spec.size) {
- ARTS_CloseDevice(this);
return SDL_SetError("Fragment size must be a power of two");
}
frag_spec |= 0x00020000; /* two fragments, for low latency */
@@ -316,9 +299,8 @@ ARTS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
/* Allocate mixing buffer */
this->hidden->mixlen = this->spec.size;
- this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
+ this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->hidden->mixlen);
if (this->hidden->mixbuf == NULL) {
- ARTS_CloseDevice(this);
return SDL_OutOfMemory();
}
SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
@@ -367,7 +349,6 @@ ARTS_Init(SDL_AudioDriverImpl * impl)
impl->WaitDevice = ARTS_WaitDevice;
impl->GetDeviceBuf = ARTS_GetDeviceBuf;
impl->CloseDevice = ARTS_CloseDevice;
- impl->WaitDone = ARTS_WaitDone;
impl->Deinitialize = ARTS_Deinitialize;
impl->OnlyHasDefaultOutputDevice = 1;
diff --git a/Engine/lib/sdl/src/audio/bsd/SDL_bsdaudio.c b/Engine/lib/sdl/src/audio/bsd/SDL_bsdaudio.c
index eeb257371..6a970b9c7 100644
--- a/Engine/lib/sdl/src/audio/bsd/SDL_bsdaudio.c
+++ b/Engine/lib/sdl/src/audio/bsd/SDL_bsdaudio.c
@@ -38,7 +38,6 @@
#include "SDL_timer.h"
#include "SDL_audio.h"
-#include "../SDL_audiomem.h"
#include "../SDL_audio_c.h"
#include "../SDL_audiodev_c.h"
#include "SDL_bsdaudio.h"
@@ -63,13 +62,17 @@ BSDAUDIO_Status(_THIS)
#ifdef DEBUG_AUDIO
/* *INDENT-OFF* */
audio_info_t info;
+ const audio_prinfo *prinfo;
if (ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info) < 0) {
fprintf(stderr, "AUDIO_GETINFO failed.\n");
return;
}
+
+ prinfo = this->iscapture ? &info.play : &info.record;
+
fprintf(stderr, "\n"
- "[play/record info]\n"
+ "[%s info]\n"
"buffer size : %d bytes\n"
"sample rate : %i Hz\n"
"channels : %i\n"
@@ -83,18 +86,19 @@ BSDAUDIO_Status(_THIS)
"waiting : %s\n"
"active : %s\n"
"",
- info.play.buffer_size,
- info.play.sample_rate,
- info.play.channels,
- info.play.precision,
- info.play.encoding,
- info.play.seek,
- info.play.samples,
- info.play.eof,
- info.play.pause ? "yes" : "no",
- info.play.error ? "yes" : "no",
- info.play.waiting ? "yes" : "no",
- info.play.active ? "yes" : "no");
+ this->iscapture ? "record" : "play",
+ prinfo->buffer_size,
+ prinfo->sample_rate,
+ prinfo->channels,
+ prinfo->precision,
+ prinfo->encoding,
+ prinfo->seek,
+ prinfo->samples,
+ prinfo->eof,
+ prinfo->pause ? "yes" : "no",
+ prinfo->error ? "yes" : "no",
+ prinfo->waiting ? "yes" : "no",
+ prinfo->active ? "yes" : "no");
fprintf(stderr, "\n"
"[audio info]\n"
@@ -182,11 +186,15 @@ BSDAUDIO_PlayDevice(_THIS)
break;
}
- if (p < written
+#ifdef DEBUG_AUDIO
+ fprintf(stderr, "Wrote %d bytes of audio data\n", written);
+#endif
+
+ if (p < this->hidden->mixlen
|| ((written < 0) && ((errno == 0) || (errno == EAGAIN)))) {
SDL_Delay(1); /* Let a little CPU time go by */
}
- } while (p < written);
+ } while (p < this->hidden->mixlen);
/* If timer synchronization is enabled, set the next write frame */
if (this->hidden->frame_ticks) {
@@ -197,9 +205,6 @@ BSDAUDIO_PlayDevice(_THIS)
if (written < 0) {
SDL_OpenedAudioDeviceDisconnected(this);
}
-#ifdef DEBUG_AUDIO
- fprintf(stderr, "Wrote %d bytes of audio data\n", written);
-#endif
}
static Uint8 *
@@ -208,27 +213,74 @@ BSDAUDIO_GetDeviceBuf(_THIS)
return (this->hidden->mixbuf);
}
+
+static int
+BSDAUDIO_CaptureFromDevice(_THIS, void *_buffer, int buflen)
+{
+ Uint8 *buffer = (Uint8 *) _buffer;
+ int br, p = 0;
+
+ /* Write the audio data, checking for EAGAIN on broken audio drivers */
+ do {
+ br = read(this->hidden->audio_fd, buffer + p, buflen - p);
+ if (br > 0)
+ p += br;
+ if (br == -1 && errno != 0 && errno != EAGAIN && errno != EINTR) {
+ /* Non recoverable error has occurred. It should be reported!!! */
+ perror("audio");
+ return p ? p : -1;
+ }
+
+#ifdef DEBUG_AUDIO
+ fprintf(stderr, "Captured %d bytes of audio data\n", br);
+#endif
+
+ if (p < buflen
+ || ((br < 0) && ((errno == 0) || (errno == EAGAIN)))) {
+ SDL_Delay(1); /* Let a little CPU time go by */
+ }
+ } while (p < buflen);
+}
+
+static void
+BSDAUDIO_FlushCapture(_THIS)
+{
+ audio_info_t info;
+ size_t remain;
+ Uint8 buf[512];
+
+ if (ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info) < 0) {
+ return; /* oh well. */
+ }
+
+ remain = (size_t) (info.record.samples * (SDL_AUDIO_BITSIZE(this->spec.format) / 8));
+ while (remain > 0) {
+ const size_t len = SDL_min(sizeof (buf), remain);
+ const int br = read(this->hidden->audio_fd, buf, len);
+ if (br <= 0) {
+ return; /* oh well. */
+ }
+ remain -= br;
+ }
+}
+
static void
BSDAUDIO_CloseDevice(_THIS)
{
- if (this->hidden != NULL) {
- SDL_FreeAudioMem(this->hidden->mixbuf);
- this->hidden->mixbuf = NULL;
- if (this->hidden->audio_fd >= 0) {
- close(this->hidden->audio_fd);
- this->hidden->audio_fd = -1;
- }
- SDL_free(this->hidden);
- this->hidden = NULL;
+ if (this->hidden->audio_fd >= 0) {
+ close(this->hidden->audio_fd);
}
+ SDL_free(this->hidden->mixbuf);
+ SDL_free(this->hidden);
}
static int
BSDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
- const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT);
+ const int flags = iscapture ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT;
SDL_AudioFormat format = 0;
audio_info_t info;
+ audio_prinfo *prinfo = iscapture ? &info.play : &info.record;
/* We don't care what the devname is...we'll try to open anything. */
/* ...but default to first name in the list... */
@@ -245,7 +297,7 @@ BSDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
if (this->hidden == NULL) {
return SDL_OutOfMemory();
}
- SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+ SDL_zerop(this->hidden);
/* Open the audio device */
this->hidden->audio_fd = open(devname, flags, 0);
@@ -259,9 +311,8 @@ BSDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
SDL_CalculateAudioSpec(&this->spec);
/* Set to play mode */
- info.mode = AUMODE_PLAY;
+ info.mode = iscapture ? AUMODE_RECORD : AUMODE_PLAY;
if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) < 0) {
- BSDAUDIO_CloseDevice(this);
return SDL_SetError("Couldn't put device into play mode");
}
@@ -270,28 +321,28 @@ BSDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
format; format = SDL_NextAudioFormat()) {
switch (format) {
case AUDIO_U8:
- info.play.encoding = AUDIO_ENCODING_ULINEAR;
- info.play.precision = 8;
+ prinfo->encoding = AUDIO_ENCODING_ULINEAR;
+ prinfo->precision = 8;
break;
case AUDIO_S8:
- info.play.encoding = AUDIO_ENCODING_SLINEAR;
- info.play.precision = 8;
+ prinfo->encoding = AUDIO_ENCODING_SLINEAR;
+ prinfo->precision = 8;
break;
case AUDIO_S16LSB:
- info.play.encoding = AUDIO_ENCODING_SLINEAR_LE;
- info.play.precision = 16;
+ prinfo->encoding = AUDIO_ENCODING_SLINEAR_LE;
+ prinfo->precision = 16;
break;
case AUDIO_S16MSB:
- info.play.encoding = AUDIO_ENCODING_SLINEAR_BE;
- info.play.precision = 16;
+ prinfo->encoding = AUDIO_ENCODING_SLINEAR_BE;
+ prinfo->precision = 16;
break;
case AUDIO_U16LSB:
- info.play.encoding = AUDIO_ENCODING_ULINEAR_LE;
- info.play.precision = 16;
+ prinfo->encoding = AUDIO_ENCODING_ULINEAR_LE;
+ prinfo->precision = 16;
break;
case AUDIO_U16MSB:
- info.play.encoding = AUDIO_ENCODING_ULINEAR_BE;
- info.play.precision = 16;
+ prinfo->encoding = AUDIO_ENCODING_ULINEAR_BE;
+ prinfo->precision = 16;
break;
default:
continue;
@@ -303,33 +354,34 @@ BSDAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
}
if (!format) {
- BSDAUDIO_CloseDevice(this);
return SDL_SetError("No supported encoding for 0x%x", this->spec.format);
}
this->spec.format = format;
AUDIO_INITINFO(&info);
- info.play.channels = this->spec.channels;
+ prinfo->channels = this->spec.channels;
if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) == -1) {
this->spec.channels = 1;
}
AUDIO_INITINFO(&info);
- info.play.sample_rate = this->spec.freq;
+ prinfo->sample_rate = this->spec.freq;
info.blocksize = this->spec.size;
info.hiwat = 5;
info.lowat = 3;
(void) ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info);
(void) ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info);
- this->spec.freq = info.play.sample_rate;
- /* Allocate mixing buffer */
- this->hidden->mixlen = this->spec.size;
- this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
- if (this->hidden->mixbuf == NULL) {
- BSDAUDIO_CloseDevice(this);
- return SDL_OutOfMemory();
+ this->spec.freq = prinfo->sample_rate;
+
+ if (!iscapture) {
+ /* Allocate mixing buffer */
+ this->hidden->mixlen = this->spec.size;
+ this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->hidden->mixlen);
+ if (this->hidden->mixbuf == NULL) {
+ return SDL_OutOfMemory();
+ }
+ SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
}
- SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
BSDAUDIO_Status(this);
@@ -347,7 +399,10 @@ BSDAUDIO_Init(SDL_AudioDriverImpl * impl)
impl->WaitDevice = BSDAUDIO_WaitDevice;
impl->GetDeviceBuf = BSDAUDIO_GetDeviceBuf;
impl->CloseDevice = BSDAUDIO_CloseDevice;
+ impl->CaptureFromDevice = BSDAUDIO_CaptureFromDevice;
+ impl->FlushCapture = BSDAUDIO_FlushCapture;
+ impl->HasCaptureSupport = SDL_TRUE;
impl->AllowsArbitraryDeviceNames = 1;
return 1; /* this audio target is available. */
diff --git a/Engine/lib/sdl/src/audio/coreaudio/SDL_coreaudio.h b/Engine/lib/sdl/src/audio/coreaudio/SDL_coreaudio.h
index 577f9fb32..b7e5b8e21 100644
--- a/Engine/lib/sdl/src/audio/coreaudio/SDL_coreaudio.h
+++ b/Engine/lib/sdl/src/audio/coreaudio/SDL_coreaudio.h
@@ -33,9 +33,11 @@
#include
#include
#else
-#include
+#import
+#import
#endif
+#include
#include
/* Hidden "this" pointer for the audio functions */
@@ -43,13 +45,21 @@
struct SDL_PrivateAudioData
{
- AudioUnit audioUnit;
- int audioUnitOpened;
+ SDL_Thread *thread;
+ AudioQueueRef audioQueue;
+ AudioQueueBufferRef audioBuffer[2];
void *buffer;
UInt32 bufferOffset;
UInt32 bufferSize;
+ AudioStreamBasicDescription strdesc;
+ SDL_sem *ready_semaphore;
+ char *thread_error;
+ SDL_atomic_t shutdown;
#if MACOSX_COREAUDIO
AudioDeviceID deviceID;
+#else
+ SDL_bool interrupted;
+ CFTypeRef interruption_listener;
#endif
};
diff --git a/Engine/lib/sdl/src/audio/coreaudio/SDL_coreaudio.c b/Engine/lib/sdl/src/audio/coreaudio/SDL_coreaudio.m
similarity index 52%
rename from Engine/lib/sdl/src/audio/coreaudio/SDL_coreaudio.c
rename to Engine/lib/sdl/src/audio/coreaudio/SDL_coreaudio.m
index 46b617dc0..85129050f 100644
--- a/Engine/lib/sdl/src/audio/coreaudio/SDL_coreaudio.c
+++ b/Engine/lib/sdl/src/audio/coreaudio/SDL_coreaudio.m
@@ -22,19 +22,19 @@
#if SDL_AUDIO_DRIVER_COREAUDIO
+/* !!! FIXME: clean out some of the macro salsa in here. */
+
#include "SDL_audio.h"
#include "../SDL_audio_c.h"
#include "../SDL_sysaudio.h"
#include "SDL_coreaudio.h"
#include "SDL_assert.h"
+#include "../../thread/SDL_systhread.h"
#define DEBUG_COREAUDIO 0
-static void COREAUDIO_CloseDevice(_THIS);
-
#define CHECK_RESULT(msg) \
if (result != noErr) { \
- COREAUDIO_CloseDevice(this); \
SDL_SetError("CoreAudio error (%s): %d", msg, (int) result); \
return 0; \
}
@@ -185,7 +185,7 @@ build_device_list(int iscapture, addDevFn addfn, void *addfndata)
#if DEBUG_COREAUDIO
printf("COREAUDIO: Found %s device #%d: '%s' (devid %d)\n",
((iscapture) ? "capture" : "output"),
- (int) *devCount, ptr, (int) dev);
+ (int) i, ptr, (int) dev);
#endif
addfn(ptr, iscapture, dev, addfndata);
}
@@ -268,42 +268,147 @@ device_list_changed(AudioObjectID systemObj, UInt32 num_addr, const AudioObjectP
}
#endif
-/* The CoreAudio callback */
-static OSStatus
-outputCallback(void *inRefCon,
- AudioUnitRenderActionFlags * ioActionFlags,
- const AudioTimeStamp * inTimeStamp,
- UInt32 inBusNumber, UInt32 inNumberFrames,
- AudioBufferList * ioData)
-{
- SDL_AudioDevice *this = (SDL_AudioDevice *) inRefCon;
- AudioBuffer *abuf;
- UInt32 remaining, len;
- void *ptr;
- UInt32 i;
- /* Only do anything if audio is enabled and not paused */
- if (!this->enabled || this->paused) {
- for (i = 0; i < ioData->mNumberBuffers; i++) {
- abuf = &ioData->mBuffers[i];
- SDL_memset(abuf->mData, this->spec.silence, abuf->mDataByteSize);
+static int open_playback_devices = 0;
+static int open_capture_devices = 0;
+
+#if !MACOSX_COREAUDIO
+
+static void interruption_begin(_THIS)
+{
+ if (this != NULL && this->hidden->audioQueue != NULL) {
+ this->hidden->interrupted = SDL_TRUE;
+ AudioQueuePause(this->hidden->audioQueue);
+ }
+}
+
+static void interruption_end(_THIS)
+{
+ if (this != NULL && this->hidden != NULL && this->hidden->audioQueue != NULL
+ && this->hidden->interrupted) {
+ this->hidden->interrupted = SDL_FALSE;
+ AudioQueueStart(this->hidden->audioQueue, NULL);
+ }
+}
+
+@interface SDLInterruptionListener : NSObject
+
+@property (nonatomic, assign) SDL_AudioDevice *device;
+
+@end
+
+@implementation SDLInterruptionListener
+
+- (void)audioSessionInterruption:(NSNotification *)note
+{
+ @synchronized (self) {
+ NSNumber *type = note.userInfo[AVAudioSessionInterruptionTypeKey];
+ if (type.unsignedIntegerValue == AVAudioSessionInterruptionTypeBegan) {
+ interruption_begin(self.device);
+ } else {
+ interruption_end(self.device);
+ }
+ }
+}
+
+- (void)applicationBecameActive:(NSNotification *)note
+{
+ @synchronized (self) {
+ interruption_end(self.device);
+ }
+}
+
+@end
+
+static BOOL update_audio_session(_THIS, SDL_bool open)
+{
+ @autoreleasepool {
+ AVAudioSession *session = [AVAudioSession sharedInstance];
+ NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
+ NSString *category;
+ NSError *err = nil;
+
+ if (open_playback_devices && open_capture_devices) {
+ category = AVAudioSessionCategoryPlayAndRecord;
+ } else if (open_capture_devices) {
+ category = AVAudioSessionCategoryRecord;
+ } else {
+ /* Set category to ambient so that other music continues playing.
+ You can change this at runtime in your own code if you need different
+ behavior. If this is common, we can add an SDL hint for this. */
+ category = AVAudioSessionCategoryAmbient;
+ }
+
+ if (![session setCategory:category error:&err]) {
+ NSString *desc = err.description;
+ SDL_SetError("Could not set Audio Session category: %s", desc.UTF8String);
+ return NO;
+ }
+
+ if (open_playback_devices + open_capture_devices == 1) {
+ if (![session setActive:YES error:&err]) {
+ NSString *desc = err.description;
+ SDL_SetError("Could not activate Audio Session: %s", desc.UTF8String);
+ return NO;
+ }
+ } else if (!open_playback_devices && !open_capture_devices) {
+ [session setActive:NO error:nil];
+ }
+
+ if (open) {
+ SDLInterruptionListener *listener = [SDLInterruptionListener new];
+ listener.device = this;
+
+ [center addObserver:listener
+ selector:@selector(audioSessionInterruption:)
+ name:AVAudioSessionInterruptionNotification
+ object:session];
+
+ /* An interruption end notification is not guaranteed to be sent if
+ we were previously interrupted... resuming if needed when the app
+ becomes active seems to be the way to go. */
+ [center addObserver:listener
+ selector:@selector(applicationBecameActive:)
+ name:UIApplicationDidBecomeActiveNotification
+ object:session];
+
+ [center addObserver:listener
+ selector:@selector(applicationBecameActive:)
+ name:UIApplicationWillEnterForegroundNotification
+ object:session];
+
+ this->hidden->interruption_listener = CFBridgingRetain(listener);
+ } else {
+ if (this->hidden->interruption_listener != NULL) {
+ SDLInterruptionListener *listener = nil;
+ listener = (SDLInterruptionListener *) CFBridgingRelease(this->hidden->interruption_listener);
+ @synchronized (listener) {
+ listener.device = NULL;
+ }
+ [center removeObserver:listener];
+ }
}
- return 0;
}
- /* No SDL conversion should be needed here, ever, since we accept
- any input format in OpenAudio, and leave the conversion to CoreAudio.
- */
- /*
- SDL_assert(!this->convert.needed);
- SDL_assert(this->spec.channels == ioData->mNumberChannels);
- */
+ return YES;
+}
+#endif
+
+
+/* The AudioQueue callback */
+static void
+outputCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer)
+{
+ SDL_AudioDevice *this = (SDL_AudioDevice *) inUserData;
+ if (!SDL_AtomicGet(&this->enabled) || SDL_AtomicGet(&this->paused)) {
+ /* Supply silence if audio is enabled and not paused */
+ SDL_memset(inBuffer->mAudioData, this->spec.silence, inBuffer->mAudioDataBytesCapacity);
+ } else {
+ UInt32 remaining = inBuffer->mAudioDataBytesCapacity;
+ Uint8 *ptr = (Uint8 *) inBuffer->mAudioData;
- for (i = 0; i < ioData->mNumberBuffers; i++) {
- abuf = &ioData->mBuffers[i];
- remaining = abuf->mDataByteSize;
- ptr = abuf->mData;
while (remaining > 0) {
+ UInt32 len;
if (this->hidden->bufferOffset >= this->hidden->bufferSize) {
/* Generate the data */
SDL_LockMutex(this->mixer_lock);
@@ -314,29 +419,56 @@ outputCallback(void *inRefCon,
}
len = this->hidden->bufferSize - this->hidden->bufferOffset;
- if (len > remaining)
+ if (len > remaining) {
len = remaining;
+ }
SDL_memcpy(ptr, (char *)this->hidden->buffer +
this->hidden->bufferOffset, len);
- ptr = (char *)ptr + len;
+ ptr = ptr + len;
remaining -= len;
this->hidden->bufferOffset += len;
}
}
- return 0;
+ if (!SDL_AtomicGet(&this->hidden->shutdown)) {
+ AudioQueueEnqueueBuffer(this->hidden->audioQueue, inBuffer, 0, NULL);
+ }
+
+ inBuffer->mAudioDataByteSize = inBuffer->mAudioDataBytesCapacity;
}
-static OSStatus
-inputCallback(void *inRefCon,
- AudioUnitRenderActionFlags * ioActionFlags,
- const AudioTimeStamp * inTimeStamp,
- UInt32 inBusNumber, UInt32 inNumberFrames,
- AudioBufferList * ioData)
+static void
+inputCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer,
+ const AudioTimeStamp *inStartTime, UInt32 inNumberPacketDescriptions,
+ const AudioStreamPacketDescription *inPacketDescs )
{
- /* err = AudioUnitRender(afr->fAudioUnit, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, afr->fAudioBuffer); */
- /* !!! FIXME: write me! */
- return noErr;
+ SDL_AudioDevice *this = (SDL_AudioDevice *) inUserData;
+ if (SDL_AtomicGet(&this->enabled) && !SDL_AtomicGet(&this->paused)) { /* ignore unless we're active. */
+ const Uint8 *ptr = (const Uint8 *) inBuffer->mAudioData;
+ UInt32 remaining = inBuffer->mAudioDataByteSize;
+ while (remaining > 0) {
+ UInt32 len = this->hidden->bufferSize - this->hidden->bufferOffset;
+ if (len > remaining) {
+ len = remaining;
+ }
+
+ SDL_memcpy((char *)this->hidden->buffer + this->hidden->bufferOffset, ptr, len);
+ ptr += len;
+ remaining -= len;
+ this->hidden->bufferOffset += len;
+
+ if (this->hidden->bufferOffset >= this->hidden->bufferSize) {
+ SDL_LockMutex(this->mixer_lock);
+ (*this->spec.callback)(this->spec.userdata, this->hidden->buffer, this->hidden->bufferSize);
+ SDL_UnlockMutex(this->mixer_lock);
+ this->hidden->bufferOffset = 0;
+ }
+ }
+ }
+
+ if (!SDL_AtomicGet(&this->hidden->shutdown)) {
+ AudioQueueEnqueueBuffer(this->hidden->audioQueue, inBuffer, 0, NULL);
+ }
}
@@ -357,7 +489,7 @@ device_unplugged(AudioObjectID devid, UInt32 num_addr, const AudioObjectProperty
UInt32 size = sizeof (isAlive);
OSStatus error;
- if (!this->enabled) {
+ if (!SDL_AtomicGet(&this->enabled)) {
return 0; /* already known to be dead. */
}
@@ -381,43 +513,46 @@ device_unplugged(AudioObjectID devid, UInt32 num_addr, const AudioObjectProperty
static void
COREAUDIO_CloseDevice(_THIS)
{
- if (this->hidden != NULL) {
- if (this->hidden->audioUnitOpened) {
- #if MACOSX_COREAUDIO
- /* Unregister our disconnect callback. */
- AudioObjectRemovePropertyListener(this->hidden->deviceID, &alive_address, device_unplugged, this);
- #endif
+ const SDL_bool iscapture = this->iscapture;
+ int i;
- AURenderCallbackStruct callback;
- const AudioUnitElement output_bus = 0;
- const AudioUnitElement input_bus = 1;
- const int iscapture = this->iscapture;
- const AudioUnitElement bus =
- ((iscapture) ? input_bus : output_bus);
- const AudioUnitScope scope =
- ((iscapture) ? kAudioUnitScope_Output :
- kAudioUnitScope_Input);
+/* !!! FIXME: what does iOS do when a bluetooth audio device vanishes? Headphones unplugged? */
+/* !!! FIXME: (we only do a "default" device on iOS right now...can we do more?) */
+#if MACOSX_COREAUDIO
+ /* Fire a callback if the device stops being "alive" (disconnected, etc). */
+ AudioObjectRemovePropertyListener(this->hidden->deviceID, &alive_address, device_unplugged, this);
+#endif
- /* stop processing the audio unit */
- AudioOutputUnitStop(this->hidden->audioUnit);
+#if !MACOSX_COREAUDIO
+ update_audio_session(this, SDL_FALSE);
+#endif
- /* Remove the input callback */
- SDL_memset(&callback, 0, sizeof(AURenderCallbackStruct));
- AudioUnitSetProperty(this->hidden->audioUnit,
- kAudioUnitProperty_SetRenderCallback,
- scope, bus, &callback, sizeof(callback));
+ if (this->hidden->thread) {
+ SDL_AtomicSet(&this->hidden->shutdown, 1);
+ SDL_WaitThread(this->hidden->thread, NULL);
+ }
- #if MACOSX_COREAUDIO
- CloseComponent(this->hidden->audioUnit);
- #else
- AudioComponentInstanceDispose(this->hidden->audioUnit);
- #endif
-
- this->hidden->audioUnitOpened = 0;
+ if (this->hidden->audioQueue) {
+ for (i = 0; i < SDL_arraysize(this->hidden->audioBuffer); i++) {
+ if (this->hidden->audioBuffer[i]) {
+ AudioQueueFreeBuffer(this->hidden->audioQueue, this->hidden->audioBuffer[i]);
+ }
}
- SDL_free(this->hidden->buffer);
- SDL_free(this->hidden);
- this->hidden = NULL;
+ AudioQueueDispose(this->hidden->audioQueue, 1);
+ }
+
+ if (this->hidden->ready_semaphore) {
+ SDL_DestroySemaphore(this->hidden->ready_semaphore);
+ }
+
+ SDL_free(this->hidden->thread_error);
+ SDL_free(this->hidden->buffer);
+ SDL_free(this->hidden);
+
+ if (iscapture) {
+ open_capture_devices--;
+ } else {
+ open_playback_devices--;
}
}
@@ -477,116 +612,105 @@ prepare_device(_THIS, void *handle, int iscapture)
#endif
static int
-prepare_audiounit(_THIS, void *handle, int iscapture,
- const AudioStreamBasicDescription * strdesc)
+prepare_audioqueue(_THIS)
{
- OSStatus result = noErr;
- AURenderCallbackStruct callback;
-#if MACOSX_COREAUDIO
- ComponentDescription desc;
- Component comp = NULL;
-#else
- AudioComponentDescription desc;
- AudioComponent comp = NULL;
-#endif
- const AudioUnitElement output_bus = 0;
- const AudioUnitElement input_bus = 1;
- const AudioUnitElement bus = ((iscapture) ? input_bus : output_bus);
- const AudioUnitScope scope = ((iscapture) ? kAudioUnitScope_Output :
- kAudioUnitScope_Input);
+ const AudioStreamBasicDescription *strdesc = &this->hidden->strdesc;
+ const int iscapture = this->iscapture;
+ OSStatus result;
+ int i;
-#if MACOSX_COREAUDIO
- if (!prepare_device(this, handle, iscapture)) {
- return 0;
- }
-#endif
+ SDL_assert(CFRunLoopGetCurrent() != NULL);
- SDL_zero(desc);
- desc.componentType = kAudioUnitType_Output;
- desc.componentManufacturer = kAudioUnitManufacturer_Apple;
-
-#if MACOSX_COREAUDIO
- desc.componentSubType = kAudioUnitSubType_DefaultOutput;
- comp = FindNextComponent(NULL, &desc);
-#else
- desc.componentSubType = kAudioUnitSubType_RemoteIO;
- comp = AudioComponentFindNext(NULL, &desc);
-#endif
-
- if (comp == NULL) {
- SDL_SetError("Couldn't find requested CoreAudio component");
- return 0;
+ if (iscapture) {
+ result = AudioQueueNewInput(strdesc, inputCallback, this, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, 0, &this->hidden->audioQueue);
+ CHECK_RESULT("AudioQueueNewInput");
+ } else {
+ result = AudioQueueNewOutput(strdesc, outputCallback, this, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode, 0, &this->hidden->audioQueue);
+ CHECK_RESULT("AudioQueueNewOutput");
}
- /* Open & initialize the audio unit */
#if MACOSX_COREAUDIO
- result = OpenAComponent(comp, &this->hidden->audioUnit);
- CHECK_RESULT("OpenAComponent");
-#else
- /*
- AudioComponentInstanceNew only available on iPhone OS 2.0 and Mac OS X 10.6
- We can't use OpenAComponent on iPhone because it is not present
- */
- result = AudioComponentInstanceNew(comp, &this->hidden->audioUnit);
- CHECK_RESULT("AudioComponentInstanceNew");
+{
+ const AudioObjectPropertyAddress prop = {
+ kAudioDevicePropertyDeviceUID,
+ iscapture ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput,
+ kAudioObjectPropertyElementMaster
+ };
+ CFStringRef devuid;
+ UInt32 devuidsize = sizeof (devuid);
+ result = AudioObjectGetPropertyData(this->hidden->deviceID, &prop, 0, NULL, &devuidsize, &devuid);
+ CHECK_RESULT("AudioObjectGetPropertyData (kAudioDevicePropertyDeviceUID)");
+ result = AudioQueueSetProperty(this->hidden->audioQueue, kAudioQueueProperty_CurrentDevice, &devuid, devuidsize);
+ CHECK_RESULT("AudioQueueSetProperty (kAudioQueueProperty_CurrentDevice)");
+
+ /* !!! FIXME: what does iOS do when a bluetooth audio device vanishes? Headphones unplugged? */
+ /* !!! FIXME: (we only do a "default" device on iOS right now...can we do more?) */
+ /* Fire a callback if the device stops being "alive" (disconnected, etc). */
+ AudioObjectAddPropertyListener(this->hidden->deviceID, &alive_address, device_unplugged, this);
+}
#endif
- this->hidden->audioUnitOpened = 1;
-
-#if MACOSX_COREAUDIO
- result = AudioUnitSetProperty(this->hidden->audioUnit,
- kAudioOutputUnitProperty_CurrentDevice,
- kAudioUnitScope_Global, 0,
- &this->hidden->deviceID,
- sizeof(AudioDeviceID));
- CHECK_RESULT
- ("AudioUnitSetProperty (kAudioOutputUnitProperty_CurrentDevice)");
-#endif
-
- /* Set the data format of the audio unit. */
- result = AudioUnitSetProperty(this->hidden->audioUnit,
- kAudioUnitProperty_StreamFormat,
- scope, bus, strdesc, sizeof(*strdesc));
- CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_StreamFormat)");
-
- /* Set the audio callback */
- SDL_memset(&callback, 0, sizeof(AURenderCallbackStruct));
- callback.inputProc = ((iscapture) ? inputCallback : outputCallback);
- callback.inputProcRefCon = this;
- result = AudioUnitSetProperty(this->hidden->audioUnit,
- kAudioUnitProperty_SetRenderCallback,
- scope, bus, &callback, sizeof(callback));
- CHECK_RESULT
- ("AudioUnitSetProperty (kAudioUnitProperty_SetRenderCallback)");
-
/* Calculate the final parameters for this audio specification */
SDL_CalculateAudioSpec(&this->spec);
/* Allocate a sample buffer */
- this->hidden->bufferOffset = this->hidden->bufferSize = this->spec.size;
+ this->hidden->bufferSize = this->spec.size;
+ this->hidden->bufferOffset = iscapture ? 0 : this->hidden->bufferSize;
+
this->hidden->buffer = SDL_malloc(this->hidden->bufferSize);
+ if (this->hidden->buffer == NULL) {
+ SDL_OutOfMemory();
+ return 0;
+ }
- result = AudioUnitInitialize(this->hidden->audioUnit);
- CHECK_RESULT("AudioUnitInitialize");
+ for (i = 0; i < SDL_arraysize(this->hidden->audioBuffer); i++) {
+ result = AudioQueueAllocateBuffer(this->hidden->audioQueue, this->spec.size, &this->hidden->audioBuffer[i]);
+ CHECK_RESULT("AudioQueueAllocateBuffer");
+ SDL_memset(this->hidden->audioBuffer[i]->mAudioData, this->spec.silence, this->hidden->audioBuffer[i]->mAudioDataBytesCapacity);
+ this->hidden->audioBuffer[i]->mAudioDataByteSize = this->hidden->audioBuffer[i]->mAudioDataBytesCapacity;
+ result = AudioQueueEnqueueBuffer(this->hidden->audioQueue, this->hidden->audioBuffer[i], 0, NULL);
+ CHECK_RESULT("AudioQueueEnqueueBuffer");
+ }
- /* Finally, start processing of the audio unit */
- result = AudioOutputUnitStart(this->hidden->audioUnit);
- CHECK_RESULT("AudioOutputUnitStart");
-
-#if MACOSX_COREAUDIO
- /* Fire a callback if the device stops being "alive" (disconnected, etc). */
- AudioObjectAddPropertyListener(this->hidden->deviceID, &alive_address, device_unplugged, this);
-#endif
+ result = AudioQueueStart(this->hidden->audioQueue, NULL);
+ CHECK_RESULT("AudioQueueStart");
/* We're running! */
return 1;
}
+static int
+audioqueue_thread(void *arg)
+{
+ SDL_AudioDevice *this = (SDL_AudioDevice *) arg;
+ const int rc = prepare_audioqueue(this);
+ if (!rc) {
+ this->hidden->thread_error = SDL_strdup(SDL_GetError());
+ SDL_SemPost(this->hidden->ready_semaphore);
+ return 0;
+ }
+
+ /* init was successful, alert parent thread and start running... */
+ SDL_SemPost(this->hidden->ready_semaphore);
+ while (!SDL_AtomicGet(&this->hidden->shutdown)) {
+ CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.10, 1);
+ }
+
+ if (this->iscapture) { /* just stop immediately for capture devices. */
+ AudioQueueStop(this->hidden->audioQueue, 1);
+ } else { /* Drain off any pending playback. */
+ AudioQueueStop(this->hidden->audioQueue, 0);
+ const CFTimeInterval secs = (((this->spec.size / (SDL_AUDIO_BITSIZE(this->spec.format) / 8)) / this->spec.channels) / ((CFTimeInterval) this->spec.freq)) * 2.0;
+ CFRunLoopRunInMode(kCFRunLoopDefaultMode, secs, 0);
+ }
+
+ return 0;
+}
static int
COREAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
- AudioStreamBasicDescription strdesc;
+ AudioStreamBasicDescription *strdesc;
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
int valid_datatype = 0;
@@ -596,15 +720,29 @@ COREAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
if (this->hidden == NULL) {
return SDL_OutOfMemory();
}
- SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+ SDL_zerop(this->hidden);
+
+ strdesc = &this->hidden->strdesc;
+
+ if (iscapture) {
+ open_capture_devices++;
+ } else {
+ open_playback_devices++;
+ }
+
+#if !MACOSX_COREAUDIO
+ if (!update_audio_session(this, SDL_TRUE)) {
+ return -1;
+ }
+#endif
/* Setup a AudioStreamBasicDescription with the requested format */
- SDL_memset(&strdesc, '\0', sizeof(AudioStreamBasicDescription));
- strdesc.mFormatID = kAudioFormatLinearPCM;
- strdesc.mFormatFlags = kLinearPCMFormatFlagIsPacked;
- strdesc.mChannelsPerFrame = this->spec.channels;
- strdesc.mSampleRate = this->spec.freq;
- strdesc.mFramesPerPacket = 1;
+ SDL_zerop(strdesc);
+ strdesc->mFormatID = kAudioFormatLinearPCM;
+ strdesc->mFormatFlags = kLinearPCMFormatFlagIsPacked;
+ strdesc->mChannelsPerFrame = this->spec.channels;
+ strdesc->mSampleRate = this->spec.freq;
+ strdesc->mFramesPerPacket = 1;
while ((!valid_datatype) && (test_format)) {
this->spec.format = test_format;
@@ -621,34 +759,53 @@ COREAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
case AUDIO_F32LSB:
case AUDIO_F32MSB:
valid_datatype = 1;
- strdesc.mBitsPerChannel = SDL_AUDIO_BITSIZE(this->spec.format);
+ strdesc->mBitsPerChannel = SDL_AUDIO_BITSIZE(this->spec.format);
if (SDL_AUDIO_ISBIGENDIAN(this->spec.format))
- strdesc.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian;
+ strdesc->mFormatFlags |= kLinearPCMFormatFlagIsBigEndian;
if (SDL_AUDIO_ISFLOAT(this->spec.format))
- strdesc.mFormatFlags |= kLinearPCMFormatFlagIsFloat;
+ strdesc->mFormatFlags |= kLinearPCMFormatFlagIsFloat;
else if (SDL_AUDIO_ISSIGNED(this->spec.format))
- strdesc.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
+ strdesc->mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
break;
}
}
if (!valid_datatype) { /* shouldn't happen, but just in case... */
- COREAUDIO_CloseDevice(this);
return SDL_SetError("Unsupported audio format");
}
- strdesc.mBytesPerFrame =
- strdesc.mBitsPerChannel * strdesc.mChannelsPerFrame / 8;
- strdesc.mBytesPerPacket =
- strdesc.mBytesPerFrame * strdesc.mFramesPerPacket;
+ strdesc->mBytesPerFrame = strdesc->mBitsPerChannel * strdesc->mChannelsPerFrame / 8;
+ strdesc->mBytesPerPacket = strdesc->mBytesPerFrame * strdesc->mFramesPerPacket;
- if (!prepare_audiounit(this, handle, iscapture, &strdesc)) {
- COREAUDIO_CloseDevice(this);
- return -1; /* prepare_audiounit() will call SDL_SetError()... */
+#if MACOSX_COREAUDIO
+ if (!prepare_device(this, handle, iscapture)) {
+ return -1;
+ }
+#endif
+
+ /* This has to init in a new thread so it can get its own CFRunLoop. :/ */
+ SDL_AtomicSet(&this->hidden->shutdown, 0);
+ this->hidden->ready_semaphore = SDL_CreateSemaphore(0);
+ if (!this->hidden->ready_semaphore) {
+ return -1; /* oh well. */
}
- return 0; /* good to go. */
+ this->hidden->thread = SDL_CreateThreadInternal(audioqueue_thread, "AudioQueue thread", 512 * 1024, this);
+ if (!this->hidden->thread) {
+ return -1;
+ }
+
+ SDL_SemWait(this->hidden->ready_semaphore);
+ SDL_DestroySemaphore(this->hidden->ready_semaphore);
+ this->hidden->ready_semaphore = NULL;
+
+ if ((this->hidden->thread != NULL) && (this->hidden->thread_error != NULL)) {
+ SDL_SetError("%s", this->hidden->thread_error);
+ return -1;
+ }
+
+ return (this->hidden->thread != NULL) ? 0 : -1;
}
static void
@@ -674,17 +831,11 @@ COREAUDIO_Init(SDL_AudioDriverImpl * impl)
AudioObjectAddPropertyListener(kAudioObjectSystemObject, &devlist_address, device_list_changed, NULL);
#else
impl->OnlyHasDefaultOutputDevice = 1;
-
- /* Set category to ambient sound so that other music continues playing.
- You can change this at runtime in your own code if you need different
- behavior. If this is common, we can add an SDL hint for this.
- */
- AudioSessionInitialize(NULL, NULL, NULL, nil);
- UInt32 category = kAudioSessionCategory_AmbientSound;
- AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(UInt32), &category);
+ impl->OnlyHasDefaultCaptureDevice = 1;
#endif
impl->ProvidesOwnCallbackThread = 1;
+ impl->HasCaptureSupport = 1;
return 1; /* this audio target is available. */
}
diff --git a/Engine/lib/sdl/src/audio/directsound/SDL_directsound.c b/Engine/lib/sdl/src/audio/directsound/SDL_directsound.c
index 065e163a6..5d261c92e 100644
--- a/Engine/lib/sdl/src/audio/directsound/SDL_directsound.c
+++ b/Engine/lib/sdl/src/audio/directsound/SDL_directsound.c
@@ -24,6 +24,7 @@
/* Allow access to a raw mixing buffer */
+#include "SDL_assert.h"
#include "SDL_timer.h"
#include "SDL_loadso.h"
#include "SDL_audio.h"
@@ -36,11 +37,13 @@
/* DirectX function pointers for audio */
static void* DSoundDLL = NULL;
-typedef HRESULT(WINAPI*fnDirectSoundCreate8)(LPGUID,LPDIRECTSOUND*,LPUNKNOWN);
-typedef HRESULT(WINAPI*fnDirectSoundEnumerateW)(LPDSENUMCALLBACKW, LPVOID);
-typedef HRESULT(WINAPI*fnDirectSoundCaptureEnumerateW)(LPDSENUMCALLBACKW,LPVOID);
+typedef HRESULT (WINAPI *fnDirectSoundCreate8)(LPGUID,LPDIRECTSOUND*,LPUNKNOWN);
+typedef HRESULT (WINAPI *fnDirectSoundEnumerateW)(LPDSENUMCALLBACKW, LPVOID);
+typedef HRESULT (WINAPI *fnDirectSoundCaptureCreate8)(LPCGUID,LPDIRECTSOUNDCAPTURE8 *,LPUNKNOWN);
+typedef HRESULT (WINAPI *fnDirectSoundCaptureEnumerateW)(LPDSENUMCALLBACKW,LPVOID);
static fnDirectSoundCreate8 pDirectSoundCreate8 = NULL;
static fnDirectSoundEnumerateW pDirectSoundEnumerateW = NULL;
+static fnDirectSoundCaptureCreate8 pDirectSoundCaptureCreate8 = NULL;
static fnDirectSoundCaptureEnumerateW pDirectSoundCaptureEnumerateW = NULL;
static void
@@ -48,6 +51,7 @@ DSOUND_Unload(void)
{
pDirectSoundCreate8 = NULL;
pDirectSoundEnumerateW = NULL;
+ pDirectSoundCaptureCreate8 = NULL;
pDirectSoundCaptureEnumerateW = NULL;
if (DSoundDLL != NULL) {
@@ -76,6 +80,7 @@ DSOUND_Load(void)
loaded = 1; /* will reset if necessary. */
DSOUNDLOAD(DirectSoundCreate8);
DSOUNDLOAD(DirectSoundEnumerateW);
+ DSOUNDLOAD(DirectSoundCaptureCreate8);
DSOUNDLOAD(DirectSoundCaptureEnumerateW);
#undef DSOUNDLOAD
@@ -155,7 +160,7 @@ FindAllDevs(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVOID data)
{
const int iscapture = (int) ((size_t) data);
if (guid != NULL) { /* skip default device */
- char *str = WIN_StringToUTF8(desc);
+ char *str = WIN_LookupAudioDeviceName(desc, guid);
if (str != NULL) {
LPGUID cpyguid = (LPGUID) SDL_malloc(sizeof (GUID));
SDL_memcpy(cpyguid, guid, sizeof (GUID));
@@ -197,7 +202,7 @@ DSOUND_WaitDevice(_THIS)
return;
}
- while ((cursor / this->hidden->mixlen) == this->hidden->lastchunk) {
+ while ((cursor / this->spec.size) == this->hidden->lastchunk) {
/* FIXME: find out how much time is left and sleep that long */
SDL_Delay(1);
@@ -239,9 +244,8 @@ DSOUND_PlayDevice(_THIS)
if (this->hidden->locked_buf) {
IDirectSoundBuffer_Unlock(this->hidden->mixbuf,
this->hidden->locked_buf,
- this->hidden->mixlen, NULL, 0);
+ this->spec.size, NULL, 0);
}
-
}
static Uint8 *
@@ -265,7 +269,7 @@ DSOUND_GetDeviceBuf(_THIS)
SetDSerror("DirectSound GetCurrentPosition", result);
return (NULL);
}
- cursor /= this->hidden->mixlen;
+ cursor /= this->spec.size;
#ifdef DEBUG_SOUND
/* Detect audio dropouts */
{
@@ -281,17 +285,17 @@ DSOUND_GetDeviceBuf(_THIS)
#endif
this->hidden->lastchunk = cursor;
cursor = (cursor + 1) % this->hidden->num_buffers;
- cursor *= this->hidden->mixlen;
+ cursor *= this->spec.size;
/* Lock the audio buffer */
result = IDirectSoundBuffer_Lock(this->hidden->mixbuf, cursor,
- this->hidden->mixlen,
+ this->spec.size,
(LPVOID *) & this->hidden->locked_buf,
&rawlen, NULL, &junk, 0);
if (result == DSERR_BUFFERLOST) {
IDirectSoundBuffer_Restore(this->hidden->mixbuf);
result = IDirectSoundBuffer_Lock(this->hidden->mixbuf, cursor,
- this->hidden->mixlen,
+ this->spec.size,
(LPVOID *) & this->
hidden->locked_buf, &rawlen, NULL,
&junk, 0);
@@ -303,109 +307,106 @@ DSOUND_GetDeviceBuf(_THIS)
return (this->hidden->locked_buf);
}
-static void
-DSOUND_WaitDone(_THIS)
+static int
+DSOUND_CaptureFromDevice(_THIS, void *buffer, int buflen)
{
- Uint8 *stream = DSOUND_GetDeviceBuf(this);
+ struct SDL_PrivateAudioData *h = this->hidden;
+ DWORD junk, cursor, ptr1len, ptr2len;
+ VOID *ptr1, *ptr2;
- /* Wait for the playing chunk to finish */
- if (stream != NULL) {
- SDL_memset(stream, this->spec.silence, this->hidden->mixlen);
- DSOUND_PlayDevice(this);
+ SDL_assert(buflen == this->spec.size);
+
+ while (SDL_TRUE) {
+ if (SDL_AtomicGet(&this->shutdown)) { /* in case the buffer froze... */
+ SDL_memset(buffer, this->spec.silence, buflen);
+ return buflen;
+ }
+
+ if (IDirectSoundCaptureBuffer_GetCurrentPosition(h->capturebuf, &junk, &cursor) != DS_OK) {
+ return -1;
+ }
+ if ((cursor / this->spec.size) == h->lastchunk) {
+ SDL_Delay(1); /* FIXME: find out how much time is left and sleep that long */
+ } else {
+ break;
+ }
}
- DSOUND_WaitDevice(this);
- /* Stop the looping sound buffer */
- IDirectSoundBuffer_Stop(this->hidden->mixbuf);
+ if (IDirectSoundCaptureBuffer_Lock(h->capturebuf, h->lastchunk * this->spec.size, this->spec.size, &ptr1, &ptr1len, &ptr2, &ptr2len, 0) != DS_OK) {
+ return -1;
+ }
+
+ SDL_assert(ptr1len == this->spec.size);
+ SDL_assert(ptr2 == NULL);
+ SDL_assert(ptr2len == 0);
+
+ SDL_memcpy(buffer, ptr1, ptr1len);
+
+ if (IDirectSoundCaptureBuffer_Unlock(h->capturebuf, ptr1, ptr1len, ptr2, ptr2len) != DS_OK) {
+ return -1;
+ }
+
+ h->lastchunk = (h->lastchunk + 1) % h->num_buffers;
+
+ return ptr1len;
+}
+
+static void
+DSOUND_FlushCapture(_THIS)
+{
+ struct SDL_PrivateAudioData *h = this->hidden;
+ DWORD junk, cursor;
+ if (IDirectSoundCaptureBuffer_GetCurrentPosition(h->capturebuf, &junk, &cursor) == DS_OK) {
+ h->lastchunk = cursor / this->spec.size;
+ }
}
static void
DSOUND_CloseDevice(_THIS)
{
- if (this->hidden != NULL) {
- if (this->hidden->sound != NULL) {
- if (this->hidden->mixbuf != NULL) {
- /* Clean up the audio buffer */
- IDirectSoundBuffer_Release(this->hidden->mixbuf);
- this->hidden->mixbuf = NULL;
- }
- IDirectSound_Release(this->hidden->sound);
- this->hidden->sound = NULL;
- }
-
- SDL_free(this->hidden);
- this->hidden = NULL;
+ if (this->hidden->mixbuf != NULL) {
+ IDirectSoundBuffer_Stop(this->hidden->mixbuf);
+ IDirectSoundBuffer_Release(this->hidden->mixbuf);
}
+ if (this->hidden->sound != NULL) {
+ IDirectSound_Release(this->hidden->sound);
+ }
+ if (this->hidden->capturebuf != NULL) {
+ IDirectSoundCaptureBuffer_Stop(this->hidden->capturebuf);
+ IDirectSoundCaptureBuffer_Release(this->hidden->capturebuf);
+ }
+ if (this->hidden->capture != NULL) {
+ IDirectSoundCapture_Release(this->hidden->capture);
+ }
+ SDL_free(this->hidden);
}
/* This function tries to create a secondary audio buffer, and returns the
- number of audio chunks available in the created buffer.
+ number of audio chunks available in the created buffer. This is for
+ playback devices, not capture.
*/
static int
-CreateSecondary(_THIS, HWND focus)
+CreateSecondary(_THIS, const DWORD bufsize, WAVEFORMATEX *wfmt)
{
LPDIRECTSOUND sndObj = this->hidden->sound;
LPDIRECTSOUNDBUFFER *sndbuf = &this->hidden->mixbuf;
- Uint32 chunksize = this->spec.size;
- const int numchunks = 8;
HRESULT result = DS_OK;
DSBUFFERDESC format;
LPVOID pvAudioPtr1, pvAudioPtr2;
DWORD dwAudioBytes1, dwAudioBytes2;
- WAVEFORMATEX wfmt;
-
- SDL_zero(wfmt);
-
- if (SDL_AUDIO_ISFLOAT(this->spec.format)) {
- wfmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
- } else {
- wfmt.wFormatTag = WAVE_FORMAT_PCM;
- }
-
- wfmt.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
- wfmt.nChannels = this->spec.channels;
- wfmt.nSamplesPerSec = this->spec.freq;
- wfmt.nBlockAlign = wfmt.nChannels * (wfmt.wBitsPerSample / 8);
- wfmt.nAvgBytesPerSec = wfmt.nSamplesPerSec * wfmt.nBlockAlign;
-
- /* Update the fragment size as size in bytes */
- SDL_CalculateAudioSpec(&this->spec);
-
- /* Try to set primary mixing privileges */
- if (focus) {
- result = IDirectSound_SetCooperativeLevel(sndObj,
- focus, DSSCL_PRIORITY);
- } else {
- result = IDirectSound_SetCooperativeLevel(sndObj,
- GetDesktopWindow(),
- DSSCL_NORMAL);
- }
- if (result != DS_OK) {
- return SetDSerror("DirectSound SetCooperativeLevel", result);
- }
/* Try to create the secondary buffer */
SDL_zero(format);
format.dwSize = sizeof(format);
format.dwFlags = DSBCAPS_GETCURRENTPOSITION2;
- if (!focus) {
- format.dwFlags |= DSBCAPS_GLOBALFOCUS;
- } else {
- format.dwFlags |= DSBCAPS_STICKYFOCUS;
- }
- format.dwBufferBytes = numchunks * chunksize;
- if ((format.dwBufferBytes < DSBSIZE_MIN) ||
- (format.dwBufferBytes > DSBSIZE_MAX)) {
- return SDL_SetError("Sound buffer size must be between %d and %d",
- DSBSIZE_MIN / numchunks, DSBSIZE_MAX / numchunks);
- }
- format.dwReserved = 0;
- format.lpwfxFormat = &wfmt;
+ format.dwFlags |= DSBCAPS_GLOBALFOCUS;
+ format.dwBufferBytes = bufsize;
+ format.lpwfxFormat = wfmt;
result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL);
if (result != DS_OK) {
return SetDSerror("DirectSound CreateSoundBuffer", result);
}
- IDirectSoundBuffer_SetFormat(*sndbuf, &wfmt);
+ IDirectSoundBuffer_SetFormat(*sndbuf, wfmt);
/* Silence the initial audio buffer */
result = IDirectSoundBuffer_Lock(*sndbuf, 0, format.dwBufferBytes,
@@ -420,31 +421,90 @@ CreateSecondary(_THIS, HWND focus)
}
/* We're ready to go */
- return (numchunks);
+ return 0;
+}
+
+/* This function tries to create a capture buffer, and returns the
+ number of audio chunks available in the created buffer. This is for
+ capture devices, not playback.
+*/
+static int
+CreateCaptureBuffer(_THIS, const DWORD bufsize, WAVEFORMATEX *wfmt)
+{
+ LPDIRECTSOUNDCAPTURE capture = this->hidden->capture;
+ LPDIRECTSOUNDCAPTUREBUFFER *capturebuf = &this->hidden->capturebuf;
+ DSCBUFFERDESC format;
+// DWORD junk, cursor;
+ HRESULT result;
+
+ SDL_zero(format);
+ format.dwSize = sizeof (format);
+ format.dwFlags = DSCBCAPS_WAVEMAPPED;
+ format.dwBufferBytes = bufsize;
+ format.lpwfxFormat = wfmt;
+
+ result = IDirectSoundCapture_CreateCaptureBuffer(capture, &format, capturebuf, NULL);
+ if (result != DS_OK) {
+ return SetDSerror("DirectSound CreateCaptureBuffer", result);
+ }
+
+ result = IDirectSoundCaptureBuffer_Start(*capturebuf, DSCBSTART_LOOPING);
+ if (result != DS_OK) {
+ IDirectSoundCaptureBuffer_Release(*capturebuf);
+ return SetDSerror("DirectSound Start", result);
+ }
+
+#if 0
+ /* presumably this starts at zero, but just in case... */
+ result = IDirectSoundCaptureBuffer_GetCurrentPosition(*capturebuf, &junk, &cursor);
+ if (result != DS_OK) {
+ IDirectSoundCaptureBuffer_Stop(*capturebuf);
+ IDirectSoundCaptureBuffer_Release(*capturebuf);
+ return SetDSerror("DirectSound GetCurrentPosition", result);
+ }
+
+ this->hidden->lastchunk = cursor / this->spec.size;
+#endif
+
+ return 0;
}
static int
DSOUND_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
+ const DWORD numchunks = 8;
HRESULT result;
SDL_bool valid_format = SDL_FALSE;
SDL_bool tried_format = SDL_FALSE;
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
LPGUID guid = (LPGUID) handle;
-
+ DWORD bufsize;
+
/* Initialize all variables that we clean on shutdown */
this->hidden = (struct SDL_PrivateAudioData *)
SDL_malloc((sizeof *this->hidden));
if (this->hidden == NULL) {
return SDL_OutOfMemory();
}
- SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+ SDL_zerop(this->hidden);
/* Open the audio device */
- result = pDirectSoundCreate8(guid, &this->hidden->sound, NULL);
- if (result != DS_OK) {
- DSOUND_CloseDevice(this);
- return SetDSerror("DirectSoundCreate", result);
+ if (iscapture) {
+ result = pDirectSoundCaptureCreate8(guid, &this->hidden->capture, NULL);
+ if (result != DS_OK) {
+ return SetDSerror("DirectSoundCaptureCreate8", result);
+ }
+ } else {
+ result = pDirectSoundCreate8(guid, &this->hidden->sound, NULL);
+ if (result != DS_OK) {
+ return SetDSerror("DirectSoundCreate8", result);
+ }
+ result = IDirectSound_SetCooperativeLevel(this->hidden->sound,
+ GetDesktopWindow(),
+ DSSCL_NORMAL);
+ if (result != DS_OK) {
+ return SetDSerror("DirectSound SetCooperativeLevel", result);
+ }
}
while ((!valid_format) && (test_format)) {
@@ -454,10 +514,38 @@ DSOUND_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
case AUDIO_S32:
case AUDIO_F32:
tried_format = SDL_TRUE;
+
this->spec.format = test_format;
- this->hidden->num_buffers = CreateSecondary(this, NULL);
- if (this->hidden->num_buffers > 0) {
- valid_format = SDL_TRUE;
+
+ /* Update the fragment size as size in bytes */
+ SDL_CalculateAudioSpec(&this->spec);
+
+ bufsize = numchunks * this->spec.size;
+ if ((bufsize < DSBSIZE_MIN) || (bufsize > DSBSIZE_MAX)) {
+ SDL_SetError("Sound buffer size must be between %d and %d",
+ (DSBSIZE_MIN < numchunks) ? 1 : DSBSIZE_MIN / numchunks,
+ DSBSIZE_MAX / numchunks);
+ } else {
+ int rc;
+ WAVEFORMATEX wfmt;
+ SDL_zero(wfmt);
+ if (SDL_AUDIO_ISFLOAT(this->spec.format)) {
+ wfmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
+ } else {
+ wfmt.wFormatTag = WAVE_FORMAT_PCM;
+ }
+
+ wfmt.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
+ wfmt.nChannels = this->spec.channels;
+ wfmt.nSamplesPerSec = this->spec.freq;
+ wfmt.nBlockAlign = wfmt.nChannels * (wfmt.wBitsPerSample / 8);
+ wfmt.nAvgBytesPerSec = wfmt.nSamplesPerSec * wfmt.nBlockAlign;
+
+ rc = iscapture ? CreateCaptureBuffer(this, bufsize, &wfmt) : CreateSecondary(this, bufsize, &wfmt);
+ if (rc == 0) {
+ this->hidden->num_buffers = numchunks;
+ valid_format = SDL_TRUE;
+ }
}
break;
}
@@ -465,15 +553,13 @@ DSOUND_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
}
if (!valid_format) {
- DSOUND_CloseDevice(this);
if (tried_format) {
return -1; /* CreateSecondary() should have called SDL_SetError(). */
}
return SDL_SetError("DirectSound: Unsupported audio format");
}
- /* The buffer will auto-start playing in DSOUND_WaitDevice() */
- this->hidden->mixlen = this->spec.size;
+ /* Playback buffers will auto-start playing in DSOUND_WaitDevice() */
return 0; /* good to go. */
}
@@ -498,13 +584,15 @@ DSOUND_Init(SDL_AudioDriverImpl * impl)
impl->OpenDevice = DSOUND_OpenDevice;
impl->PlayDevice = DSOUND_PlayDevice;
impl->WaitDevice = DSOUND_WaitDevice;
- impl->WaitDone = DSOUND_WaitDone;
impl->GetDeviceBuf = DSOUND_GetDeviceBuf;
+ impl->CaptureFromDevice = DSOUND_CaptureFromDevice;
+ impl->FlushCapture = DSOUND_FlushCapture;
impl->CloseDevice = DSOUND_CloseDevice;
impl->FreeDeviceHandle = DSOUND_FreeDeviceHandle;
-
impl->Deinitialize = DSOUND_Deinitialize;
+ impl->HasCaptureSupport = SDL_TRUE;
+
return 1; /* this audio target is available. */
}
diff --git a/Engine/lib/sdl/src/audio/directsound/SDL_directsound.h b/Engine/lib/sdl/src/audio/directsound/SDL_directsound.h
index 0d5f6bd76..d646c303f 100644
--- a/Engine/lib/sdl/src/audio/directsound/SDL_directsound.h
+++ b/Engine/lib/sdl/src/audio/directsound/SDL_directsound.h
@@ -35,8 +35,9 @@ struct SDL_PrivateAudioData
{
LPDIRECTSOUND sound;
LPDIRECTSOUNDBUFFER mixbuf;
+ LPDIRECTSOUNDCAPTURE capture;
+ LPDIRECTSOUNDCAPTUREBUFFER capturebuf;
int num_buffers;
- int mixlen;
DWORD lastchunk;
Uint8 *locked_buf;
};
diff --git a/Engine/lib/sdl/src/audio/disk/SDL_diskaudio.c b/Engine/lib/sdl/src/audio/disk/SDL_diskaudio.c
index 28745f9d0..ee5368844 100644
--- a/Engine/lib/sdl/src/audio/disk/SDL_diskaudio.c
+++ b/Engine/lib/sdl/src/audio/disk/SDL_diskaudio.c
@@ -31,46 +31,33 @@
#include "SDL_rwops.h"
#include "SDL_timer.h"
#include "SDL_audio.h"
-#include "../SDL_audiomem.h"
#include "../SDL_audio_c.h"
#include "SDL_diskaudio.h"
+/* !!! FIXME: these should be SDL hints, not environment variables. */
/* environment variables and defaults. */
#define DISKENVR_OUTFILE "SDL_DISKAUDIOFILE"
#define DISKDEFAULT_OUTFILE "sdlaudio.raw"
-#define DISKENVR_WRITEDELAY "SDL_DISKAUDIODELAY"
-#define DISKDEFAULT_WRITEDELAY 150
-
-static const char *
-DISKAUD_GetOutputFilename(const char *devname)
-{
- if (devname == NULL) {
- devname = SDL_getenv(DISKENVR_OUTFILE);
- if (devname == NULL) {
- devname = DISKDEFAULT_OUTFILE;
- }
- }
- return devname;
-}
+#define DISKENVR_INFILE "SDL_DISKAUDIOFILEIN"
+#define DISKDEFAULT_INFILE "sdlaudio-in.raw"
+#define DISKENVR_IODELAY "SDL_DISKAUDIODELAY"
/* This function waits until it is possible to write a full sound buffer */
static void
-DISKAUD_WaitDevice(_THIS)
+DISKAUDIO_WaitDevice(_THIS)
{
- SDL_Delay(this->hidden->write_delay);
+ SDL_Delay(this->hidden->io_delay);
}
static void
-DISKAUD_PlayDevice(_THIS)
+DISKAUDIO_PlayDevice(_THIS)
{
- size_t written;
-
- /* Write the audio data */
- written = SDL_RWwrite(this->hidden->output,
- this->hidden->mixbuf, 1, this->hidden->mixlen);
+ const size_t written = SDL_RWwrite(this->hidden->io,
+ this->hidden->mixbuf,
+ 1, this->spec.size);
/* If we couldn't write, assume fatal error for now */
- if (written != this->hidden->mixlen) {
+ if (written != this->spec.size) {
SDL_OpenedAudioDeviceDisconnected(this);
}
#ifdef DEBUG_AUDIO
@@ -79,63 +66,105 @@ DISKAUD_PlayDevice(_THIS)
}
static Uint8 *
-DISKAUD_GetDeviceBuf(_THIS)
+DISKAUDIO_GetDeviceBuf(_THIS)
{
return (this->hidden->mixbuf);
}
-static void
-DISKAUD_CloseDevice(_THIS)
+static int
+DISKAUDIO_CaptureFromDevice(_THIS, void *buffer, int buflen)
{
- if (this->hidden != NULL) {
- SDL_FreeAudioMem(this->hidden->mixbuf);
- this->hidden->mixbuf = NULL;
- if (this->hidden->output != NULL) {
- SDL_RWclose(this->hidden->output);
- this->hidden->output = NULL;
+ struct SDL_PrivateAudioData *h = this->hidden;
+ const int origbuflen = buflen;
+
+ SDL_Delay(h->io_delay);
+
+ if (h->io) {
+ const size_t br = SDL_RWread(h->io, buffer, 1, buflen);
+ buflen -= (int) br;
+ buffer = ((Uint8 *) buffer) + br;
+ if (buflen > 0) { /* EOF (or error, but whatever). */
+ SDL_RWclose(h->io);
+ h->io = NULL;
}
- SDL_free(this->hidden);
- this->hidden = NULL;
}
+
+ /* if we ran out of file, just write silence. */
+ SDL_memset(buffer, this->spec.silence, buflen);
+
+ return origbuflen;
+}
+
+static void
+DISKAUDIO_FlushCapture(_THIS)
+{
+ /* no op...we don't advance the file pointer or anything. */
+}
+
+
+static void
+DISKAUDIO_CloseDevice(_THIS)
+{
+ if (this->hidden->io != NULL) {
+ SDL_RWclose(this->hidden->io);
+ }
+ SDL_free(this->hidden->mixbuf);
+ SDL_free(this->hidden);
+}
+
+
+static const char *
+get_filename(const int iscapture, const char *devname)
+{
+ if (devname == NULL) {
+ devname = SDL_getenv(iscapture ? DISKENVR_INFILE : DISKENVR_OUTFILE);
+ if (devname == NULL) {
+ devname = iscapture ? DISKDEFAULT_INFILE : DISKDEFAULT_OUTFILE;
+ }
+ }
+ return devname;
}
static int
-DISKAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
+DISKAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
/* handle != NULL means "user specified the placeholder name on the fake detected device list" */
- const char *fname = DISKAUD_GetOutputFilename(handle ? NULL : devname);
- const char *envr = SDL_getenv(DISKENVR_WRITEDELAY);
+ const char *fname = get_filename(iscapture, handle ? NULL : devname);
+ const char *envr = SDL_getenv(DISKENVR_IODELAY);
this->hidden = (struct SDL_PrivateAudioData *)
SDL_malloc(sizeof(*this->hidden));
if (this->hidden == NULL) {
return SDL_OutOfMemory();
}
- SDL_memset(this->hidden, 0, sizeof(*this->hidden));
+ SDL_zerop(this->hidden);
- this->hidden->mixlen = this->spec.size;
- this->hidden->write_delay =
- (envr) ? SDL_atoi(envr) : DISKDEFAULT_WRITEDELAY;
+ if (envr != NULL) {
+ this->hidden->io_delay = SDL_atoi(envr);
+ } else {
+ this->hidden->io_delay = ((this->spec.samples * 1000) / this->spec.freq);
+ }
/* Open the audio device */
- this->hidden->output = SDL_RWFromFile(fname, "wb");
- if (this->hidden->output == NULL) {
- DISKAUD_CloseDevice(this);
+ this->hidden->io = SDL_RWFromFile(fname, iscapture ? "rb" : "wb");
+ if (this->hidden->io == NULL) {
return -1;
}
/* Allocate mixing buffer */
- this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
- if (this->hidden->mixbuf == NULL) {
- DISKAUD_CloseDevice(this);
- return -1;
+ if (!iscapture) {
+ this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->spec.size);
+ if (this->hidden->mixbuf == NULL) {
+ return SDL_OutOfMemory();
+ }
+ SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
}
- SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
#if HAVE_STDIO_H
fprintf(stderr,
- "WARNING: You are using the SDL disk writer audio driver!\n"
- " Writing to file [%s].\n", fname);
+ "WARNING: You are using the SDL disk i/o audio driver!\n"
+ " %s file [%s].\n", iscapture ? "Reading from" : "Writing to",
+ fname);
#endif
/* We're ready to rock and roll. :-) */
@@ -143,30 +172,34 @@ DISKAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
}
static void
-DISKAUD_DetectDevices(void)
+DISKAUDIO_DetectDevices(void)
{
- /* !!! FIXME: stole this literal string from DEFAULT_OUTPUT_DEVNAME in SDL_audio.c */
- SDL_AddAudioDevice(SDL_FALSE, "System audio output device", (void *) 0x1);
+ SDL_AddAudioDevice(SDL_FALSE, DEFAULT_OUTPUT_DEVNAME, (void *) 0x1);
+ SDL_AddAudioDevice(SDL_TRUE, DEFAULT_INPUT_DEVNAME, (void *) 0x2);
}
static int
-DISKAUD_Init(SDL_AudioDriverImpl * impl)
+DISKAUDIO_Init(SDL_AudioDriverImpl * impl)
{
/* Set the function pointers */
- impl->OpenDevice = DISKAUD_OpenDevice;
- impl->WaitDevice = DISKAUD_WaitDevice;
- impl->PlayDevice = DISKAUD_PlayDevice;
- impl->GetDeviceBuf = DISKAUD_GetDeviceBuf;
- impl->CloseDevice = DISKAUD_CloseDevice;
- impl->DetectDevices = DISKAUD_DetectDevices;
+ impl->OpenDevice = DISKAUDIO_OpenDevice;
+ impl->WaitDevice = DISKAUDIO_WaitDevice;
+ impl->PlayDevice = DISKAUDIO_PlayDevice;
+ impl->GetDeviceBuf = DISKAUDIO_GetDeviceBuf;
+ impl->CaptureFromDevice = DISKAUDIO_CaptureFromDevice;
+ impl->FlushCapture = DISKAUDIO_FlushCapture;
+
+ impl->CloseDevice = DISKAUDIO_CloseDevice;
+ impl->DetectDevices = DISKAUDIO_DetectDevices;
impl->AllowsArbitraryDeviceNames = 1;
+ impl->HasCaptureSupport = SDL_TRUE;
return 1; /* this audio target is available. */
}
-AudioBootStrap DISKAUD_bootstrap = {
- "disk", "direct-to-disk audio", DISKAUD_Init, 1
+AudioBootStrap DISKAUDIO_bootstrap = {
+ "disk", "direct-to-disk audio", DISKAUDIO_Init, 1
};
#endif /* SDL_AUDIO_DRIVER_DISK */
diff --git a/Engine/lib/sdl/src/audio/disk/SDL_diskaudio.h b/Engine/lib/sdl/src/audio/disk/SDL_diskaudio.h
index b5666f7fc..ad152a9ce 100644
--- a/Engine/lib/sdl/src/audio/disk/SDL_diskaudio.h
+++ b/Engine/lib/sdl/src/audio/disk/SDL_diskaudio.h
@@ -32,10 +32,9 @@
struct SDL_PrivateAudioData
{
/* The file descriptor for the audio device */
- SDL_RWops *output;
+ SDL_RWops *io;
+ Uint32 io_delay;
Uint8 *mixbuf;
- Uint32 mixlen;
- Uint32 write_delay;
};
#endif /* _SDL_diskaudio_h */
diff --git a/Engine/lib/sdl/src/audio/dsp/SDL_dspaudio.c b/Engine/lib/sdl/src/audio/dsp/SDL_dspaudio.c
index 17e029e1d..a5a31b3aa 100644
--- a/Engine/lib/sdl/src/audio/dsp/SDL_dspaudio.c
+++ b/Engine/lib/sdl/src/audio/dsp/SDL_dspaudio.c
@@ -44,7 +44,6 @@
#include "SDL_timer.h"
#include "SDL_audio.h"
-#include "../SDL_audiomem.h"
#include "../SDL_audio_c.h"
#include "../SDL_audiodev_c.h"
#include "SDL_dspaudio.h"
@@ -60,16 +59,11 @@ DSP_DetectDevices(void)
static void
DSP_CloseDevice(_THIS)
{
- if (this->hidden != NULL) {
- SDL_FreeAudioMem(this->hidden->mixbuf);
- this->hidden->mixbuf = NULL;
- if (this->hidden->audio_fd >= 0) {
- close(this->hidden->audio_fd);
- this->hidden->audio_fd = -1;
- }
- SDL_free(this->hidden);
- this->hidden = NULL;
+ if (this->hidden->audio_fd >= 0) {
+ close(this->hidden->audio_fd);
}
+ SDL_free(this->hidden->mixbuf);
+ SDL_free(this->hidden);
}
@@ -106,23 +100,20 @@ DSP_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
if (this->hidden == NULL) {
return SDL_OutOfMemory();
}
- SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+ SDL_zerop(this->hidden);
/* Open the audio device */
this->hidden->audio_fd = open(devname, flags, 0);
if (this->hidden->audio_fd < 0) {
- DSP_CloseDevice(this);
return SDL_SetError("Couldn't open %s: %s", devname, strerror(errno));
}
- this->hidden->mixbuf = NULL;
- /* Make the file descriptor use blocking writes with fcntl() */
+ /* Make the file descriptor use blocking i/o with fcntl() */
{
long ctlflags;
ctlflags = fcntl(this->hidden->audio_fd, F_GETFL);
ctlflags &= ~O_NONBLOCK;
if (fcntl(this->hidden->audio_fd, F_SETFL, ctlflags) < 0) {
- DSP_CloseDevice(this);
return SDL_SetError("Couldn't set audio blocking mode");
}
}
@@ -130,7 +121,6 @@ DSP_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
/* Get a list of supported hardware formats */
if (ioctl(this->hidden->audio_fd, SNDCTL_DSP_GETFMTS, &value) < 0) {
perror("SNDCTL_DSP_GETFMTS");
- DSP_CloseDevice(this);
return SDL_SetError("Couldn't get audio format list");
}
@@ -187,7 +177,6 @@ DSP_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
}
}
if (format == 0) {
- DSP_CloseDevice(this);
return SDL_SetError("Couldn't find any hardware audio formats");
}
this->spec.format = test_format;
@@ -197,7 +186,6 @@ DSP_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
if ((ioctl(this->hidden->audio_fd, SNDCTL_DSP_SETFMT, &value) < 0) ||
(value != format)) {
perror("SNDCTL_DSP_SETFMT");
- DSP_CloseDevice(this);
return SDL_SetError("Couldn't set audio format");
}
@@ -205,7 +193,6 @@ DSP_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
value = this->spec.channels;
if (ioctl(this->hidden->audio_fd, SNDCTL_DSP_CHANNELS, &value) < 0) {
perror("SNDCTL_DSP_CHANNELS");
- DSP_CloseDevice(this);
return SDL_SetError("Cannot set the number of channels");
}
this->spec.channels = value;
@@ -214,7 +201,6 @@ DSP_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
value = this->spec.freq;
if (ioctl(this->hidden->audio_fd, SNDCTL_DSP_SPEED, &value) < 0) {
perror("SNDCTL_DSP_SPEED");
- DSP_CloseDevice(this);
return SDL_SetError("Couldn't set audio frequency");
}
this->spec.freq = value;
@@ -225,7 +211,6 @@ DSP_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
/* Determine the power of two of the fragment size */
for (frag_spec = 0; (0x01U << frag_spec) < this->spec.size; ++frag_spec);
if ((0x01U << frag_spec) != this->spec.size) {
- DSP_CloseDevice(this);
return SDL_SetError("Fragment size must be a power of two");
}
frag_spec |= 0x00020000; /* two fragments, for low latency */
@@ -250,13 +235,14 @@ DSP_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
#endif
/* Allocate mixing buffer */
- this->hidden->mixlen = this->spec.size;
- this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
- if (this->hidden->mixbuf == NULL) {
- DSP_CloseDevice(this);
- return SDL_OutOfMemory();
+ if (!iscapture) {
+ this->hidden->mixlen = this->spec.size;
+ this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->hidden->mixlen);
+ if (this->hidden->mixbuf == NULL) {
+ return SDL_OutOfMemory();
+ }
+ SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
}
- SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
/* We're ready to rock and roll. :-) */
return 0;
@@ -266,14 +252,13 @@ DSP_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
static void
DSP_PlayDevice(_THIS)
{
- const Uint8 *mixbuf = this->hidden->mixbuf;
- const int mixlen = this->hidden->mixlen;
- if (write(this->hidden->audio_fd, mixbuf, mixlen) == -1) {
+ struct SDL_PrivateAudioData *h = this->hidden;
+ if (write(h->audio_fd, h->mixbuf, h->mixlen) == -1) {
perror("Audio write");
SDL_OpenedAudioDeviceDisconnected(this);
}
#ifdef DEBUG_AUDIO
- fprintf(stderr, "Wrote %d bytes of audio data\n", mixlen);
+ fprintf(stderr, "Wrote %d bytes of audio data\n", h->mixlen);
#endif
}
@@ -283,6 +268,30 @@ DSP_GetDeviceBuf(_THIS)
return (this->hidden->mixbuf);
}
+static int
+DSP_CaptureFromDevice(_THIS, void *buffer, int buflen)
+{
+ return (int) read(this->hidden->audio_fd, buffer, buflen);
+}
+
+static void
+DSP_FlushCapture(_THIS)
+{
+ struct SDL_PrivateAudioData *h = this->hidden;
+ audio_buf_info info;
+ if (ioctl(h->audio_fd, SNDCTL_DSP_GETISPACE, &info) == 0) {
+ while (info.bytes > 0) {
+ char buf[512];
+ const size_t len = SDL_min(sizeof (buf), info.bytes);
+ const ssize_t br = read(h->audio_fd, buf, len);
+ if (br <= 0) {
+ break;
+ }
+ info.bytes -= br;
+ }
+ }
+}
+
static int
DSP_Init(SDL_AudioDriverImpl * impl)
{
@@ -292,8 +301,11 @@ DSP_Init(SDL_AudioDriverImpl * impl)
impl->PlayDevice = DSP_PlayDevice;
impl->GetDeviceBuf = DSP_GetDeviceBuf;
impl->CloseDevice = DSP_CloseDevice;
+ impl->CaptureFromDevice = DSP_CaptureFromDevice;
+ impl->FlushCapture = DSP_FlushCapture;
impl->AllowsArbitraryDeviceNames = 1;
+ impl->HasCaptureSupport = SDL_TRUE;
return 1; /* this audio target is available. */
}
diff --git a/Engine/lib/sdl/src/audio/dummy/SDL_dummyaudio.c b/Engine/lib/sdl/src/audio/dummy/SDL_dummyaudio.c
index 107f0b073..b39f8e327 100644
--- a/Engine/lib/sdl/src/audio/dummy/SDL_dummyaudio.c
+++ b/Engine/lib/sdl/src/audio/dummy/SDL_dummyaudio.c
@@ -22,27 +22,44 @@
/* Output audio to nowhere... */
+#include "SDL_timer.h"
#include "SDL_audio.h"
#include "../SDL_audio_c.h"
#include "SDL_dummyaudio.h"
static int
-DUMMYAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
+DUMMYAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
return 0; /* always succeeds. */
}
static int
-DUMMYAUD_Init(SDL_AudioDriverImpl * impl)
+DUMMYAUDIO_CaptureFromDevice(_THIS, void *buffer, int buflen)
+{
+ /* Delay to make this sort of simulate real audio input. */
+ SDL_Delay((this->spec.samples * 1000) / this->spec.freq);
+
+ /* always return a full buffer of silence. */
+ SDL_memset(buffer, this->spec.silence, buflen);
+ return buflen;
+}
+
+static int
+DUMMYAUDIO_Init(SDL_AudioDriverImpl * impl)
{
/* Set the function pointers */
- impl->OpenDevice = DUMMYAUD_OpenDevice;
+ impl->OpenDevice = DUMMYAUDIO_OpenDevice;
+ impl->CaptureFromDevice = DUMMYAUDIO_CaptureFromDevice;
+
impl->OnlyHasDefaultOutputDevice = 1;
+ impl->OnlyHasDefaultCaptureDevice = 1;
+ impl->HasCaptureSupport = SDL_TRUE;
+
return 1; /* this audio target is available. */
}
-AudioBootStrap DUMMYAUD_bootstrap = {
- "dummy", "SDL dummy audio driver", DUMMYAUD_Init, 1
+AudioBootStrap DUMMYAUDIO_bootstrap = {
+ "dummy", "SDL dummy audio driver", DUMMYAUDIO_Init, 1
};
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/audio/emscripten/SDL_emscriptenaudio.c b/Engine/lib/sdl/src/audio/emscripten/SDL_emscriptenaudio.c
index 8378233ca..839d445ee 100644
--- a/Engine/lib/sdl/src/audio/emscripten/SDL_emscriptenaudio.c
+++ b/Engine/lib/sdl/src/audio/emscripten/SDL_emscriptenaudio.c
@@ -61,16 +61,15 @@ HandleAudioProcess(_THIS)
Uint8 *buf = NULL;
int byte_len = 0;
int bytes = SDL_AUDIO_BITSIZE(this->spec.format) / 8;
- int bytes_in = SDL_AUDIO_BITSIZE(this->convert.src_format) / 8;
- /* Only do soemthing if audio is enabled */
- if (!this->enabled)
- return;
-
- if (this->paused)
+ /* Only do something if audio is enabled */
+ if (!SDL_AtomicGet(&this->enabled) || SDL_AtomicGet(&this->paused)) {
return;
+ }
if (this->convert.needed) {
+ const int bytes_in = SDL_AUDIO_BITSIZE(this->convert.src_format) / 8;
+
if (this->hidden->conv_in_len != 0) {
this->convert.len = this->hidden->conv_in_len * bytes_in * this->spec.channels;
}
@@ -128,7 +127,7 @@ HandleAudioProcess(_THIS)
}
for (var j = 0; j < $1; ++j) {
- channelData[j] = getValue($0 + (j*numChannels + c)*4, 'float');
+ channelData[j] = HEAPF32[$0 + ((j*numChannels + c) << 2) >> 2];
}
}
}, buf, byte_len / bytes / this->spec.channels);
@@ -136,29 +135,147 @@ HandleAudioProcess(_THIS)
}
static void
-Emscripten_CloseDevice(_THIS)
+HandleCaptureProcess(_THIS)
{
- if (this->hidden != NULL) {
- if (this->hidden->mixbuf != NULL) {
- /* Clean up the audio buffer */
- SDL_free(this->hidden->mixbuf);
- this->hidden->mixbuf = NULL;
- }
+ Uint8 *buf;
+ int buflen;
- SDL_free(this->hidden);
- this->hidden = NULL;
+ /* Only do something if audio is enabled */
+ if (!SDL_AtomicGet(&this->enabled) || SDL_AtomicGet(&this->paused)) {
+ return;
}
+
+ if (this->convert.needed) {
+ buf = this->convert.buf;
+ buflen = this->convert.len_cvt;
+ } else {
+ if (!this->hidden->mixbuf) {
+ this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->spec.size);
+ if (!this->hidden->mixbuf) {
+ return; /* oh well. */
+ }
+ }
+ buf = this->hidden->mixbuf;
+ buflen = this->spec.size;
+ }
+
+ EM_ASM_ARGS({
+ var numChannels = SDL2.capture.currentCaptureBuffer.numberOfChannels;
+ if (numChannels == 1) { /* fastpath this a little for the common (mono) case. */
+ var channelData = SDL2.capture.currentCaptureBuffer.getChannelData(0);
+ if (channelData.length != $1) {
+ throw 'Web Audio capture buffer length mismatch! Destination size: ' + channelData.length + ' samples vs expected ' + $1 + ' samples!';
+ }
+ for (var j = 0; j < $1; ++j) {
+ setValue($0 + (j * 4), channelData[j], 'float');
+ }
+ } else {
+ for (var c = 0; c < numChannels; ++c) {
+ var channelData = SDL2.capture.currentCaptureBuffer.getChannelData(c);
+ if (channelData.length != $1) {
+ throw 'Web Audio capture buffer length mismatch! Destination size: ' + channelData.length + ' samples vs expected ' + $1 + ' samples!';
+ }
+
+ for (var j = 0; j < $1; ++j) {
+ setValue($0 + (((j * numChannels) + c) * 4), channelData[j], 'float');
+ }
+ }
+ }
+ }, buf, (this->spec.size / sizeof (float)) / this->spec.channels);
+
+ /* okay, we've got an interleaved float32 array in C now. */
+
+ if (this->convert.needed) {
+ SDL_ConvertAudio(&this->convert);
+ }
+
+ /* Send it to the app. */
+ (*this->spec.callback) (this->spec.userdata, buf, buflen);
+}
+
+
+
+static void
+EMSCRIPTENAUDIO_CloseDevice(_THIS)
+{
+ EM_ASM_({
+ if ($0) {
+ if (SDL2.capture.silenceTimer !== undefined) {
+ clearTimeout(SDL2.capture.silenceTimer);
+ }
+ if (SDL2.capture.stream !== undefined) {
+ var tracks = SDL2.capture.stream.getAudioTracks();
+ for (var i = 0; i < tracks.length; i++) {
+ SDL2.capture.stream.removeTrack(tracks[i]);
+ }
+ SDL2.capture.stream = undefined;
+ }
+ if (SDL2.capture.scriptProcessorNode !== undefined) {
+ SDL2.capture.scriptProcessorNode.onaudioprocess = function(audioProcessingEvent) {};
+ SDL2.capture.scriptProcessorNode.disconnect();
+ SDL2.capture.scriptProcessorNode = undefined;
+ }
+ if (SDL2.capture.mediaStreamNode !== undefined) {
+ SDL2.capture.mediaStreamNode.disconnect();
+ SDL2.capture.mediaStreamNode = undefined;
+ }
+ if (SDL2.capture.silenceBuffer !== undefined) {
+ SDL2.capture.silenceBuffer = undefined
+ }
+ SDL2.capture = undefined;
+ } else {
+ if (SDL2.audio.scriptProcessorNode != undefined) {
+ SDL2.audio.scriptProcessorNode.disconnect();
+ SDL2.audio.scriptProcessorNode = undefined;
+ }
+ SDL2.audio = undefined;
+ }
+ if ((SDL2.audioContext !== undefined) && (SDL2.audio === undefined) && (SDL2.capture === undefined)) {
+ SDL2.audioContext.close();
+ SDL2.audioContext = undefined;
+ }
+ }, this->iscapture);
+
+ SDL_free(this->hidden->mixbuf);
+ SDL_free(this->hidden);
}
static int
-Emscripten_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
+EMSCRIPTENAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
SDL_bool valid_format = SDL_FALSE;
- SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
+ SDL_AudioFormat test_format;
int i;
float f;
int result;
+ /* based on parts of library_sdl.js */
+
+ /* create context (TODO: this puts stuff in the global namespace...)*/
+ result = EM_ASM_INT({
+ if(typeof(SDL2) === 'undefined') {
+ SDL2 = {};
+ }
+ if (!$0) {
+ SDL2.audio = {};
+ } else {
+ SDL2.capture = {};
+ }
+
+ if (!SDL2.audioContext) {
+ if (typeof(AudioContext) !== 'undefined') {
+ SDL2.audioContext = new AudioContext();
+ } else if (typeof(webkitAudioContext) !== 'undefined') {
+ SDL2.audioContext = new webkitAudioContext();
+ }
+ }
+ return SDL2.audioContext === undefined ? -1 : 0;
+ }, iscapture);
+ if (result < 0) {
+ return SDL_SetError("Web Audio API is not available!");
+ }
+
+ test_format = SDL_FirstAudioFormat(this->spec.format);
while ((!valid_format) && (test_format)) {
switch (test_format) {
case AUDIO_F32: /* web audio only supports floats */
@@ -181,36 +298,11 @@ Emscripten_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
if (this->hidden == NULL) {
return SDL_OutOfMemory();
}
- SDL_memset(this->hidden, 0, (sizeof *this->hidden));
-
- /* based on parts of library_sdl.js */
-
- /* create context (TODO: this puts stuff in the global namespace...)*/
- result = EM_ASM_INT_V({
- if(typeof(SDL2) === 'undefined')
- SDL2 = {};
-
- if(typeof(SDL2.audio) === 'undefined')
- SDL2.audio = {};
-
- if (!SDL2.audioContext) {
- if (typeof(AudioContext) !== 'undefined') {
- SDL2.audioContext = new AudioContext();
- } else if (typeof(webkitAudioContext) !== 'undefined') {
- SDL2.audioContext = new webkitAudioContext();
- } else {
- return -1;
- }
- }
- return 0;
- });
- if (result < 0) {
- return SDL_SetError("Web Audio API is not available!");
- }
+ SDL_zerop(this->hidden);
/* limit to native freq */
- int sampleRate = EM_ASM_INT_V({
- return SDL2.audioContext['sampleRate'];
+ const int sampleRate = EM_ASM_INT_V({
+ return SDL2.audioContext.sampleRate;
});
if(this->spec.freq != sampleRate) {
@@ -227,26 +319,86 @@ Emscripten_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
SDL_CalculateAudioSpec(&this->spec);
- /* setup a ScriptProcessorNode */
- EM_ASM_ARGS({
- SDL2.audio.scriptProcessorNode = SDL2.audioContext['createScriptProcessor']($1, 0, $0);
- SDL2.audio.scriptProcessorNode['onaudioprocess'] = function (e) {
- SDL2.audio.currentOutputBuffer = e['outputBuffer'];
- Runtime.dynCall('vi', $2, [$3]);
- };
- SDL2.audio.scriptProcessorNode['connect'](SDL2.audioContext['destination']);
- }, this->spec.channels, this->spec.samples, HandleAudioProcess, this);
+ if (iscapture) {
+ /* The idea is to take the capture media stream, hook it up to an
+ audio graph where we can pass it through a ScriptProcessorNode
+ to access the raw PCM samples and push them to the SDL app's
+ callback. From there, we "process" the audio data into silence
+ and forget about it. */
+
+ /* This should, strictly speaking, use MediaRecorder for capture, but
+ this API is cleaner to use and better supported, and fires a
+ callback whenever there's enough data to fire down into the app.
+ The downside is that we are spending CPU time silencing a buffer
+ that the audiocontext uselessly mixes into any output. On the
+ upside, both of those things are not only run in native code in
+ the browser, they're probably SIMD code, too. MediaRecorder
+ feels like it's a pretty inefficient tapdance in similar ways,
+ to be honest. */
+
+ EM_ASM_({
+ var have_microphone = function(stream) {
+ //console.log('SDL audio capture: we have a microphone! Replacing silence callback.');
+ if (SDL2.capture.silenceTimer !== undefined) {
+ clearTimeout(SDL2.capture.silenceTimer);
+ SDL2.capture.silenceTimer = undefined;
+ }
+ SDL2.capture.mediaStreamNode = SDL2.audioContext.createMediaStreamSource(stream);
+ SDL2.capture.scriptProcessorNode = SDL2.audioContext.createScriptProcessor($1, $0, 1);
+ SDL2.capture.scriptProcessorNode.onaudioprocess = function(audioProcessingEvent) {
+ if ((SDL2 === undefined) || (SDL2.capture === undefined)) { return; }
+ audioProcessingEvent.outputBuffer.getChannelData(0).fill(0.0);
+ SDL2.capture.currentCaptureBuffer = audioProcessingEvent.inputBuffer;
+ Runtime.dynCall('vi', $2, [$3]);
+ };
+ SDL2.capture.mediaStreamNode.connect(SDL2.capture.scriptProcessorNode);
+ SDL2.capture.scriptProcessorNode.connect(SDL2.audioContext.destination);
+ SDL2.capture.stream = stream;
+ };
+
+ var no_microphone = function(error) {
+ //console.log('SDL audio capture: we DO NOT have a microphone! (' + error.name + ')...leaving silence callback running.');
+ };
+
+ /* we write silence to the audio callback until the microphone is available (user approves use, etc). */
+ SDL2.capture.silenceBuffer = SDL2.audioContext.createBuffer($0, $1, SDL2.audioContext.sampleRate);
+ SDL2.capture.silenceBuffer.getChannelData(0).fill(0.0);
+ var silence_callback = function() {
+ SDL2.capture.currentCaptureBuffer = SDL2.capture.silenceBuffer;
+ Runtime.dynCall('vi', $2, [$3]);
+ };
+
+ SDL2.capture.silenceTimer = setTimeout(silence_callback, ($1 / SDL2.audioContext.sampleRate) * 1000);
+
+ if ((navigator.mediaDevices !== undefined) && (navigator.mediaDevices.getUserMedia !== undefined)) {
+ navigator.mediaDevices.getUserMedia({ audio: true, video: false }).then(have_microphone).catch(no_microphone);
+ } else if (navigator.webkitGetUserMedia !== undefined) {
+ navigator.webkitGetUserMedia({ audio: true, video: false }, have_microphone, no_microphone);
+ }
+ }, this->spec.channels, this->spec.samples, HandleCaptureProcess, this);
+ } else {
+ /* setup a ScriptProcessorNode */
+ EM_ASM_ARGS({
+ SDL2.audio.scriptProcessorNode = SDL2.audioContext['createScriptProcessor']($1, 0, $0);
+ SDL2.audio.scriptProcessorNode['onaudioprocess'] = function (e) {
+ if ((SDL2 === undefined) || (SDL2.audio === undefined)) { return; }
+ SDL2.audio.currentOutputBuffer = e['outputBuffer'];
+ Runtime.dynCall('vi', $2, [$3]);
+ };
+ SDL2.audio.scriptProcessorNode['connect'](SDL2.audioContext['destination']);
+ }, this->spec.channels, this->spec.samples, HandleAudioProcess, this);
+ }
+
return 0;
}
static int
-Emscripten_Init(SDL_AudioDriverImpl * impl)
+EMSCRIPTENAUDIO_Init(SDL_AudioDriverImpl * impl)
{
/* Set the function pointers */
- impl->OpenDevice = Emscripten_OpenDevice;
- impl->CloseDevice = Emscripten_CloseDevice;
+ impl->OpenDevice = EMSCRIPTENAUDIO_OpenDevice;
+ impl->CloseDevice = EMSCRIPTENAUDIO_CloseDevice;
- /* only one output */
impl->OnlyHasDefaultOutputDevice = 1;
/* no threads here */
@@ -254,7 +406,7 @@ Emscripten_Init(SDL_AudioDriverImpl * impl)
impl->ProvidesOwnCallbackThread = 1;
/* check availability */
- int available = EM_ASM_INT_V({
+ const int available = EM_ASM_INT_V({
if (typeof(AudioContext) !== 'undefined') {
return 1;
} else if (typeof(webkitAudioContext) !== 'undefined') {
@@ -267,11 +419,23 @@ Emscripten_Init(SDL_AudioDriverImpl * impl)
SDL_SetError("No audio context available");
}
+ const int capture_available = available && EM_ASM_INT_V({
+ if ((typeof(navigator.mediaDevices) !== 'undefined') && (typeof(navigator.mediaDevices.getUserMedia) !== 'undefined')) {
+ return 1;
+ } else if (typeof(navigator.webkitGetUserMedia) !== 'undefined') {
+ return 1;
+ }
+ return 0;
+ });
+
+ impl->HasCaptureSupport = capture_available ? SDL_TRUE : SDL_FALSE;
+ impl->OnlyHasDefaultCaptureDevice = capture_available ? SDL_TRUE : SDL_FALSE;
+
return available;
}
-AudioBootStrap EmscriptenAudio_bootstrap = {
- "emscripten", "SDL emscripten audio driver", Emscripten_Init, 0
+AudioBootStrap EMSCRIPTENAUDIO_bootstrap = {
+ "emscripten", "SDL emscripten audio driver", EMSCRIPTENAUDIO_Init, 0
};
#endif /* SDL_AUDIO_DRIVER_EMSCRIPTEN */
diff --git a/Engine/lib/sdl/src/audio/esd/SDL_esdaudio.c b/Engine/lib/sdl/src/audio/esd/SDL_esdaudio.c
index 6a7882dcb..3eb719791 100644
--- a/Engine/lib/sdl/src/audio/esd/SDL_esdaudio.c
+++ b/Engine/lib/sdl/src/audio/esd/SDL_esdaudio.c
@@ -32,7 +32,6 @@
#include "SDL_timer.h"
#include "SDL_audio.h"
-#include "../SDL_audiomem.h"
#include "../SDL_audio_c.h"
#include "SDL_esdaudio.h"
@@ -174,17 +173,11 @@ ESD_GetDeviceBuf(_THIS)
static void
ESD_CloseDevice(_THIS)
{
- if (this->hidden != NULL) {
- SDL_FreeAudioMem(this->hidden->mixbuf);
- this->hidden->mixbuf = NULL;
- if (this->hidden->audio_fd >= 0) {
- SDL_NAME(esd_close) (this->hidden->audio_fd);
- this->hidden->audio_fd = -1;
- }
-
- SDL_free(this->hidden);
- this->hidden = NULL;
+ if (this->hidden->audio_fd >= 0) {
+ SDL_NAME(esd_close) (this->hidden->audio_fd);
}
+ SDL_free(this->hidden->mixbuf);
+ SDL_free(this->hidden);
}
/* Try to get the name of the program */
@@ -227,7 +220,7 @@ ESD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
if (this->hidden == NULL) {
return SDL_OutOfMemory();
}
- SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+ SDL_zerop(this->hidden);
this->hidden->audio_fd = -1;
/* Convert audio spec to the ESD audio format */
@@ -252,7 +245,6 @@ ESD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
}
if (!found) {
- ESD_CloseDevice(this);
return SDL_SetError("Couldn't find any hardware audio formats");
}
@@ -271,7 +263,6 @@ ESD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
get_progname());
if (this->hidden->audio_fd < 0) {
- ESD_CloseDevice(this);
return SDL_SetError("Couldn't open ESD connection");
}
@@ -283,9 +274,8 @@ ESD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
/* Allocate mixing buffer */
this->hidden->mixlen = this->spec.size;
- this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
+ this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->hidden->mixlen);
if (this->hidden->mixbuf == NULL) {
- ESD_CloseDevice(this);
return SDL_OutOfMemory();
}
SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
diff --git a/Engine/lib/sdl/src/audio/fusionsound/SDL_fsaudio.c b/Engine/lib/sdl/src/audio/fusionsound/SDL_fsaudio.c
index b22a3e9a3..daa0f9dd6 100644
--- a/Engine/lib/sdl/src/audio/fusionsound/SDL_fsaudio.c
+++ b/Engine/lib/sdl/src/audio/fusionsound/SDL_fsaudio.c
@@ -22,6 +22,8 @@
#if SDL_AUDIO_DRIVER_FUSIONSOUND
+/* !!! FIXME: why is this is SDL_FS_* instead of FUSIONSOUND_*? */
+
/* Allow access to a raw mixing buffer */
#ifdef HAVE_SIGNAL_H
@@ -31,7 +33,6 @@
#include "SDL_timer.h"
#include "SDL_audio.h"
-#include "../SDL_audiomem.h"
#include "../SDL_audio_c.h"
#include "SDL_fsaudio.h"
@@ -150,13 +151,6 @@ SDL_FS_PlayDevice(_THIS)
#endif
}
-static void
-SDL_FS_WaitDone(_THIS)
-{
- this->hidden->stream->Wait(this->hidden->stream,
- this->hidden->mixsamples * FUSION_BUFFERS);
-}
-
static Uint8 *
SDL_FS_GetDeviceBuf(_THIS)
@@ -168,20 +162,14 @@ SDL_FS_GetDeviceBuf(_THIS)
static void
SDL_FS_CloseDevice(_THIS)
{
- if (this->hidden != NULL) {
- SDL_FreeAudioMem(this->hidden->mixbuf);
- this->hidden->mixbuf = NULL;
- if (this->hidden->stream) {
- this->hidden->stream->Release(this->hidden->stream);
- this->hidden->stream = NULL;
- }
- if (this->hidden->fs) {
- this->hidden->fs->Release(this->hidden->fs);
- this->hidden->fs = NULL;
- }
- SDL_free(this->hidden);
- this->hidden = NULL;
+ if (this->hidden->stream) {
+ this->hidden->stream->Release(this->hidden->stream);
}
+ if (this->hidden->fs) {
+ this->hidden->fs->Release(this->hidden->fs);
+ }
+ SDL_free(this->hidden->mixbuf);
+ SDL_free(this->hidden);
}
@@ -200,7 +188,7 @@ SDL_FS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
if (this->hidden == NULL) {
return SDL_OutOfMemory();
}
- SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+ SDL_zerop(this->hidden);
/* Try for a closest match on audio format */
for (test_format = SDL_FirstAudioFormat(this->spec.format);
@@ -239,7 +227,6 @@ SDL_FS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
}
if (format == 0) {
- SDL_FS_CloseDevice(this);
return SDL_SetError("Couldn't find any hardware audio formats");
}
this->spec.format = test_format;
@@ -247,7 +234,6 @@ SDL_FS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
/* Retrieve the main sound interface. */
ret = SDL_NAME(FusionSoundCreate) (&this->hidden->fs);
if (ret) {
- SDL_FS_CloseDevice(this);
return SDL_SetError("Unable to initialize FusionSound: %d", ret);
}
@@ -266,7 +252,6 @@ SDL_FS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
this->hidden->fs->CreateStream(this->hidden->fs, &desc,
&this->hidden->stream);
if (ret) {
- SDL_FS_CloseDevice(this);
return SDL_SetError("Unable to create FusionSoundStream: %d", ret);
}
@@ -285,9 +270,8 @@ SDL_FS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
/* Allocate mixing buffer */
this->hidden->mixlen = this->spec.size;
- this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
+ this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->hidden->mixlen);
if (this->hidden->mixbuf == NULL) {
- SDL_FS_CloseDevice(this);
return SDL_OutOfMemory();
}
SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
@@ -328,7 +312,6 @@ SDL_FS_Init(SDL_AudioDriverImpl * impl)
impl->WaitDevice = SDL_FS_WaitDevice;
impl->GetDeviceBuf = SDL_FS_GetDeviceBuf;
impl->CloseDevice = SDL_FS_CloseDevice;
- impl->WaitDone = SDL_FS_WaitDone;
impl->Deinitialize = SDL_FS_Deinitialize;
impl->OnlyHasDefaultOutputDevice = 1;
diff --git a/Engine/lib/sdl/src/audio/haiku/SDL_haikuaudio.cc b/Engine/lib/sdl/src/audio/haiku/SDL_haikuaudio.cc
index 38f3b9621..25b1fa217 100644
--- a/Engine/lib/sdl/src/audio/haiku/SDL_haikuaudio.cc
+++ b/Engine/lib/sdl/src/audio/haiku/SDL_haikuaudio.cc
@@ -49,10 +49,11 @@ FillSound(void *device, void *stream, size_t len,
SDL_AudioDevice *audio = (SDL_AudioDevice *) device;
/* Only do soemthing if audio is enabled */
- if (!audio->enabled)
+ if (!SDL_AtomicGet(&audio->enabled)) {
return;
+ }
- if (!audio->paused) {
+ if (!SDL_AtomicGet(&audio->paused)) {
if (audio->convert.needed) {
SDL_LockMutex(audio->mixer_lock);
(*audio->spec.callback) (audio->spec.userdata,
@@ -73,16 +74,11 @@ FillSound(void *device, void *stream, size_t len,
static void
HAIKUAUDIO_CloseDevice(_THIS)
{
- if (_this->hidden != NULL) {
- if (_this->hidden->audio_obj) {
- _this->hidden->audio_obj->Stop();
- delete _this->hidden->audio_obj;
- _this->hidden->audio_obj = NULL;
- }
-
- delete _this->hidden;
- _this->hidden = NULL;
+ if (_this->hidden->audio_obj) {
+ _this->hidden->audio_obj->Stop();
+ delete _this->hidden->audio_obj;
}
+ delete _this->hidden;
}
@@ -122,10 +118,10 @@ HAIKUAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
if (_this->hidden == NULL) {
return SDL_OutOfMemory();
}
- SDL_memset(_this->hidden, 0, (sizeof *_this->hidden));
+ SDL_zerop(_this->hidden);
/* Parse the audio format and fill the Be raw audio format */
- SDL_memset(&format, '\0', sizeof(media_raw_audio_format));
+ SDL_zero(format);
format.byte_order = B_MEDIA_LITTLE_ENDIAN;
format.frame_rate = (float) _this->spec.freq;
format.channel_count = _this->spec.channels; /* !!! FIXME: support > 2? */
@@ -176,7 +172,6 @@ HAIKUAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
}
if (!valid_datatype) { /* shouldn't happen, but just in case... */
- HAIKUAUDIO_CloseDevice(_this);
return SDL_SetError("Unsupported audio format");
}
@@ -195,7 +190,6 @@ HAIKUAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
if (_this->hidden->audio_obj->Start() == B_NO_ERROR) {
_this->hidden->audio_obj->SetHasData(true);
} else {
- HAIKUAUDIO_CloseDevice(_this);
return SDL_SetError("Unable to start Be audio");
}
diff --git a/Engine/lib/sdl/src/audio/nacl/SDL_naclaudio.c b/Engine/lib/sdl/src/audio/nacl/SDL_naclaudio.c
index 2d1ee73e9..33cbe1c83 100644
--- a/Engine/lib/sdl/src/audio/nacl/SDL_naclaudio.c
+++ b/Engine/lib/sdl/src/audio/nacl/SDL_naclaudio.c
@@ -27,7 +27,6 @@
#include "SDL_audio.h"
#include "SDL_mutex.h"
-#include "../SDL_audiomem.h"
#include "../SDL_audio_c.h"
#include "../SDL_audiodev_c.h"
@@ -38,22 +37,20 @@
#include "ppapi_simple/ps_event.h"
/* The tag name used by NACL audio */
-#define NACLAUD_DRIVER_NAME "nacl"
+#define NACLAUDIO_DRIVER_NAME "nacl"
#define SAMPLE_FRAME_COUNT 4096
/* Audio driver functions */
-static int NACLAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture);
-static void NACLAUD_CloseDevice(_THIS);
static void nacl_audio_callback(void* samples, uint32_t buffer_size, PP_TimeDelta latency, void* data);
/* FIXME: Make use of latency if needed */
static void nacl_audio_callback(void* samples, uint32_t buffer_size, PP_TimeDelta latency, void* data) {
SDL_AudioDevice* _this = (SDL_AudioDevice*) data;
- SDL_LockMutex(private->mutex);
+ SDL_LockMutex(private->mutex); /* !!! FIXME: is this mutex necessary? */
- if (_this->enabled && !_this->paused) {
+ if (SDL_AtomicGet(&_this->enabled) && !SDL_AtomicGet(&_this->paused)) {
if (_this->convert.needed) {
SDL_LockMutex(_this->mixer_lock);
(*_this->spec.callback) (_this->spec.userdata,
@@ -68,13 +65,13 @@ static void nacl_audio_callback(void* samples, uint32_t buffer_size, PP_TimeDelt
SDL_UnlockMutex(_this->mixer_lock);
}
} else {
- SDL_memset(samples, 0, buffer_size);
+ SDL_memset(samples, _this->spec.silence, buffer_size);
}
- return;
+ SDL_UnlockMutex(private->mutex);
}
-static void NACLAUD_CloseDevice(SDL_AudioDevice *device) {
+static void NACLAUDIO_CloseDevice(SDL_AudioDevice *device) {
const PPB_Core *core = PSInterfaceCore();
const PPB_Audio *ppb_audio = PSInterfaceAudio();
SDL_PrivateAudioData *hidden = (SDL_PrivateAudioData *) device->hidden;
@@ -85,7 +82,7 @@ static void NACLAUD_CloseDevice(SDL_AudioDevice *device) {
}
static int
-NACLAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) {
+NACLAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) {
PP_Instance instance = PSGetInstanceId();
const PPB_Audio *ppb_audio = PSInterfaceAudio();
const PPB_AudioConfig *ppb_audiocfg = PSInterfaceAudioConfig();
@@ -121,30 +118,30 @@ NACLAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture) {
}
static int
-NACLAUD_Init(SDL_AudioDriverImpl * impl)
+NACLAUDIO_Init(SDL_AudioDriverImpl * impl)
{
if (PSGetInstanceId() == 0) {
return 0;
}
/* Set the function pointers */
- impl->OpenDevice = NACLAUD_OpenDevice;
- impl->CloseDevice = NACLAUD_CloseDevice;
+ impl->OpenDevice = NACLAUDIO_OpenDevice;
+ impl->CloseDevice = NACLAUDIO_CloseDevice;
impl->OnlyHasDefaultOutputDevice = 1;
impl->ProvidesOwnCallbackThread = 1;
/*
- * impl->WaitDevice = NACLAUD_WaitDevice;
- * impl->GetDeviceBuf = NACLAUD_GetDeviceBuf;
- * impl->PlayDevice = NACLAUD_PlayDevice;
- * impl->Deinitialize = NACLAUD_Deinitialize;
+ * impl->WaitDevice = NACLAUDIO_WaitDevice;
+ * impl->GetDeviceBuf = NACLAUDIO_GetDeviceBuf;
+ * impl->PlayDevice = NACLAUDIO_PlayDevice;
+ * impl->Deinitialize = NACLAUDIO_Deinitialize;
*/
return 1;
}
-AudioBootStrap NACLAUD_bootstrap = {
- NACLAUD_DRIVER_NAME, "SDL NaCl Audio Driver",
- NACLAUD_Init, 0
+AudioBootStrap NACLAUDIO_bootstrap = {
+ NACLAUDIO_DRIVER_NAME, "SDL NaCl Audio Driver",
+ NACLAUDIO_Init, 0
};
#endif /* SDL_AUDIO_DRIVER_NACL */
diff --git a/Engine/lib/sdl/src/audio/nas/SDL_nasaudio.c b/Engine/lib/sdl/src/audio/nas/SDL_nasaudio.c
index 9de5ff8b4..fe15cd696 100644
--- a/Engine/lib/sdl/src/audio/nas/SDL_nasaudio.c
+++ b/Engine/lib/sdl/src/audio/nas/SDL_nasaudio.c
@@ -30,22 +30,21 @@
#include "SDL_timer.h"
#include "SDL_audio.h"
#include "SDL_loadso.h"
-#include "../SDL_audiomem.h"
#include "../SDL_audio_c.h"
#include "SDL_nasaudio.h"
-static struct SDL_PrivateAudioData *this2 = NULL;
-
-
static void (*NAS_AuCloseServer) (AuServer *);
static void (*NAS_AuNextEvent) (AuServer *, AuBool, AuEvent *);
static AuBool(*NAS_AuDispatchEvent) (AuServer *, AuEvent *);
+static void (*NAS_AuHandleEvents) (AuServer *);
static AuFlowID(*NAS_AuCreateFlow) (AuServer *, AuStatus *);
static void (*NAS_AuStartFlow) (AuServer *, AuFlowID, AuStatus *);
static void (*NAS_AuSetElements)
(AuServer *, AuFlowID, AuBool, int, AuElement *, AuStatus *);
static void (*NAS_AuWriteElement)
(AuServer *, AuFlowID, int, AuUint32, AuPointer, AuBool, AuStatus *);
+static AuUint32 (*NAS_AuReadElement)
+ (AuServer *, AuFlowID, int, AuUint32, AuPointer, AuStatus *);
static AuServer *(*NAS_AuOpenServer)
(_AuConst char *, int, _AuConst char *, int, _AuConst char *, char **);
static AuEventHandlerRec *(*NAS_AuRegisterEventHandler)
@@ -80,10 +79,12 @@ load_nas_syms(void)
SDL_NAS_SYM(AuCloseServer);
SDL_NAS_SYM(AuNextEvent);
SDL_NAS_SYM(AuDispatchEvent);
+ SDL_NAS_SYM(AuHandleEvents);
SDL_NAS_SYM(AuCreateFlow);
SDL_NAS_SYM(AuStartFlow);
SDL_NAS_SYM(AuSetElements);
SDL_NAS_SYM(AuWriteElement);
+ SDL_NAS_SYM(AuReadElement);
SDL_NAS_SYM(AuOpenServer);
SDL_NAS_SYM(AuRegisterEventHandler);
return 0;
@@ -187,19 +188,53 @@ NAS_GetDeviceBuf(_THIS)
return (this->hidden->mixbuf);
}
+static int
+NAS_CaptureFromDevice(_THIS, void *buffer, int buflen)
+{
+ struct SDL_PrivateAudioData *h = this->hidden;
+ int retval;
+
+ while (SDL_TRUE) {
+ /* just keep the event queue moving and the server chattering. */
+ NAS_AuHandleEvents(h->aud);
+
+ retval = (int) NAS_AuReadElement(h->aud, h->flow, 1, buflen, buffer, NULL);
+ /*printf("read %d capture bytes\n", (int) retval);*/
+ if (retval == 0) {
+ SDL_Delay(10); /* don't burn the CPU if we're waiting for data. */
+ } else {
+ break;
+ }
+ }
+
+ return retval;
+}
+
+static void
+NAS_FlushCapture(_THIS)
+{
+ struct SDL_PrivateAudioData *h = this->hidden;
+ AuUint32 total = 0;
+ AuUint32 br;
+ Uint8 buf[512];
+
+ do {
+ /* just keep the event queue moving and the server chattering. */
+ NAS_AuHandleEvents(h->aud);
+ br = NAS_AuReadElement(h->aud, h->flow, 1, sizeof (buf), buf, NULL);
+ /*printf("flushed %d capture bytes\n", (int) br);*/
+ total += br;
+ } while ((br == sizeof (buf)) && (total < this->spec.size));
+}
+
static void
NAS_CloseDevice(_THIS)
{
- if (this->hidden != NULL) {
- SDL_FreeAudioMem(this->hidden->mixbuf);
- this->hidden->mixbuf = NULL;
- if (this->hidden->aud) {
- NAS_AuCloseServer(this->hidden->aud);
- this->hidden->aud = 0;
- }
- SDL_free(this->hidden);
- this2 = this->hidden = NULL;
+ if (this->hidden->aud) {
+ NAS_AuCloseServer(this->hidden->aud);
}
+ SDL_free(this->hidden->mixbuf);
+ SDL_free(this->hidden);
}
static unsigned char
@@ -225,6 +260,12 @@ sdlformat_to_auformat(unsigned int fmt)
static AuBool
event_handler(AuServer * aud, AuEvent * ev, AuEventHandlerRec * hnd)
{
+ SDL_AudioDevice *this = (SDL_AudioDevice *) hnd->data;
+ struct SDL_PrivateAudioData *h = this->hidden;
+ if (this->iscapture) {
+ return AuTrue; /* we don't (currently) care about any of this for capture devices */
+ }
+
switch (ev->type) {
case AuEventTypeElementNotify:
{
@@ -232,24 +273,24 @@ event_handler(AuServer * aud, AuEvent * ev, AuEventHandlerRec * hnd)
switch (event->kind) {
case AuElementNotifyKindLowWater:
- if (this2->buf_free >= 0) {
- this2->really += event->num_bytes;
- gettimeofday(&this2->last_tv, 0);
- this2->buf_free += event->num_bytes;
+ if (h->buf_free >= 0) {
+ h->really += event->num_bytes;
+ gettimeofday(&h->last_tv, 0);
+ h->buf_free += event->num_bytes;
} else {
- this2->buf_free = event->num_bytes;
+ h->buf_free = event->num_bytes;
}
break;
case AuElementNotifyKindState:
switch (event->cur_state) {
case AuStatePause:
if (event->reason != AuReasonUser) {
- if (this2->buf_free >= 0) {
- this2->really += event->num_bytes;
- gettimeofday(&this2->last_tv, 0);
- this2->buf_free += event->num_bytes;
+ if (h->buf_free >= 0) {
+ h->really += event->num_bytes;
+ gettimeofday(&h->last_tv, 0);
+ h->buf_free += event->num_bytes;
} else {
- this2->buf_free = event->num_bytes;
+ h->buf_free = event->num_bytes;
}
}
break;
@@ -261,15 +302,29 @@ event_handler(AuServer * aud, AuEvent * ev, AuEventHandlerRec * hnd)
}
static AuDeviceID
-find_device(_THIS, int nch)
+find_device(_THIS)
{
/* These "Au" things are all macros, not functions... */
+ struct SDL_PrivateAudioData *h = this->hidden;
+ const unsigned int devicekind = this->iscapture ? AuComponentKindPhysicalInput : AuComponentKindPhysicalOutput;
+ const int numdevs = AuServerNumDevices(h->aud);
+ const int nch = this->spec.channels;
int i;
- for (i = 0; i < AuServerNumDevices(this->hidden->aud); i++) {
- if ((AuDeviceKind(AuServerDevice(this->hidden->aud, i)) ==
- AuComponentKindPhysicalOutput) &&
- AuDeviceNumTracks(AuServerDevice(this->hidden->aud, i)) == nch) {
- return AuDeviceIdentifier(AuServerDevice(this->hidden->aud, i));
+
+ /* Try to find exact match on channels first... */
+ for (i = 0; i < numdevs; i++) {
+ const AuDeviceAttributes *dev = AuServerDevice(h->aud, i);
+ if ((AuDeviceKind(dev) == devicekind) && (AuDeviceNumTracks(dev) == nch)) {
+ return AuDeviceIdentifier(dev);
+ }
+ }
+
+ /* Take anything, then... */
+ for (i = 0; i < numdevs; i++) {
+ const AuDeviceAttributes *dev = AuServerDevice(h->aud, i);
+ if (AuDeviceKind(dev) == devicekind) {
+ this->spec.channels = AuDeviceNumTracks(dev);
+ return AuDeviceIdentifier(dev);
}
}
return AuNone;
@@ -288,7 +343,7 @@ NAS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
if (this->hidden == NULL) {
return SDL_OutOfMemory();
}
- SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+ SDL_zerop(this->hidden);
/* Try for a closest match on audio format */
format = 0;
@@ -300,21 +355,18 @@ NAS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
}
}
if (format == 0) {
- NAS_CloseDevice(this);
return SDL_SetError("NAS: Couldn't find any hardware audio formats");
}
this->spec.format = test_format;
this->hidden->aud = NAS_AuOpenServer("", 0, NULL, 0, NULL, NULL);
if (this->hidden->aud == 0) {
- NAS_CloseDevice(this);
return SDL_SetError("NAS: Couldn't open connection to NAS server");
}
- this->hidden->dev = find_device(this, this->spec.channels);
+ this->hidden->dev = find_device(this);
if ((this->hidden->dev == AuNone)
|| (!(this->hidden->flow = NAS_AuCreateFlow(this->hidden->aud, 0)))) {
- NAS_CloseDevice(this);
return SDL_SetError("NAS: Couldn't find a fitting device on NAS server");
}
@@ -328,29 +380,38 @@ NAS_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
/* Calculate the final parameters for this audio specification */
SDL_CalculateAudioSpec(&this->spec);
- this2 = this->hidden;
+ if (iscapture) {
+ AuMakeElementImportDevice(elms, this->spec.freq, this->hidden->dev,
+ AuUnlimitedSamples, 0, NULL);
+ AuMakeElementExportClient(elms + 1, 0, this->spec.freq, format,
+ this->spec.channels, AuTrue, buffer_size,
+ buffer_size, 0, NULL);
+ } else {
+ AuMakeElementImportClient(elms, this->spec.freq, format,
+ this->spec.channels, AuTrue, buffer_size,
+ buffer_size / 4, 0, NULL);
+ AuMakeElementExportDevice(elms + 1, 0, this->hidden->dev, this->spec.freq,
+ AuUnlimitedSamples, 0, NULL);
+ }
+
+ NAS_AuSetElements(this->hidden->aud, this->hidden->flow, AuTrue,
+ 2, elms, NULL);
- AuMakeElementImportClient(elms, this->spec.freq, format,
- this->spec.channels, AuTrue, buffer_size,
- buffer_size / 4, 0, NULL);
- AuMakeElementExportDevice(elms + 1, 0, this->hidden->dev, this->spec.freq,
- AuUnlimitedSamples, 0, NULL);
- NAS_AuSetElements(this->hidden->aud, this->hidden->flow, AuTrue, 2, elms,
- NULL);
NAS_AuRegisterEventHandler(this->hidden->aud, AuEventHandlerIDMask, 0,
this->hidden->flow, event_handler,
- (AuPointer) NULL);
+ (AuPointer) this);
NAS_AuStartFlow(this->hidden->aud, this->hidden->flow, NULL);
/* Allocate mixing buffer */
- this->hidden->mixlen = this->spec.size;
- this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
- if (this->hidden->mixbuf == NULL) {
- NAS_CloseDevice(this);
- return SDL_OutOfMemory();
+ if (!iscapture) {
+ this->hidden->mixlen = this->spec.size;
+ this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->hidden->mixlen);
+ if (this->hidden->mixbuf == NULL) {
+ return SDL_OutOfMemory();
+ }
+ SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
}
- SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
/* We're ready to rock and roll. :-) */
return 0;
@@ -381,9 +442,14 @@ NAS_Init(SDL_AudioDriverImpl * impl)
impl->PlayDevice = NAS_PlayDevice;
impl->WaitDevice = NAS_WaitDevice;
impl->GetDeviceBuf = NAS_GetDeviceBuf;
+ impl->CaptureFromDevice = NAS_CaptureFromDevice;
+ impl->FlushCapture = NAS_FlushCapture;
impl->CloseDevice = NAS_CloseDevice;
impl->Deinitialize = NAS_Deinitialize;
- impl->OnlyHasDefaultOutputDevice = 1; /* !!! FIXME: is this true? */
+
+ impl->OnlyHasDefaultOutputDevice = 1;
+ impl->OnlyHasDefaultCaptureDevice = 1;
+ impl->HasCaptureSupport = SDL_TRUE;
return 1; /* this audio target is available. */
}
diff --git a/Engine/lib/sdl/src/audio/paudio/SDL_paudio.c b/Engine/lib/sdl/src/audio/paudio/SDL_paudio.c
index 14c9701f4..57202245f 100644
--- a/Engine/lib/sdl/src/audio/paudio/SDL_paudio.c
+++ b/Engine/lib/sdl/src/audio/paudio/SDL_paudio.c
@@ -35,7 +35,6 @@
#include "SDL_timer.h"
#include "SDL_audio.h"
#include "SDL_stdinc.h"
-#include "../SDL_audiomem.h"
#include "../SDL_audio_c.h"
#include "SDL_paudio.h"
@@ -228,16 +227,11 @@ PAUDIO_GetDeviceBuf(_THIS)
static void
PAUDIO_CloseDevice(_THIS)
{
- if (this->hidden != NULL) {
- SDL_FreeAudioMem(this->hidden->mixbuf);
- this->hidden->mixbuf = NULL;
- if (this->hidden->audio_fd >= 0) {
- close(this->hidden->audio_fd);
- this->hidden->audio_fd = -1;
- }
- SDL_free(this->hidden);
- this->hidden = NULL;
+ if (this->hidden->audio_fd >= 0) {
+ close(this->hidden->audio_fd);
}
+ SDL_free(this->hidden->mixbuf);
+ SDL_free(this->hidden);
}
static int
@@ -262,13 +256,12 @@ PAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
if (this->hidden == NULL) {
return SDL_OutOfMemory();
}
- SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+ SDL_zerop(this->hidden);
/* Open the audio device */
fd = OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0);
this->hidden->audio_fd = fd;
if (fd < 0) {
- PAUDIO_CloseDevice(this);
return SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno));
}
@@ -277,7 +270,6 @@ PAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
* that we can have.
*/
if (ioctl(fd, AUDIO_BUFFER, &paud_bufinfo) < 0) {
- PAUDIO_CloseDevice(this);
return SDL_SetError("Couldn't get audio buffer information");
}
@@ -391,7 +383,6 @@ PAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
#ifdef DEBUG_AUDIO
fprintf(stderr, "Couldn't find any hardware audio formats\n");
#endif
- PAUDIO_CloseDevice(this);
return SDL_SetError("Couldn't find any hardware audio formats");
}
this->spec.format = test_format;
@@ -449,15 +440,13 @@ PAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
}
if (err != NULL) {
- PAUDIO_CloseDevice(this);
return SDL_SetError("Paudio: %s", err);
}
/* Allocate mixing buffer */
this->hidden->mixlen = this->spec.size;
- this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
+ this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->hidden->mixlen);
if (this->hidden->mixbuf == NULL) {
- PAUDIO_CloseDevice(this);
return SDL_OutOfMemory();
}
SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
@@ -492,7 +481,6 @@ PAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
paud_control.ioctl_request = AUDIO_START;
paud_control.position = 0;
if (ioctl(fd, AUDIO_CONTROL, &paud_control) < 0) {
- PAUDIO_CloseDevice(this);
#ifdef DEBUG_AUDIO
fprintf(stderr, "Can't start audio play\n");
#endif
diff --git a/Engine/lib/sdl/src/audio/psp/SDL_pspaudio.c b/Engine/lib/sdl/src/audio/psp/SDL_pspaudio.c
index 18d2947e4..bd3456d3f 100644
--- a/Engine/lib/sdl/src/audio/psp/SDL_pspaudio.c
+++ b/Engine/lib/sdl/src/audio/psp/SDL_pspaudio.c
@@ -30,7 +30,6 @@
#include "SDL_audio.h"
#include "SDL_error.h"
#include "SDL_timer.h"
-#include "../SDL_audiomem.h"
#include "../SDL_audio_c.h"
#include "../SDL_audiodev_c.h"
#include "../SDL_sysaudio.h"
@@ -40,10 +39,10 @@
#include
/* The tag name used by PSP audio */
-#define PSPAUD_DRIVER_NAME "psp"
+#define PSPAUDIO_DRIVER_NAME "psp"
static int
-PSPAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
+PSPAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
{
int format, mixlen, i;
this->hidden = (struct SDL_PrivateAudioData *)
@@ -51,7 +50,7 @@ PSPAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
if (this->hidden == NULL) {
return SDL_OutOfMemory();
}
- SDL_memset(this->hidden, 0, sizeof(*this->hidden));
+ SDL_zerop(this->hidden);
switch (this->spec.format & 0xff) {
case 8:
case 16:
@@ -66,20 +65,7 @@ PSPAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
this->spec.freq = 44100;
/* Update the fragment size as size in bytes. */
-/* SDL_CalculateAudioSpec(this->spec); MOD */
- switch (this->spec.format) {
- case AUDIO_U8:
- this->spec.silence = 0x80;
- break;
- default:
- this->spec.silence = 0x00;
- break;
- }
- this->spec.size = SDL_AUDIO_BITSIZE(this->spec.format) / 8;
- this->spec.size *= this->spec.channels;
- this->spec.size *= this->spec.samples;
-
-/* ========================================== */
+ SDL_CalculateAudioSpec(&this->spec);
/* Allocate the mixing buffer. Its size and starting address must
be a multiple of 64 bytes. Our sample count is already a multiple of
@@ -112,7 +98,7 @@ PSPAUD_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
return 0;
}
-static void PSPAUD_PlayDevice(_THIS)
+static void PSPAUDIO_PlayDevice(_THIS)
{
Uint8 *mixbuf = this->hidden->mixbufs[this->hidden->next_buffer];
@@ -126,28 +112,25 @@ static void PSPAUD_PlayDevice(_THIS)
}
/* This function waits until it is possible to write a full sound buffer */
-static void PSPAUD_WaitDevice(_THIS)
+static void PSPAUDIO_WaitDevice(_THIS)
{
/* Because we block when sending audio, there's no need for this function to do anything. */
}
-static Uint8 *PSPAUD_GetDeviceBuf(_THIS)
+static Uint8 *PSPAUDIO_GetDeviceBuf(_THIS)
{
return this->hidden->mixbufs[this->hidden->next_buffer];
}
-static void PSPAUD_CloseDevice(_THIS)
+static void PSPAUDIO_CloseDevice(_THIS)
{
if (this->hidden->channel >= 0) {
sceAudioChRelease(this->hidden->channel);
- this->hidden->channel = -1;
- }
-
- if (this->hidden->rawbuf != NULL) {
- free(this->hidden->rawbuf);
- this->hidden->rawbuf = NULL;
}
+ free(this->hidden->rawbuf); /* this uses memalign(), not SDL_malloc(). */
+ SDL_free(this->hidden);
}
-static void PSPAUD_ThreadInit(_THIS)
+
+static void PSPAUDIO_ThreadInit(_THIS)
{
/* Increase the priority of this audio thread by 1 to put it
ahead of other SDL threads. */
@@ -162,24 +145,22 @@ static void PSPAUD_ThreadInit(_THIS)
static int
-PSPAUD_Init(SDL_AudioDriverImpl * impl)
+PSPAUDIO_Init(SDL_AudioDriverImpl * impl)
{
-
/* Set the function pointers */
- impl->OpenDevice = PSPAUD_OpenDevice;
- impl->PlayDevice = PSPAUD_PlayDevice;
- impl->WaitDevice = PSPAUD_WaitDevice;
- impl->GetDeviceBuf = PSPAUD_GetDeviceBuf;
- impl->WaitDone = PSPAUD_WaitDevice;
- impl->CloseDevice = PSPAUD_CloseDevice;
- impl->ThreadInit = PSPAUD_ThreadInit;
+ impl->OpenDevice = PSPAUDIO_OpenDevice;
+ impl->PlayDevice = PSPAUDIO_PlayDevice;
+ impl->WaitDevice = PSPAUDIO_WaitDevice;
+ impl->GetDeviceBuf = PSPAUDIO_GetDeviceBuf;
+ impl->CloseDevice = PSPAUDIO_CloseDevice;
+ impl->ThreadInit = PSPAUDIO_ThreadInit;
/* PSP audio device */
impl->OnlyHasDefaultOutputDevice = 1;
/*
impl->HasCaptureSupport = 1;
- impl->OnlyHasDefaultInputDevice = 1;
+ impl->OnlyHasDefaultCaptureDevice = 1;
*/
/*
impl->DetectDevices = DSOUND_DetectDevices;
@@ -188,8 +169,8 @@ PSPAUD_Init(SDL_AudioDriverImpl * impl)
return 1; /* this audio target is available. */
}
-AudioBootStrap PSPAUD_bootstrap = {
- "psp", "PSP audio driver", PSPAUD_Init, 0
+AudioBootStrap PSPAUDIO_bootstrap = {
+ "psp", "PSP audio driver", PSPAUDIO_Init, 0
};
/* SDL_AUDI */
diff --git a/Engine/lib/sdl/src/audio/pulseaudio/SDL_pulseaudio.c b/Engine/lib/sdl/src/audio/pulseaudio/SDL_pulseaudio.c
index 6b11e066f..9ced49d21 100644
--- a/Engine/lib/sdl/src/audio/pulseaudio/SDL_pulseaudio.c
+++ b/Engine/lib/sdl/src/audio/pulseaudio/SDL_pulseaudio.c
@@ -42,10 +42,10 @@
#include "SDL_timer.h"
#include "SDL_audio.h"
-#include "../SDL_audiomem.h"
#include "../SDL_audio_c.h"
#include "SDL_pulseaudio.h"
#include "SDL_loadso.h"
+#include "../../thread/SDL_systhread.h"
#if (PA_API_VERSION < 12)
/** Return non-zero if the passed state is one of the connected states */
@@ -99,12 +99,19 @@ static pa_stream * (*PULSEAUDIO_pa_stream_new) (pa_context *, const char *,
const pa_sample_spec *, const pa_channel_map *);
static int (*PULSEAUDIO_pa_stream_connect_playback) (pa_stream *, const char *,
const pa_buffer_attr *, pa_stream_flags_t, pa_cvolume *, pa_stream *);
+static int (*PULSEAUDIO_pa_stream_connect_record) (pa_stream *, const char *,
+ const pa_buffer_attr *, pa_stream_flags_t);
static pa_stream_state_t (*PULSEAUDIO_pa_stream_get_state) (pa_stream *);
static size_t (*PULSEAUDIO_pa_stream_writable_size) (pa_stream *);
+static size_t (*PULSEAUDIO_pa_stream_readable_size) (pa_stream *);
static int (*PULSEAUDIO_pa_stream_write) (pa_stream *, const void *, size_t,
pa_free_cb_t, int64_t, pa_seek_mode_t);
static pa_operation * (*PULSEAUDIO_pa_stream_drain) (pa_stream *,
pa_stream_success_cb_t, void *);
+static int (*PULSEAUDIO_pa_stream_peek) (pa_stream *, const void **, size_t *);
+static int (*PULSEAUDIO_pa_stream_drop) (pa_stream *);
+static pa_operation * (*PULSEAUDIO_pa_stream_flush) (pa_stream *,
+ pa_stream_success_cb_t, void *);
static int (*PULSEAUDIO_pa_stream_disconnect) (pa_stream *);
static void (*PULSEAUDIO_pa_stream_unref) (pa_stream *);
@@ -205,11 +212,16 @@ load_pulseaudio_syms(void)
SDL_PULSEAUDIO_SYM(pa_context_unref);
SDL_PULSEAUDIO_SYM(pa_stream_new);
SDL_PULSEAUDIO_SYM(pa_stream_connect_playback);
+ SDL_PULSEAUDIO_SYM(pa_stream_connect_record);
SDL_PULSEAUDIO_SYM(pa_stream_get_state);
SDL_PULSEAUDIO_SYM(pa_stream_writable_size);
+ SDL_PULSEAUDIO_SYM(pa_stream_readable_size);
SDL_PULSEAUDIO_SYM(pa_stream_write);
SDL_PULSEAUDIO_SYM(pa_stream_drain);
SDL_PULSEAUDIO_SYM(pa_stream_disconnect);
+ SDL_PULSEAUDIO_SYM(pa_stream_peek);
+ SDL_PULSEAUDIO_SYM(pa_stream_drop);
+ SDL_PULSEAUDIO_SYM(pa_stream_flush);
SDL_PULSEAUDIO_SYM(pa_stream_unref);
SDL_PULSEAUDIO_SYM(pa_channel_map_init_auto);
SDL_PULSEAUDIO_SYM(pa_strerror);
@@ -238,6 +250,12 @@ getAppName(void)
return "SDL Application"; /* oh well. */
}
+static void
+stream_operation_complete_no_op(pa_stream *s, int success, void *userdata)
+{
+ /* no-op for pa_stream_drain(), etc, to use for callback. */
+}
+
static void
WaitForPulseOperation(pa_mainloop *mainloop, pa_operation *o)
{
@@ -325,7 +343,7 @@ PULSEAUDIO_WaitDevice(_THIS)
{
struct SDL_PrivateAudioData *h = this->hidden;
- while (this->enabled) {
+ while (SDL_AtomicGet(&this->enabled)) {
if (PULSEAUDIO_pa_context_get_state(h->context) != PA_CONTEXT_READY ||
PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY ||
PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) {
@@ -343,41 +361,13 @@ PULSEAUDIO_PlayDevice(_THIS)
{
/* Write the audio data */
struct SDL_PrivateAudioData *h = this->hidden;
- if (this->enabled) {
+ if (SDL_AtomicGet(&this->enabled)) {
if (PULSEAUDIO_pa_stream_write(h->stream, h->mixbuf, h->mixlen, NULL, 0LL, PA_SEEK_RELATIVE) < 0) {
SDL_OpenedAudioDeviceDisconnected(this);
}
}
}
-static void
-stream_drain_complete(pa_stream *s, int success, void *userdata)
-{
- /* no-op for pa_stream_drain() to use for callback. */
-}
-
-static void
-PULSEAUDIO_WaitDone(_THIS)
-{
- if (this->enabled) {
- struct SDL_PrivateAudioData *h = this->hidden;
- pa_operation *o = PULSEAUDIO_pa_stream_drain(h->stream, stream_drain_complete, NULL);
- if (o) {
- while (PULSEAUDIO_pa_operation_get_state(o) != PA_OPERATION_DONE) {
- if (PULSEAUDIO_pa_context_get_state(h->context) != PA_CONTEXT_READY ||
- PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY ||
- PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) {
- PULSEAUDIO_pa_operation_cancel(o);
- break;
- }
- }
- PULSEAUDIO_pa_operation_unref(o);
- }
- }
-}
-
-
-
static Uint8 *
PULSEAUDIO_GetDeviceBuf(_THIS)
{
@@ -385,24 +375,96 @@ PULSEAUDIO_GetDeviceBuf(_THIS)
}
+static int
+PULSEAUDIO_CaptureFromDevice(_THIS, void *buffer, int buflen)
+{
+ struct SDL_PrivateAudioData *h = this->hidden;
+ const void *data = NULL;
+ size_t nbytes = 0;
+
+ while (SDL_AtomicGet(&this->enabled)) {
+ if (h->capturebuf != NULL) {
+ const int cpy = SDL_min(buflen, h->capturelen);
+ SDL_memcpy(buffer, h->capturebuf, cpy);
+ /*printf("PULSEAUDIO: fed %d captured bytes\n", cpy);*/
+ h->capturebuf += cpy;
+ h->capturelen -= cpy;
+ if (h->capturelen == 0) {
+ h->capturebuf = NULL;
+ PULSEAUDIO_pa_stream_drop(h->stream); /* done with this fragment. */
+ }
+ return cpy; /* new data, return it. */
+ }
+
+ if (PULSEAUDIO_pa_context_get_state(h->context) != PA_CONTEXT_READY ||
+ PULSEAUDIO_pa_stream_get_state(h->stream) != PA_STREAM_READY ||
+ PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) {
+ SDL_OpenedAudioDeviceDisconnected(this);
+ return -1; /* uhoh, pulse failed! */
+ }
+
+ if (PULSEAUDIO_pa_stream_readable_size(h->stream) == 0) {
+ continue; /* no data available yet. */
+ }
+
+ /* a new fragment is available! */
+ PULSEAUDIO_pa_stream_peek(h->stream, &data, &nbytes);
+ SDL_assert(nbytes > 0);
+ if (data == NULL) { /* NULL==buffer had a hole. Ignore that. */
+ PULSEAUDIO_pa_stream_drop(h->stream); /* drop this fragment. */
+ } else {
+ /* store this fragment's data, start feeding it to SDL. */
+ /*printf("PULSEAUDIO: captured %d new bytes\n", (int) nbytes);*/
+ h->capturebuf = (const Uint8 *) data;
+ h->capturelen = nbytes;
+ }
+ }
+
+ return -1; /* not enabled? */
+}
+
+static void
+PULSEAUDIO_FlushCapture(_THIS)
+{
+ struct SDL_PrivateAudioData *h = this->hidden;
+
+ if (h->capturebuf != NULL) {
+ PULSEAUDIO_pa_stream_drop(h->stream);
+ h->capturebuf = NULL;
+ h->capturelen = 0;
+ }
+
+ WaitForPulseOperation(h->mainloop, PULSEAUDIO_pa_stream_flush(h->stream, stream_operation_complete_no_op, NULL));
+}
+
static void
PULSEAUDIO_CloseDevice(_THIS)
{
- if (this->hidden != NULL) {
- SDL_FreeAudioMem(this->hidden->mixbuf);
- SDL_free(this->hidden->device_name);
- if (this->hidden->stream) {
- PULSEAUDIO_pa_stream_disconnect(this->hidden->stream);
- PULSEAUDIO_pa_stream_unref(this->hidden->stream);
+ if (this->hidden->stream) {
+ if (this->hidden->capturebuf != NULL) {
+ PULSEAUDIO_pa_stream_drop(this->hidden->stream);
}
- DisconnectFromPulseServer(this->hidden->mainloop, this->hidden->context);
- SDL_free(this->hidden);
- this->hidden = NULL;
+ PULSEAUDIO_pa_stream_disconnect(this->hidden->stream);
+ PULSEAUDIO_pa_stream_unref(this->hidden->stream);
+ }
+
+ DisconnectFromPulseServer(this->hidden->mainloop, this->hidden->context);
+ SDL_free(this->hidden->mixbuf);
+ SDL_free(this->hidden->device_name);
+ SDL_free(this->hidden);
+}
+
+static void
+SinkDeviceNameCallback(pa_context *c, const pa_sink_info *i, int is_last, void *data)
+{
+ if (i) {
+ char **devname = (char **) data;
+ *devname = SDL_strdup(i->name);
}
}
static void
-DeviceNameCallback(pa_context *c, const pa_sink_info *i, int is_last, void *data)
+SourceDeviceNameCallback(pa_context *c, const pa_source_info *i, int is_last, void *data)
{
if (i) {
char **devname = (char **) data;
@@ -411,7 +473,7 @@ DeviceNameCallback(pa_context *c, const pa_sink_info *i, int is_last, void *data
}
static SDL_bool
-FindDeviceName(struct SDL_PrivateAudioData *h, void *handle)
+FindDeviceName(struct SDL_PrivateAudioData *h, const int iscapture, void *handle)
{
const uint32_t idx = ((uint32_t) ((size_t) handle)) - 1;
@@ -419,7 +481,16 @@ FindDeviceName(struct SDL_PrivateAudioData *h, void *handle)
return SDL_TRUE;
}
- WaitForPulseOperation(h->mainloop, PULSEAUDIO_pa_context_get_sink_info_by_index(h->context, idx, DeviceNameCallback, &h->device_name));
+ if (iscapture) {
+ WaitForPulseOperation(h->mainloop,
+ PULSEAUDIO_pa_context_get_source_info_by_index(h->context, idx,
+ SourceDeviceNameCallback, &h->device_name));
+ } else {
+ WaitForPulseOperation(h->mainloop,
+ PULSEAUDIO_pa_context_get_sink_info_by_index(h->context, idx,
+ SinkDeviceNameCallback, &h->device_name));
+ }
+
return (h->device_name != NULL);
}
@@ -433,15 +504,15 @@ PULSEAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
pa_channel_map pacmap;
pa_stream_flags_t flags = 0;
int state = 0;
+ int rc = 0;
/* Initialize all variables that we clean on shutdown */
- this->hidden = (struct SDL_PrivateAudioData *)
+ h = this->hidden = (struct SDL_PrivateAudioData *)
SDL_malloc((sizeof *this->hidden));
if (this->hidden == NULL) {
return SDL_OutOfMemory();
}
- SDL_memset(this->hidden, 0, (sizeof *this->hidden));
- h = this->hidden;
+ SDL_zerop(this->hidden);
paspec.format = PA_SAMPLE_INVALID;
@@ -482,7 +553,6 @@ PULSEAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
}
}
if (paspec.format == PA_SAMPLE_INVALID) {
- PULSEAUDIO_CloseDevice(this);
return SDL_SetError("Couldn't find any hardware audio formats");
}
this->spec.format = test_format;
@@ -494,13 +564,14 @@ PULSEAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
SDL_CalculateAudioSpec(&this->spec);
/* Allocate mixing buffer */
- h->mixlen = this->spec.size;
- h->mixbuf = (Uint8 *) SDL_AllocAudioMem(h->mixlen);
- if (h->mixbuf == NULL) {
- PULSEAUDIO_CloseDevice(this);
- return SDL_OutOfMemory();
+ if (!iscapture) {
+ h->mixlen = this->spec.size;
+ h->mixbuf = (Uint8 *) SDL_malloc(h->mixlen);
+ if (h->mixbuf == NULL) {
+ return SDL_OutOfMemory();
+ }
+ SDL_memset(h->mixbuf, this->spec.silence, this->spec.size);
}
- SDL_memset(h->mixbuf, this->spec.silence, this->spec.size);
paspec.channels = this->spec.channels;
paspec.rate = this->spec.freq;
@@ -522,13 +593,11 @@ PULSEAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
#endif
if (ConnectToPulseServer(&h->mainloop, &h->context) < 0) {
- PULSEAUDIO_CloseDevice(this);
return SDL_SetError("Could not connect to PulseAudio server");
}
- if (!FindDeviceName(h, handle)) {
- PULSEAUDIO_CloseDevice(this);
- return SDL_SetError("Requested PulseAudio sink missing?");
+ if (!FindDeviceName(h, iscapture, handle)) {
+ return SDL_SetError("Requested PulseAudio sink/source missing?");
}
/* The SDL ALSA output hints us that we use Windows' channel mapping */
@@ -544,7 +613,6 @@ PULSEAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
);
if (h->stream == NULL) {
- PULSEAUDIO_CloseDevice(this);
return SDL_SetError("Could not set up PulseAudio stream");
}
@@ -554,20 +622,22 @@ PULSEAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
flags |= PA_STREAM_DONT_MOVE;
}
- if (PULSEAUDIO_pa_stream_connect_playback(h->stream, h->device_name, &paattr, flags,
- NULL, NULL) < 0) {
- PULSEAUDIO_CloseDevice(this);
+ if (iscapture) {
+ rc = PULSEAUDIO_pa_stream_connect_record(h->stream, h->device_name, &paattr, flags);
+ } else {
+ rc = PULSEAUDIO_pa_stream_connect_playback(h->stream, h->device_name, &paattr, flags, NULL, NULL);
+ }
+
+ if (rc < 0) {
return SDL_SetError("Could not connect PulseAudio stream");
}
do {
if (PULSEAUDIO_pa_mainloop_iterate(h->mainloop, 1, NULL) < 0) {
- PULSEAUDIO_CloseDevice(this);
return SDL_SetError("pa_mainloop_iterate() failed");
}
state = PULSEAUDIO_pa_stream_get_state(h->stream);
if (!PA_STREAM_IS_GOOD(state)) {
- PULSEAUDIO_CloseDevice(this);
return SDL_SetError("Could not connect PulseAudio stream");
}
} while (state != PA_STREAM_READY);
@@ -646,7 +716,7 @@ PULSEAUDIO_DetectDevices()
WaitForPulseOperation(hotplug_mainloop, PULSEAUDIO_pa_context_get_source_info_list(hotplug_context, SourceInfoCallback, NULL));
/* ok, we have a sane list, let's set up hotplug notifications now... */
- hotplug_thread = SDL_CreateThread(HotplugThread, "PulseHotplug", NULL);
+ hotplug_thread = SDL_CreateThreadInternal(HotplugThread, "PulseHotplug", 256 * 1024, NULL);
}
static void
@@ -684,8 +754,11 @@ PULSEAUDIO_Init(SDL_AudioDriverImpl * impl)
impl->WaitDevice = PULSEAUDIO_WaitDevice;
impl->GetDeviceBuf = PULSEAUDIO_GetDeviceBuf;
impl->CloseDevice = PULSEAUDIO_CloseDevice;
- impl->WaitDone = PULSEAUDIO_WaitDone;
impl->Deinitialize = PULSEAUDIO_Deinitialize;
+ impl->CaptureFromDevice = PULSEAUDIO_CaptureFromDevice;
+ impl->FlushCapture = PULSEAUDIO_FlushCapture;
+
+ impl->HasCaptureSupport = SDL_TRUE;
return 1; /* this audio target is available. */
}
diff --git a/Engine/lib/sdl/src/audio/pulseaudio/SDL_pulseaudio.h b/Engine/lib/sdl/src/audio/pulseaudio/SDL_pulseaudio.h
index c57ab7132..e12000f2a 100644
--- a/Engine/lib/sdl/src/audio/pulseaudio/SDL_pulseaudio.h
+++ b/Engine/lib/sdl/src/audio/pulseaudio/SDL_pulseaudio.h
@@ -42,6 +42,9 @@ struct SDL_PrivateAudioData
/* Raw mixing buffer */
Uint8 *mixbuf;
int mixlen;
+
+ const Uint8 *capturebuf;
+ int capturelen;
};
#endif /* _SDL_pulseaudio_h */
diff --git a/Engine/lib/sdl/src/audio/qsa/SDL_qsa_audio.c b/Engine/lib/sdl/src/audio/qsa/SDL_qsa_audio.c
index 1899ca6d9..149cad90a 100644
--- a/Engine/lib/sdl/src/audio/qsa/SDL_qsa_audio.c
+++ b/Engine/lib/sdl/src/audio/qsa/SDL_qsa_audio.c
@@ -45,7 +45,6 @@
#include "SDL_timer.h"
#include "SDL_audio.h"
-#include "../SDL_audiomem.h"
#include "../SDL_audio_c.h"
#include "SDL_qsa_audio.h"
@@ -138,8 +137,7 @@ QSA_ThreadInit(_THIS)
static void
QSA_InitAudioParams(snd_pcm_channel_params_t * cpars)
{
- SDL_memset(cpars, 0, sizeof(snd_pcm_channel_params_t));
-
+ SDL_zerop(cpars);
cpars->channel = SND_PCM_CHANNEL_PLAYBACK;
cpars->mode = SND_PCM_MODE_BLOCK;
cpars->start_mode = SND_PCM_START_DATA;
@@ -229,7 +227,7 @@ QSA_PlayDevice(_THIS)
int towrite;
void *pcmbuffer;
- if ((!this->enabled) || (!this->hidden)) {
+ if (!SDL_AtomicGet(&this->enabled) || !this->hidden) {
return;
}
@@ -262,7 +260,7 @@ QSA_PlayDevice(_THIS)
continue;
} else {
if ((errno == EINVAL) || (errno == EIO)) {
- SDL_memset(&cstatus, 0, sizeof(cstatus));
+ SDL_zero(cstatus);
if (!this->hidden->iscapture) {
cstatus.channel = SND_PCM_CHANNEL_PLAYBACK;
} else {
@@ -305,7 +303,7 @@ QSA_PlayDevice(_THIS)
towrite -= written;
pcmbuffer += written * this->spec.channels;
}
- } while ((towrite > 0) && (this->enabled));
+ } while ((towrite > 0) && SDL_AtomicGet(&this->enabled));
/* If we couldn't write, assume fatal error for now */
if (towrite != 0) {
@@ -322,27 +320,21 @@ QSA_GetDeviceBuf(_THIS)
static void
QSA_CloseDevice(_THIS)
{
- if (this->hidden != NULL) {
- if (this->hidden->audio_handle != NULL) {
- if (!this->hidden->iscapture) {
- /* Finish playing available samples */
- snd_pcm_plugin_flush(this->hidden->audio_handle,
- SND_PCM_CHANNEL_PLAYBACK);
- } else {
- /* Cancel unread samples during capture */
- snd_pcm_plugin_flush(this->hidden->audio_handle,
- SND_PCM_CHANNEL_CAPTURE);
- }
- snd_pcm_close(this->hidden->audio_handle);
- this->hidden->audio_handle = NULL;
+ if (this->hidden->audio_handle != NULL) {
+ if (!this->hidden->iscapture) {
+ /* Finish playing available samples */
+ snd_pcm_plugin_flush(this->hidden->audio_handle,
+ SND_PCM_CHANNEL_PLAYBACK);
+ } else {
+ /* Cancel unread samples during capture */
+ snd_pcm_plugin_flush(this->hidden->audio_handle,
+ SND_PCM_CHANNEL_CAPTURE);
}
-
- SDL_FreeAudioMem(this->hidden->pcm_buf);
- this->hidden->pcm_buf = NULL;
-
- SDL_free(this->hidden);
- this->hidden = NULL;
+ snd_pcm_close(this->hidden->audio_handle);
}
+
+ SDL_free(this->hidden->pcm_buf);
+ SDL_free(this->hidden);
}
static int
@@ -365,13 +357,13 @@ QSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
if (this->hidden == NULL) {
return SDL_OutOfMemory();
}
- SDL_memset(this->hidden, 0, sizeof(struct SDL_PrivateAudioData));
+ SDL_zerop(this->hidden);
/* Initialize channel transfer parameters to default */
QSA_InitAudioParams(&cparams);
/* Initialize channel direction: capture or playback */
- this->hidden->iscapture = iscapture;
+ this->hidden->iscapture = iscapture ? SDL_TRUE : SDL_FALSE;
if (device != NULL) {
/* Open requested audio device */
@@ -391,7 +383,6 @@ QSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
/* Check if requested device is opened */
if (status < 0) {
this->hidden->audio_handle = NULL;
- QSA_CloseDevice(this);
return QSA_SetError("snd_pcm_open", status);
}
@@ -401,7 +392,6 @@ QSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
snd_pcm_plugin_set_disable(this->hidden->audio_handle,
PLUGIN_DISABLE_MMAP);
if (status < 0) {
- QSA_CloseDevice(this);
return QSA_SetError("snd_pcm_plugin_set_disable", status);
}
}
@@ -487,7 +477,6 @@ QSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
/* assumes test_format not 0 on success */
if (test_format == 0) {
- QSA_CloseDevice(this);
return SDL_SetError("QSA: Couldn't find any hardware audio formats");
}
@@ -505,12 +494,11 @@ QSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
/* Setup the transfer parameters according to cparams */
status = snd_pcm_plugin_params(this->hidden->audio_handle, &cparams);
if (status < 0) {
- QSA_CloseDevice(this);
return QSA_SetError("snd_pcm_channel_params", status);
}
/* Make sure channel is setup right one last time */
- SDL_memset(&csetup, 0, sizeof(csetup));
+ SDL_zero(csetup);
if (!this->hidden->iscapture) {
csetup.channel = SND_PCM_CHANNEL_PLAYBACK;
} else {
@@ -519,7 +507,6 @@ QSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
/* Setup an audio channel */
if (snd_pcm_plugin_setup(this->hidden->audio_handle, &csetup) < 0) {
- QSA_CloseDevice(this);
return SDL_SetError("QSA: Unable to setup channel");
}
@@ -540,9 +527,8 @@ QSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
* closest multiple)
*/
this->hidden->pcm_buf =
- (Uint8 *) SDL_AllocAudioMem(this->hidden->pcm_len);
+ (Uint8 *) SDL_malloc(this->hidden->pcm_len);
if (this->hidden->pcm_buf == NULL) {
- QSA_CloseDevice(this);
return SDL_OutOfMemory();
}
SDL_memset(this->hidden->pcm_buf, this->spec.silence,
@@ -560,7 +546,6 @@ QSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
}
if (this->hidden->audio_fd < 0) {
- QSA_CloseDevice(this);
return QSA_SetError("snd_pcm_file_descriptor", status);
}
@@ -578,7 +563,6 @@ QSA_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
}
if (status < 0) {
- QSA_CloseDevice(this);
return QSA_SetError("snd_pcm_plugin_prepare", status);
}
@@ -724,32 +708,13 @@ QSA_DetectDevices(void)
}
}
-static void
-QSA_WaitDone(_THIS)
-{
- if (!this->hidden->iscapture) {
- if (this->hidden->audio_handle != NULL) {
- /* Wait till last fragment is played and stop channel */
- snd_pcm_plugin_flush(this->hidden->audio_handle,
- SND_PCM_CHANNEL_PLAYBACK);
- }
- } else {
- if (this->hidden->audio_handle != NULL) {
- /* Discard all unread data and stop channel */
- snd_pcm_plugin_flush(this->hidden->audio_handle,
- SND_PCM_CHANNEL_CAPTURE);
- }
- }
-}
-
static void
QSA_Deinitialize(void)
{
/* Clear devices array on shutdown */
- SDL_memset(qsa_playback_device, 0x00,
- sizeof(QSA_Device) * QSA_MAX_DEVICES);
- SDL_memset(qsa_capture_device, 0x00,
- sizeof(QSA_Device) * QSA_MAX_DEVICES);
+ /* !!! FIXME: we zero these on init...any reason to do it here? */
+ SDL_zero(qsa_playback_device);
+ SDL_zero(qsa_capture_device);
qsa_playback_devices = 0;
qsa_capture_devices = 0;
}
@@ -761,10 +726,8 @@ QSA_Init(SDL_AudioDriverImpl * impl)
int32_t status = 0;
/* Clear devices array */
- SDL_memset(qsa_playback_device, 0x00,
- sizeof(QSA_Device) * QSA_MAX_DEVICES);
- SDL_memset(qsa_capture_device, 0x00,
- sizeof(QSA_Device) * QSA_MAX_DEVICES);
+ SDL_zero(qsa_playback_device);
+ SDL_zero(qsa_capture_device);
qsa_playback_devices = 0;
qsa_capture_devices = 0;
@@ -778,7 +741,6 @@ QSA_Init(SDL_AudioDriverImpl * impl)
impl->PlayDevice = QSA_PlayDevice;
impl->GetDeviceBuf = QSA_GetDeviceBuf;
impl->CloseDevice = QSA_CloseDevice;
- impl->WaitDone = QSA_WaitDone;
impl->Deinitialize = QSA_Deinitialize;
impl->LockDevice = NULL;
impl->UnlockDevice = NULL;
@@ -788,7 +750,7 @@ QSA_Init(SDL_AudioDriverImpl * impl)
impl->SkipMixerLock = 0;
impl->HasCaptureSupport = 1;
impl->OnlyHasDefaultOutputDevice = 0;
- impl->OnlyHasDefaultInputDevice = 0;
+ impl->OnlyHasDefaultCaptureDevice = 0;
/* Check if io-audio manager is running or not */
status = snd_cards();
diff --git a/Engine/lib/sdl/src/audio/qsa/SDL_qsa_audio.h b/Engine/lib/sdl/src/audio/qsa/SDL_qsa_audio.h
index 53d37e96f..19a2215aa 100644
--- a/Engine/lib/sdl/src/audio/qsa/SDL_qsa_audio.h
+++ b/Engine/lib/sdl/src/audio/qsa/SDL_qsa_audio.h
@@ -34,7 +34,7 @@
struct SDL_PrivateAudioData
{
/* SDL capture state */
- int iscapture;
+ SDL_bool iscapture;
/* The audio device handle */
int cardno;
diff --git a/Engine/lib/sdl/src/audio/sdlgenaudiocvt.pl b/Engine/lib/sdl/src/audio/sdlgenaudiocvt.pl
old mode 100644
new mode 100755
diff --git a/Engine/lib/sdl/src/audio/sndio/SDL_sndioaudio.c b/Engine/lib/sdl/src/audio/sndio/SDL_sndioaudio.c
index 64565ae88..fb7d78ff1 100644
--- a/Engine/lib/sdl/src/audio/sndio/SDL_sndioaudio.c
+++ b/Engine/lib/sdl/src/audio/sndio/SDL_sndioaudio.c
@@ -36,7 +36,6 @@
#include
#include "SDL_audio.h"
-#include "../SDL_audiomem.h"
#include "../SDL_audio_c.h"
#include "SDL_sndioaudio.h"
@@ -171,25 +170,15 @@ SNDIO_GetDeviceBuf(_THIS)
return this->hidden->mixbuf;
}
-static void
-SNDIO_WaitDone(_THIS)
-{
- SNDIO_sio_stop(this->hidden->dev);
-}
-
static void
SNDIO_CloseDevice(_THIS)
{
- if (this->hidden != NULL) {
- SDL_FreeAudioMem(this->hidden->mixbuf);
- this->hidden->mixbuf = NULL;
- if ( this->hidden->dev != NULL ) {
- SNDIO_sio_close(this->hidden->dev);
- this->hidden->dev = NULL;
- }
- SDL_free(this->hidden);
- this->hidden = NULL;
+ if ( this->hidden->dev != NULL ) {
+ SNDIO_sio_stop(this->hidden->dev);
+ SNDIO_sio_close(this->hidden->dev);
}
+ SDL_free(this->hidden->mixbuf);
+ SDL_free(this->hidden);
}
static int
@@ -204,13 +193,12 @@ SNDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
if (this->hidden == NULL) {
return SDL_OutOfMemory();
}
- SDL_memset(this->hidden, 0, sizeof(*this->hidden));
+ SDL_zerop(this->hidden);
this->hidden->mixlen = this->spec.size;
/* !!! FIXME: SIO_DEVANY can be a specific device... */
if ((this->hidden->dev = SNDIO_sio_open(SIO_DEVANY, SIO_PLAY, 0)) == NULL) {
- SNDIO_CloseDevice(this);
return SDL_SetError("sio_open() failed");
}
@@ -233,7 +221,6 @@ SNDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
continue;
}
if (SNDIO_sio_getpar(this->hidden->dev, &par) == 0) {
- SNDIO_CloseDevice(this);
return SDL_SetError("sio_getpar() failed");
}
if (par.bps != SIO_BPS(par.bits)) {
@@ -248,7 +235,6 @@ SNDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
}
if (status < 0) {
- SNDIO_CloseDevice(this);
return SDL_SetError("sndio: Couldn't find any hardware audio formats");
}
@@ -269,7 +255,6 @@ SNDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
else if ((par.bps == 1) && (!par.sig))
this->spec.format = AUDIO_U8;
else {
- SNDIO_CloseDevice(this);
return SDL_SetError("sndio: Got unsupported hardware audio format.");
}
@@ -282,9 +267,8 @@ SNDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
/* Allocate mixing buffer */
this->hidden->mixlen = this->spec.size;
- this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
+ this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->hidden->mixlen);
if (this->hidden->mixbuf == NULL) {
- SNDIO_CloseDevice(this);
return SDL_OutOfMemory();
}
SDL_memset(this->hidden->mixbuf, this->spec.silence, this->hidden->mixlen);
@@ -315,7 +299,6 @@ SNDIO_Init(SDL_AudioDriverImpl * impl)
impl->WaitDevice = SNDIO_WaitDevice;
impl->PlayDevice = SNDIO_PlayDevice;
impl->GetDeviceBuf = SNDIO_GetDeviceBuf;
- impl->WaitDone = SNDIO_WaitDone;
impl->CloseDevice = SNDIO_CloseDevice;
impl->Deinitialize = SNDIO_Deinitialize;
impl->OnlyHasDefaultOutputDevice = 1; /* !!! FIXME: sndio can handle multiple devices. */
diff --git a/Engine/lib/sdl/src/audio/sun/SDL_sunaudio.c b/Engine/lib/sdl/src/audio/sun/SDL_sunaudio.c
index 71029d21f..b994c12c3 100644
--- a/Engine/lib/sdl/src/audio/sun/SDL_sunaudio.c
+++ b/Engine/lib/sdl/src/audio/sun/SDL_sunaudio.c
@@ -40,7 +40,6 @@
#include "SDL_timer.h"
#include "SDL_audio.h"
-#include "../SDL_audiomem.h"
#include "../SDL_audio_c.h"
#include "../SDL_audiodev_c.h"
#include "SDL_sunaudio.h"
@@ -183,18 +182,12 @@ SUNAUDIO_GetDeviceBuf(_THIS)
static void
SUNAUDIO_CloseDevice(_THIS)
{
- if (this->hidden != NULL) {
- SDL_FreeAudioMem(this->hidden->mixbuf);
- this->hidden->mixbuf = NULL;
- SDL_free(this->hidden->ulaw_buf);
- this->hidden->ulaw_buf = NULL;
- if (this->hidden->audio_fd >= 0) {
- close(this->hidden->audio_fd);
- this->hidden->audio_fd = -1;
- }
- SDL_free(this->hidden);
- this->hidden = NULL;
+ SDL_free(this->hidden->ulaw_buf);
+ if (this->hidden->audio_fd >= 0) {
+ close(this->hidden->audio_fd);
}
+ SDL_free(this->hidden->mixbuf);
+ SDL_free(this->hidden);
}
static int
@@ -219,7 +212,7 @@ SUNAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
if (this->hidden == NULL) {
return SDL_OutOfMemory();
}
- SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+ SDL_zerop(this->hidden);
/* Open the audio device */
this->hidden->audio_fd = open(devname, flags, 0);
@@ -340,7 +333,7 @@ SUNAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
SDL_CalculateAudioSpec(&this->spec);
/* Allocate mixing buffer */
- this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->spec.size);
+ this->hidden->mixbuf = (Uint8 *) SDL_malloc(this->spec.size);
if (this->hidden->mixbuf == NULL) {
return SDL_OutOfMemory();
}
diff --git a/Engine/lib/sdl/src/audio/winmm/SDL_winmm.c b/Engine/lib/sdl/src/audio/winmm/SDL_winmm.c
index 6d05a65ef..34f543ddb 100644
--- a/Engine/lib/sdl/src/audio/winmm/SDL_winmm.c
+++ b/Engine/lib/sdl/src/audio/winmm/SDL_winmm.c
@@ -27,6 +27,7 @@
#include "../../core/windows/SDL_windows.h"
#include
+#include "SDL_assert.h"
#include "SDL_timer.h"
#include "SDL_audio.h"
#include "../SDL_audio_c.h"
@@ -40,11 +41,11 @@
static void DetectWave##typ##Devs(void) { \
const UINT iscapture = iscap ? 1 : 0; \
const UINT devcount = wave##typ##GetNumDevs(); \
- capstyp caps; \
+ capstyp##2W caps; \
UINT i; \
for (i = 0; i < devcount; i++) { \
- if (wave##typ##GetDevCaps(i,&caps,sizeof(caps))==MMSYSERR_NOERROR) { \
- char *name = WIN_StringToUTF8(caps.szPname); \
+ if (wave##typ##GetDevCaps(i,(LP##capstyp##W)&caps,sizeof(caps))==MMSYSERR_NOERROR) { \
+ char *name = WIN_LookupAudioDeviceName(caps.szPname,&caps.NameGuid); \
if (name != NULL) { \
SDL_AddAudioDevice((int) iscapture, name, (void *) ((size_t) i+1)); \
SDL_free(name); \
@@ -134,63 +135,87 @@ WINMM_PlayDevice(_THIS)
this->hidden->next_buffer = (this->hidden->next_buffer + 1) % NUM_BUFFERS;
}
-static void
-WINMM_WaitDone(_THIS)
+static int
+WINMM_CaptureFromDevice(_THIS, void *buffer, int buflen)
{
- int i, left;
+ const int nextbuf = this->hidden->next_buffer;
+ MMRESULT result;
- do {
- left = NUM_BUFFERS;
- for (i = 0; i < NUM_BUFFERS; ++i) {
- if (this->hidden->wavebuf[i].dwFlags & WHDR_DONE) {
- --left;
- }
- }
- if (left > 0) {
- SDL_Delay(100);
- }
- } while (left > 0);
+ SDL_assert(buflen == this->spec.size);
+
+ /* Wait for an audio chunk to finish */
+ WaitForSingleObject(this->hidden->audio_sem, INFINITE);
+
+ /* Copy it to caller's buffer... */
+ SDL_memcpy(buffer, this->hidden->wavebuf[nextbuf].lpData, this->spec.size);
+
+ /* requeue the buffer that just finished. */
+ result = waveInAddBuffer(this->hidden->hin,
+ &this->hidden->wavebuf[nextbuf],
+ sizeof (this->hidden->wavebuf[nextbuf]));
+ if (result != MMSYSERR_NOERROR) {
+ return -1; /* uhoh! Disable the device. */
+ }
+
+ /* queue the next buffer in sequence, next time. */
+ this->hidden->next_buffer = (nextbuf + 1) % NUM_BUFFERS;
+ return this->spec.size;
+}
+
+static void
+WINMM_FlushCapture(_THIS)
+{
+ /* Wait for an audio chunk to finish */
+ if (WaitForSingleObject(this->hidden->audio_sem, 0) == WAIT_OBJECT_0) {
+ const int nextbuf = this->hidden->next_buffer;
+ /* requeue the buffer that just finished without reading from it. */
+ waveInAddBuffer(this->hidden->hin,
+ &this->hidden->wavebuf[nextbuf],
+ sizeof (this->hidden->wavebuf[nextbuf]));
+ this->hidden->next_buffer = (nextbuf + 1) % NUM_BUFFERS;
+ }
}
static void
WINMM_CloseDevice(_THIS)
{
- /* Close up audio */
- if (this->hidden != NULL) {
- int i;
+ int i;
- if (this->hidden->audio_sem) {
- CloseHandle(this->hidden->audio_sem);
- this->hidden->audio_sem = 0;
- }
+ if (this->hidden->hout) {
+ waveOutReset(this->hidden->hout);
/* Clean up mixing buffers */
for (i = 0; i < NUM_BUFFERS; ++i) {
if (this->hidden->wavebuf[i].dwUser != 0xFFFF) {
waveOutUnprepareHeader(this->hidden->hout,
&this->hidden->wavebuf[i],
- sizeof(this->hidden->wavebuf[i]));
- this->hidden->wavebuf[i].dwUser = 0xFFFF;
+ sizeof (this->hidden->wavebuf[i]));
}
}
- /* Free raw mixing buffer */
- SDL_free(this->hidden->mixbuf);
- this->hidden->mixbuf = NULL;
-
- if (this->hidden->hin) {
- waveInClose(this->hidden->hin);
- this->hidden->hin = 0;
- }
-
- if (this->hidden->hout) {
- waveOutClose(this->hidden->hout);
- this->hidden->hout = 0;
- }
-
- SDL_free(this->hidden);
- this->hidden = NULL;
+ waveOutClose(this->hidden->hout);
}
+
+ if (this->hidden->hin) {
+ waveInReset(this->hidden->hin);
+
+ /* Clean up mixing buffers */
+ for (i = 0; i < NUM_BUFFERS; ++i) {
+ if (this->hidden->wavebuf[i].dwUser != 0xFFFF) {
+ waveInUnprepareHeader(this->hidden->hin,
+ &this->hidden->wavebuf[i],
+ sizeof (this->hidden->wavebuf[i]));
+ }
+ }
+ waveInClose(this->hidden->hin);
+ }
+
+ if (this->hidden->audio_sem) {
+ CloseHandle(this->hidden->audio_sem);
+ }
+
+ SDL_free(this->hidden->mixbuf);
+ SDL_free(this->hidden);
}
static SDL_bool
@@ -239,7 +264,7 @@ WINMM_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
if (this->hidden == NULL) {
return SDL_OutOfMemory();
}
- SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+ SDL_zerop(this->hidden);
/* Initialize the wavebuf structures for closing */
for (i = 0; i < NUM_BUFFERS; ++i)
@@ -269,7 +294,6 @@ WINMM_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
}
if (!valid_datatype) {
- WINMM_CloseDevice(this);
return SDL_SetError("Unsupported audio format");
}
@@ -281,36 +305,45 @@ WINMM_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
result = waveInOpen(&this->hidden->hin, devId, &waveformat,
(DWORD_PTR) CaptureSound, (DWORD_PTR) this,
CALLBACK_FUNCTION);
+ if (result != MMSYSERR_NOERROR) {
+ return SetMMerror("waveInOpen()", result);
+ }
} else {
result = waveOutOpen(&this->hidden->hout, devId, &waveformat,
(DWORD_PTR) FillSound, (DWORD_PTR) this,
CALLBACK_FUNCTION);
+ if (result != MMSYSERR_NOERROR) {
+ return SetMMerror("waveOutOpen()", result);
+ }
}
- if (result != MMSYSERR_NOERROR) {
- WINMM_CloseDevice(this);
- return SetMMerror("waveOutOpen()", result);
- }
#ifdef SOUND_DEBUG
/* Check the sound device we retrieved */
{
- WAVEOUTCAPS caps;
-
- result = waveOutGetDevCaps((UINT) this->hidden->hout,
- &caps, sizeof(caps));
- if (result != MMSYSERR_NOERROR) {
- WINMM_CloseDevice(this);
- return SetMMerror("waveOutGetDevCaps()", result);
+ if (iscapture) {
+ WAVEINCAPS caps;
+ result = waveInGetDevCaps((UINT) this->hidden->hout,
+ &caps, sizeof (caps));
+ if (result != MMSYSERR_NOERROR) {
+ return SetMMerror("waveInGetDevCaps()", result);
+ }
+ printf("Audio device: %s\n", caps.szPname);
+ } else {
+ WAVEOUTCAPS caps;
+ result = waveOutGetDevCaps((UINT) this->hidden->hout,
+ &caps, sizeof(caps));
+ if (result != MMSYSERR_NOERROR) {
+ return SetMMerror("waveOutGetDevCaps()", result);
+ }
+ printf("Audio device: %s\n", caps.szPname);
}
- printf("Audio device: %s\n", caps.szPname);
}
#endif
/* Create the audio buffer semaphore */
this->hidden->audio_sem =
- CreateSemaphore(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
+ CreateSemaphore(NULL, iscapture ? 0 : NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
if (this->hidden->audio_sem == NULL) {
- WINMM_CloseDevice(this);
return SDL_SetError("Couldn't create semaphore");
}
@@ -318,22 +351,44 @@ WINMM_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
this->hidden->mixbuf =
(Uint8 *) SDL_malloc(NUM_BUFFERS * this->spec.size);
if (this->hidden->mixbuf == NULL) {
- WINMM_CloseDevice(this);
return SDL_OutOfMemory();
}
+
+ SDL_zero(this->hidden->wavebuf);
for (i = 0; i < NUM_BUFFERS; ++i) {
- SDL_memset(&this->hidden->wavebuf[i], 0,
- sizeof(this->hidden->wavebuf[i]));
this->hidden->wavebuf[i].dwBufferLength = this->spec.size;
this->hidden->wavebuf[i].dwFlags = WHDR_DONE;
this->hidden->wavebuf[i].lpData =
(LPSTR) & this->hidden->mixbuf[i * this->spec.size];
- result = waveOutPrepareHeader(this->hidden->hout,
- &this->hidden->wavebuf[i],
- sizeof(this->hidden->wavebuf[i]));
+
+ if (iscapture) {
+ result = waveInPrepareHeader(this->hidden->hin,
+ &this->hidden->wavebuf[i],
+ sizeof(this->hidden->wavebuf[i]));
+ if (result != MMSYSERR_NOERROR) {
+ return SetMMerror("waveInPrepareHeader()", result);
+ }
+
+ result = waveInAddBuffer(this->hidden->hin,
+ &this->hidden->wavebuf[i],
+ sizeof(this->hidden->wavebuf[i]));
+ if (result != MMSYSERR_NOERROR) {
+ return SetMMerror("waveInAddBuffer()", result);
+ }
+ } else {
+ result = waveOutPrepareHeader(this->hidden->hout,
+ &this->hidden->wavebuf[i],
+ sizeof(this->hidden->wavebuf[i]));
+ if (result != MMSYSERR_NOERROR) {
+ return SetMMerror("waveOutPrepareHeader()", result);
+ }
+ }
+ }
+
+ if (iscapture) {
+ result = waveInStart(this->hidden->hin);
if (result != MMSYSERR_NOERROR) {
- WINMM_CloseDevice(this);
- return SetMMerror("waveOutPrepareHeader()", result);
+ return SetMMerror("waveInStart()", result);
}
}
@@ -349,10 +404,13 @@ WINMM_Init(SDL_AudioDriverImpl * impl)
impl->OpenDevice = WINMM_OpenDevice;
impl->PlayDevice = WINMM_PlayDevice;
impl->WaitDevice = WINMM_WaitDevice;
- impl->WaitDone = WINMM_WaitDone;
impl->GetDeviceBuf = WINMM_GetDeviceBuf;
+ impl->CaptureFromDevice = WINMM_CaptureFromDevice;
+ impl->FlushCapture = WINMM_FlushCapture;
impl->CloseDevice = WINMM_CloseDevice;
+ impl->HasCaptureSupport = SDL_TRUE;
+
return 1; /* this audio target is available. */
}
diff --git a/Engine/lib/sdl/src/audio/xaudio2/SDL_xaudio2.c b/Engine/lib/sdl/src/audio/xaudio2/SDL_xaudio2.c
index dff234b40..a18e5d24e 100644
--- a/Engine/lib/sdl/src/audio/xaudio2/SDL_xaudio2.c
+++ b/Engine/lib/sdl/src/audio/xaudio2/SDL_xaudio2.c
@@ -195,7 +195,7 @@ XAUDIO2_PlayDevice(_THIS)
IXAudio2SourceVoice *source = this->hidden->source;
HRESULT result = S_OK;
- if (!this->enabled) { /* shutting down? */
+ if (!SDL_AtomicGet(&this->enabled)) { /* shutting down? */
return;
}
@@ -226,64 +226,47 @@ XAUDIO2_PlayDevice(_THIS)
static void
XAUDIO2_WaitDevice(_THIS)
{
- if (this->enabled) {
+ if (SDL_AtomicGet(&this->enabled)) {
SDL_SemWait(this->hidden->semaphore);
}
}
static void
-XAUDIO2_WaitDone(_THIS)
+XAUDIO2_PrepareToClose(_THIS)
{
IXAudio2SourceVoice *source = this->hidden->source;
- XAUDIO2_VOICE_STATE state;
- SDL_assert(!this->enabled); /* flag that stops playing. */
- IXAudio2SourceVoice_Discontinuity(source);
-#if SDL_XAUDIO2_WIN8
- IXAudio2SourceVoice_GetState(source, &state, XAUDIO2_VOICE_NOSAMPLESPLAYED);
-#else
- IXAudio2SourceVoice_GetState(source, &state);
-#endif
- while (state.BuffersQueued > 0) {
- SDL_SemWait(this->hidden->semaphore);
-#if SDL_XAUDIO2_WIN8
- IXAudio2SourceVoice_GetState(source, &state, XAUDIO2_VOICE_NOSAMPLESPLAYED);
-#else
- IXAudio2SourceVoice_GetState(source, &state);
-#endif
+ if (source) {
+ IXAudio2SourceVoice_Discontinuity(source);
}
}
-
static void
XAUDIO2_CloseDevice(_THIS)
{
- if (this->hidden != NULL) {
- IXAudio2 *ixa2 = this->hidden->ixa2;
- IXAudio2SourceVoice *source = this->hidden->source;
- IXAudio2MasteringVoice *mastering = this->hidden->mastering;
+ IXAudio2 *ixa2 = this->hidden->ixa2;
+ IXAudio2SourceVoice *source = this->hidden->source;
+ IXAudio2MasteringVoice *mastering = this->hidden->mastering;
- if (source != NULL) {
- IXAudio2SourceVoice_Stop(source, 0, XAUDIO2_COMMIT_NOW);
- IXAudio2SourceVoice_FlushSourceBuffers(source);
- IXAudio2SourceVoice_DestroyVoice(source);
- }
- if (ixa2 != NULL) {
- IXAudio2_StopEngine(ixa2);
- }
- if (mastering != NULL) {
- IXAudio2MasteringVoice_DestroyVoice(mastering);
- }
- if (ixa2 != NULL) {
- IXAudio2_Release(ixa2);
- }
- SDL_free(this->hidden->mixbuf);
- if (this->hidden->semaphore != NULL) {
- SDL_DestroySemaphore(this->hidden->semaphore);
- }
-
- SDL_free(this->hidden);
- this->hidden = NULL;
+ if (source != NULL) {
+ IXAudio2SourceVoice_Stop(source, 0, XAUDIO2_COMMIT_NOW);
+ IXAudio2SourceVoice_FlushSourceBuffers(source);
+ IXAudio2SourceVoice_DestroyVoice(source);
}
+ if (ixa2 != NULL) {
+ IXAudio2_StopEngine(ixa2);
+ }
+ if (mastering != NULL) {
+ IXAudio2MasteringVoice_DestroyVoice(mastering);
+ }
+ if (ixa2 != NULL) {
+ IXAudio2_Release(ixa2);
+ }
+ if (this->hidden->semaphore != NULL) {
+ SDL_DestroySemaphore(this->hidden->semaphore);
+ }
+
+ SDL_free(this->hidden->mixbuf);
+ SDL_free(this->hidden);
}
static int
@@ -345,12 +328,11 @@ XAUDIO2_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
IXAudio2_Release(ixa2);
return SDL_OutOfMemory();
}
- SDL_memset(this->hidden, 0, (sizeof *this->hidden));
+ SDL_zerop(this->hidden);
this->hidden->ixa2 = ixa2;
this->hidden->semaphore = SDL_CreateSemaphore(1);
if (this->hidden->semaphore == NULL) {
- XAUDIO2_CloseDevice(this);
return SDL_SetError("XAudio2: CreateSemaphore() failed!");
}
@@ -368,7 +350,6 @@ XAUDIO2_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
}
if (!valid_format) {
- XAUDIO2_CloseDevice(this);
return SDL_SetError("XAudio2: Unsupported audio format");
}
@@ -379,11 +360,10 @@ XAUDIO2_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
this->hidden->mixlen = this->spec.size;
this->hidden->mixbuf = (Uint8 *) SDL_malloc(2 * this->hidden->mixlen);
if (this->hidden->mixbuf == NULL) {
- XAUDIO2_CloseDevice(this);
return SDL_OutOfMemory();
}
this->hidden->nextbuf = this->hidden->mixbuf;
- SDL_memset(this->hidden->mixbuf, 0, 2 * this->hidden->mixlen);
+ SDL_memset(this->hidden->mixbuf, this->spec.silence, 2 * this->hidden->mixlen);
/* We use XAUDIO2_DEFAULT_CHANNELS instead of this->spec.channels. On
Xbox360, this means 5.1 output, but on Windows, it means "figure out
@@ -401,7 +381,6 @@ XAUDIO2_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
this->spec.freq, 0, devId, NULL);
#endif
if (result != S_OK) {
- XAUDIO2_CloseDevice(this);
return SDL_SetError("XAudio2: Couldn't create mastering voice");
}
@@ -436,7 +415,6 @@ XAUDIO2_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
#endif
if (result != S_OK) {
- XAUDIO2_CloseDevice(this);
return SDL_SetError("XAudio2: Couldn't create source voice");
}
this->hidden->source = source;
@@ -444,13 +422,11 @@ XAUDIO2_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
/* Start everything playing! */
result = IXAudio2_StartEngine(ixa2);
if (result != S_OK) {
- XAUDIO2_CloseDevice(this);
return SDL_SetError("XAudio2: Couldn't start engine");
}
result = IXAudio2SourceVoice_Start(source, 0, XAUDIO2_COMMIT_NOW);
if (result != S_OK) {
- XAUDIO2_CloseDevice(this);
return SDL_SetError("XAudio2: Couldn't start source voice");
}
@@ -499,7 +475,7 @@ XAUDIO2_Init(SDL_AudioDriverImpl * impl)
impl->OpenDevice = XAUDIO2_OpenDevice;
impl->PlayDevice = XAUDIO2_PlayDevice;
impl->WaitDevice = XAUDIO2_WaitDevice;
- impl->WaitDone = XAUDIO2_WaitDone;
+ impl->PrepareToClose = XAUDIO2_PrepareToClose;
impl->GetDeviceBuf = XAUDIO2_GetDeviceBuf;
impl->CloseDevice = XAUDIO2_CloseDevice;
impl->Deinitialize = XAUDIO2_Deinitialize;
diff --git a/Engine/lib/sdl/src/core/android/SDL_android.c b/Engine/lib/sdl/src/core/android/SDL_android.c
index f6e0a833c..b93b16255 100644
--- a/Engine/lib/sdl/src/core/android/SDL_android.c
+++ b/Engine/lib/sdl/src/core/android/SDL_android.c
@@ -71,10 +71,14 @@ static jclass mActivityClass;
/* method signatures */
static jmethodID midGetNativeSurface;
-static jmethodID midAudioInit;
+static jmethodID midAudioOpen;
static jmethodID midAudioWriteShortBuffer;
static jmethodID midAudioWriteByteBuffer;
-static jmethodID midAudioQuit;
+static jmethodID midAudioClose;
+static jmethodID midCaptureOpen;
+static jmethodID midCaptureReadShortBuffer;
+static jmethodID midCaptureReadByteBuffer;
+static jmethodID midCaptureClose;
static jmethodID midPollInputDevices;
/* Accelerometer data storage */
@@ -118,34 +122,45 @@ JNIEXPORT void JNICALL SDL_Android_Init(JNIEnv* mEnv, jclass cls)
midGetNativeSurface = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
"getNativeSurface","()Landroid/view/Surface;");
- midAudioInit = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
- "audioInit", "(IZZI)I");
+ midAudioOpen = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
+ "audioOpen", "(IZZI)I");
midAudioWriteShortBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
"audioWriteShortBuffer", "([S)V");
midAudioWriteByteBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
"audioWriteByteBuffer", "([B)V");
- midAudioQuit = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
- "audioQuit", "()V");
+ midAudioClose = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
+ "audioClose", "()V");
+ midCaptureOpen = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
+ "captureOpen", "(IZZI)I");
+ midCaptureReadShortBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
+ "captureReadShortBuffer", "([SZ)I");
+ midCaptureReadByteBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
+ "captureReadByteBuffer", "([BZ)I");
+ midCaptureClose = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
+ "captureClose", "()V");
midPollInputDevices = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
"pollInputDevices", "()V");
bHasNewData = SDL_FALSE;
- if (!midGetNativeSurface || !midAudioInit ||
- !midAudioWriteShortBuffer || !midAudioWriteByteBuffer || !midAudioQuit || !midPollInputDevices) {
+ if (!midGetNativeSurface ||
+ !midAudioOpen || !midAudioWriteShortBuffer || !midAudioWriteByteBuffer || !midAudioClose ||
+ !midCaptureOpen || !midCaptureReadShortBuffer || !midCaptureReadByteBuffer || !midCaptureClose ||
+ !midPollInputDevices) {
__android_log_print(ANDROID_LOG_WARN, "SDL", "SDL: Couldn't locate Java callbacks, check that they're named and typed correctly");
}
__android_log_print(ANDROID_LOG_INFO, "SDL", "SDL_Android_Init() finished!");
}
/* Drop file */
-void Java_org_libsdl_app_SDLActivity_onNativeDropFile(
+JNIEXPORT void JNICALL Java_org_libsdl_app_SDLActivity_onNativeDropFile(
JNIEnv* env, jclass jcls,
jstring filename)
{
const char *path = (*env)->GetStringUTFChars(env, filename, NULL);
- SDL_SendDropFile(path);
+ SDL_SendDropFile(NULL, path);
(*env)->ReleaseStringUTFChars(env, filename, path);
+ SDL_SendDropComplete(NULL);
}
/* Resize */
@@ -555,11 +570,15 @@ int Android_JNI_SetupThread(void)
static jboolean audioBuffer16Bit = JNI_FALSE;
static jobject audioBuffer = NULL;
static void* audioBufferPinned = NULL;
+static jboolean captureBuffer16Bit = JNI_FALSE;
+static jobject captureBuffer = NULL;
-int Android_JNI_OpenAudioDevice(int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames)
+int Android_JNI_OpenAudioDevice(int iscapture, int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames)
{
jboolean audioBufferStereo;
int audioBufferFrames;
+ jobject jbufobj = NULL;
+ jboolean isCopy;
JNIEnv *env = Android_JNI_GetEnv();
@@ -568,14 +587,24 @@ int Android_JNI_OpenAudioDevice(int sampleRate, int is16Bit, int channelCount, i
}
Android_JNI_SetupThread();
- __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device");
- audioBuffer16Bit = is16Bit;
audioBufferStereo = channelCount > 1;
- if ((*env)->CallStaticIntMethod(env, mActivityClass, midAudioInit, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames) != 0) {
- /* Error during audio initialization */
- __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: error on AudioTrack initialization!");
- return 0;
+ if (iscapture) {
+ __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device for capture");
+ captureBuffer16Bit = is16Bit;
+ if ((*env)->CallStaticIntMethod(env, mActivityClass, midCaptureOpen, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames) != 0) {
+ /* Error during audio initialization */
+ __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: error on AudioRecord initialization!");
+ return 0;
+ }
+ } else {
+ __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device for output");
+ audioBuffer16Bit = is16Bit;
+ if ((*env)->CallStaticIntMethod(env, mActivityClass, midAudioOpen, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames) != 0) {
+ /* Error during audio initialization */
+ __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: error on AudioTrack initialization!");
+ return 0;
+ }
}
/* Allocating the audio buffer from the Java side and passing it as the return value for audioInit no longer works on
@@ -584,31 +613,43 @@ int Android_JNI_OpenAudioDevice(int sampleRate, int is16Bit, int channelCount, i
if (is16Bit) {
jshortArray audioBufferLocal = (*env)->NewShortArray(env, desiredBufferFrames * (audioBufferStereo ? 2 : 1));
if (audioBufferLocal) {
- audioBuffer = (*env)->NewGlobalRef(env, audioBufferLocal);
+ jbufobj = (*env)->NewGlobalRef(env, audioBufferLocal);
(*env)->DeleteLocalRef(env, audioBufferLocal);
}
}
else {
jbyteArray audioBufferLocal = (*env)->NewByteArray(env, desiredBufferFrames * (audioBufferStereo ? 2 : 1));
if (audioBufferLocal) {
- audioBuffer = (*env)->NewGlobalRef(env, audioBufferLocal);
+ jbufobj = (*env)->NewGlobalRef(env, audioBufferLocal);
(*env)->DeleteLocalRef(env, audioBufferLocal);
}
}
- if (audioBuffer == NULL) {
+ if (jbufobj == NULL) {
__android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: could not allocate an audio buffer!");
return 0;
}
- jboolean isCopy = JNI_FALSE;
- if (audioBuffer16Bit) {
- audioBufferPinned = (*env)->GetShortArrayElements(env, (jshortArray)audioBuffer, &isCopy);
+ if (iscapture) {
+ captureBuffer = jbufobj;
+ } else {
+ audioBuffer = jbufobj;
+ }
+
+ isCopy = JNI_FALSE;
+
+ if (is16Bit) {
+ if (!iscapture) {
+ audioBufferPinned = (*env)->GetShortArrayElements(env, (jshortArray)audioBuffer, &isCopy);
+ }
audioBufferFrames = (*env)->GetArrayLength(env, (jshortArray)audioBuffer);
} else {
- audioBufferPinned = (*env)->GetByteArrayElements(env, (jbyteArray)audioBuffer, &isCopy);
+ if (!iscapture) {
+ audioBufferPinned = (*env)->GetByteArrayElements(env, (jbyteArray)audioBuffer, &isCopy);
+ }
audioBufferFrames = (*env)->GetArrayLength(env, (jbyteArray)audioBuffer);
}
+
if (audioBufferStereo) {
audioBufferFrames /= 2;
}
@@ -636,16 +677,71 @@ void Android_JNI_WriteAudioBuffer(void)
/* JNI_COMMIT means the changes are committed to the VM but the buffer remains pinned */
}
-void Android_JNI_CloseAudioDevice(void)
+int Android_JNI_CaptureAudioBuffer(void *buffer, int buflen)
+{
+ JNIEnv *env = Android_JNI_GetEnv();
+ jboolean isCopy = JNI_FALSE;
+ jint br;
+
+ if (captureBuffer16Bit) {
+ SDL_assert((*env)->GetArrayLength(env, (jshortArray)captureBuffer) == (buflen / 2));
+ br = (*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_TRUE);
+ if (br > 0) {
+ jshort *ptr = (*env)->GetShortArrayElements(env, (jshortArray)captureBuffer, &isCopy);
+ br *= 2;
+ SDL_memcpy(buffer, ptr, br);
+ (*env)->ReleaseShortArrayElements(env, (jshortArray)captureBuffer, (jshort *)ptr, JNI_ABORT);
+ }
+ } else {
+ SDL_assert((*env)->GetArrayLength(env, (jshortArray)captureBuffer) == buflen);
+ br = (*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_TRUE);
+ if (br > 0) {
+ jbyte *ptr = (*env)->GetByteArrayElements(env, (jbyteArray)captureBuffer, &isCopy);
+ SDL_memcpy(buffer, ptr, br);
+ (*env)->ReleaseByteArrayElements(env, (jbyteArray)captureBuffer, (jbyte *)ptr, JNI_ABORT);
+ }
+ }
+
+ return (int) br;
+}
+
+void Android_JNI_FlushCapturedAudio(void)
+{
+ JNIEnv *env = Android_JNI_GetEnv();
+ #if 0 /* !!! FIXME: this needs API 23, or it'll do blocking reads and never end. */
+ if (captureBuffer16Bit) {
+ const jint len = (*env)->GetArrayLength(env, (jshortArray)captureBuffer);
+ while ((*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_FALSE) == len) { /* spin */ }
+ } else {
+ const jint len = (*env)->GetArrayLength(env, (jbyteArray)captureBuffer);
+ while ((*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_FALSE) == len) { /* spin */ }
+ }
+ #else
+ if (captureBuffer16Bit) {
+ (*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadShortBuffer, (jshortArray)captureBuffer, JNI_FALSE);
+ } else {
+ (*env)->CallStaticIntMethod(env, mActivityClass, midCaptureReadByteBuffer, (jbyteArray)captureBuffer, JNI_FALSE);
+ }
+ #endif
+}
+
+void Android_JNI_CloseAudioDevice(const int iscapture)
{
JNIEnv *env = Android_JNI_GetEnv();
- (*env)->CallStaticVoidMethod(env, mActivityClass, midAudioQuit);
-
- if (audioBuffer) {
- (*env)->DeleteGlobalRef(env, audioBuffer);
- audioBuffer = NULL;
- audioBufferPinned = NULL;
+ if (iscapture) {
+ (*env)->CallStaticVoidMethod(env, mActivityClass, midCaptureClose);
+ if (captureBuffer) {
+ (*env)->DeleteGlobalRef(env, captureBuffer);
+ captureBuffer = NULL;
+ }
+ } else {
+ (*env)->CallStaticVoidMethod(env, mActivityClass, midAudioClose);
+ if (audioBuffer) {
+ (*env)->DeleteGlobalRef(env, audioBuffer);
+ audioBuffer = NULL;
+ audioBufferPinned = NULL;
+ }
}
}
@@ -653,10 +749,12 @@ void Android_JNI_CloseAudioDevice(void)
/* If the parameter silent is truthy then SDL_SetError() will not be called. */
static SDL_bool Android_JNI_ExceptionOccurred(SDL_bool silent)
{
- SDL_assert(LocalReferenceHolder_IsActive());
JNIEnv *mEnv = Android_JNI_GetEnv();
+ jthrowable exception;
- jthrowable exception = (*mEnv)->ExceptionOccurred(mEnv);
+ SDL_assert(LocalReferenceHolder_IsActive());
+
+ exception = (*mEnv)->ExceptionOccurred(mEnv);
if (exception != NULL) {
jmethodID mid;
@@ -666,13 +764,16 @@ static SDL_bool Android_JNI_ExceptionOccurred(SDL_bool silent)
if (!silent) {
jclass exceptionClass = (*mEnv)->GetObjectClass(mEnv, exception);
jclass classClass = (*mEnv)->FindClass(mEnv, "java/lang/Class");
+ jstring exceptionName;
+ const char* exceptionNameUTF8;
+ jstring exceptionMessage;
mid = (*mEnv)->GetMethodID(mEnv, classClass, "getName", "()Ljava/lang/String;");
- jstring exceptionName = (jstring)(*mEnv)->CallObjectMethod(mEnv, exceptionClass, mid);
- const char* exceptionNameUTF8 = (*mEnv)->GetStringUTFChars(mEnv, exceptionName, 0);
+ exceptionName = (jstring)(*mEnv)->CallObjectMethod(mEnv, exceptionClass, mid);
+ exceptionNameUTF8 = (*mEnv)->GetStringUTFChars(mEnv, exceptionName, 0);
mid = (*mEnv)->GetMethodID(mEnv, exceptionClass, "getMessage", "()Ljava/lang/String;");
- jstring exceptionMessage = (jstring)(*mEnv)->CallObjectMethod(mEnv, exception, mid);
+ exceptionMessage = (jstring)(*mEnv)->CallObjectMethod(mEnv, exception, mid);
if (exceptionMessage != NULL) {
const char* exceptionMessageUTF8 = (*mEnv)->GetStringUTFChars(mEnv, exceptionMessage, 0);
@@ -855,6 +956,7 @@ int Android_JNI_FileOpen(SDL_RWops* ctx,
struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
JNIEnv *mEnv = Android_JNI_GetEnv();
int retval;
+ jstring fileNameJString;
if (!LocalReferenceHolder_Init(&refs, mEnv)) {
LocalReferenceHolder_Cleanup(&refs);
@@ -866,7 +968,7 @@ int Android_JNI_FileOpen(SDL_RWops* ctx,
return -1;
}
- jstring fileNameJString = (*mEnv)->NewStringUTF(mEnv, fileName);
+ fileNameJString = (*mEnv)->NewStringUTF(mEnv, fileName);
ctx->hidden.androidio.fileNameRef = (*mEnv)->NewGlobalRef(mEnv, fileNameJString);
ctx->hidden.androidio.inputStreamRef = NULL;
ctx->hidden.androidio.readableByteChannelRef = NULL;
@@ -885,10 +987,11 @@ size_t Android_JNI_FileRead(SDL_RWops* ctx, void* buffer,
if (ctx->hidden.androidio.assetFileDescriptorRef) {
size_t bytesMax = size * maxnum;
+ size_t result;
if (ctx->hidden.androidio.size != -1 /* UNKNOWN_LENGTH */ && ctx->hidden.androidio.position + bytesMax > ctx->hidden.androidio.size) {
bytesMax = ctx->hidden.androidio.size - ctx->hidden.androidio.position;
}
- size_t result = read(ctx->hidden.androidio.fd, buffer, bytesMax );
+ result = read(ctx->hidden.androidio.fd, buffer, bytesMax );
if (result > 0) {
ctx->hidden.androidio.position += result;
LocalReferenceHolder_Cleanup(&refs);
@@ -900,19 +1003,23 @@ size_t Android_JNI_FileRead(SDL_RWops* ctx, void* buffer,
jlong bytesRemaining = (jlong) (size * maxnum);
jlong bytesMax = (jlong) (ctx->hidden.androidio.size - ctx->hidden.androidio.position);
int bytesRead = 0;
+ JNIEnv *mEnv;
+ jobject readableByteChannel;
+ jmethodID readMethod;
+ jobject byteBuffer;
/* Don't read more bytes than those that remain in the file, otherwise we get an exception */
if (bytesRemaining > bytesMax) bytesRemaining = bytesMax;
- JNIEnv *mEnv = Android_JNI_GetEnv();
+ mEnv = Android_JNI_GetEnv();
if (!LocalReferenceHolder_Init(&refs, mEnv)) {
LocalReferenceHolder_Cleanup(&refs);
return 0;
}
- jobject readableByteChannel = (jobject)ctx->hidden.androidio.readableByteChannelRef;
- jmethodID readMethod = (jmethodID)ctx->hidden.androidio.readMethod;
- jobject byteBuffer = (*mEnv)->NewDirectByteBuffer(mEnv, buffer, bytesRemaining);
+ readableByteChannel = (jobject)ctx->hidden.androidio.readableByteChannelRef;
+ readMethod = (jmethodID)ctx->hidden.androidio.readMethod;
+ byteBuffer = (*mEnv)->NewDirectByteBuffer(mEnv, buffer, bytesRemaining);
while (bytesRemaining > 0) {
/* result = readableByteChannel.read(...); */
@@ -1002,6 +1109,7 @@ Sint64 Android_JNI_FileSize(SDL_RWops* ctx)
Sint64 Android_JNI_FileSeek(SDL_RWops* ctx, Sint64 offset, int whence)
{
if (ctx->hidden.androidio.assetFileDescriptorRef) {
+ off_t ret;
switch (whence) {
case RW_SEEK_SET:
if (ctx->hidden.androidio.size != -1 /* UNKNOWN_LENGTH */ && offset > ctx->hidden.androidio.size) offset = ctx->hidden.androidio.size;
@@ -1020,11 +1128,12 @@ Sint64 Android_JNI_FileSeek(SDL_RWops* ctx, Sint64 offset, int whence)
}
whence = SEEK_SET;
- off_t ret = lseek(ctx->hidden.androidio.fd, (off_t)offset, SEEK_SET);
+ ret = lseek(ctx->hidden.androidio.fd, (off_t)offset, SEEK_SET);
if (ret == -1) return -1;
ctx->hidden.androidio.position = ret - ctx->hidden.androidio.offset;
} else {
Sint64 newPosition;
+ Sint64 movement;
switch (whence) {
case RW_SEEK_SET:
@@ -1048,17 +1157,18 @@ Sint64 Android_JNI_FileSeek(SDL_RWops* ctx, Sint64 offset, int whence)
newPosition = ctx->hidden.androidio.size;
}
- Sint64 movement = newPosition - ctx->hidden.androidio.position;
+ movement = newPosition - ctx->hidden.androidio.position;
if (movement > 0) {
unsigned char buffer[4096];
/* The easy case where we're seeking forwards */
while (movement > 0) {
Sint64 amount = sizeof (buffer);
+ size_t result;
if (amount > movement) {
amount = movement;
}
- size_t result = Android_JNI_FileRead(ctx, buffer, 1, amount);
+ result = Android_JNI_FileRead(ctx, buffer, 1, amount);
if (result <= 0) {
/* Failed to read/skip the required amount, so fail */
return -1;
@@ -1091,21 +1201,23 @@ static jobject Android_JNI_GetSystemServiceObject(const char* name)
struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
JNIEnv* env = Android_JNI_GetEnv();
jobject retval = NULL;
+ jstring service;
+ jmethodID mid;
+ jobject context;
+ jobject manager;
if (!LocalReferenceHolder_Init(&refs, env)) {
LocalReferenceHolder_Cleanup(&refs);
return NULL;
}
- jstring service = (*env)->NewStringUTF(env, name);
-
- jmethodID mid;
+ service = (*env)->NewStringUTF(env, name);
mid = (*env)->GetStaticMethodID(env, mActivityClass, "getContext", "()Landroid/content/Context;");
- jobject context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
+ context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
mid = (*env)->GetMethodID(env, mActivityClass, "getSystemServiceFromUiThread", "(Ljava/lang/String;)Ljava/lang/Object;");
- jobject manager = (*env)->CallObjectMethod(env, context, mid, service);
+ manager = (*env)->CallObjectMethod(env, context, mid, service);
(*env)->DeleteLocalRef(env, service);
@@ -1117,11 +1229,12 @@ static jobject Android_JNI_GetSystemServiceObject(const char* name)
#define SETUP_CLIPBOARD(error) \
struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__); \
JNIEnv* env = Android_JNI_GetEnv(); \
+ jobject clipboard; \
if (!LocalReferenceHolder_Init(&refs, env)) { \
LocalReferenceHolder_Cleanup(&refs); \
return error; \
} \
- jobject clipboard = Android_JNI_GetSystemServiceObject("clipboard"); \
+ clipboard = Android_JNI_GetSystemServiceObject("clipboard"); \
if (!clipboard) { \
LocalReferenceHolder_Cleanup(&refs); \
return error; \
@@ -1132,14 +1245,17 @@ static jobject Android_JNI_GetSystemServiceObject(const char* name)
int Android_JNI_SetClipboardText(const char* text)
{
+ /* Watch out for C89 scoping rules because of the macro */
SETUP_CLIPBOARD(-1)
- jmethodID mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, clipboard), "setText", "(Ljava/lang/CharSequence;)V");
- jstring string = (*env)->NewStringUTF(env, text);
- (*env)->CallVoidMethod(env, clipboard, mid, string);
- (*env)->DeleteGlobalRef(env, clipboard);
- (*env)->DeleteLocalRef(env, string);
-
+ /* Nest the following in a scope to avoid C89 declaration rules triggered by the macro */
+ {
+ jmethodID mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, clipboard), "setText", "(Ljava/lang/CharSequence;)V");
+ jstring string = (*env)->NewStringUTF(env, text);
+ (*env)->CallVoidMethod(env, clipboard, mid, string);
+ (*env)->DeleteGlobalRef(env, clipboard);
+ (*env)->DeleteLocalRef(env, string);
+ }
CLEANUP_CLIPBOARD();
return 0;
@@ -1147,25 +1263,30 @@ int Android_JNI_SetClipboardText(const char* text)
char* Android_JNI_GetClipboardText(void)
{
+ /* Watch out for C89 scoping rules because of the macro */
SETUP_CLIPBOARD(SDL_strdup(""))
- jmethodID mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, clipboard), "getText", "()Ljava/lang/CharSequence;");
- jobject sequence = (*env)->CallObjectMethod(env, clipboard, mid);
- (*env)->DeleteGlobalRef(env, clipboard);
- if (sequence) {
- mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, sequence), "toString", "()Ljava/lang/String;");
- jstring string = (jstring)((*env)->CallObjectMethod(env, sequence, mid));
- const char* utf = (*env)->GetStringUTFChars(env, string, 0);
- if (utf) {
- char* text = SDL_strdup(utf);
- (*env)->ReleaseStringUTFChars(env, string, utf);
+ /* Nest the following in a scope to avoid C89 declaration rules triggered by the macro */
+ {
+ jmethodID mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, clipboard), "getText", "()Ljava/lang/CharSequence;");
+ jobject sequence = (*env)->CallObjectMethod(env, clipboard, mid);
+ (*env)->DeleteGlobalRef(env, clipboard);
+ if (sequence) {
+ jstring string;
+ const char* utf;
+ mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, sequence), "toString", "()Ljava/lang/String;");
+ string = (jstring)((*env)->CallObjectMethod(env, sequence, mid));
+ utf = (*env)->GetStringUTFChars(env, string, 0);
+ if (utf) {
+ char* text = SDL_strdup(utf);
+ (*env)->ReleaseStringUTFChars(env, string, utf);
- CLEANUP_CLIPBOARD();
+ CLEANUP_CLIPBOARD();
- return text;
+ return text;
+ }
}
}
-
CLEANUP_CLIPBOARD();
return SDL_strdup("");
@@ -1173,10 +1294,13 @@ char* Android_JNI_GetClipboardText(void)
SDL_bool Android_JNI_HasClipboardText(void)
{
+ jmethodID mid;
+ jboolean has;
+ /* Watch out for C89 scoping rules because of the macro */
SETUP_CLIPBOARD(SDL_FALSE)
- jmethodID mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, clipboard), "hasText", "()Z");
- jboolean has = (*env)->CallBooleanMethod(env, clipboard, mid);
+ mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, clipboard), "hasText", "()Z");
+ has = (*env)->CallBooleanMethod(env, clipboard, mid);
(*env)->DeleteGlobalRef(env, clipboard);
CLEANUP_CLIPBOARD();
@@ -1193,49 +1317,61 @@ int Android_JNI_GetPowerInfo(int* plugged, int* charged, int* battery, int* seco
{
struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
JNIEnv* env = Android_JNI_GetEnv();
+ jmethodID mid;
+ jobject context;
+ jstring action;
+ jclass cls;
+ jobject filter;
+ jobject intent;
+ jstring iname;
+ jmethodID imid;
+ jstring bname;
+ jmethodID bmid;
if (!LocalReferenceHolder_Init(&refs, env)) {
LocalReferenceHolder_Cleanup(&refs);
return -1;
}
- jmethodID mid;
mid = (*env)->GetStaticMethodID(env, mActivityClass, "getContext", "()Landroid/content/Context;");
- jobject context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
+ context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
- jstring action = (*env)->NewStringUTF(env, "android.intent.action.BATTERY_CHANGED");
+ action = (*env)->NewStringUTF(env, "android.intent.action.BATTERY_CHANGED");
- jclass cls = (*env)->FindClass(env, "android/content/IntentFilter");
+ cls = (*env)->FindClass(env, "android/content/IntentFilter");
mid = (*env)->GetMethodID(env, cls, "", "(Ljava/lang/String;)V");
- jobject filter = (*env)->NewObject(env, cls, mid, action);
+ filter = (*env)->NewObject(env, cls, mid, action);
(*env)->DeleteLocalRef(env, action);
mid = (*env)->GetMethodID(env, mActivityClass, "registerReceiver", "(Landroid/content/BroadcastReceiver;Landroid/content/IntentFilter;)Landroid/content/Intent;");
- jobject intent = (*env)->CallObjectMethod(env, context, mid, NULL, filter);
+ intent = (*env)->CallObjectMethod(env, context, mid, NULL, filter);
(*env)->DeleteLocalRef(env, filter);
cls = (*env)->GetObjectClass(env, intent);
- jstring iname;
- jmethodID imid = (*env)->GetMethodID(env, cls, "getIntExtra", "(Ljava/lang/String;I)I");
+ imid = (*env)->GetMethodID(env, cls, "getIntExtra", "(Ljava/lang/String;I)I");
+ /* Watch out for C89 scoping rules because of the macro */
#define GET_INT_EXTRA(var, key) \
+ int var; \
iname = (*env)->NewStringUTF(env, key); \
- int var = (*env)->CallIntMethod(env, intent, imid, iname, -1); \
+ var = (*env)->CallIntMethod(env, intent, imid, iname, -1); \
(*env)->DeleteLocalRef(env, iname);
- jstring bname;
- jmethodID bmid = (*env)->GetMethodID(env, cls, "getBooleanExtra", "(Ljava/lang/String;Z)Z");
+ bmid = (*env)->GetMethodID(env, cls, "getBooleanExtra", "(Ljava/lang/String;Z)Z");
+ /* Watch out for C89 scoping rules because of the macro */
#define GET_BOOL_EXTRA(var, key) \
+ int var; \
bname = (*env)->NewStringUTF(env, key); \
- int var = (*env)->CallBooleanMethod(env, intent, bmid, bname, JNI_FALSE); \
+ var = (*env)->CallBooleanMethod(env, intent, bmid, bname, JNI_FALSE); \
(*env)->DeleteLocalRef(env, bname);
if (plugged) {
+ /* Watch out for C89 scoping rules because of the macro */
GET_INT_EXTRA(plug, "plugged") /* == BatteryManager.EXTRA_PLUGGED (API 5) */
if (plug == -1) {
LocalReferenceHolder_Cleanup(&refs);
@@ -1247,6 +1383,7 @@ int Android_JNI_GetPowerInfo(int* plugged, int* charged, int* battery, int* seco
}
if (charged) {
+ /* Watch out for C89 scoping rules because of the macro */
GET_INT_EXTRA(status, "status") /* == BatteryManager.EXTRA_STATUS (API 5) */
if (status == -1) {
LocalReferenceHolder_Cleanup(&refs);
@@ -1266,8 +1403,20 @@ int Android_JNI_GetPowerInfo(int* plugged, int* charged, int* battery, int* seco
}
if (percent) {
- GET_INT_EXTRA(level, "level") /* == BatteryManager.EXTRA_LEVEL (API 5) */
- GET_INT_EXTRA(scale, "scale") /* == BatteryManager.EXTRA_SCALE (API 5) */
+ int level;
+ int scale;
+
+ /* Watch out for C89 scoping rules because of the macro */
+ {
+ GET_INT_EXTRA(level_temp, "level") /* == BatteryManager.EXTRA_LEVEL (API 5) */
+ level = level_temp;
+ }
+ /* Watch out for C89 scoping rules because of the macro */
+ {
+ GET_INT_EXTRA(scale_temp, "scale") /* == BatteryManager.EXTRA_SCALE (API 5) */
+ scale = scale_temp;
+ }
+
if ((level == -1) || (scale == -1)) {
LocalReferenceHolder_Cleanup(&refs);
return -1;
@@ -1320,14 +1469,16 @@ void Android_JNI_PollInputDevices(void)
int Android_JNI_SendMessage(int command, int param)
{
JNIEnv *env = Android_JNI_GetEnv();
+ jmethodID mid;
+ jboolean success;
if (!env) {
return -1;
}
- jmethodID mid = (*env)->GetStaticMethodID(env, mActivityClass, "sendMessage", "(II)Z");
+ mid = (*env)->GetStaticMethodID(env, mActivityClass, "sendMessage", "(II)Z");
if (!mid) {
return -1;
}
- jboolean success = (*env)->CallStaticBooleanMethod(env, mActivityClass, mid, command, param);
+ success = (*env)->CallStaticBooleanMethod(env, mActivityClass, mid, command, param);
return success ? 0 : -1;
}
@@ -1339,11 +1490,12 @@ void Android_JNI_SuspendScreenSaver(SDL_bool suspend)
void Android_JNI_ShowTextInput(SDL_Rect *inputRect)
{
JNIEnv *env = Android_JNI_GetEnv();
+ jmethodID mid;
if (!env) {
return;
}
- jmethodID mid = (*env)->GetStaticMethodID(env, mActivityClass, "showTextInput", "(IIII)Z");
+ mid = (*env)->GetStaticMethodID(env, mActivityClass, "showTextInput", "(IIII)Z");
if (!mid) {
return;
}
diff --git a/Engine/lib/sdl/src/core/android/SDL_android.h b/Engine/lib/sdl/src/core/android/SDL_android.h
index 8e2ab93c3..cb7ff0736 100644
--- a/Engine/lib/sdl/src/core/android/SDL_android.h
+++ b/Engine/lib/sdl/src/core/android/SDL_android.h
@@ -40,10 +40,12 @@ extern void Android_JNI_HideTextInput(void);
extern ANativeWindow* Android_JNI_GetNativeWindow(void);
/* Audio support */
-extern int Android_JNI_OpenAudioDevice(int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames);
+extern int Android_JNI_OpenAudioDevice(int iscapture, int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames);
extern void* Android_JNI_GetAudioBuffer(void);
extern void Android_JNI_WriteAudioBuffer(void);
-extern void Android_JNI_CloseAudioDevice(void);
+extern int Android_JNI_CaptureAudioBuffer(void *buffer, int buflen);
+extern void Android_JNI_FlushCapturedAudio(void);
+extern void Android_JNI_CloseAudioDevice(const int iscapture);
#include "SDL_rwops.h"
diff --git a/Engine/lib/sdl/src/core/linux/SDL_dbus.c b/Engine/lib/sdl/src/core/linux/SDL_dbus.c
index 5d0df050c..ab73ca17c 100644
--- a/Engine/lib/sdl/src/core/linux/SDL_dbus.c
+++ b/Engine/lib/sdl/src/core/linux/SDL_dbus.c
@@ -27,7 +27,7 @@
static const char *dbus_library = "libdbus-1.so.3";
static void *dbus_handle = NULL;
static unsigned int screensaver_cookie = 0;
-static SDL_DBusContext dbus = {0};
+static SDL_DBusContext dbus;
static int
LoadDBUSSyms(void)
diff --git a/Engine/lib/sdl/src/core/linux/SDL_evdev.c b/Engine/lib/sdl/src/core/linux/SDL_evdev.c
index a8f2b138e..4761f3e46 100644
--- a/Engine/lib/sdl/src/core/linux/SDL_evdev.c
+++ b/Engine/lib/sdl/src/core/linux/SDL_evdev.c
@@ -29,10 +29,7 @@
* The evtest application is also useful to debug the protocol
*/
-
#include "SDL_evdev.h"
-#define _THIS SDL_EVDEV_PrivateData *_this
-static _THIS = NULL;
#include
#include
@@ -43,18 +40,8 @@ static _THIS = NULL;
#ifdef SDL_INPUT_LINUXKD
#include
#include
-#endif
-
-
-/* We need this to prevent keystrokes from appear in the console */
-#ifndef KDSKBMUTE
-#define KDSKBMUTE 0x4B51
-#endif
-#ifndef KDSKBMODE
-#define KDSKBMODE 0x4B45
-#endif
-#ifndef K_OFF
-#define K_OFF 0x04
+#include
+#include /* for TIOCL_GETSHIFTSTATE */
#endif
#include "SDL.h"
@@ -63,273 +50,71 @@ static _THIS = NULL;
#include "../../core/linux/SDL_udev.h"
#include "SDL_scancode.h"
#include "../../events/SDL_events_c.h"
+#include "../../events/scancodes_linux.h" /* adds linux_scancode_table */
/* This isn't defined in older Linux kernel headers */
#ifndef SYN_DROPPED
#define SYN_DROPPED 3
#endif
+typedef struct SDL_evdevlist_item
+{
+ char *path;
+ int fd;
+
+ /* TODO: use this for every device, not just touchscreen */
+ int out_of_sync;
+
+ /* TODO: expand on this to have data for every possible class (mouse,
+ keyboard, touchpad, etc.). Also there's probably some things in here we
+ can pull out to the SDL_evdevlist_item i.e. name */
+ int is_touchscreen;
+ struct {
+ char* name;
+
+ int min_x, max_x, range_x;
+ int min_y, max_y, range_y;
+
+ int max_slots;
+ int current_slot;
+ struct {
+ enum {
+ EVDEV_TOUCH_SLOTDELTA_NONE = 0,
+ EVDEV_TOUCH_SLOTDELTA_DOWN,
+ EVDEV_TOUCH_SLOTDELTA_UP,
+ EVDEV_TOUCH_SLOTDELTA_MOVE
+ } delta;
+ int tracking_id;
+ int x, y;
+ } * slots;
+ } * touchscreen_data;
+
+ struct SDL_evdevlist_item *next;
+} SDL_evdevlist_item;
+
+typedef struct SDL_EVDEV_PrivateData
+{
+ SDL_evdevlist_item *first;
+ SDL_evdevlist_item *last;
+ int num_devices;
+ int ref_count;
+ int console_fd;
+ int kb_mode;
+} SDL_EVDEV_PrivateData;
+
+#define _THIS SDL_EVDEV_PrivateData *_this
+static _THIS = NULL;
+
static SDL_Scancode SDL_EVDEV_translate_keycode(int keycode);
static void SDL_EVDEV_sync_device(SDL_evdevlist_item *item);
-static int SDL_EVDEV_device_removed(const char *devpath);
+static int SDL_EVDEV_device_removed(const char *dev_path);
#if SDL_USE_LIBUDEV
-static int SDL_EVDEV_device_added(const char *devpath);
-void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath);
+static int SDL_EVDEV_device_added(const char *dev_path, int udev_class);
+void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class,
+ const char *dev_path);
#endif /* SDL_USE_LIBUDEV */
-static SDL_Scancode EVDEV_Keycodes[] = {
- SDL_SCANCODE_UNKNOWN, /* KEY_RESERVED 0 */
- SDL_SCANCODE_ESCAPE, /* KEY_ESC 1 */
- SDL_SCANCODE_1, /* KEY_1 2 */
- SDL_SCANCODE_2, /* KEY_2 3 */
- SDL_SCANCODE_3, /* KEY_3 4 */
- SDL_SCANCODE_4, /* KEY_4 5 */
- SDL_SCANCODE_5, /* KEY_5 6 */
- SDL_SCANCODE_6, /* KEY_6 7 */
- SDL_SCANCODE_7, /* KEY_7 8 */
- SDL_SCANCODE_8, /* KEY_8 9 */
- SDL_SCANCODE_9, /* KEY_9 10 */
- SDL_SCANCODE_0, /* KEY_0 11 */
- SDL_SCANCODE_MINUS, /* KEY_MINUS 12 */
- SDL_SCANCODE_EQUALS, /* KEY_EQUAL 13 */
- SDL_SCANCODE_BACKSPACE, /* KEY_BACKSPACE 14 */
- SDL_SCANCODE_TAB, /* KEY_TAB 15 */
- SDL_SCANCODE_Q, /* KEY_Q 16 */
- SDL_SCANCODE_W, /* KEY_W 17 */
- SDL_SCANCODE_E, /* KEY_E 18 */
- SDL_SCANCODE_R, /* KEY_R 19 */
- SDL_SCANCODE_T, /* KEY_T 20 */
- SDL_SCANCODE_Y, /* KEY_Y 21 */
- SDL_SCANCODE_U, /* KEY_U 22 */
- SDL_SCANCODE_I, /* KEY_I 23 */
- SDL_SCANCODE_O, /* KEY_O 24 */
- SDL_SCANCODE_P, /* KEY_P 25 */
- SDL_SCANCODE_LEFTBRACKET, /* KEY_LEFTBRACE 26 */
- SDL_SCANCODE_RIGHTBRACKET, /* KEY_RIGHTBRACE 27 */
- SDL_SCANCODE_RETURN, /* KEY_ENTER 28 */
- SDL_SCANCODE_LCTRL, /* KEY_LEFTCTRL 29 */
- SDL_SCANCODE_A, /* KEY_A 30 */
- SDL_SCANCODE_S, /* KEY_S 31 */
- SDL_SCANCODE_D, /* KEY_D 32 */
- SDL_SCANCODE_F, /* KEY_F 33 */
- SDL_SCANCODE_G, /* KEY_G 34 */
- SDL_SCANCODE_H, /* KEY_H 35 */
- SDL_SCANCODE_J, /* KEY_J 36 */
- SDL_SCANCODE_K, /* KEY_K 37 */
- SDL_SCANCODE_L, /* KEY_L 38 */
- SDL_SCANCODE_SEMICOLON, /* KEY_SEMICOLON 39 */
- SDL_SCANCODE_APOSTROPHE, /* KEY_APOSTROPHE 40 */
- SDL_SCANCODE_GRAVE, /* KEY_GRAVE 41 */
- SDL_SCANCODE_LSHIFT, /* KEY_LEFTSHIFT 42 */
- SDL_SCANCODE_BACKSLASH, /* KEY_BACKSLASH 43 */
- SDL_SCANCODE_Z, /* KEY_Z 44 */
- SDL_SCANCODE_X, /* KEY_X 45 */
- SDL_SCANCODE_C, /* KEY_C 46 */
- SDL_SCANCODE_V, /* KEY_V 47 */
- SDL_SCANCODE_B, /* KEY_B 48 */
- SDL_SCANCODE_N, /* KEY_N 49 */
- SDL_SCANCODE_M, /* KEY_M 50 */
- SDL_SCANCODE_COMMA, /* KEY_COMMA 51 */
- SDL_SCANCODE_PERIOD, /* KEY_DOT 52 */
- SDL_SCANCODE_SLASH, /* KEY_SLASH 53 */
- SDL_SCANCODE_RSHIFT, /* KEY_RIGHTSHIFT 54 */
- SDL_SCANCODE_KP_MULTIPLY, /* KEY_KPASTERISK 55 */
- SDL_SCANCODE_LALT, /* KEY_LEFTALT 56 */
- SDL_SCANCODE_SPACE, /* KEY_SPACE 57 */
- SDL_SCANCODE_CAPSLOCK, /* KEY_CAPSLOCK 58 */
- SDL_SCANCODE_F1, /* KEY_F1 59 */
- SDL_SCANCODE_F2, /* KEY_F2 60 */
- SDL_SCANCODE_F3, /* KEY_F3 61 */
- SDL_SCANCODE_F4, /* KEY_F4 62 */
- SDL_SCANCODE_F5, /* KEY_F5 63 */
- SDL_SCANCODE_F6, /* KEY_F6 64 */
- SDL_SCANCODE_F7, /* KEY_F7 65 */
- SDL_SCANCODE_F8, /* KEY_F8 66 */
- SDL_SCANCODE_F9, /* KEY_F9 67 */
- SDL_SCANCODE_F10, /* KEY_F10 68 */
- SDL_SCANCODE_NUMLOCKCLEAR, /* KEY_NUMLOCK 69 */
- SDL_SCANCODE_SCROLLLOCK, /* KEY_SCROLLLOCK 70 */
- SDL_SCANCODE_KP_7, /* KEY_KP7 71 */
- SDL_SCANCODE_KP_8, /* KEY_KP8 72 */
- SDL_SCANCODE_KP_9, /* KEY_KP9 73 */
- SDL_SCANCODE_KP_MINUS, /* KEY_KPMINUS 74 */
- SDL_SCANCODE_KP_4, /* KEY_KP4 75 */
- SDL_SCANCODE_KP_5, /* KEY_KP5 76 */
- SDL_SCANCODE_KP_6, /* KEY_KP6 77 */
- SDL_SCANCODE_KP_PLUS, /* KEY_KPPLUS 78 */
- SDL_SCANCODE_KP_1, /* KEY_KP1 79 */
- SDL_SCANCODE_KP_2, /* KEY_KP2 80 */
- SDL_SCANCODE_KP_3, /* KEY_KP3 81 */
- SDL_SCANCODE_KP_0, /* KEY_KP0 82 */
- SDL_SCANCODE_KP_PERIOD, /* KEY_KPDOT 83 */
- SDL_SCANCODE_UNKNOWN, /* 84 */
- SDL_SCANCODE_LANG5, /* KEY_ZENKAKUHANKAKU 85 */
- SDL_SCANCODE_UNKNOWN, /* KEY_102ND 86 */
- SDL_SCANCODE_F11, /* KEY_F11 87 */
- SDL_SCANCODE_F12, /* KEY_F12 88 */
- SDL_SCANCODE_UNKNOWN, /* KEY_RO 89 */
- SDL_SCANCODE_LANG3, /* KEY_KATAKANA 90 */
- SDL_SCANCODE_LANG4, /* KEY_HIRAGANA 91 */
- SDL_SCANCODE_UNKNOWN, /* KEY_HENKAN 92 */
- SDL_SCANCODE_LANG3, /* KEY_KATAKANAHIRAGANA 93 */
- SDL_SCANCODE_UNKNOWN, /* KEY_MUHENKAN 94 */
- SDL_SCANCODE_KP_COMMA, /* KEY_KPJPCOMMA 95 */
- SDL_SCANCODE_KP_ENTER, /* KEY_KPENTER 96 */
- SDL_SCANCODE_RCTRL, /* KEY_RIGHTCTRL 97 */
- SDL_SCANCODE_KP_DIVIDE, /* KEY_KPSLASH 98 */
- SDL_SCANCODE_SYSREQ, /* KEY_SYSRQ 99 */
- SDL_SCANCODE_RALT, /* KEY_RIGHTALT 100 */
- SDL_SCANCODE_UNKNOWN, /* KEY_LINEFEED 101 */
- SDL_SCANCODE_HOME, /* KEY_HOME 102 */
- SDL_SCANCODE_UP, /* KEY_UP 103 */
- SDL_SCANCODE_PAGEUP, /* KEY_PAGEUP 104 */
- SDL_SCANCODE_LEFT, /* KEY_LEFT 105 */
- SDL_SCANCODE_RIGHT, /* KEY_RIGHT 106 */
- SDL_SCANCODE_END, /* KEY_END 107 */
- SDL_SCANCODE_DOWN, /* KEY_DOWN 108 */
- SDL_SCANCODE_PAGEDOWN, /* KEY_PAGEDOWN 109 */
- SDL_SCANCODE_INSERT, /* KEY_INSERT 110 */
- SDL_SCANCODE_DELETE, /* KEY_DELETE 111 */
- SDL_SCANCODE_UNKNOWN, /* KEY_MACRO 112 */
- SDL_SCANCODE_MUTE, /* KEY_MUTE 113 */
- SDL_SCANCODE_VOLUMEDOWN, /* KEY_VOLUMEDOWN 114 */
- SDL_SCANCODE_VOLUMEUP, /* KEY_VOLUMEUP 115 */
- SDL_SCANCODE_POWER, /* KEY_POWER 116 SC System Power Down */
- SDL_SCANCODE_KP_EQUALS, /* KEY_KPEQUAL 117 */
- SDL_SCANCODE_KP_MINUS, /* KEY_KPPLUSMINUS 118 */
- SDL_SCANCODE_PAUSE, /* KEY_PAUSE 119 */
- SDL_SCANCODE_UNKNOWN, /* KEY_SCALE 120 AL Compiz Scale (Expose) */
- SDL_SCANCODE_KP_COMMA, /* KEY_KPCOMMA 121 */
- SDL_SCANCODE_LANG1, /* KEY_HANGEUL,KEY_HANGUEL 122 */
- SDL_SCANCODE_LANG2, /* KEY_HANJA 123 */
- SDL_SCANCODE_INTERNATIONAL3,/* KEY_YEN 124 */
- SDL_SCANCODE_LGUI, /* KEY_LEFTMETA 125 */
- SDL_SCANCODE_RGUI, /* KEY_RIGHTMETA 126 */
- SDL_SCANCODE_APPLICATION, /* KEY_COMPOSE 127 */
- SDL_SCANCODE_STOP, /* KEY_STOP 128 AC Stop */
- SDL_SCANCODE_AGAIN, /* KEY_AGAIN 129 */
- SDL_SCANCODE_UNKNOWN, /* KEY_PROPS 130 AC Properties */
- SDL_SCANCODE_UNDO, /* KEY_UNDO 131 AC Undo */
- SDL_SCANCODE_UNKNOWN, /* KEY_FRONT 132 */
- SDL_SCANCODE_COPY, /* KEY_COPY 133 AC Copy */
- SDL_SCANCODE_UNKNOWN, /* KEY_OPEN 134 AC Open */
- SDL_SCANCODE_PASTE, /* KEY_PASTE 135 AC Paste */
- SDL_SCANCODE_FIND, /* KEY_FIND 136 AC Search */
- SDL_SCANCODE_CUT, /* KEY_CUT 137 AC Cut */
- SDL_SCANCODE_HELP, /* KEY_HELP 138 AL Integrated Help Center */
- SDL_SCANCODE_MENU, /* KEY_MENU 139 Menu (show menu) */
- SDL_SCANCODE_CALCULATOR, /* KEY_CALC 140 AL Calculator */
- SDL_SCANCODE_UNKNOWN, /* KEY_SETUP 141 */
- SDL_SCANCODE_SLEEP, /* KEY_SLEEP 142 SC System Sleep */
- SDL_SCANCODE_UNKNOWN, /* KEY_WAKEUP 143 System Wake Up */
- SDL_SCANCODE_UNKNOWN, /* KEY_FILE 144 AL Local Machine Browser */
- SDL_SCANCODE_UNKNOWN, /* KEY_SENDFILE 145 */
- SDL_SCANCODE_UNKNOWN, /* KEY_DELETEFILE 146 */
- SDL_SCANCODE_UNKNOWN, /* KEY_XFER 147 */
- SDL_SCANCODE_APP1, /* KEY_PROG1 148 */
- SDL_SCANCODE_APP1, /* KEY_PROG2 149 */
- SDL_SCANCODE_WWW, /* KEY_WWW 150 AL Internet Browser */
- SDL_SCANCODE_UNKNOWN, /* KEY_MSDOS 151 */
- SDL_SCANCODE_UNKNOWN, /* KEY_COFFEE,KEY_SCREENLOCK 152 AL Terminal Lock/Screensaver */
- SDL_SCANCODE_UNKNOWN, /* KEY_DIRECTION 153 */
- SDL_SCANCODE_UNKNOWN, /* KEY_CYCLEWINDOWS 154 */
- SDL_SCANCODE_MAIL, /* KEY_MAIL 155 */
- SDL_SCANCODE_AC_BOOKMARKS, /* KEY_BOOKMARKS 156 AC Bookmarks */
- SDL_SCANCODE_COMPUTER, /* KEY_COMPUTER 157 */
- SDL_SCANCODE_AC_BACK, /* KEY_BACK 158 AC Back */
- SDL_SCANCODE_AC_FORWARD, /* KEY_FORWARD 159 AC Forward */
- SDL_SCANCODE_UNKNOWN, /* KEY_CLOSECD 160 */
- SDL_SCANCODE_EJECT, /* KEY_EJECTCD 161 */
- SDL_SCANCODE_UNKNOWN, /* KEY_EJECTCLOSECD 162 */
- SDL_SCANCODE_AUDIONEXT, /* KEY_NEXTSONG 163 */
- SDL_SCANCODE_AUDIOPLAY, /* KEY_PLAYPAUSE 164 */
- SDL_SCANCODE_AUDIOPREV, /* KEY_PREVIOUSSONG 165 */
- SDL_SCANCODE_AUDIOSTOP, /* KEY_STOPCD 166 */
- SDL_SCANCODE_UNKNOWN, /* KEY_RECORD 167 */
- SDL_SCANCODE_UNKNOWN, /* KEY_REWIND 168 */
- SDL_SCANCODE_UNKNOWN, /* KEY_PHONE 169 Media Select Telephone */
- SDL_SCANCODE_UNKNOWN, /* KEY_ISO 170 */
- SDL_SCANCODE_UNKNOWN, /* KEY_CONFIG 171 AL Consumer Control Configuration */
- SDL_SCANCODE_AC_HOME, /* KEY_HOMEPAGE 172 AC Home */
- SDL_SCANCODE_AC_REFRESH, /* KEY_REFRESH 173 AC Refresh */
- SDL_SCANCODE_UNKNOWN, /* KEY_EXIT 174 AC Exit */
- SDL_SCANCODE_UNKNOWN, /* KEY_MOVE 175 */
- SDL_SCANCODE_UNKNOWN, /* KEY_EDIT 176 */
- SDL_SCANCODE_UNKNOWN, /* KEY_SCROLLUP 177 */
- SDL_SCANCODE_UNKNOWN, /* KEY_SCROLLDOWN 178 */
- SDL_SCANCODE_KP_LEFTPAREN, /* KEY_KPLEFTPAREN 179 */
- SDL_SCANCODE_KP_RIGHTPAREN, /* KEY_KPRIGHTPAREN 180 */
- SDL_SCANCODE_UNKNOWN, /* KEY_NEW 181 AC New */
- SDL_SCANCODE_AGAIN, /* KEY_REDO 182 AC Redo/Repeat */
- SDL_SCANCODE_F13, /* KEY_F13 183 */
- SDL_SCANCODE_F14, /* KEY_F14 184 */
- SDL_SCANCODE_F15, /* KEY_F15 185 */
- SDL_SCANCODE_F16, /* KEY_F16 186 */
- SDL_SCANCODE_F17, /* KEY_F17 187 */
- SDL_SCANCODE_F18, /* KEY_F18 188 */
- SDL_SCANCODE_F19, /* KEY_F19 189 */
- SDL_SCANCODE_F20, /* KEY_F20 190 */
- SDL_SCANCODE_F21, /* KEY_F21 191 */
- SDL_SCANCODE_F22, /* KEY_F22 192 */
- SDL_SCANCODE_F23, /* KEY_F23 193 */
- SDL_SCANCODE_F24, /* KEY_F24 194 */
- SDL_SCANCODE_UNKNOWN, /* 195 */
- SDL_SCANCODE_UNKNOWN, /* 196 */
- SDL_SCANCODE_UNKNOWN, /* 197 */
- SDL_SCANCODE_UNKNOWN, /* 198 */
- SDL_SCANCODE_UNKNOWN, /* 199 */
- SDL_SCANCODE_UNKNOWN, /* KEY_PLAYCD 200 */
- SDL_SCANCODE_UNKNOWN, /* KEY_PAUSECD 201 */
- SDL_SCANCODE_UNKNOWN, /* KEY_PROG3 202 */
- SDL_SCANCODE_UNKNOWN, /* KEY_PROG4 203 */
- SDL_SCANCODE_UNKNOWN, /* KEY_DASHBOARD 204 AL Dashboard */
- SDL_SCANCODE_UNKNOWN, /* KEY_SUSPEND 205 */
- SDL_SCANCODE_UNKNOWN, /* KEY_CLOSE 206 AC Close */
- SDL_SCANCODE_UNKNOWN, /* KEY_PLAY 207 */
- SDL_SCANCODE_UNKNOWN, /* KEY_FASTFORWARD 208 */
- SDL_SCANCODE_UNKNOWN, /* KEY_BASSBOOST 209 */
- SDL_SCANCODE_UNKNOWN, /* KEY_PRINT 210 AC Print */
- SDL_SCANCODE_UNKNOWN, /* KEY_HP 211 */
- SDL_SCANCODE_UNKNOWN, /* KEY_CAMERA 212 */
- SDL_SCANCODE_UNKNOWN, /* KEY_SOUND 213 */
- SDL_SCANCODE_UNKNOWN, /* KEY_QUESTION 214 */
- SDL_SCANCODE_UNKNOWN, /* KEY_EMAIL 215 */
- SDL_SCANCODE_UNKNOWN, /* KEY_CHAT 216 */
- SDL_SCANCODE_UNKNOWN, /* KEY_SEARCH 217 */
- SDL_SCANCODE_UNKNOWN, /* KEY_CONNECT 218 */
- SDL_SCANCODE_UNKNOWN, /* KEY_FINANCE 219 AL Checkbook/Finance */
- SDL_SCANCODE_UNKNOWN, /* KEY_SPORT 220 */
- SDL_SCANCODE_UNKNOWN, /* KEY_SHOP 221 */
- SDL_SCANCODE_UNKNOWN, /* KEY_ALTERASE 222 */
- SDL_SCANCODE_UNKNOWN, /* KEY_CANCEL 223 AC Cancel */
- SDL_SCANCODE_UNKNOWN, /* KEY_BRIGHTNESSDOWN 224 */
- SDL_SCANCODE_UNKNOWN, /* KEY_BRIGHTNESSUP 225 */
- SDL_SCANCODE_UNKNOWN, /* KEY_MEDIA 226 */
- SDL_SCANCODE_UNKNOWN, /* KEY_SWITCHVIDEOMODE 227 Cycle between available video outputs (Monitor/LCD/TV-out/etc) */
- SDL_SCANCODE_UNKNOWN, /* KEY_KBDILLUMTOGGLE 228 */
- SDL_SCANCODE_UNKNOWN, /* KEY_KBDILLUMDOWN 229 */
- SDL_SCANCODE_UNKNOWN, /* KEY_KBDILLUMUP 230 */
- SDL_SCANCODE_UNKNOWN, /* KEY_SEND 231 AC Send */
- SDL_SCANCODE_UNKNOWN, /* KEY_REPLY 232 AC Reply */
- SDL_SCANCODE_UNKNOWN, /* KEY_FORWARDMAIL 233 AC Forward Msg */
- SDL_SCANCODE_UNKNOWN, /* KEY_SAVE 234 AC Save */
- SDL_SCANCODE_UNKNOWN, /* KEY_DOCUMENTS 235 */
- SDL_SCANCODE_UNKNOWN, /* KEY_BATTERY 236 */
- SDL_SCANCODE_UNKNOWN, /* KEY_BLUETOOTH 237 */
- SDL_SCANCODE_UNKNOWN, /* KEY_WLAN 238 */
- SDL_SCANCODE_UNKNOWN, /* KEY_UWB 239 */
- SDL_SCANCODE_UNKNOWN, /* KEY_UNKNOWN 240 */
- SDL_SCANCODE_UNKNOWN, /* KEY_VIDEO_NEXT 241 drive next video source */
- SDL_SCANCODE_UNKNOWN, /* KEY_VIDEO_PREV 242 drive previous video source */
- SDL_SCANCODE_UNKNOWN, /* KEY_BRIGHTNESS_CYCLE 243 brightness up, after max is min */
- SDL_SCANCODE_UNKNOWN, /* KEY_BRIGHTNESS_ZERO 244 brightness off, use ambient */
- SDL_SCANCODE_UNKNOWN, /* KEY_DISPLAY_OFF 245 display device to off state */
- SDL_SCANCODE_UNKNOWN, /* KEY_WIMAX 246 */
- SDL_SCANCODE_UNKNOWN, /* KEY_RFKILL 247 Key that controls all radios */
- SDL_SCANCODE_UNKNOWN, /* KEY_MICMUTE 248 Mute / unmute the microphone */
-};
-
static Uint8 EVDEV_MouseButtons[] = {
SDL_BUTTON_LEFT, /* BTN_LEFT 0x110 */
SDL_BUTTON_RIGHT, /* BTN_RIGHT 0x111 */
@@ -342,121 +127,98 @@ static Uint8 EVDEV_MouseButtons[] = {
};
static const char* EVDEV_consoles[] = {
- "/proc/self/fd/0",
+ /* "/proc/self/fd/0",
"/dev/tty",
- "/dev/tty0",
+ "/dev/tty0", */ /* the tty ioctl's prohibit these */
"/dev/tty1",
"/dev/tty2",
"/dev/tty3",
"/dev/tty4",
"/dev/tty5",
"/dev/tty6",
+ "/dev/tty7", /* usually X is spawned in tty7 */
"/dev/vc/0",
"/dev/console"
};
-#define IS_CONSOLE(fd) isatty (fd) && ioctl(fd, KDGKBTYPE, &arg) == 0 && ((arg == KB_101) || (arg == KB_84))
-
-static int SDL_EVDEV_get_console_fd(void)
-{
- int fd, i;
- char arg = 0;
+static int SDL_EVDEV_is_console(int fd) {
+ int type;
- /* Try a few consoles to see which one we have read access to */
-
- for(i = 0; i < SDL_arraysize(EVDEV_consoles); i++) {
- fd = open(EVDEV_consoles[i], O_RDONLY);
- if (fd >= 0) {
- if (IS_CONSOLE(fd)) return fd;
- close(fd);
- }
- }
-
- /* Try stdin, stdout, stderr */
-
- for(fd = 0; fd < 3; fd++) {
- if (IS_CONSOLE(fd)) return fd;
- }
-
- /* We won't be able to send SDL_TEXTINPUT events */
- return -1;
+ return isatty(fd) && ioctl(fd, KDGKBTYPE, &type) == 0 &&
+ (type == KB_101 || type == KB_84);
}
/* Prevent keystrokes from reaching the tty */
-static int SDL_EVDEV_mute_keyboard(int tty, int *kb_mode)
+static int SDL_EVDEV_mute_keyboard(int tty_fd, int* old_kb_mode)
{
- char arg;
-
- *kb_mode = 0; /* FIXME: Is this a sane default in case KDGKBMODE fails? */
- if (!IS_CONSOLE(tty)) {
+ if (!SDL_EVDEV_is_console(tty_fd)) {
return SDL_SetError("Tried to mute an invalid tty");
}
- ioctl(tty, KDGKBMODE, kb_mode); /* It's not fatal if this fails */
- if (ioctl(tty, KDSKBMUTE, 1) && ioctl(tty, KDSKBMODE, K_OFF)) {
- return SDL_SetError("EVDEV: Failed muting keyboard");
+
+ if (ioctl(tty_fd, KDGKBMODE, old_kb_mode) < 0) {
+ return SDL_SetError("Failed to get keyboard mode during muting");
}
+ /* FIXME: atm this absolutely ruins the vt, and KDSKBMUTE isn't implemented
+ in the kernel */
+ /*
+ if (ioctl(tty_fd, KDSKBMODE, K_OFF) < 0) {
+ return SDL_SetError("Failed to set keyboard mode during muting");
+ }
+ */
+
return 0;
}
/* Restore the keyboard mode for given tty */
-static void SDL_EVDEV_unmute_keyboard(int tty, int kb_mode)
+static void SDL_EVDEV_unmute_keyboard(int tty_fd, int kb_mode)
{
- if (ioctl(tty, KDSKBMUTE, 0) && ioctl(tty, KDSKBMODE, kb_mode)) {
- SDL_Log("EVDEV: Failed restoring keyboard mode");
+ /* read above */
+ /*
+ if (ioctl(tty_fd, KDSKBMODE, kb_mode) < 0) {
+ SDL_Log("Failed to unmute keyboard");
}
+ */
}
-/* Read /sys/class/tty/tty0/active and open the tty */
static int SDL_EVDEV_get_active_tty()
-{
- int fd, len;
- char ttyname[NAME_MAX + 1];
- char ttypath[PATH_MAX+1] = "/dev/";
- char arg;
+{
+ int i, fd, ret, tty = 0;
+ char tiocl;
+ struct vt_stat vt_state;
+ char path[PATH_MAX + 1];
- fd = open("/sys/class/tty/tty0/active", O_RDONLY);
- if (fd < 0) {
- return SDL_SetError("Could not determine which tty is active");
- }
-
- len = read(fd, ttyname, NAME_MAX);
- close(fd);
-
- if (len <= 0) {
- return SDL_SetError("Could not read which tty is active");
- }
-
- if (ttyname[len-1] == '\n') {
- ttyname[len-1] = '\0';
- }
- else {
- ttyname[len] = '\0';
- }
-
- SDL_strlcat(ttypath, ttyname, PATH_MAX);
- fd = open(ttypath, O_RDWR | O_NOCTTY);
- if (fd < 0) {
- return SDL_SetError("Could not open tty: %s", ttypath);
- }
-
- if (!IS_CONSOLE(fd)) {
+ for(i = 0; i < SDL_arraysize(EVDEV_consoles); i++) {
+ fd = open(EVDEV_consoles[i], O_RDONLY);
+
+ if (fd < 0 && !SDL_EVDEV_is_console(fd))
+ break;
+
+ tiocl = TIOCL_GETFGCONSOLE;
+ if ((ret = ioctl(fd, TIOCLINUX, &tiocl)) >= 0)
+ tty = ret + 1;
+ else if (ioctl(fd, VT_GETSTATE, &vt_state) == 0)
+ tty = vt_state.v_active;
+
close(fd);
- return SDL_SetError("Invalid tty obtained: %s", ttypath);
+
+ if (tty) {
+ sprintf(path, "/dev/tty%u", tty);
+ fd = open(path, O_RDONLY);
+ if (fd >= 0 && SDL_EVDEV_is_console(fd))
+ return fd;
+ }
}
-
- return fd;
+
+ return SDL_SetError("Failed to determine active tty");
}
int
SDL_EVDEV_Init(void)
{
- int retval = 0;
-
if (_this == NULL) {
-
- _this = (SDL_EVDEV_PrivateData *) SDL_calloc(1, sizeof(*_this));
- if(_this == NULL) {
+ _this = (SDL_EVDEV_PrivateData*)SDL_calloc(1, sizeof(*_this));
+ if (_this == NULL) {
return SDL_OutOfMemory();
}
@@ -469,7 +231,9 @@ SDL_EVDEV_Init(void)
/* Set up the udev callback */
if (SDL_UDEV_AddCallback(SDL_EVDEV_udev_callback) < 0) {
- SDL_EVDEV_Quit();
+ SDL_UDEV_Quit();
+ SDL_free(_this);
+ _this = NULL;
return -1;
}
@@ -479,26 +243,18 @@ SDL_EVDEV_Init(void)
/* TODO: Scan the devices manually, like a caveman */
#endif /* SDL_USE_LIBUDEV */
- /* We need a physical terminal (not PTS) to be able to translate key code to symbols via the kernel tables */
- _this->console_fd = SDL_EVDEV_get_console_fd();
+ /* We need a physical terminal (not PTS) to be able to translate key
+ code to symbols via the kernel tables */
+ _this->console_fd = SDL_EVDEV_get_active_tty();
- /* Mute the keyboard so keystrokes only generate evdev events and do not leak through to the console */
- _this->tty = STDIN_FILENO;
- if (SDL_EVDEV_mute_keyboard(_this->tty, &_this->kb_mode) < 0) {
- /* stdin is not a tty, probably we were launched remotely, so we try to disable the active tty */
- _this->tty = SDL_EVDEV_get_active_tty();
- if (_this->tty >= 0) {
- if (SDL_EVDEV_mute_keyboard(_this->tty, &_this->kb_mode) < 0) {
- close(_this->tty);
- _this->tty = -1;
- }
- }
- }
+ /* Mute the keyboard so keystrokes only generate evdev events and do not
+ leak through to the console */
+ SDL_EVDEV_mute_keyboard(_this->console_fd, &_this->kb_mode);
}
_this->ref_count += 1;
- return retval;
+ return 0;
}
void
@@ -511,21 +267,16 @@ SDL_EVDEV_Quit(void)
_this->ref_count -= 1;
if (_this->ref_count < 1) {
-
#if SDL_USE_LIBUDEV
SDL_UDEV_DelCallback(SDL_EVDEV_udev_callback);
SDL_UDEV_Quit();
#endif /* SDL_USE_LIBUDEV */
if (_this->console_fd >= 0) {
+ SDL_EVDEV_unmute_keyboard(_this->console_fd, _this->kb_mode);
close(_this->console_fd);
}
- if (_this->tty >= 0) {
- SDL_EVDEV_unmute_keyboard(_this->tty, _this->kb_mode);
- close(_this->tty);
- }
-
/* Remove existing devices */
while(_this->first != NULL) {
SDL_EVDEV_device_removed(_this->first->path);
@@ -533,7 +284,7 @@ SDL_EVDEV_Quit(void)
SDL_assert(_this->first == NULL);
SDL_assert(_this->last == NULL);
- SDL_assert(_this->numdevices == 0);
+ SDL_assert(_this->num_devices == 0);
SDL_free(_this);
_this = NULL;
@@ -541,47 +292,116 @@ SDL_EVDEV_Quit(void)
}
#if SDL_USE_LIBUDEV
-void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath)
+void SDL_EVDEV_udev_callback(SDL_UDEV_deviceevent udev_event, int udev_class,
+ const char* dev_path)
{
- if (devpath == NULL) {
+ if (dev_path == NULL) {
return;
}
- switch(udev_type) {
+ switch(udev_event) {
case SDL_UDEV_DEVICEADDED:
- if (!(udev_class & (SDL_UDEV_DEVICE_MOUSE|SDL_UDEV_DEVICE_KEYBOARD))) {
+ if (!(udev_class & (SDL_UDEV_DEVICE_MOUSE | SDL_UDEV_DEVICE_KEYBOARD |
+ SDL_UDEV_DEVICE_TOUCHSCREEN)))
return;
- }
- SDL_EVDEV_device_added(devpath);
- break;
-
+
+ SDL_EVDEV_device_added(dev_path, udev_class);
+ break;
case SDL_UDEV_DEVICEREMOVED:
- SDL_EVDEV_device_removed(devpath);
+ SDL_EVDEV_device_removed(dev_path);
break;
-
default:
break;
}
}
-
#endif /* SDL_USE_LIBUDEV */
+#ifdef SDL_INPUT_LINUXKD
+/* this logic is pulled from kbd_keycode() in drivers/tty/vt/keyboard.c in the
+ Linux kernel source */
+static void SDL_EVDEV_do_text_input(unsigned short keycode) {
+ char shift_state;
+ int locks_state;
+ struct kbentry kbe;
+ unsigned char type;
+ char text[2] = { 0 };
+
+ if (_this->console_fd < 0)
+ return;
+
+ shift_state = TIOCL_GETSHIFTSTATE;
+ if (ioctl(_this->console_fd, TIOCLINUX, &shift_state) < 0) {
+ /* TODO: error */
+ return;
+ }
+
+ kbe.kb_table = shift_state;
+ kbe.kb_index = keycode;
+
+ if (ioctl(_this->console_fd, KDGKBENT, &kbe) < 0) {
+ /* TODO: error */
+ return;
+ }
+
+ type = KTYP(kbe.kb_value);
+
+ if (type < 0xf0) {
+ /*
+ * FIXME: keysyms with a type below 0xf0 represent a unicode character
+ * which requires special handling due to dead characters, diacritics,
+ * etc. For perfect input a proper way to deal with such characters
+ * should be implemented.
+ *
+ * For reference, the only place I was able to find out about this
+ * special 0xf0 value was in an unused? couple of patches listed below.
+ *
+ * http://ftp.tc.edu.tw/pub/docs/Unicode/utf8/linux-2.3.12-keyboard.diff
+ * http://ftp.tc.edu.tw/pub/docs/Unicode/utf8/linux-2.3.12-console.diff
+ */
+
+ return;
+ }
+
+ type -= 0xf0;
+
+ /* if type is KT_LETTER then it can be affected by Caps Lock */
+ if (type == KT_LETTER) {
+ type = KT_LATIN;
+
+ if (ioctl(_this->console_fd, KDGKBLED, &locks_state) < 0) {
+ /* TODO: error */
+ return;
+ }
+
+ if (locks_state & K_CAPSLOCK) {
+ kbe.kb_table = shift_state ^ (1 << KG_SHIFT);
+
+ if (ioctl(_this->console_fd, KDGKBENT, &kbe) < 0) {
+ /* TODO: error */
+ return;
+ }
+ }
+ }
+
+ /* TODO: convert values >= 0x80 from ISO-8859-1? to UTF-8 */
+ if (type != KT_LATIN || KVAL(kbe.kb_value) >= 0x80)
+ return;
+
+ *text = KVAL(kbe.kb_value);
+ SDL_SendKeyboardText(text);
+}
+#endif /* SDL_INPUT_LINUXKD */
+
void
SDL_EVDEV_Poll(void)
{
struct input_event events[32];
- int i, len;
+ int i, j, len;
SDL_evdevlist_item *item;
SDL_Scancode scan_code;
int mouse_button;
SDL_Mouse *mouse;
-#ifdef SDL_INPUT_LINUXKD
- Uint16 modstate;
- struct kbentry kbe;
- static char keysym[8];
- char *end;
- Uint32 kval;
-#endif
+ float norm_x, norm_y;
if (!_this) {
return;
@@ -597,6 +417,13 @@ SDL_EVDEV_Poll(void)
while ((len = read(item->fd, events, (sizeof events))) > 0) {
len /= sizeof(events[0]);
for (i = 0; i < len; ++i) {
+ /* special handling for touchscreen, that should eventually be
+ used for all devices */
+ if (item->out_of_sync && item->is_touchscreen &&
+ events[i].type == EV_SYN && events[i].code != SYN_REPORT) {
+ break;
+ }
+
switch (events[i].type) {
case EV_KEY:
if (events[i].code >= BTN_MOUSE && events[i].code < BTN_MOUSE + SDL_arraysize(EVDEV_MouseButtons)) {
@@ -614,57 +441,55 @@ SDL_EVDEV_Poll(void)
if (scan_code != SDL_SCANCODE_UNKNOWN) {
if (events[i].value == 0) {
SDL_SendKeyboardKey(SDL_RELEASED, scan_code);
- } else if (events[i].value == 1 || events[i].value == 2 /* Key repeated */) {
+ } else if (events[i].value == 1 || events[i].value == 2 /* key repeated */) {
SDL_SendKeyboardKey(SDL_PRESSED, scan_code);
#ifdef SDL_INPUT_LINUXKD
- if (_this->console_fd >= 0) {
- kbe.kb_index = events[i].code;
- /* Convert the key to an UTF-8 char */
- /* Ref: http://www.linuxjournal.com/article/2783 */
- modstate = SDL_GetModState();
- kbe.kb_table = 0;
-
- /* Ref: http://graphics.stanford.edu/~seander/bithacks.html#ConditionalSetOrClearBitsWithoutBranching */
- kbe.kb_table |= -((modstate & KMOD_LCTRL) != 0) & (1 << KG_CTRLL | 1 << KG_CTRL);
- kbe.kb_table |= -((modstate & KMOD_RCTRL) != 0) & (1 << KG_CTRLR | 1 << KG_CTRL);
- kbe.kb_table |= -((modstate & KMOD_LSHIFT) != 0) & (1 << KG_SHIFTL | 1 << KG_SHIFT);
- kbe.kb_table |= -((modstate & KMOD_RSHIFT) != 0) & (1 << KG_SHIFTR | 1 << KG_SHIFT);
- kbe.kb_table |= -((modstate & KMOD_LALT) != 0) & (1 << KG_ALT);
- kbe.kb_table |= -((modstate & KMOD_RALT) != 0) & (1 << KG_ALTGR);
-
- if (ioctl(_this->console_fd, KDGKBENT, (unsigned long)&kbe) == 0 &&
- ((KTYP(kbe.kb_value) == KT_LATIN) || (KTYP(kbe.kb_value) == KT_ASCII) || (KTYP(kbe.kb_value) == KT_LETTER)))
- {
- kval = KVAL(kbe.kb_value);
-
- /* While there's a KG_CAPSSHIFT symbol, it's not useful to build the table index with it
- * because 1 << KG_CAPSSHIFT overflows the 8 bits of kb_table
- * So, we do the CAPS LOCK logic here. Note that isalpha depends on the locale!
- */
- if (modstate & KMOD_CAPS && isalpha(kval)) {
- if (isupper(kval)) {
- kval = tolower(kval);
- } else {
- kval = toupper(kval);
- }
- }
-
- /* Convert to UTF-8 and send */
- end = SDL_UCS4ToUTF8(kval, keysym);
- *end = '\0';
- SDL_SendKeyboardText(keysym);
- }
- }
+ SDL_EVDEV_do_text_input(events[i].code);
#endif /* SDL_INPUT_LINUXKD */
}
}
break;
case EV_ABS:
switch(events[i].code) {
+ case ABS_MT_SLOT:
+ if (!item->is_touchscreen) /* FIXME: temp hack */
+ break;
+ item->touchscreen_data->current_slot = events[i].value;
+ break;
+ case ABS_MT_TRACKING_ID:
+ if (!item->is_touchscreen) /* FIXME: temp hack */
+ break;
+ if (events[i].value >= 0) {
+ item->touchscreen_data->slots[item->touchscreen_data->current_slot].tracking_id = events[i].value;
+ item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_DOWN;
+ } else {
+ item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_UP;
+ }
+ break;
+ case ABS_MT_POSITION_X:
+ if (!item->is_touchscreen) /* FIXME: temp hack */
+ break;
+ item->touchscreen_data->slots[item->touchscreen_data->current_slot].x = events[i].value;
+ if (item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta == EVDEV_TOUCH_SLOTDELTA_NONE) {
+ item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_MOVE;
+ }
+ break;
+ case ABS_MT_POSITION_Y:
+ if (!item->is_touchscreen) /* FIXME: temp hack */
+ break;
+ item->touchscreen_data->slots[item->touchscreen_data->current_slot].y = events[i].value;
+ if (item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta == EVDEV_TOUCH_SLOTDELTA_NONE) {
+ item->touchscreen_data->slots[item->touchscreen_data->current_slot].delta = EVDEV_TOUCH_SLOTDELTA_MOVE;
+ }
+ break;
case ABS_X:
+ if (item->is_touchscreen) /* FIXME: temp hack */
+ break;
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, events[i].value, mouse->y);
break;
case ABS_Y:
+ if (item->is_touchscreen) /* FIXME: temp hack */
+ break;
SDL_SendMouseMotion(mouse->focus, mouse->mouseID, SDL_FALSE, mouse->x, events[i].value);
break;
default:
@@ -691,7 +516,41 @@ SDL_EVDEV_Poll(void)
break;
case EV_SYN:
switch (events[i].code) {
+ case SYN_REPORT:
+ if (!item->is_touchscreen) /* FIXME: temp hack */
+ break;
+
+ for(j = 0; j < item->touchscreen_data->max_slots; j++) {
+ norm_x = (float)(item->touchscreen_data->slots[j].x - item->touchscreen_data->min_x) /
+ (float)item->touchscreen_data->range_x;
+ norm_y = (float)(item->touchscreen_data->slots[j].y - item->touchscreen_data->min_y) /
+ (float)item->touchscreen_data->range_y;
+
+ switch(item->touchscreen_data->slots[j].delta) {
+ case EVDEV_TOUCH_SLOTDELTA_DOWN:
+ SDL_SendTouch(item->fd, item->touchscreen_data->slots[j].tracking_id, SDL_TRUE, norm_x, norm_y, 1.0f);
+ item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE;
+ break;
+ case EVDEV_TOUCH_SLOTDELTA_UP:
+ SDL_SendTouch(item->fd, item->touchscreen_data->slots[j].tracking_id, SDL_FALSE, norm_x, norm_y, 1.0f);
+ item->touchscreen_data->slots[j].tracking_id = -1;
+ item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE;
+ break;
+ case EVDEV_TOUCH_SLOTDELTA_MOVE:
+ SDL_SendTouchMotion(item->fd, item->touchscreen_data->slots[j].tracking_id, norm_x, norm_y, 1.0f);
+ item->touchscreen_data->slots[j].delta = EVDEV_TOUCH_SLOTDELTA_NONE;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (item->out_of_sync)
+ item->out_of_sync = 0;
+ break;
case SYN_DROPPED:
+ if (item->is_touchscreen)
+ item->out_of_sync = 1;
SDL_EVDEV_sync_device(item);
break;
default:
@@ -709,30 +568,227 @@ SDL_EVDEV_translate_keycode(int keycode)
{
SDL_Scancode scancode = SDL_SCANCODE_UNKNOWN;
- if (keycode < SDL_arraysize(EVDEV_Keycodes)) {
- scancode = EVDEV_Keycodes[keycode];
- }
+ if (keycode < SDL_arraysize(linux_scancode_table))
+ scancode = linux_scancode_table[keycode];
+
if (scancode == SDL_SCANCODE_UNKNOWN) {
- SDL_Log("The key you just pressed is not recognized by SDL. To help get this fixed, please report this to the SDL mailing list EVDEV KeyCode %d \n", keycode);
+ SDL_Log("The key you just pressed is not recognized by SDL. To help "
+ "get this fixed, please report this to the SDL mailing list "
+ " EVDEV KeyCode %d\n", keycode);
}
+
return scancode;
}
+#ifdef SDL_USE_LIBUDEV
+static int
+SDL_EVDEV_init_touchscreen(SDL_evdevlist_item* item)
+{
+ int ret, i;
+ char name[64];
+ struct input_absinfo abs_info;
+
+ if (!item->is_touchscreen)
+ return 0;
+
+ item->touchscreen_data = SDL_calloc(1, sizeof(*item->touchscreen_data));
+ if (item->touchscreen_data == NULL)
+ return SDL_OutOfMemory();
+
+ ret = ioctl(item->fd, EVIOCGNAME(sizeof(name)), name);
+ if (ret < 0) {
+ SDL_free(item->touchscreen_data);
+ return SDL_SetError("Failed to get evdev touchscreen name");
+ }
+
+ item->touchscreen_data->name = SDL_strdup(name);
+ if (item->touchscreen_data->name == NULL) {
+ SDL_free(item->touchscreen_data);
+ return SDL_OutOfMemory();
+ }
+
+ ret = ioctl(item->fd, EVIOCGABS(ABS_MT_POSITION_X), &abs_info);
+ if (ret < 0) {
+ SDL_free(item->touchscreen_data->name);
+ SDL_free(item->touchscreen_data);
+ return SDL_SetError("Failed to get evdev touchscreen limits");
+ }
+ item->touchscreen_data->min_x = abs_info.minimum;
+ item->touchscreen_data->max_x = abs_info.maximum;
+ item->touchscreen_data->range_x = abs_info.maximum - abs_info.minimum;
+
+ ret = ioctl(item->fd, EVIOCGABS(ABS_MT_POSITION_Y), &abs_info);
+ if (ret < 0) {
+ SDL_free(item->touchscreen_data->name);
+ SDL_free(item->touchscreen_data);
+ return SDL_SetError("Failed to get evdev touchscreen limits");
+ }
+ item->touchscreen_data->min_y = abs_info.minimum;
+ item->touchscreen_data->max_y = abs_info.maximum;
+ item->touchscreen_data->range_y = abs_info.maximum - abs_info.minimum;
+
+ ret = ioctl(item->fd, EVIOCGABS(ABS_MT_SLOT), &abs_info);
+ if (ret < 0) {
+ SDL_free(item->touchscreen_data->name);
+ SDL_free(item->touchscreen_data);
+ return SDL_SetError("Failed to get evdev touchscreen limits");
+ }
+ item->touchscreen_data->max_slots = abs_info.maximum + 1;
+
+ item->touchscreen_data->slots = SDL_calloc(
+ item->touchscreen_data->max_slots,
+ sizeof(*item->touchscreen_data->slots));
+ if (item->touchscreen_data->slots == NULL) {
+ SDL_free(item->touchscreen_data->name);
+ SDL_free(item->touchscreen_data);
+ return SDL_OutOfMemory();
+ }
+
+ for(i = 0; i < item->touchscreen_data->max_slots; i++) {
+ item->touchscreen_data->slots[i].tracking_id = -1;
+ }
+
+ ret = SDL_AddTouch(item->fd, /* I guess our fd is unique enough */
+ item->touchscreen_data->name);
+ if (ret < 0) {
+ SDL_free(item->touchscreen_data->slots);
+ SDL_free(item->touchscreen_data->name);
+ SDL_free(item->touchscreen_data);
+ return ret;
+ }
+
+ return 0;
+}
+#endif /* SDL_USE_LIBUDEV */
+
+static void
+SDL_EVDEV_destroy_touchscreen(SDL_evdevlist_item* item) {
+ if (!item->is_touchscreen)
+ return;
+
+ SDL_DelTouch(item->fd);
+ SDL_free(item->touchscreen_data->slots);
+ SDL_free(item->touchscreen_data->name);
+ SDL_free(item->touchscreen_data);
+}
+
static void
SDL_EVDEV_sync_device(SDL_evdevlist_item *item)
{
- /* TODO: get full state of device and report whatever is required */
+#ifdef EVIOCGMTSLOTS
+ int i, ret;
+ struct input_absinfo abs_info;
+ /*
+ * struct input_mt_request_layout {
+ * __u32 code;
+ * __s32 values[num_slots];
+ * };
+ *
+ * this is the structure we're trying to emulate
+ */
+ __u32* mt_req_code;
+ __s32* mt_req_values;
+ size_t mt_req_size;
+
+ /* TODO: sync devices other than touchscreen */
+ if (!item->is_touchscreen)
+ return;
+
+ mt_req_size = sizeof(*mt_req_code) +
+ sizeof(*mt_req_values) * item->touchscreen_data->max_slots;
+
+ mt_req_code = SDL_calloc(1, mt_req_size);
+ if (mt_req_code == NULL) {
+ return;
+ }
+
+ mt_req_values = (__s32*)mt_req_code + 1;
+
+ *mt_req_code = ABS_MT_TRACKING_ID;
+ ret = ioctl(item->fd, EVIOCGMTSLOTS(mt_req_size), mt_req_code);
+ if (ret < 0) {
+ SDL_free(mt_req_code);
+ return;
+ }
+ for(i = 0; i < item->touchscreen_data->max_slots; i++) {
+ /*
+ * This doesn't account for the very edge case of the user removing their
+ * finger and replacing it on the screen during the time we're out of sync,
+ * which'll mean that we're not going from down -> up or up -> down, we're
+ * going from down -> down but with a different tracking id, meaning we'd
+ * have to tell SDL of the two events, but since we wait till SYN_REPORT in
+ * SDL_EVDEV_Poll to tell SDL, the current structure of this code doesn't
+ * allow it. Lets just pray to God it doesn't happen.
+ */
+ if (item->touchscreen_data->slots[i].tracking_id < 0 &&
+ mt_req_values[i] >= 0) {
+ item->touchscreen_data->slots[i].tracking_id = mt_req_values[i];
+ item->touchscreen_data->slots[i].delta = EVDEV_TOUCH_SLOTDELTA_DOWN;
+ } else if (item->touchscreen_data->slots[i].tracking_id >= 0 &&
+ mt_req_values[i] < 0) {
+ item->touchscreen_data->slots[i].tracking_id = -1;
+ item->touchscreen_data->slots[i].delta = EVDEV_TOUCH_SLOTDELTA_UP;
+ }
+ }
+
+ *mt_req_code = ABS_MT_POSITION_X;
+ ret = ioctl(item->fd, EVIOCGMTSLOTS(mt_req_size), mt_req_code);
+ if (ret < 0) {
+ SDL_free(mt_req_code);
+ return;
+ }
+ for(i = 0; i < item->touchscreen_data->max_slots; i++) {
+ if (item->touchscreen_data->slots[i].tracking_id >= 0 &&
+ item->touchscreen_data->slots[i].x != mt_req_values[i]) {
+ item->touchscreen_data->slots[i].x = mt_req_values[i];
+ if (item->touchscreen_data->slots[i].delta ==
+ EVDEV_TOUCH_SLOTDELTA_NONE) {
+ item->touchscreen_data->slots[i].delta =
+ EVDEV_TOUCH_SLOTDELTA_MOVE;
+ }
+ }
+ }
+
+ *mt_req_code = ABS_MT_POSITION_Y;
+ ret = ioctl(item->fd, EVIOCGMTSLOTS(mt_req_size), mt_req_code);
+ if (ret < 0) {
+ SDL_free(mt_req_code);
+ return;
+ }
+ for(i = 0; i < item->touchscreen_data->max_slots; i++) {
+ if (item->touchscreen_data->slots[i].tracking_id >= 0 &&
+ item->touchscreen_data->slots[i].y != mt_req_values[i]) {
+ item->touchscreen_data->slots[i].y = mt_req_values[i];
+ if (item->touchscreen_data->slots[i].delta ==
+ EVDEV_TOUCH_SLOTDELTA_NONE) {
+ item->touchscreen_data->slots[i].delta =
+ EVDEV_TOUCH_SLOTDELTA_MOVE;
+ }
+ }
+ }
+
+ ret = ioctl(item->fd, EVIOCGABS(ABS_MT_SLOT), &abs_info);
+ if (ret < 0) {
+ SDL_free(mt_req_code);
+ return;
+ }
+ item->touchscreen_data->current_slot = abs_info.value;
+
+ SDL_free(mt_req_code);
+
+#endif /* EVIOCGMTSLOTS */
}
#if SDL_USE_LIBUDEV
static int
-SDL_EVDEV_device_added(const char *devpath)
+SDL_EVDEV_device_added(const char *dev_path, int udev_class)
{
+ int ret;
SDL_evdevlist_item *item;
/* Check to make sure it's not already in list. */
for (item = _this->first; item != NULL; item = item->next) {
- if (SDL_strcmp(devpath, item->path) == 0) {
+ if (SDL_strcmp(dev_path, item->path) == 0) {
return -1; /* already have this one */
}
}
@@ -742,21 +798,28 @@ SDL_EVDEV_device_added(const char *devpath)
return SDL_OutOfMemory();
}
- item->fd = open(devpath, O_RDONLY, 0);
+ item->fd = open(dev_path, O_RDONLY | O_NONBLOCK);
if (item->fd < 0) {
SDL_free(item);
- return SDL_SetError("Unable to open %s", devpath);
+ return SDL_SetError("Unable to open %s", dev_path);
}
- item->path = SDL_strdup(devpath);
+ item->path = SDL_strdup(dev_path);
if (item->path == NULL) {
close(item->fd);
SDL_free(item);
return SDL_OutOfMemory();
}
- /* Non blocking read mode */
- fcntl(item->fd, F_SETFL, O_NONBLOCK);
+ if (udev_class & SDL_UDEV_DEVICE_TOUCHSCREEN) {
+ item->is_touchscreen = 1;
+
+ if ((ret = SDL_EVDEV_init_touchscreen(item)) < 0) {
+ close(item->fd);
+ SDL_free(item);
+ return ret;
+ }
+ }
if (_this->last == NULL) {
_this->first = _this->last = item;
@@ -767,19 +830,19 @@ SDL_EVDEV_device_added(const char *devpath)
SDL_EVDEV_sync_device(item);
- return _this->numdevices++;
+ return _this->num_devices++;
}
#endif /* SDL_USE_LIBUDEV */
static int
-SDL_EVDEV_device_removed(const char *devpath)
+SDL_EVDEV_device_removed(const char *dev_path)
{
SDL_evdevlist_item *item;
SDL_evdevlist_item *prev = NULL;
for (item = _this->first; item != NULL; item = item->next) {
/* found it, remove it. */
- if (SDL_strcmp(devpath, item->path) == 0) {
+ if (SDL_strcmp(dev_path, item->path) == 0) {
if (prev != NULL) {
prev->next = item->next;
} else {
@@ -789,10 +852,13 @@ SDL_EVDEV_device_removed(const char *devpath)
if (item == _this->last) {
_this->last = prev;
}
+ if (item->is_touchscreen) {
+ SDL_EVDEV_destroy_touchscreen(item);
+ }
close(item->fd);
SDL_free(item->path);
SDL_free(item);
- _this->numdevices--;
+ _this->num_devices--;
return 0;
}
prev = item;
@@ -805,4 +871,3 @@ SDL_EVDEV_device_removed(const char *devpath)
#endif /* SDL_INPUT_LINUXEV */
/* vi: set ts=4 sw=4 expandtab: */
-
diff --git a/Engine/lib/sdl/src/core/linux/SDL_evdev.h b/Engine/lib/sdl/src/core/linux/SDL_evdev.h
index 989ced858..85b193864 100644
--- a/Engine/lib/sdl/src/core/linux/SDL_evdev.h
+++ b/Engine/lib/sdl/src/core/linux/SDL_evdev.h
@@ -27,31 +27,11 @@
#ifdef SDL_INPUT_LINUXEV
#include "SDL_events.h"
-#include
-
-typedef struct SDL_evdevlist_item
-{
- char *path;
- int fd;
- struct SDL_evdevlist_item *next;
-} SDL_evdevlist_item;
-
-typedef struct SDL_EVDEV_PrivateData
-{
- SDL_evdevlist_item *first;
- SDL_evdevlist_item *last;
- int numdevices;
- int ref_count;
- int console_fd;
- int kb_mode;
- int tty;
-} SDL_EVDEV_PrivateData;
extern int SDL_EVDEV_Init(void);
extern void SDL_EVDEV_Quit(void);
extern void SDL_EVDEV_Poll(void);
-
#endif /* SDL_INPUT_LINUXEV */
#endif /* _SDL_evdev_h */
diff --git a/Engine/lib/sdl/src/core/linux/SDL_fcitx.c b/Engine/lib/sdl/src/core/linux/SDL_fcitx.c
new file mode 100644
index 000000000..83d19e690
--- /dev/null
+++ b/Engine/lib/sdl/src/core/linux/SDL_fcitx.c
@@ -0,0 +1,553 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2016 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#ifdef HAVE_FCITX_FRONTEND_H
+
+#include
+#include
+
+#include "SDL_fcitx.h"
+#include "SDL_keycode.h"
+#include "SDL_keyboard.h"
+#include "../../events/SDL_keyboard_c.h"
+#include "SDL_dbus.h"
+#include "SDL_syswm.h"
+#if SDL_VIDEO_DRIVER_X11
+# include "../../video/x11/SDL_x11video.h"
+#endif
+#include "SDL_hints.h"
+
+#define FCITX_DBUS_SERVICE "org.fcitx.Fcitx"
+
+#define FCITX_IM_DBUS_PATH "/inputmethod"
+#define FCITX_IC_DBUS_PATH "/inputcontext_%d"
+
+#define FCITX_IM_DBUS_INTERFACE "org.fcitx.Fcitx.InputMethod"
+#define FCITX_IC_DBUS_INTERFACE "org.fcitx.Fcitx.InputContext"
+
+#define IC_NAME_MAX 64
+#define DBUS_TIMEOUT 500
+
+typedef struct _FcitxClient
+{
+ SDL_DBusContext *dbus;
+
+ char servicename[IC_NAME_MAX];
+ char icname[IC_NAME_MAX];
+
+ int id;
+
+ SDL_Rect cursor_rect;
+} FcitxClient;
+
+static FcitxClient fcitx_client;
+
+static int
+GetDisplayNumber()
+{
+ const char *display = SDL_getenv("DISPLAY");
+ const char *p = NULL;
+ int number = 0;
+
+ if (display == NULL)
+ return 0;
+
+ display = SDL_strchr(display, ':');
+ if (display == NULL)
+ return 0;
+
+ display++;
+ p = SDL_strchr(display, '.');
+ if (p == NULL && display != NULL) {
+ number = SDL_strtod(display, NULL);
+ } else {
+ char *buffer = SDL_strdup(display);
+ buffer[p - display] = '\0';
+ number = SDL_strtod(buffer, NULL);
+ SDL_free(buffer);
+ }
+
+ return number;
+}
+
+static char*
+GetAppName()
+{
+#if defined(__LINUX__) || defined(__FREEBSD__)
+ char *spot;
+ char procfile[1024];
+ char linkfile[1024];
+ int linksize;
+
+#if defined(__LINUX__)
+ SDL_snprintf(procfile, sizeof(procfile), "/proc/%d/exe", getpid());
+#elif defined(__FREEBSD__)
+ SDL_snprintf(procfile, sizeof(procfile), "/proc/%d/file", getpid());
+#endif
+ linksize = readlink(procfile, linkfile, sizeof(linkfile) - 1);
+ if (linksize > 0) {
+ linkfile[linksize] = '\0';
+ spot = SDL_strrchr(linkfile, '/');
+ if (spot) {
+ return SDL_strdup(spot + 1);
+ } else {
+ return SDL_strdup(linkfile);
+ }
+ }
+#endif /* __LINUX__ || __FREEBSD__ */
+
+ return SDL_strdup("SDL_App");
+}
+
+/*
+ * Copied from fcitx source
+ */
+#define CONT(i) ISUTF8_CB(in[i])
+#define VAL(i, s) ((in[i]&0x3f) << s)
+
+static char *
+_fcitx_utf8_get_char(const char *i, uint32_t *chr)
+{
+ const unsigned char* in = (const unsigned char *)i;
+ if (!(in[0] & 0x80)) {
+ *(chr) = *(in);
+ return (char *)in + 1;
+ }
+
+ /* 2-byte, 0x80-0x7ff */
+ if ((in[0] & 0xe0) == 0xc0 && CONT(1)) {
+ *chr = ((in[0] & 0x1f) << 6) | VAL(1, 0);
+ return (char *)in + 2;
+ }
+
+ /* 3-byte, 0x800-0xffff */
+ if ((in[0] & 0xf0) == 0xe0 && CONT(1) && CONT(2)) {
+ *chr = ((in[0] & 0xf) << 12) | VAL(1, 6) | VAL(2, 0);
+ return (char *)in + 3;
+ }
+
+ /* 4-byte, 0x10000-0x1FFFFF */
+ if ((in[0] & 0xf8) == 0xf0 && CONT(1) && CONT(2) && CONT(3)) {
+ *chr = ((in[0] & 0x7) << 18) | VAL(1, 12) | VAL(2, 6) | VAL(3, 0);
+ return (char *)in + 4;
+ }
+
+ /* 5-byte, 0x200000-0x3FFFFFF */
+ if ((in[0] & 0xfc) == 0xf8 && CONT(1) && CONT(2) && CONT(3) && CONT(4)) {
+ *chr = ((in[0] & 0x3) << 24) | VAL(1, 18) | VAL(2, 12) | VAL(3, 6) | VAL(4, 0);
+ return (char *)in + 5;
+ }
+
+ /* 6-byte, 0x400000-0x7FFFFFF */
+ if ((in[0] & 0xfe) == 0xfc && CONT(1) && CONT(2) && CONT(3) && CONT(4) && CONT(5)) {
+ *chr = ((in[0] & 0x1) << 30) | VAL(1, 24) | VAL(2, 18) | VAL(3, 12) | VAL(4, 6) | VAL(5, 0);
+ return (char *)in + 6;
+ }
+
+ *chr = *in;
+
+ return (char *)in + 1;
+}
+
+static size_t
+_fcitx_utf8_strlen(const char *s)
+{
+ unsigned int l = 0;
+
+ while (*s) {
+ uint32_t chr;
+
+ s = _fcitx_utf8_get_char(s, &chr);
+ l++;
+ }
+
+ return l;
+}
+
+static DBusHandlerResult
+DBus_MessageFilter(DBusConnection *conn, DBusMessage *msg, void *data)
+{
+ SDL_DBusContext *dbus = (SDL_DBusContext *)data;
+
+ if (dbus->message_is_signal(msg, FCITX_IC_DBUS_INTERFACE, "CommitString")) {
+ DBusMessageIter iter;
+ const char *text = NULL;
+
+ dbus->message_iter_init(msg, &iter);
+ dbus->message_iter_get_basic(&iter, &text);
+
+ if (text)
+ SDL_SendKeyboardText(text);
+
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ if (dbus->message_is_signal(msg, FCITX_IC_DBUS_INTERFACE, "UpdatePreedit")) {
+ DBusMessageIter iter;
+ const char *text;
+
+ dbus->message_iter_init(msg, &iter);
+ dbus->message_iter_get_basic(&iter, &text);
+
+ if (text && *text) {
+ char buf[SDL_TEXTEDITINGEVENT_TEXT_SIZE];
+ size_t text_bytes = SDL_strlen(text), i = 0;
+ size_t cursor = 0;
+
+ while (i < text_bytes) {
+ size_t sz = SDL_utf8strlcpy(buf, text + i, sizeof(buf));
+ size_t chars = _fcitx_utf8_strlen(buf);
+
+ SDL_SendEditingText(buf, cursor, chars);
+
+ i += sz;
+ cursor += chars;
+ }
+ }
+
+ SDL_Fcitx_UpdateTextRect(NULL);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static DBusMessage*
+FcitxClientICNewMethod(FcitxClient *client,
+ const char *method)
+{
+ SDL_DBusContext *dbus = client->dbus;
+ return dbus->message_new_method_call(
+ client->servicename,
+ client->icname,
+ FCITX_IC_DBUS_INTERFACE,
+ method);
+}
+
+static void
+FcitxClientICCallMethod(FcitxClient *client,
+ const char *method)
+{
+ SDL_DBusContext *dbus = client->dbus;
+ DBusMessage *msg = FcitxClientICNewMethod(client, method);
+
+ if (msg == NULL)
+ return ;
+
+ if (dbus->connection_send(dbus->session_conn, msg, NULL)) {
+ dbus->connection_flush(dbus->session_conn);
+ }
+
+ dbus->message_unref(msg);
+}
+
+static void
+Fcitx_SetCapabilities(void *data,
+ const char *name,
+ const char *old_val,
+ const char *internal_editing)
+{
+ FcitxClient *client = (FcitxClient *)data;
+ SDL_DBusContext *dbus = client->dbus;
+ Uint32 caps = CAPACITY_NONE;
+
+ DBusMessage *msg = FcitxClientICNewMethod(client, "SetCapacity");
+ if (msg == NULL)
+ return ;
+
+ if (!(internal_editing && *internal_editing == '1')) {
+ caps |= CAPACITY_PREEDIT;
+ }
+
+ dbus->message_append_args(msg,
+ DBUS_TYPE_UINT32, &caps,
+ DBUS_TYPE_INVALID);
+ if (dbus->connection_send(dbus->session_conn, msg, NULL)) {
+ dbus->connection_flush(dbus->session_conn);
+ }
+
+ dbus->message_unref(msg);
+}
+
+static void
+FcitxClientCreateIC(FcitxClient *client)
+{
+ char *appname = NULL;
+ pid_t pid = 0;
+ int id = 0;
+ SDL_bool enable;
+ Uint32 arg1, arg2, arg3, arg4;
+
+ SDL_DBusContext *dbus = client->dbus;
+ DBusMessage *reply = NULL;
+ DBusMessage *msg = dbus->message_new_method_call(
+ client->servicename,
+ FCITX_IM_DBUS_PATH,
+ FCITX_IM_DBUS_INTERFACE,
+ "CreateICv3"
+ );
+
+ if (msg == NULL)
+ return ;
+
+ appname = GetAppName();
+ pid = getpid();
+ dbus->message_append_args(msg,
+ DBUS_TYPE_STRING, &appname,
+ DBUS_TYPE_INT32, &pid,
+ DBUS_TYPE_INVALID);
+
+ do {
+ reply = dbus->connection_send_with_reply_and_block(
+ dbus->session_conn,
+ msg,
+ DBUS_TIMEOUT,
+ NULL);
+
+ if (!reply)
+ break;
+ if (!dbus->message_get_args(reply, NULL,
+ DBUS_TYPE_INT32, &id,
+ DBUS_TYPE_BOOLEAN, &enable,
+ DBUS_TYPE_UINT32, &arg1,
+ DBUS_TYPE_UINT32, &arg2,
+ DBUS_TYPE_UINT32, &arg3,
+ DBUS_TYPE_UINT32, &arg4,
+ DBUS_TYPE_INVALID))
+ break;
+
+ if (id < 0)
+ break;
+ client->id = id;
+
+ SDL_snprintf(client->icname, IC_NAME_MAX,
+ FCITX_IC_DBUS_PATH, client->id);
+
+ dbus->bus_add_match(dbus->session_conn,
+ "type='signal', interface='org.fcitx.Fcitx.InputContext'",
+ NULL);
+ dbus->connection_add_filter(dbus->session_conn,
+ &DBus_MessageFilter, dbus,
+ NULL);
+ dbus->connection_flush(dbus->session_conn);
+
+ SDL_AddHintCallback(SDL_HINT_IME_INTERNAL_EDITING, &Fcitx_SetCapabilities, client);
+ }
+ while (0);
+
+ if (reply)
+ dbus->message_unref(reply);
+ dbus->message_unref(msg);
+ SDL_free(appname);
+}
+
+static Uint32
+Fcitx_ModState(void)
+{
+ Uint32 fcitx_mods = 0;
+ SDL_Keymod sdl_mods = SDL_GetModState();
+
+ if (sdl_mods & KMOD_SHIFT) fcitx_mods |= FcitxKeyState_Shift;
+ if (sdl_mods & KMOD_CAPS) fcitx_mods |= FcitxKeyState_CapsLock;
+ if (sdl_mods & KMOD_CTRL) fcitx_mods |= FcitxKeyState_Ctrl;
+ if (sdl_mods & KMOD_ALT) fcitx_mods |= FcitxKeyState_Alt;
+ if (sdl_mods & KMOD_NUM) fcitx_mods |= FcitxKeyState_NumLock;
+ if (sdl_mods & KMOD_LGUI) fcitx_mods |= FcitxKeyState_Super;
+ if (sdl_mods & KMOD_RGUI) fcitx_mods |= FcitxKeyState_Meta;
+
+ return fcitx_mods;
+}
+
+SDL_bool
+SDL_Fcitx_Init()
+{
+ fcitx_client.dbus = SDL_DBus_GetContext();
+
+ fcitx_client.cursor_rect.x = -1;
+ fcitx_client.cursor_rect.y = -1;
+ fcitx_client.cursor_rect.w = 0;
+ fcitx_client.cursor_rect.h = 0;
+
+ SDL_snprintf(fcitx_client.servicename, IC_NAME_MAX,
+ "%s-%d",
+ FCITX_DBUS_SERVICE, GetDisplayNumber());
+
+ FcitxClientCreateIC(&fcitx_client);
+
+ return SDL_TRUE;
+}
+
+void
+SDL_Fcitx_Quit()
+{
+ FcitxClientICCallMethod(&fcitx_client, "DestroyIC");
+}
+
+void
+SDL_Fcitx_SetFocus(SDL_bool focused)
+{
+ if (focused) {
+ FcitxClientICCallMethod(&fcitx_client, "FocusIn");
+ } else {
+ FcitxClientICCallMethod(&fcitx_client, "FocusOut");
+ }
+}
+
+void
+SDL_Fcitx_Reset(void)
+{
+ FcitxClientICCallMethod(&fcitx_client, "Reset");
+ FcitxClientICCallMethod(&fcitx_client, "CloseIC");
+}
+
+SDL_bool
+SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
+{
+ DBusMessage *msg = NULL;
+ DBusMessage *reply = NULL;
+ SDL_DBusContext *dbus = fcitx_client.dbus;
+
+ Uint32 state = 0;
+ SDL_bool handled = SDL_FALSE;
+ int type = FCITX_PRESS_KEY;
+ Uint32 event_time = 0;
+
+ msg = FcitxClientICNewMethod(&fcitx_client, "ProcessKeyEvent");
+ if (msg == NULL)
+ return SDL_FALSE;
+
+ state = Fcitx_ModState();
+ dbus->message_append_args(msg,
+ DBUS_TYPE_UINT32, &keysym,
+ DBUS_TYPE_UINT32, &keycode,
+ DBUS_TYPE_UINT32, &state,
+ DBUS_TYPE_INT32, &type,
+ DBUS_TYPE_UINT32, &event_time,
+ DBUS_TYPE_INVALID);
+
+ reply = dbus->connection_send_with_reply_and_block(dbus->session_conn,
+ msg,
+ -1,
+ NULL);
+
+ if (reply) {
+ dbus->message_get_args(reply,
+ NULL,
+ DBUS_TYPE_INT32, &handled,
+ DBUS_TYPE_INVALID);
+
+ dbus->message_unref(reply);
+ }
+
+ if (handled) {
+ SDL_Fcitx_UpdateTextRect(NULL);
+ }
+
+ return handled;
+}
+
+void
+SDL_Fcitx_UpdateTextRect(SDL_Rect *rect)
+{
+ SDL_Window *focused_win = NULL;
+ SDL_SysWMinfo info;
+ int x = 0, y = 0;
+ SDL_Rect *cursor = &fcitx_client.cursor_rect;
+
+ SDL_DBusContext *dbus = fcitx_client.dbus;
+ DBusMessage *msg = NULL;
+ DBusConnection *conn;
+
+ if (rect) {
+ SDL_memcpy(cursor, rect, sizeof(SDL_Rect));
+ }
+
+ focused_win = SDL_GetKeyboardFocus();
+ if (!focused_win) {
+ return ;
+ }
+
+ SDL_VERSION(&info.version);
+ if (!SDL_GetWindowWMInfo(focused_win, &info)) {
+ return;
+ }
+
+ SDL_GetWindowPosition(focused_win, &x, &y);
+
+#if SDL_VIDEO_DRIVER_X11
+ if (info.subsystem == SDL_SYSWM_X11) {
+ SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_GetDisplayForWindow(focused_win)->driverdata;
+
+ Display *x_disp = info.info.x11.display;
+ Window x_win = info.info.x11.window;
+ int x_screen = displaydata->screen;
+ Window unused;
+ X11_XTranslateCoordinates(x_disp, x_win, RootWindow(x_disp, x_screen), 0, 0, &x, &y, &unused);
+ }
+#endif
+
+ if (cursor->x == -1 && cursor->y == -1 && cursor->w == 0 && cursor->h == 0) {
+ // move to bottom left
+ int w = 0, h = 0;
+ SDL_GetWindowSize(focused_win, &w, &h);
+ cursor->x = 0;
+ cursor->y = h;
+ }
+
+ x += cursor->x;
+ y += cursor->y;
+
+ msg = FcitxClientICNewMethod(&fcitx_client, "SetCursorRect");
+ if (msg == NULL)
+ return ;
+
+ dbus->message_append_args(msg,
+ DBUS_TYPE_INT32, &x,
+ DBUS_TYPE_INT32, &y,
+ DBUS_TYPE_INT32, &cursor->w,
+ DBUS_TYPE_INT32, &cursor->h,
+ DBUS_TYPE_INVALID);
+
+ conn = dbus->session_conn;
+ if (dbus->connection_send(conn, msg, NULL))
+ dbus->connection_flush(conn);
+
+ dbus->message_unref(msg);
+}
+
+void
+SDL_Fcitx_PumpEvents()
+{
+ SDL_DBusContext *dbus = fcitx_client.dbus;
+ DBusConnection *conn = dbus->session_conn;
+
+ dbus->connection_read_write(conn, 0);
+
+ while (dbus->connection_dispatch(conn) == DBUS_DISPATCH_DATA_REMAINS) {
+ /* Do nothing, actual work happens in DBus_MessageFilter */
+ usleep(10);
+ }
+}
+
+#endif /* HAVE_FCITX_FRONTEND_H */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/core/linux/SDL_fcitx.h b/Engine/lib/sdl/src/core/linux/SDL_fcitx.h
new file mode 100644
index 000000000..64020475c
--- /dev/null
+++ b/Engine/lib/sdl/src/core/linux/SDL_fcitx.h
@@ -0,0 +1,40 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2016 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef _SDL_fcitx_h
+#define _SDL_fcitx_h
+
+#include "../../SDL_internal.h"
+
+#include "SDL_stdinc.h"
+#include "SDL_rect.h"
+
+extern SDL_bool SDL_Fcitx_Init(void);
+extern void SDL_Fcitx_Quit(void);
+extern void SDL_Fcitx_SetFocus(SDL_bool focused);
+extern void SDL_Fcitx_Reset(void);
+extern SDL_bool SDL_Fcitx_ProcessKeyEvent(Uint32 keysym, Uint32 keycode);
+extern void SDL_Fcitx_UpdateTextRect(SDL_Rect *rect);
+extern void SDL_Fcitx_PumpEvents();
+
+#endif /* _SDL_fcitx_h */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/core/linux/SDL_ibus.c b/Engine/lib/sdl/src/core/linux/SDL_ibus.c
index c9804c90a..3d63b8b30 100644
--- a/Engine/lib/sdl/src/core/linux/SDL_ibus.c
+++ b/Engine/lib/sdl/src/core/linux/SDL_ibus.c
@@ -42,7 +42,7 @@ static const char IBUS_INTERFACE[] = "org.freedesktop.IBus";
static const char IBUS_INPUT_INTERFACE[] = "org.freedesktop.IBus.InputContext";
static char *input_ctx_path = NULL;
-static SDL_Rect ibus_cursor_rect = {0};
+static SDL_Rect ibus_cursor_rect = { 0, 0, 0, 0 };
static DBusConnection *ibus_conn = NULL;
static char *ibus_addr_file = NULL;
int inotify_fd = -1, inotify_wd = -1;
@@ -341,7 +341,9 @@ IBus_SetupConnection(SDL_DBusContext *dbus, const char* addr)
const char *path = NULL;
SDL_bool result = SDL_FALSE;
DBusMessage *msg;
- DBusObjectPathVTable ibus_vtable = {0};
+ DBusObjectPathVTable ibus_vtable;
+
+ SDL_zero(ibus_vtable);
ibus_vtable.message_function = &IBus_MessageHandler;
ibus_conn = dbus->connection_open_private(addr, NULL);
diff --git a/Engine/lib/sdl/src/core/linux/SDL_ime.c b/Engine/lib/sdl/src/core/linux/SDL_ime.c
new file mode 100644
index 000000000..049bd6e02
--- /dev/null
+++ b/Engine/lib/sdl/src/core/linux/SDL_ime.c
@@ -0,0 +1,138 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2016 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "SDL_ime.h"
+#include "SDL_ibus.h"
+#include "SDL_fcitx.h"
+
+typedef SDL_bool (*_SDL_IME_Init)();
+typedef void (*_SDL_IME_Quit)();
+typedef void (*_SDL_IME_SetFocus)(SDL_bool);
+typedef void (*_SDL_IME_Reset)();
+typedef SDL_bool (*_SDL_IME_ProcessKeyEvent)(Uint32, Uint32);
+typedef void (*_SDL_IME_UpdateTextRect)(SDL_Rect *);
+typedef void (*_SDL_IME_PumpEvents)();
+
+static _SDL_IME_Init SDL_IME_Init_Real = NULL;
+static _SDL_IME_Quit SDL_IME_Quit_Real = NULL;
+static _SDL_IME_SetFocus SDL_IME_SetFocus_Real = NULL;
+static _SDL_IME_Reset SDL_IME_Reset_Real = NULL;
+static _SDL_IME_ProcessKeyEvent SDL_IME_ProcessKeyEvent_Real = NULL;
+static _SDL_IME_UpdateTextRect SDL_IME_UpdateTextRect_Real = NULL;
+static _SDL_IME_PumpEvents SDL_IME_PumpEvents_Real = NULL;
+
+static void
+InitIME()
+{
+ static SDL_bool inited = SDL_FALSE;
+#ifdef HAVE_FCITX_FRONTEND_H
+ const char *im_module = SDL_getenv("SDL_IM_MODULE");
+ const char *xmodifiers = SDL_getenv("XMODIFIERS");
+#endif
+
+ if (inited == SDL_TRUE)
+ return;
+
+ inited = SDL_TRUE;
+
+ /* See if fcitx IME support is being requested */
+#ifdef HAVE_FCITX_FRONTEND_H
+ if (!SDL_IME_Init_Real &&
+ ((im_module && SDL_strcmp(im_module, "fcitx") == 0) ||
+ (!im_module && xmodifiers && SDL_strstr(xmodifiers, "@im=fcitx") != NULL))) {
+ SDL_IME_Init_Real = SDL_Fcitx_Init;
+ SDL_IME_Quit_Real = SDL_Fcitx_Quit;
+ SDL_IME_SetFocus_Real = SDL_Fcitx_SetFocus;
+ SDL_IME_Reset_Real = SDL_Fcitx_Reset;
+ SDL_IME_ProcessKeyEvent_Real = SDL_Fcitx_ProcessKeyEvent;
+ SDL_IME_UpdateTextRect_Real = SDL_Fcitx_UpdateTextRect;
+ SDL_IME_PumpEvents_Real = SDL_Fcitx_PumpEvents;
+ }
+#endif /* HAVE_FCITX_FRONTEND_H */
+
+ /* default to IBus */
+#ifdef HAVE_IBUS_IBUS_H
+ if (!SDL_IME_Init_Real) {
+ SDL_IME_Init_Real = SDL_IBus_Init;
+ SDL_IME_Quit_Real = SDL_IBus_Quit;
+ SDL_IME_SetFocus_Real = SDL_IBus_SetFocus;
+ SDL_IME_Reset_Real = SDL_IBus_Reset;
+ SDL_IME_ProcessKeyEvent_Real = SDL_IBus_ProcessKeyEvent;
+ SDL_IME_UpdateTextRect_Real = SDL_IBus_UpdateTextRect;
+ SDL_IME_PumpEvents_Real = SDL_IBus_PumpEvents;
+ }
+#endif /* HAVE_IBUS_IBUS_H */
+}
+
+SDL_bool
+SDL_IME_Init(void)
+{
+ InitIME();
+
+ if (SDL_IME_Init_Real)
+ return SDL_IME_Init_Real();
+
+ return SDL_FALSE;
+}
+
+void
+SDL_IME_Quit(void)
+{
+ if (SDL_IME_Quit_Real)
+ SDL_IME_Quit_Real();
+}
+
+void
+SDL_IME_SetFocus(SDL_bool focused)
+{
+ if (SDL_IME_SetFocus_Real)
+ SDL_IME_SetFocus_Real(focused);
+}
+
+void
+SDL_IME_Reset(void)
+{
+ if (SDL_IME_Reset_Real)
+ SDL_IME_Reset_Real();
+}
+
+SDL_bool
+SDL_IME_ProcessKeyEvent(Uint32 keysym, Uint32 keycode)
+{
+ if (SDL_IME_ProcessKeyEvent_Real)
+ return SDL_IME_ProcessKeyEvent_Real(keysym, keycode);
+
+ return SDL_FALSE;
+}
+
+void
+SDL_IME_UpdateTextRect(SDL_Rect *rect)
+{
+ if (SDL_IME_UpdateTextRect_Real)
+ SDL_IME_UpdateTextRect_Real(rect);
+}
+
+void
+SDL_IME_PumpEvents()
+{
+ if (SDL_IME_PumpEvents_Real)
+ SDL_IME_PumpEvents_Real();
+}
diff --git a/Engine/lib/sdl/src/core/linux/SDL_ime.h b/Engine/lib/sdl/src/core/linux/SDL_ime.h
new file mode 100644
index 000000000..22b31de39
--- /dev/null
+++ b/Engine/lib/sdl/src/core/linux/SDL_ime.h
@@ -0,0 +1,38 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2016 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef _SDL_ime_h
+#define _SDL_ime_h
+
+#include "../../SDL_internal.h"
+
+#include "SDL_stdinc.h"
+#include "SDL_rect.h"
+
+extern SDL_bool SDL_IME_Init();
+extern void SDL_IME_Quit();
+extern void SDL_IME_SetFocus(SDL_bool focused);
+extern void SDL_IME_Reset();
+extern SDL_bool SDL_IME_ProcessKeyEvent(Uint32 keysym, Uint32 keycode);
+extern void SDL_IME_UpdateTextRect(SDL_Rect *rect);
+extern void SDL_IME_PumpEvents();
+
+#endif /* _SDL_ime_h */
diff --git a/Engine/lib/sdl/src/core/linux/SDL_udev.c b/Engine/lib/sdl/src/core/linux/SDL_udev.c
index 099cc435e..ae78ddd68 100644
--- a/Engine/lib/sdl/src/core/linux/SDL_udev.c
+++ b/Engine/lib/sdl/src/core/linux/SDL_udev.c
@@ -349,7 +349,9 @@ guess_device_class(struct udev_device *dev)
} else if (test_bit(BTN_MOUSE, bitmask_key)) {
devclass |= SDL_UDEV_DEVICE_MOUSE; /* ID_INPUT_MOUSE */
} else if (test_bit(BTN_TOUCH, bitmask_key)) {
- ; /* ID_INPUT_TOUCHSCREEN */
+ /* TODO: better determining between touchscreen and multitouch touchpad,
+ see https://github.com/systemd/systemd/blob/master/src/udev/udev-builtin-input_id.c */
+ devclass |= SDL_UDEV_DEVICE_TOUCHSCREEN; /* ID_INPUT_TOUCHSCREEN */
}
if (test_bit(BTN_TRIGGER, bitmask_key) ||
@@ -411,6 +413,11 @@ device_event(SDL_UDEV_deviceevent type, struct udev_device *dev)
if (val != NULL && SDL_strcmp(val, "1") == 0 ) {
devclass |= SDL_UDEV_DEVICE_MOUSE;
}
+
+ val = _this->udev_device_get_property_value(dev, "ID_INPUT_TOUCHSCREEN");
+ if (val != NULL && SDL_strcmp(val, "1") == 0 ) {
+ devclass |= SDL_UDEV_DEVICE_TOUCHSCREEN;
+ }
/* The undocumented rule is:
- All devices with keys get ID_INPUT_KEY
diff --git a/Engine/lib/sdl/src/core/linux/SDL_udev.h b/Engine/lib/sdl/src/core/linux/SDL_udev.h
index 2e4434e62..9ffbb3252 100644
--- a/Engine/lib/sdl/src/core/linux/SDL_udev.h
+++ b/Engine/lib/sdl/src/core/linux/SDL_udev.h
@@ -42,17 +42,19 @@
typedef enum
{
- SDL_UDEV_DEVICEADDED = 0x0001,
+ SDL_UDEV_DEVICEADDED = 1,
SDL_UDEV_DEVICEREMOVED
} SDL_UDEV_deviceevent;
/* A device can be any combination of these classes */
typedef enum
{
+ SDL_UDEV_DEVICE_UNKNOWN = 0x0000,
SDL_UDEV_DEVICE_MOUSE = 0x0001,
SDL_UDEV_DEVICE_KEYBOARD = 0x0002,
SDL_UDEV_DEVICE_JOYSTICK = 0x0004,
- SDL_UDEV_DEVICE_SOUND = 0x0008
+ SDL_UDEV_DEVICE_SOUND = 0x0008,
+ SDL_UDEV_DEVICE_TOUCHSCREEN = 0x0010
} SDL_UDEV_deviceclass;
typedef void (*SDL_UDEV_Callback)(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath);
diff --git a/Engine/lib/sdl/src/core/windows/SDL_windows.c b/Engine/lib/sdl/src/core/windows/SDL_windows.c
index bc4afe0aa..6433fe26f 100644
--- a/Engine/lib/sdl/src/core/windows/SDL_windows.c
+++ b/Engine/lib/sdl/src/core/windows/SDL_windows.c
@@ -124,6 +124,84 @@ BOOL WIN_IsWindowsVistaOrGreater()
#endif
}
+/*
+WAVExxxCAPS gives you 31 bytes for the device name, and just truncates if it's
+longer. However, since WinXP, you can use the WAVExxxCAPS2 structure, which
+will give you a name GUID. The full name is in the Windows Registry under
+that GUID, located here: HKLM\System\CurrentControlSet\Control\MediaCategories
+
+Note that drivers can report GUID_NULL for the name GUID, in which case,
+Windows makes a best effort to fill in those 31 bytes in the usual place.
+This info summarized from MSDN:
+
+http://web.archive.org/web/20131027093034/http://msdn.microsoft.com/en-us/library/windows/hardware/ff536382(v=vs.85).aspx
+
+Always look this up in the registry if possible, because the strings are
+different! At least on Win10, I see "Yeti Stereo Microphone" in the
+Registry, and a unhelpful "Microphone(Yeti Stereo Microph" in winmm. Sigh.
+
+(Also, DirectSound shouldn't be limited to 32 chars, but its device enum
+has the same problem.)
+*/
+char *
+WIN_LookupAudioDeviceName(const WCHAR *name, const GUID *guid)
+{
+#if __WINRT__
+ return WIN_StringToUTF8(name); /* No registry access on WinRT/UWP, go with what we've got. */
+#else
+ static const GUID nullguid = { 0 };
+ const unsigned char *ptr;
+ char keystr[128];
+ WCHAR *strw = NULL;
+ SDL_bool rc;
+ HKEY hkey;
+ DWORD len = 0;
+ char *retval = NULL;
+
+ if (SDL_memcmp(guid, &nullguid, sizeof (*guid)) == 0) {
+ return WIN_StringToUTF8(name); /* No GUID, go with what we've got. */
+ }
+
+ ptr = (const unsigned char *) guid;
+ SDL_snprintf(keystr, sizeof (keystr),
+ "System\\CurrentControlSet\\Control\\MediaCategories\\{%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
+ ptr[3], ptr[2], ptr[1], ptr[0], ptr[5], ptr[4], ptr[7], ptr[6],
+ ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13], ptr[14], ptr[15]);
+
+ strw = WIN_UTF8ToString(keystr);
+ rc = (RegOpenKeyExW(HKEY_LOCAL_MACHINE, strw, 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS);
+ SDL_free(strw);
+ if (!rc) {
+ return WIN_StringToUTF8(name); /* oh well. */
+ }
+
+ rc = (RegQueryValueExW(hkey, L"Name", NULL, NULL, NULL, &len) == ERROR_SUCCESS);
+ if (!rc) {
+ RegCloseKey(hkey);
+ return WIN_StringToUTF8(name); /* oh well. */
+ }
+
+ strw = (WCHAR *) SDL_malloc(len + sizeof (WCHAR));
+ if (!strw) {
+ RegCloseKey(hkey);
+ return WIN_StringToUTF8(name); /* oh well. */
+ }
+
+ rc = (RegQueryValueExW(hkey, L"Name", NULL, NULL, (LPBYTE) strw, &len) == ERROR_SUCCESS);
+ RegCloseKey(hkey);
+ if (!rc) {
+ SDL_free(strw);
+ return WIN_StringToUTF8(name); /* oh well. */
+ }
+
+ strw[len / 2] = 0; /* make sure it's null-terminated. */
+
+ retval = WIN_StringToUTF8(strw);
+ SDL_free(strw);
+ return retval ? retval : WIN_StringToUTF8(name);
+#endif /* if __WINRT__ / else */
+}
+
#endif /* __WIN32__ || __WINRT__ */
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/core/windows/SDL_windows.h b/Engine/lib/sdl/src/core/windows/SDL_windows.h
index 0c99b03d4..0f67e4be5 100644
--- a/Engine/lib/sdl/src/core/windows/SDL_windows.h
+++ b/Engine/lib/sdl/src/core/windows/SDL_windows.h
@@ -59,6 +59,9 @@ extern void WIN_CoUninitialize(void);
/* Returns SDL_TRUE if we're running on Windows Vista and newer */
extern BOOL WIN_IsWindowsVistaOrGreater();
+/* You need to SDL_free() the result of this call. */
+extern char *WIN_LookupAudioDeviceName(const WCHAR *name, const GUID *guid);
+
#endif /* _INCLUDED_WINDOWS_H */
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/core/winrt/SDL_winrtapp_direct3d.cpp b/Engine/lib/sdl/src/core/winrt/SDL_winrtapp_direct3d.cpp
index 5ab2ef9a2..e4ffadaad 100644
--- a/Engine/lib/sdl/src/core/winrt/SDL_winrtapp_direct3d.cpp
+++ b/Engine/lib/sdl/src/core/winrt/SDL_winrtapp_direct3d.cpp
@@ -254,6 +254,18 @@ void SDL_WinRTApp::Initialize(CoreApplicationView^ applicationView)
CoreApplication::Exiting +=
ref new EventHandler(this, &SDL_WinRTApp::OnExiting);
+
+#if NTDDI_VERSION >= NTDDI_WIN10
+ /* HACK ALERT! Xbox One doesn't seem to detect gamepads unless something
+ gets registered to receive Win10's Windows.Gaming.Input.Gamepad.GamepadAdded
+ events. We'll register an event handler for these events here, to make
+ sure that gamepad detection works later on, if requested.
+ */
+ Windows::Gaming::Input::Gamepad::GamepadAdded +=
+ ref new Windows::Foundation::EventHandler(
+ this, &SDL_WinRTApp::OnGamepadAdded
+ );
+#endif
}
#if NTDDI_VERSION > NTDDI_WIN8
@@ -810,11 +822,8 @@ static void WINRT_OnBackButtonPressed(BackButtonEventArgs ^ args)
SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_AC_BACK);
SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_AC_BACK);
- const char *hint = SDL_GetHint(SDL_HINT_WINRT_HANDLE_BACK_BUTTON);
- if (hint) {
- if (*hint == '1') {
- args->Handled = true;
- }
+ if (SDL_GetHintBoolean(SDL_HINT_WINRT_HANDLE_BACK_BUTTON, SDL_FALSE)) {
+ args->Handled = true;
}
}
@@ -832,3 +841,15 @@ void SDL_WinRTApp::OnBackButtonPressed(Platform::Object^ sender, Windows::Phone:
}
#endif
+#if NTDDI_VERSION >= NTDDI_WIN10
+void SDL_WinRTApp::OnGamepadAdded(Platform::Object ^sender, Windows::Gaming::Input::Gamepad ^gamepad)
+{
+ /* HACK ALERT: Nothing needs to be done here, as this method currently
+ only exists to allow something to be registered with Win10's
+ GamepadAdded event, an operation that seems to be necessary to get
+ Xinput-based detection to work on Xbox One.
+ */
+}
+#endif
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/core/winrt/SDL_winrtapp_direct3d.h b/Engine/lib/sdl/src/core/winrt/SDL_winrtapp_direct3d.h
index 0b69c2bb9..4b48115f0 100644
--- a/Engine/lib/sdl/src/core/winrt/SDL_winrtapp_direct3d.h
+++ b/Engine/lib/sdl/src/core/winrt/SDL_winrtapp_direct3d.h
@@ -80,6 +80,10 @@ protected:
void OnBackButtonPressed(Platform::Object^ sender, Windows::Phone::UI::Input::BackPressedEventArgs^ args);
#endif
+#if NTDDI_VERSION >= NTDDI_WIN10
+ void OnGamepadAdded(Platform::Object ^sender, Windows::Gaming::Input::Gamepad ^gamepad);
+#endif
+
private:
bool m_windowClosed;
bool m_windowVisible;
diff --git a/Engine/lib/sdl/src/dynapi/SDL_dynapi.c b/Engine/lib/sdl/src/dynapi/SDL_dynapi.c
index 1411f8c93..c26baf379 100644
--- a/Engine/lib/sdl/src/dynapi/SDL_dynapi.c
+++ b/Engine/lib/sdl/src/dynapi/SDL_dynapi.c
@@ -293,7 +293,7 @@ SDL_InitDynamicAPI(void)
* SDL_CreateThread() would also call this function before building the
* new thread).
*/
- static volatile SDL_bool already_initialized = SDL_FALSE;
+ static SDL_bool already_initialized = SDL_FALSE;
/* SDL_AtomicLock calls SDL mutex functions to emulate if
SDL_ATOMIC_DISABLED, which we can't do here, so in such a
diff --git a/Engine/lib/sdl/src/dynapi/SDL_dynapi.h b/Engine/lib/sdl/src/dynapi/SDL_dynapi.h
index 5faac2194..5e78338f2 100644
--- a/Engine/lib/sdl/src/dynapi/SDL_dynapi.h
+++ b/Engine/lib/sdl/src/dynapi/SDL_dynapi.h
@@ -43,9 +43,15 @@
#include "TargetConditionals.h"
#endif
-#if TARGET_OS_IPHONE || __native_client__ || __EMSCRIPTEN__ /* probably not useful on iOS, NACL or Emscripten. */
+#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE /* probably not useful on iOS. */
#define SDL_DYNAMIC_API 0
-#elif SDL_BUILDING_WINRT /* probaly not useful on WinRT, given current .dll loading restrictions */
+#elif defined(__native_client__) && __native_client__ /* probably not useful on NACL. */
+#define SDL_DYNAMIC_API 0
+#elif defined(__EMSCRIPTEN__) && __EMSCRIPTEN__ /* probably not useful on Emscripten. */
+#define SDL_DYNAMIC_API 0
+#elif defined(SDL_BUILDING_WINRT) && SDL_BUILDING_WINRT /* probably not useful on WinRT, given current .dll loading restrictions */
+#define SDL_DYNAMIC_API 0
+#elif defined(__PSP__) && __PSP__
#define SDL_DYNAMIC_API 0
#elif defined(__clang_analyzer__)
#define SDL_DYNAMIC_API 0 /* Turn off for static analysis, so reports are more clear. */
diff --git a/Engine/lib/sdl/src/dynapi/SDL_dynapi_overrides.h b/Engine/lib/sdl/src/dynapi/SDL_dynapi_overrides.h
index c9ebfffe2..9541611ce 100644
--- a/Engine/lib/sdl/src/dynapi/SDL_dynapi_overrides.h
+++ b/Engine/lib/sdl/src/dynapi/SDL_dynapi_overrides.h
@@ -445,6 +445,8 @@
#define SDL_iconv_close SDL_iconv_close_REAL
#define SDL_iconv SDL_iconv_REAL
#define SDL_iconv_string SDL_iconv_string_REAL
+#define SDL_CreateRGBSurfaceWithFormat SDL_CreateRGBSurfaceWithFormat_REAL
+#define SDL_CreateRGBSurfaceWithFormatFrom SDL_CreateRGBSurfaceWithFormatFrom_REAL
#define SDL_CreateRGBSurface SDL_CreateRGBSurface_REAL
#define SDL_CreateRGBSurfaceFrom SDL_CreateRGBSurfaceFrom_REAL
#define SDL_FreeSurface SDL_FreeSurface_REAL
@@ -597,3 +599,16 @@
#define SDL_JoystickCurrentPowerLevel SDL_JoystickCurrentPowerLevel_REAL
#define SDL_GameControllerFromInstanceID SDL_GameControllerFromInstanceID_REAL
#define SDL_JoystickFromInstanceID SDL_JoystickFromInstanceID_REAL
+#define SDL_GetDisplayUsableBounds SDL_GetDisplayUsableBounds_REAL
+#define SDL_GetWindowBordersSize SDL_GetWindowBordersSize_REAL
+#define SDL_SetWindowOpacity SDL_SetWindowOpacity_REAL
+#define SDL_GetWindowOpacity SDL_GetWindowOpacity_REAL
+#define SDL_SetWindowInputFocus SDL_SetWindowInputFocus_REAL
+#define SDL_SetWindowModalFor SDL_SetWindowModalFor_REAL
+#define SDL_RenderSetIntegerScale SDL_RenderSetIntegerScale_REAL
+#define SDL_RenderGetIntegerScale SDL_RenderGetIntegerScale_REAL
+#define SDL_DequeueAudio SDL_DequeueAudio_REAL
+#define SDL_SetWindowResizable SDL_SetWindowResizable_REAL
+#define SDL_CreateRGBSurfaceWithFormat SDL_CreateRGBSurfaceWithFormat_REAL
+#define SDL_CreateRGBSurfaceWithFormatFrom SDL_CreateRGBSurfaceWithFormatFrom_REAL
+#define SDL_GetHintBoolean SDL_GetHintBoolean_REAL
diff --git a/Engine/lib/sdl/src/dynapi/SDL_dynapi_procs.h b/Engine/lib/sdl/src/dynapi/SDL_dynapi_procs.h
index 3f11a25f9..a08835b26 100644
--- a/Engine/lib/sdl/src/dynapi/SDL_dynapi_procs.h
+++ b/Engine/lib/sdl/src/dynapi/SDL_dynapi_procs.h
@@ -631,3 +631,16 @@ SDL_DYNAPI_PROC(int,SDL_GetDisplayDPI,(int a, float *b, float *c, float *d),(a,b
SDL_DYNAPI_PROC(SDL_JoystickPowerLevel,SDL_JoystickCurrentPowerLevel,(SDL_Joystick *a),(a),return)
SDL_DYNAPI_PROC(SDL_GameController*,SDL_GameControllerFromInstanceID,(SDL_JoystickID a),(a),return)
SDL_DYNAPI_PROC(SDL_Joystick*,SDL_JoystickFromInstanceID,(SDL_JoystickID a),(a),return)
+SDL_DYNAPI_PROC(int,SDL_GetDisplayUsableBounds,(int a, SDL_Rect *b),(a,b),return)
+SDL_DYNAPI_PROC(int,SDL_GetWindowBordersSize,(SDL_Window *a, int *b, int *c, int *d, int *e),(a,b,c,d,e),return)
+SDL_DYNAPI_PROC(int,SDL_SetWindowOpacity,(SDL_Window *a, float b),(a,b),return)
+SDL_DYNAPI_PROC(int,SDL_GetWindowOpacity,(SDL_Window *a, float *b),(a,b),return)
+SDL_DYNAPI_PROC(int,SDL_SetWindowInputFocus,(SDL_Window *a),(a),return)
+SDL_DYNAPI_PROC(int,SDL_SetWindowModalFor,(SDL_Window *a, SDL_Window *b),(a,b),return)
+SDL_DYNAPI_PROC(int,SDL_RenderSetIntegerScale,(SDL_Renderer *a, SDL_bool b),(a,b),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_RenderGetIntegerScale,(SDL_Renderer *a),(a),return)
+SDL_DYNAPI_PROC(Uint32,SDL_DequeueAudio,(SDL_AudioDeviceID a, void *b, Uint32 c),(a,b,c),return)
+SDL_DYNAPI_PROC(void,SDL_SetWindowResizable,(SDL_Window *a, SDL_bool b),(a,b),)
+SDL_DYNAPI_PROC(SDL_Surface*,SDL_CreateRGBSurfaceWithFormat,(Uint32 a, int b, int c, int d, Uint32 e),(a,b,c,d,e),return)
+SDL_DYNAPI_PROC(SDL_Surface*,SDL_CreateRGBSurfaceWithFormatFrom,(void *a, int b, int c, int d, int e, Uint32 f),(a,b,c,d,e,f),return)
+SDL_DYNAPI_PROC(SDL_bool,SDL_GetHintBoolean,(const char *a, SDL_bool b),(a,b),return)
diff --git a/Engine/lib/sdl/src/dynapi/gendynapi.pl b/Engine/lib/sdl/src/dynapi/gendynapi.pl
old mode 100644
new mode 100755
diff --git a/Engine/lib/sdl/src/events/SDL_dropevents.c b/Engine/lib/sdl/src/events/SDL_dropevents.c
index 8f4405efa..49b07d9a6 100644
--- a/Engine/lib/sdl/src/events/SDL_dropevents.c
+++ b/Engine/lib/sdl/src/events/SDL_dropevents.c
@@ -26,21 +26,73 @@
#include "SDL_events_c.h"
#include "SDL_dropevents_c.h"
+#include "../video/SDL_sysvideo.h" /* for SDL_Window internals. */
-int
-SDL_SendDropFile(const char *file)
+
+static int
+SDL_SendDrop(SDL_Window *window, const SDL_EventType evtype, const char *data)
{
- int posted;
+ static SDL_bool app_is_dropping = SDL_FALSE;
+ int posted = 0;
/* Post the event, if desired */
- posted = 0;
- if (SDL_GetEventState(SDL_DROPFILE) == SDL_ENABLE) {
+ if (SDL_GetEventState(evtype) == SDL_ENABLE) {
+ const SDL_bool need_begin = window ? !window->is_dropping : !app_is_dropping;
SDL_Event event;
- event.type = SDL_DROPFILE;
- event.drop.file = SDL_strdup(file);
+
+ if (need_begin) {
+ SDL_zero(event);
+ event.type = SDL_DROPBEGIN;
+
+ if (window) {
+ event.drop.windowID = window->id;
+ }
+
+ posted = (SDL_PushEvent(&event) > 0);
+ if (!posted) {
+ return 0;
+ }
+ if (window) {
+ window->is_dropping = SDL_TRUE;
+ } else {
+ app_is_dropping = SDL_TRUE;
+ }
+ }
+
+ SDL_zero(event);
+ event.type = evtype;
+ event.drop.file = data ? SDL_strdup(data) : NULL;
+ event.drop.windowID = window ? window->id : 0;
posted = (SDL_PushEvent(&event) > 0);
+
+ if (posted && (evtype == SDL_DROPCOMPLETE)) {
+ if (window) {
+ window->is_dropping = SDL_FALSE;
+ } else {
+ app_is_dropping = SDL_FALSE;
+ }
+ }
}
- return (posted);
+ return posted;
}
+int
+SDL_SendDropFile(SDL_Window *window, const char *file)
+{
+ return SDL_SendDrop(window, SDL_DROPFILE, file);
+}
+
+int
+SDL_SendDropText(SDL_Window *window, const char *text)
+{
+ return SDL_SendDrop(window, SDL_DROPTEXT, text);
+}
+
+int
+SDL_SendDropComplete(SDL_Window *window)
+{
+ return SDL_SendDrop(window, SDL_DROPCOMPLETE, NULL);
+}
+
+
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/events/SDL_dropevents_c.h b/Engine/lib/sdl/src/events/SDL_dropevents_c.h
index a60e089f3..a7adb8560 100644
--- a/Engine/lib/sdl/src/events/SDL_dropevents_c.h
+++ b/Engine/lib/sdl/src/events/SDL_dropevents_c.h
@@ -23,7 +23,9 @@
#ifndef _SDL_dropevents_c_h
#define _SDL_dropevents_c_h
-extern int SDL_SendDropFile(const char *file);
+extern int SDL_SendDropFile(SDL_Window *window, const char *file);
+extern int SDL_SendDropText(SDL_Window *window, const char *text);
+extern int SDL_SendDropComplete(SDL_Window *window);
#endif /* _SDL_dropevents_c_h */
diff --git a/Engine/lib/sdl/src/events/SDL_events.c b/Engine/lib/sdl/src/events/SDL_events.c
index ffd103824..2f5b0af29 100644
--- a/Engine/lib/sdl/src/events/SDL_events.c
+++ b/Engine/lib/sdl/src/events/SDL_events.c
@@ -73,15 +73,15 @@ typedef struct _SDL_SysWMEntry
static struct
{
SDL_mutex *lock;
- volatile SDL_bool active;
- volatile int count;
- volatile int max_events_seen;
+ SDL_atomic_t active;
+ SDL_atomic_t count;
+ int max_events_seen;
SDL_EventEntry *head;
SDL_EventEntry *tail;
SDL_EventEntry *free;
SDL_SysWMEntry *wmmsg_used;
SDL_SysWMEntry *wmmsg_free;
-} SDL_EventQ = { NULL, SDL_TRUE, 0, 0, NULL, NULL, NULL, NULL, NULL };
+} SDL_EventQ = { NULL, { 1 }, { 0 }, 0, NULL, NULL, NULL, NULL, NULL };
/* Public functions */
@@ -98,7 +98,7 @@ SDL_StopEventLoop(void)
SDL_LockMutex(SDL_EventQ.lock);
}
- SDL_EventQ.active = SDL_FALSE;
+ SDL_AtomicSet(&SDL_EventQ.active, 0);
if (report && SDL_atoi(report)) {
SDL_Log("SDL EVENT QUEUE: Maximum events in-flight: %d\n",
@@ -127,7 +127,7 @@ SDL_StopEventLoop(void)
wmmsg = next;
}
- SDL_EventQ.count = 0;
+ SDL_AtomicSet(&SDL_EventQ.count, 0);
SDL_EventQ.max_events_seen = 0;
SDL_EventQ.head = NULL;
SDL_EventQ.tail = NULL;
@@ -171,7 +171,7 @@ SDL_StartEventLoop(void)
SDL_EventQ.lock = SDL_CreateMutex();
}
if (SDL_EventQ.lock == NULL) {
- return (-1);
+ return -1;
}
#endif /* !SDL_THREADS_DISABLED */
@@ -180,9 +180,9 @@ SDL_StartEventLoop(void)
SDL_EventState(SDL_TEXTEDITING, SDL_DISABLE);
SDL_EventState(SDL_SYSWMEVENT, SDL_DISABLE);
- SDL_EventQ.active = SDL_TRUE;
+ SDL_AtomicSet(&SDL_EventQ.active, 1);
- return (0);
+ return 0;
}
@@ -191,9 +191,11 @@ static int
SDL_AddEvent(SDL_Event * event)
{
SDL_EventEntry *entry;
+ const int initial_count = SDL_AtomicGet(&SDL_EventQ.count);
+ int final_count;
- if (SDL_EventQ.count >= SDL_MAX_QUEUED_EVENTS) {
- SDL_SetError("Event queue is full (%d events)", SDL_EventQ.count);
+ if (initial_count >= SDL_MAX_QUEUED_EVENTS) {
+ SDL_SetError("Event queue is full (%d events)", initial_count);
return 0;
}
@@ -225,10 +227,10 @@ SDL_AddEvent(SDL_Event * event)
entry->prev = NULL;
entry->next = NULL;
}
- ++SDL_EventQ.count;
- if (SDL_EventQ.count > SDL_EventQ.max_events_seen) {
- SDL_EventQ.max_events_seen = SDL_EventQ.count;
+ final_count = SDL_AtomicAdd(&SDL_EventQ.count, 1) + 1;
+ if (final_count > SDL_EventQ.max_events_seen) {
+ SDL_EventQ.max_events_seen = final_count;
}
return 1;
@@ -256,8 +258,8 @@ SDL_CutEvent(SDL_EventEntry *entry)
entry->next = SDL_EventQ.free;
SDL_EventQ.free = entry;
- SDL_assert(SDL_EventQ.count > 0);
- --SDL_EventQ.count;
+ SDL_assert(SDL_AtomicGet(&SDL_EventQ.count) > 0);
+ SDL_AtomicAdd(&SDL_EventQ.count, -1);
}
/* Lock the event queue, take a peep at it, and unlock it */
@@ -268,7 +270,7 @@ SDL_PeepEvents(SDL_Event * events, int numevents, SDL_eventaction action,
int i, used;
/* Don't look after we've quit */
- if (!SDL_EventQ.active) {
+ if (!SDL_AtomicGet(&SDL_EventQ.active)) {
/* We get a few spurious events at shutdown, so don't warn then */
if (action != SDL_ADDEVENT) {
SDL_SetError("The event system has been shut down");
@@ -285,56 +287,54 @@ SDL_PeepEvents(SDL_Event * events, int numevents, SDL_eventaction action,
} else {
SDL_EventEntry *entry, *next;
SDL_SysWMEntry *wmmsg, *wmmsg_next;
- SDL_Event tmpevent;
Uint32 type;
- /* If 'events' is NULL, just see if they exist */
- if (events == NULL) {
- action = SDL_PEEKEVENT;
- numevents = 1;
- events = &tmpevent;
+ if (action == SDL_GETEVENT) {
+ /* Clean out any used wmmsg data
+ FIXME: Do we want to retain the data for some period of time?
+ */
+ for (wmmsg = SDL_EventQ.wmmsg_used; wmmsg; wmmsg = wmmsg_next) {
+ wmmsg_next = wmmsg->next;
+ wmmsg->next = SDL_EventQ.wmmsg_free;
+ SDL_EventQ.wmmsg_free = wmmsg;
+ }
+ SDL_EventQ.wmmsg_used = NULL;
}
- /* Clean out any used wmmsg data
- FIXME: Do we want to retain the data for some period of time?
- */
- for (wmmsg = SDL_EventQ.wmmsg_used; wmmsg; wmmsg = wmmsg_next) {
- wmmsg_next = wmmsg->next;
- wmmsg->next = SDL_EventQ.wmmsg_free;
- SDL_EventQ.wmmsg_free = wmmsg;
- }
- SDL_EventQ.wmmsg_used = NULL;
-
- for (entry = SDL_EventQ.head; entry && used < numevents; entry = next) {
+ for (entry = SDL_EventQ.head; entry && (!events || used < numevents); entry = next) {
next = entry->next;
type = entry->event.type;
if (minType <= type && type <= maxType) {
- events[used] = entry->event;
- if (entry->event.type == SDL_SYSWMEVENT) {
- /* We need to copy the wmmsg somewhere safe.
- For now we'll guarantee it's valid at least until
- the next call to SDL_PeepEvents()
- */
- if (SDL_EventQ.wmmsg_free) {
- wmmsg = SDL_EventQ.wmmsg_free;
- SDL_EventQ.wmmsg_free = wmmsg->next;
- } else {
- wmmsg = (SDL_SysWMEntry *)SDL_malloc(sizeof(*wmmsg));
+ if (events) {
+ events[used] = entry->event;
+ if (entry->event.type == SDL_SYSWMEVENT) {
+ /* We need to copy the wmmsg somewhere safe.
+ For now we'll guarantee it's valid at least until
+ the next call to SDL_PeepEvents()
+ */
+ if (SDL_EventQ.wmmsg_free) {
+ wmmsg = SDL_EventQ.wmmsg_free;
+ SDL_EventQ.wmmsg_free = wmmsg->next;
+ } else {
+ wmmsg = (SDL_SysWMEntry *)SDL_malloc(sizeof(*wmmsg));
+ }
+ wmmsg->msg = *entry->event.syswm.msg;
+ wmmsg->next = SDL_EventQ.wmmsg_used;
+ SDL_EventQ.wmmsg_used = wmmsg;
+ events[used].syswm.msg = &wmmsg->msg;
+ }
+
+ if (action == SDL_GETEVENT) {
+ SDL_CutEvent(entry);
}
- wmmsg->msg = *entry->event.syswm.msg;
- wmmsg->next = SDL_EventQ.wmmsg_used;
- SDL_EventQ.wmmsg_used = wmmsg;
- events[used].syswm.msg = &wmmsg->msg;
}
++used;
-
- if (action == SDL_GETEVENT) {
- SDL_CutEvent(entry);
- }
}
}
}
- SDL_UnlockMutex(SDL_EventQ.lock);
+ if (SDL_EventQ.lock) {
+ SDL_UnlockMutex(SDL_EventQ.lock);
+ }
} else {
return SDL_SetError("Couldn't lock event queue");
}
@@ -363,7 +363,7 @@ void
SDL_FlushEvents(Uint32 minType, Uint32 maxType)
{
/* Don't look after we've quit */
- if (!SDL_EventQ.active) {
+ if (!SDL_AtomicGet(&SDL_EventQ.active)) {
return;
}
@@ -376,7 +376,7 @@ SDL_FlushEvents(Uint32 minType, Uint32 maxType)
#endif
/* Lock the event queue */
- if (SDL_LockMutex(SDL_EventQ.lock) == 0) {
+ if (SDL_EventQ.lock && SDL_LockMutex(SDL_EventQ.lock) == 0) {
SDL_EventEntry *entry, *next;
Uint32 type;
for (entry = SDL_EventQ.head; entry; entry = next) {
@@ -437,8 +437,6 @@ SDL_WaitEventTimeout(SDL_Event * event, int timeout)
switch (SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT)) {
case -1:
return 0;
- case 1:
- return 1;
case 0:
if (timeout == 0) {
/* Polling and no events, just return */
@@ -450,6 +448,9 @@ SDL_WaitEventTimeout(SDL_Event * event, int timeout)
}
SDL_Delay(10);
break;
+ default:
+ /* Has events */
+ return 1;
}
}
}
diff --git a/Engine/lib/sdl/src/events/SDL_gesture.c b/Engine/lib/sdl/src/events/SDL_gesture.c
index 66def4429..43914202c 100644
--- a/Engine/lib/sdl/src/events/SDL_gesture.c
+++ b/Engine/lib/sdl/src/events/SDL_gesture.c
@@ -21,7 +21,7 @@
#include "../SDL_internal.h"
-/* General mouse handling code for SDL */
+/* General gesture handling code for SDL */
#include "SDL_events.h"
#include "SDL_endian.h"
diff --git a/Engine/lib/sdl/src/events/SDL_mouse.c b/Engine/lib/sdl/src/events/SDL_mouse.c
index 7793de870..4236a9901 100644
--- a/Engine/lib/sdl/src/events/SDL_mouse.c
+++ b/Engine/lib/sdl/src/events/SDL_mouse.c
@@ -322,15 +322,13 @@ static SDL_MouseClickState *GetMouseClickState(SDL_Mouse *mouse, Uint8 button)
return &mouse->clickstate[button];
}
-int
-SDL_SendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state, Uint8 button)
+static int
+SDL_PrivateSendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state, Uint8 button, int clicks)
{
SDL_Mouse *mouse = SDL_GetMouse();
int posted;
Uint32 type;
Uint32 buttonstate = mouse->buttonstate;
- SDL_MouseClickState *clickstate = GetMouseClickState(mouse, button);
- Uint8 click_count;
/* Figure out which event to perform */
switch (state) {
@@ -358,25 +356,28 @@ SDL_SendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state, Uint8
}
mouse->buttonstate = buttonstate;
- if (clickstate) {
- if (state == SDL_PRESSED) {
- Uint32 now = SDL_GetTicks();
+ if (clicks < 0) {
+ SDL_MouseClickState *clickstate = GetMouseClickState(mouse, button);
+ if (clickstate) {
+ if (state == SDL_PRESSED) {
+ Uint32 now = SDL_GetTicks();
- if (SDL_TICKS_PASSED(now, clickstate->last_timestamp + SDL_double_click_time) ||
- SDL_abs(mouse->x - clickstate->last_x) > SDL_double_click_radius ||
- SDL_abs(mouse->y - clickstate->last_y) > SDL_double_click_radius) {
- clickstate->click_count = 0;
- }
- clickstate->last_timestamp = now;
- clickstate->last_x = mouse->x;
- clickstate->last_y = mouse->y;
- if (clickstate->click_count < 255) {
- ++clickstate->click_count;
+ if (SDL_TICKS_PASSED(now, clickstate->last_timestamp + SDL_double_click_time) ||
+ SDL_abs(mouse->x - clickstate->last_x) > SDL_double_click_radius ||
+ SDL_abs(mouse->y - clickstate->last_y) > SDL_double_click_radius) {
+ clickstate->click_count = 0;
+ }
+ clickstate->last_timestamp = now;
+ clickstate->last_x = mouse->x;
+ clickstate->last_y = mouse->y;
+ if (clickstate->click_count < 255) {
+ ++clickstate->click_count;
+ }
}
+ clicks = clickstate->click_count;
+ } else {
+ clicks = 1;
}
- click_count = clickstate->click_count;
- } else {
- click_count = 1;
}
/* Post the event, if desired */
@@ -388,7 +389,7 @@ SDL_SendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state, Uint8
event.button.which = mouseID;
event.button.state = state;
event.button.button = button;
- event.button.clicks = click_count;
+ event.button.clicks = (Uint8) SDL_min(clicks, 255);
event.button.x = mouse->x;
event.button.y = mouse->y;
posted = (SDL_PushEvent(&event) > 0);
@@ -398,10 +399,23 @@ SDL_SendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state, Uint8
if (window && state == SDL_RELEASED) {
SDL_UpdateMouseFocus(window, mouse->x, mouse->y, buttonstate);
}
-
+
return posted;
}
+int
+SDL_SendMouseButtonClicks(SDL_Window * window, SDL_MouseID mouseID, Uint8 state, Uint8 button, int clicks)
+{
+ clicks = SDL_max(clicks, 0);
+ return SDL_PrivateSendMouseButton(window, mouseID, state, button, clicks);
+}
+
+int
+SDL_SendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state, Uint8 button)
+{
+ return SDL_PrivateSendMouseButton(window, mouseID, state, button, -1);
+}
+
int
SDL_SendMouseWheel(SDL_Window * window, SDL_MouseID mouseID, int x, int y, SDL_MouseWheelDirection direction)
{
@@ -550,21 +564,11 @@ SDL_WarpMouseGlobal(int x, int y)
static SDL_bool
ShouldUseRelativeModeWarp(SDL_Mouse *mouse)
{
- const char *hint;
-
if (!mouse->SetRelativeMouseMode) {
return SDL_TRUE;
}
- hint = SDL_GetHint(SDL_HINT_MOUSE_RELATIVE_MODE_WARP);
- if (hint) {
- if (*hint == '0') {
- return SDL_FALSE;
- } else {
- return SDL_TRUE;
- }
- }
- return SDL_FALSE;
+ return SDL_GetHintBoolean(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, SDL_FALSE);
}
int
diff --git a/Engine/lib/sdl/src/events/SDL_mouse_c.h b/Engine/lib/sdl/src/events/SDL_mouse_c.h
index 03aca0a5c..06dc88701 100644
--- a/Engine/lib/sdl/src/events/SDL_mouse_c.h
+++ b/Engine/lib/sdl/src/events/SDL_mouse_c.h
@@ -119,6 +119,9 @@ extern int SDL_SendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int rel
/* Send a mouse button event */
extern int SDL_SendMouseButton(SDL_Window * window, SDL_MouseID mouseID, Uint8 state, Uint8 button);
+/* Send a mouse button event with a click count */
+extern int SDL_SendMouseButtonClicks(SDL_Window * window, SDL_MouseID mouseID, Uint8 state, Uint8 button, int clicks);
+
/* Send a mouse wheel event */
extern int SDL_SendMouseWheel(SDL_Window * window, SDL_MouseID mouseID, int x, int y, SDL_MouseWheelDirection direction);
diff --git a/Engine/lib/sdl/src/events/SDL_quit.c b/Engine/lib/sdl/src/events/SDL_quit.c
index 5b7105ef8..3cb6b3d4f 100644
--- a/Engine/lib/sdl/src/events/SDL_quit.c
+++ b/Engine/lib/sdl/src/events/SDL_quit.c
@@ -91,9 +91,7 @@ SDL_QuitInit_Internal(void)
int
SDL_QuitInit(void)
{
- const char *hint = SDL_GetHint(SDL_HINT_NO_SIGNAL_HANDLERS);
- disable_signals = hint && (SDL_atoi(hint) == 1);
- if (!disable_signals) {
+ if (!SDL_GetHintBoolean(SDL_HINT_NO_SIGNAL_HANDLERS, SDL_FALSE)) {
return SDL_QuitInit_Internal();
}
return 0;
diff --git a/Engine/lib/sdl/src/events/SDL_windowevents.c b/Engine/lib/sdl/src/events/SDL_windowevents.c
index 785ea4e0c..b45015bd0 100644
--- a/Engine/lib/sdl/src/events/SDL_windowevents.c
+++ b/Engine/lib/sdl/src/events/SDL_windowevents.c
@@ -70,6 +70,20 @@ RemovePendingMoveEvents(void * userdata, SDL_Event *event)
return 1;
}
+static int
+RemovePendingExposedEvents(void * userdata, SDL_Event *event)
+{
+ SDL_Event *new_event = (SDL_Event *)userdata;
+
+ if (event->type == SDL_WINDOWEVENT &&
+ event->window.event == SDL_WINDOWEVENT_EXPOSED &&
+ event->window.windowID == new_event->window.windowID) {
+ /* We're about to post a new exposed event, drop the old one */
+ return 0;
+ }
+ return 1;
+}
+
int
SDL_SendWindowEvent(SDL_Window * window, Uint8 windowevent, int data1,
int data2)
@@ -195,7 +209,9 @@ SDL_SendWindowEvent(SDL_Window * window, Uint8 windowevent, int data1,
if (windowevent == SDL_WINDOWEVENT_MOVED) {
SDL_FilterEvents(RemovePendingMoveEvents, &event);
}
-
+ if (windowevent == SDL_WINDOWEVENT_EXPOSED) {
+ SDL_FilterEvents(RemovePendingExposedEvents, &event);
+ }
posted = (SDL_PushEvent(&event) > 0);
}
diff --git a/Engine/lib/sdl/src/events/scancodes_linux.h b/Engine/lib/sdl/src/events/scancodes_linux.h
index 8db37df5b..e197ee3fe 100644
--- a/Engine/lib/sdl/src/events/scancodes_linux.h
+++ b/Engine/lib/sdl/src/events/scancodes_linux.h
@@ -111,7 +111,7 @@ static SDL_Scancode const linux_scancode_table[] = {
/* 82 */ SDL_SCANCODE_KP_0,
/* 83 */ SDL_SCANCODE_KP_PERIOD,
0,
- /* 85 */ SDL_SCANCODE_UNKNOWN, /* KEY_ZENKAKUHANKAKU */
+ /* 85 */ SDL_SCANCODE_LANG5, /* KEY_ZENKAKUHANKAKU */
/* 86 */ SDL_SCANCODE_NONUSBACKSLASH, /* KEY_102ND */
/* 87 */ SDL_SCANCODE_F11,
/* 88 */ SDL_SCANCODE_F12,
@@ -153,7 +153,7 @@ static SDL_Scancode const linux_scancode_table[] = {
/* 124 */ SDL_SCANCODE_INTERNATIONAL3, /* KEY_YEN */
/* 125 */ SDL_SCANCODE_LGUI,
/* 126 */ SDL_SCANCODE_RGUI,
- /* 127 */ SDL_SCANCODE_UNKNOWN, /* KEY_COMPOSE */
+ /* 127 */ SDL_SCANCODE_APPLICATION, /* KEY_COMPOSE */
/* 128 */ SDL_SCANCODE_STOP,
/* 129 */ SDL_SCANCODE_AGAIN,
/* 130 */ SDL_SCANCODE_UNKNOWN, /* KEY_PROPS */
@@ -174,9 +174,9 @@ static SDL_Scancode const linux_scancode_table[] = {
/* 145 */ SDL_SCANCODE_UNKNOWN, /* KEY_SENDFILE */
/* 146 */ SDL_SCANCODE_UNKNOWN, /* KEY_DELETEFILE */
/* 147 */ SDL_SCANCODE_UNKNOWN, /* KEY_XFER */
- /* 148 */ SDL_SCANCODE_UNKNOWN, /* KEY_PROG1 */
- /* 149 */ SDL_SCANCODE_UNKNOWN, /* KEY_PROG2 */
- /* 150 */ SDL_SCANCODE_UNKNOWN, /* KEY_WWW */
+ /* 148 */ SDL_SCANCODE_APP1, /* KEY_PROG1 */
+ /* 149 */ SDL_SCANCODE_APP2, /* KEY_PROG2 */
+ /* 150 */ SDL_SCANCODE_WWW, /* KEY_WWW */
/* 151 */ SDL_SCANCODE_UNKNOWN, /* KEY_MSDOS */
/* 152 */ SDL_SCANCODE_UNKNOWN, /* KEY_COFFEE */
/* 153 */ SDL_SCANCODE_UNKNOWN, /* KEY_DIRECTION */
@@ -192,7 +192,7 @@ static SDL_Scancode const linux_scancode_table[] = {
/* 163 */ SDL_SCANCODE_AUDIONEXT, /* KEY_NEXTSONG */
/* 164 */ SDL_SCANCODE_AUDIOPLAY, /* KEY_PLAYPAUSE */
/* 165 */ SDL_SCANCODE_AUDIOPREV, /* KEY_PREVIOUSSONG */
- /* 166 */ SDL_SCANCODE_UNKNOWN, /* KEY_STOPCD */
+ /* 166 */ SDL_SCANCODE_AUDIOSTOP, /* KEY_STOPCD */
/* 167 */ SDL_SCANCODE_UNKNOWN, /* KEY_RECORD */
/* 168 */ SDL_SCANCODE_UNKNOWN, /* KEY_REWIND */
/* 169 */ SDL_SCANCODE_UNKNOWN, /* KEY_PHONE */
@@ -221,7 +221,7 @@ static SDL_Scancode const linux_scancode_table[] = {
/* 192 */ SDL_SCANCODE_F22,
/* 193 */ SDL_SCANCODE_F23,
/* 194 */ SDL_SCANCODE_F24,
- 0, 0, 0, 0,
+ 0, 0, 0, 0, 0,
/* 200 */ SDL_SCANCODE_UNKNOWN, /* KEY_PLAYCD */
/* 201 */ SDL_SCANCODE_UNKNOWN, /* KEY_PAUSECD */
/* 202 */ SDL_SCANCODE_UNKNOWN, /* KEY_PROG3 */
diff --git a/Engine/lib/sdl/src/events/scancodes_xfree86.h b/Engine/lib/sdl/src/events/scancodes_xfree86.h
index 29d9ef944..804196ca4 100644
--- a/Engine/lib/sdl/src/events/scancodes_xfree86.h
+++ b/Engine/lib/sdl/src/events/scancodes_xfree86.h
@@ -418,4 +418,89 @@ static const SDL_Scancode xfree86_scancode_table2[] = {
/* 238 */ SDL_SCANCODE_UNKNOWN, /* XF86WLAN */
};
+/* Xvnc / Xtightvnc scancodes from xmodmap -pk */
+static const SDL_Scancode xvnc_scancode_table[] = {
+ /* 0 */ SDL_SCANCODE_LCTRL,
+ /* 1 */ SDL_SCANCODE_RCTRL,
+ /* 2 */ SDL_SCANCODE_LSHIFT,
+ /* 3 */ SDL_SCANCODE_RSHIFT,
+ /* 4 */ SDL_SCANCODE_UNKNOWN, /* Meta_L */
+ /* 5 */ SDL_SCANCODE_UNKNOWN, /* Meta_R */
+ /* 6 */ SDL_SCANCODE_LALT,
+ /* 7 */ SDL_SCANCODE_RALT,
+ /* 8 */ SDL_SCANCODE_SPACE,
+ /* 9 */ SDL_SCANCODE_0,
+ /* 10 */ SDL_SCANCODE_1,
+ /* 11 */ SDL_SCANCODE_2,
+ /* 12 */ SDL_SCANCODE_3,
+ /* 13 */ SDL_SCANCODE_4,
+ /* 14 */ SDL_SCANCODE_5,
+ /* 15 */ SDL_SCANCODE_6,
+ /* 16 */ SDL_SCANCODE_7,
+ /* 17 */ SDL_SCANCODE_8,
+ /* 18 */ SDL_SCANCODE_9,
+ /* 19 */ SDL_SCANCODE_MINUS,
+ /* 20 */ SDL_SCANCODE_EQUALS,
+ /* 21 */ SDL_SCANCODE_LEFTBRACKET,
+ /* 22 */ SDL_SCANCODE_RIGHTBRACKET,
+ /* 23 */ SDL_SCANCODE_SEMICOLON,
+ /* 24 */ SDL_SCANCODE_APOSTROPHE,
+ /* 25 */ SDL_SCANCODE_GRAVE,
+ /* 26 */ SDL_SCANCODE_COMMA,
+ /* 27 */ SDL_SCANCODE_PERIOD,
+ /* 28 */ SDL_SCANCODE_SLASH,
+ /* 29 */ SDL_SCANCODE_BACKSLASH,
+ /* 30 */ SDL_SCANCODE_A,
+ /* 31 */ SDL_SCANCODE_B,
+ /* 32 */ SDL_SCANCODE_C,
+ /* 33 */ SDL_SCANCODE_D,
+ /* 34 */ SDL_SCANCODE_E,
+ /* 35 */ SDL_SCANCODE_F,
+ /* 36 */ SDL_SCANCODE_G,
+ /* 37 */ SDL_SCANCODE_H,
+ /* 38 */ SDL_SCANCODE_I,
+ /* 39 */ SDL_SCANCODE_J,
+ /* 40 */ SDL_SCANCODE_K,
+ /* 41 */ SDL_SCANCODE_L,
+ /* 42 */ SDL_SCANCODE_M,
+ /* 43 */ SDL_SCANCODE_N,
+ /* 44 */ SDL_SCANCODE_O,
+ /* 45 */ SDL_SCANCODE_P,
+ /* 46 */ SDL_SCANCODE_Q,
+ /* 47 */ SDL_SCANCODE_R,
+ /* 48 */ SDL_SCANCODE_S,
+ /* 49 */ SDL_SCANCODE_T,
+ /* 50 */ SDL_SCANCODE_U,
+ /* 51 */ SDL_SCANCODE_V,
+ /* 52 */ SDL_SCANCODE_W,
+ /* 53 */ SDL_SCANCODE_X,
+ /* 54 */ SDL_SCANCODE_Y,
+ /* 55 */ SDL_SCANCODE_Z,
+ /* 56 */ SDL_SCANCODE_BACKSPACE,
+ /* 57 */ SDL_SCANCODE_RETURN,
+ /* 58 */ SDL_SCANCODE_TAB,
+ /* 59 */ SDL_SCANCODE_ESCAPE,
+ /* 60 */ SDL_SCANCODE_DELETE,
+ /* 61 */ SDL_SCANCODE_HOME,
+ /* 62 */ SDL_SCANCODE_END,
+ /* 63 */ SDL_SCANCODE_PAGEUP,
+ /* 64 */ SDL_SCANCODE_PAGEDOWN,
+ /* 65 */ SDL_SCANCODE_UP,
+ /* 66 */ SDL_SCANCODE_DOWN,
+ /* 67 */ SDL_SCANCODE_LEFT,
+ /* 68 */ SDL_SCANCODE_RIGHT,
+ /* 69 */ SDL_SCANCODE_F1,
+ /* 70 */ SDL_SCANCODE_F2,
+ /* 71 */ SDL_SCANCODE_F3,
+ /* 72 */ SDL_SCANCODE_F4,
+ /* 73 */ SDL_SCANCODE_F5,
+ /* 74 */ SDL_SCANCODE_F6,
+ /* 75 */ SDL_SCANCODE_F7,
+ /* 76 */ SDL_SCANCODE_F8,
+ /* 77 */ SDL_SCANCODE_F9,
+ /* 78 */ SDL_SCANCODE_F10,
+ /* 79 */ SDL_SCANCODE_F11,
+ /* 80 */ SDL_SCANCODE_F12,
+};
+
/* *INDENT-ON* */
diff --git a/Engine/lib/sdl/src/filesystem/dummy/SDL_sysfilesystem.c b/Engine/lib/sdl/src/filesystem/dummy/SDL_sysfilesystem.c
index 45273f24a..2570f4c75 100644
--- a/Engine/lib/sdl/src/filesystem/dummy/SDL_sysfilesystem.c
+++ b/Engine/lib/sdl/src/filesystem/dummy/SDL_sysfilesystem.c
@@ -20,7 +20,7 @@
*/
#include "../../SDL_internal.h"
-#ifdef SDL_FILESYSTEM_DUMMY
+#if defined(SDL_FILESYSTEM_DUMMY) || defined(SDL_FILESYSTEM_DISABLED)
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* System dependent filesystem routines */
@@ -42,6 +42,6 @@ SDL_GetPrefPath(const char *org, const char *app)
return NULL;
}
-#endif /* SDL_FILESYSTEM_DUMMY */
+#endif /* SDL_FILESYSTEM_DUMMY || SDL_FILESYSTEM_DISABLED */
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/filesystem/unix/SDL_sysfilesystem.c b/Engine/lib/sdl/src/filesystem/unix/SDL_sysfilesystem.c
index fa034a456..bd2e84cd1 100644
--- a/Engine/lib/sdl/src/filesystem/unix/SDL_sysfilesystem.c
+++ b/Engine/lib/sdl/src/filesystem/unix/SDL_sysfilesystem.c
@@ -33,7 +33,7 @@
#include
#include
-#ifdef __FREEBSD__
+#if defined(__FREEBSD__) || defined(__OPENBSD__)
#include
#endif
@@ -90,7 +90,26 @@ SDL_GetBasePath(void)
return NULL;
}
}
-#elif defined(__SOLARIS__)
+#endif
+#if defined(__OPENBSD__)
+ char **retvalargs;
+ size_t len;
+ const int mib[] = { CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ARGV };
+ if (sysctl(mib, 4, NULL, &len, NULL, 0) != -1) {
+ retvalargs = SDL_malloc(len);
+ if (!retvalargs) {
+ SDL_OutOfMemory();
+ return NULL;
+ }
+ sysctl(mib, 4, retvalargs, &len, NULL, 0);
+ retval = SDL_malloc(PATH_MAX + 1);
+ if (retval)
+ realpath(retvalargs[0], retval);
+
+ SDL_free(retvalargs);
+ }
+#endif
+#if defined(__SOLARIS__)
const char *path = getexecname();
if ((path != NULL) && (path[0] == '/')) { /* must be absolute path... */
retval = SDL_strdup(path);
diff --git a/Engine/lib/sdl/src/haptic/linux/SDL_syshaptic.c b/Engine/lib/sdl/src/haptic/linux/SDL_syshaptic.c
index e8d785535..7bd966449 100644
--- a/Engine/lib/sdl/src/haptic/linux/SDL_syshaptic.c
+++ b/Engine/lib/sdl/src/haptic/linux/SDL_syshaptic.c
@@ -609,7 +609,7 @@ SDL_SYS_HapticQuit(void)
/* Opened and not closed haptics are leaked, this is on purpose.
* Close your haptic devices after usage. */
SDL_free(item->fname);
- item->fname = NULL;
+ SDL_free(item);
}
#if SDL_USE_LIBUDEV
@@ -690,7 +690,7 @@ SDL_SYS_ToDirection(Uint16 *dest, SDL_HapticDirection * src)
else if (!src->dir[0])
*dest = (src->dir[1] >= 0 ? 0x8000 : 0);
else {
- float f = atan2(src->dir[1], src->dir[0]); /* Ideally we'd use fixed point math instead of floats... */
+ float f = SDL_atan2(src->dir[1], src->dir[0]); /* Ideally we'd use fixed point math instead of floats... */
/*
atan2 takes the parameters: Y-axis-value and X-axis-value (in that order)
- Y-axis-value is the second coordinate (from center to SOUTH)
diff --git a/Engine/lib/sdl/src/haptic/windows/SDL_dinputhaptic.c b/Engine/lib/sdl/src/haptic/windows/SDL_dinputhaptic.c
index c51470dd5..c81432c26 100644
--- a/Engine/lib/sdl/src/haptic/windows/SDL_dinputhaptic.c
+++ b/Engine/lib/sdl/src/haptic/windows/SDL_dinputhaptic.c
@@ -325,20 +325,12 @@ SDL_DINPUT_HapticOpenFromDevice(SDL_Haptic * haptic, LPDIRECTINPUTDEVICE8 device
/* Set data format. */
ret = IDirectInputDevice8_SetDataFormat(haptic->hwdata->device,
- &c_dfDIJoystick2);
+ &SDL_c_dfDIJoystick2);
if (FAILED(ret)) {
DI_SetError("Setting data format", ret);
goto acquire_err;
}
- /* Get number of axes. */
- ret = IDirectInputDevice8_EnumObjects(haptic->hwdata->device,
- DI_DeviceObjectCallback,
- haptic, DIDFT_AXIS);
- if (FAILED(ret)) {
- DI_SetError("Getting device axes", ret);
- goto acquire_err;
- }
/* Acquire the device. */
ret = IDirectInputDevice8_Acquire(haptic->hwdata->device);
@@ -348,6 +340,15 @@ SDL_DINPUT_HapticOpenFromDevice(SDL_Haptic * haptic, LPDIRECTINPUTDEVICE8 device
}
}
+ /* Get number of axes. */
+ ret = IDirectInputDevice8_EnumObjects(haptic->hwdata->device,
+ DI_DeviceObjectCallback,
+ haptic, DIDFT_AXIS);
+ if (FAILED(ret)) {
+ DI_SetError("Getting device axes", ret);
+ goto acquire_err;
+ }
+
/* Reset all actuators - just in case. */
ret = IDirectInputDevice8_SendForceFeedbackCommand(haptic->hwdata->device,
DISFFC_RESET);
diff --git a/Engine/lib/sdl/src/haptic/windows/SDL_windowshaptic.c b/Engine/lib/sdl/src/haptic/windows/SDL_windowshaptic.c
index 0c038fb1b..c6bcba1f3 100644
--- a/Engine/lib/sdl/src/haptic/windows/SDL_windowshaptic.c
+++ b/Engine/lib/sdl/src/haptic/windows/SDL_windowshaptic.c
@@ -255,7 +255,7 @@ SDL_SYS_HapticQuit(void)
for (hapticitem = SDL_haptics; hapticitem; hapticitem = hapticitem->next) {
if ((hapticitem->hwdata->bXInputHaptic) && (hapticitem->hwdata->thread)) {
/* we _have_ to stop the thread before we free the XInput DLL! */
- hapticitem->hwdata->stopThread = 1;
+ SDL_AtomicSet(&hapticitem->hwdata->stopThread, 1);
SDL_WaitThread(hapticitem->hwdata->thread, NULL);
hapticitem->hwdata->thread = NULL;
}
diff --git a/Engine/lib/sdl/src/haptic/windows/SDL_windowshaptic_c.h b/Engine/lib/sdl/src/haptic/windows/SDL_windowshaptic_c.h
index 89fdd2cb9..f34426442 100644
--- a/Engine/lib/sdl/src/haptic/windows/SDL_windowshaptic_c.h
+++ b/Engine/lib/sdl/src/haptic/windows/SDL_windowshaptic_c.h
@@ -42,8 +42,8 @@ struct haptic_hwdata
Uint8 userid; /* XInput userid index for this joystick */
SDL_Thread *thread;
SDL_mutex *mutex;
- volatile Uint32 stopTicks;
- volatile int stopThread;
+ Uint32 stopTicks;
+ SDL_atomic_t stopThread;
};
diff --git a/Engine/lib/sdl/src/haptic/windows/SDL_xinputhaptic.c b/Engine/lib/sdl/src/haptic/windows/SDL_xinputhaptic.c
index a46ae5f97..afbab456a 100644
--- a/Engine/lib/sdl/src/haptic/windows/SDL_xinputhaptic.c
+++ b/Engine/lib/sdl/src/haptic/windows/SDL_xinputhaptic.c
@@ -33,6 +33,7 @@
#include "SDL_xinputhaptic_c.h"
#include "../../core/windows/SDL_xinput.h"
#include "../../joystick/windows/SDL_windowsjoystick_c.h"
+#include "../../thread/SDL_systhread.h"
/*
* Internal stuff.
@@ -43,8 +44,7 @@ static SDL_bool loaded_xinput = SDL_FALSE;
int
SDL_XINPUT_HapticInit(void)
{
- const char *env = SDL_GetHint(SDL_HINT_XINPUT_ENABLED);
- if (!env || SDL_atoi(env)) {
+ if (SDL_GetHintBoolean(SDL_HINT_XINPUT_ENABLED, SDL_TRUE)) {
loaded_xinput = (WIN_LoadXInputDLL() == 0);
}
@@ -146,7 +146,7 @@ SDL_RunXInputHaptic(void *arg)
{
struct haptic_hwdata *hwdata = (struct haptic_hwdata *) arg;
- while (!hwdata->stopThread) {
+ while (!SDL_AtomicGet(&hwdata->stopThread)) {
SDL_Delay(50);
SDL_LockMutex(hwdata->mutex);
/* If we're currently running and need to stop... */
@@ -205,17 +205,8 @@ SDL_XINPUT_HapticOpenFromUserIndex(SDL_Haptic *haptic, const Uint8 userid)
}
SDL_snprintf(threadName, sizeof(threadName), "SDLXInputDev%d", (int)userid);
+ haptic->hwdata->thread = SDL_CreateThreadInternal(SDL_RunXInputHaptic, threadName, 64 * 1024, haptic->hwdata);
-#if defined(__WIN32__) && !defined(HAVE_LIBC) /* !!! FIXME: this is nasty. */
-#undef SDL_CreateThread
-#if SDL_DYNAMIC_API
- haptic->hwdata->thread = SDL_CreateThread_REAL(SDL_RunXInputHaptic, threadName, haptic->hwdata, NULL, NULL);
-#else
- haptic->hwdata->thread = SDL_CreateThread(SDL_RunXInputHaptic, threadName, haptic->hwdata, NULL, NULL);
-#endif
-#else
- haptic->hwdata->thread = SDL_CreateThread(SDL_RunXInputHaptic, threadName, haptic->hwdata);
-#endif
if (haptic->hwdata->thread == NULL) {
SDL_DestroyMutex(haptic->hwdata->mutex);
SDL_free(haptic->effects);
@@ -261,7 +252,7 @@ SDL_XINPUT_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick)
void
SDL_XINPUT_HapticClose(SDL_Haptic * haptic)
{
- haptic->hwdata->stopThread = 1;
+ SDL_AtomicSet(&haptic->hwdata->stopThread, 1);
SDL_WaitThread(haptic->hwdata->thread, NULL);
SDL_DestroyMutex(haptic->hwdata->mutex);
}
diff --git a/Engine/lib/sdl/src/joystick/SDL_gamecontroller.c b/Engine/lib/sdl/src/joystick/SDL_gamecontroller.c
index 0fd1ef4a7..1d3a4c203 100644
--- a/Engine/lib/sdl/src/joystick/SDL_gamecontroller.c
+++ b/Engine/lib/sdl/src/joystick/SDL_gamecontroller.c
@@ -45,7 +45,8 @@ struct _SDL_HatMapping
Uint8 mask;
};
-#define k_nMaxReverseEntries 20
+/* We need 36 entries for Android (as of SDL v2.0.4) */
+#define k_nMaxReverseEntries 48
/**
* We are encoding the "HAT" as 0xhm. where h == hat ID and m == mask
@@ -105,6 +106,35 @@ struct _SDL_GameController
int SDL_PrivateGameControllerAxis(SDL_GameController * gamecontroller, SDL_GameControllerAxis axis, Sint16 value);
int SDL_PrivateGameControllerButton(SDL_GameController * gamecontroller, SDL_GameControllerButton button, Uint8 state);
+/*
+ * If there is an existing add event in the queue, it needs to be modified
+ * to have the right value for which, because the number of controllers in
+ * the system is now one less.
+ */
+static void UpdateEventsForDeviceRemoval()
+{
+ int i, num_events;
+ SDL_Event *events;
+
+ num_events = SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, SDL_CONTROLLERDEVICEADDED, SDL_CONTROLLERDEVICEADDED);
+ if (num_events <= 0) {
+ return;
+ }
+
+ events = SDL_stack_alloc(SDL_Event, num_events);
+ if (!events) {
+ return;
+ }
+
+ num_events = SDL_PeepEvents(events, num_events, SDL_GETEVENT, SDL_CONTROLLERDEVICEADDED, SDL_CONTROLLERDEVICEADDED);
+ for (i = 0; i < num_events; ++i) {
+ --events[i].cdevice.which;
+ }
+ SDL_PeepEvents(events, num_events, SDL_ADDEVENT, 0, 0);
+
+ SDL_stack_free(events);
+}
+
/*
* Event filter to fire controller events from joystick ones
*/
@@ -115,7 +145,11 @@ int SDL_GameControllerEventWatcher(void *userdata, SDL_Event * event)
{
SDL_GameController *controllerlist;
- if (event->jaxis.axis >= k_nMaxReverseEntries) break;
+ if (event->jaxis.axis >= k_nMaxReverseEntries)
+ {
+ SDL_SetError("SDL_GameControllerEventWatcher: Axis index %d too large, ignoring motion", (int)event->jaxis.axis);
+ break;
+ }
controllerlist = SDL_gamecontrollers;
while (controllerlist) {
@@ -126,8 +160,8 @@ int SDL_GameControllerEventWatcher(void *userdata, SDL_Event * event)
switch (axis) {
case SDL_CONTROLLER_AXIS_TRIGGERLEFT:
case SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
- /* Shift it to be 0 - 32767. */
value = value / 2 + 16384;
+ break;
default:
break;
}
@@ -146,7 +180,11 @@ int SDL_GameControllerEventWatcher(void *userdata, SDL_Event * event)
{
SDL_GameController *controllerlist;
- if (event->jbutton.button >= k_nMaxReverseEntries) break;
+ if (event->jbutton.button >= k_nMaxReverseEntries)
+ {
+ SDL_SetError("SDL_GameControllerEventWatcher: Button index %d too large, ignoring update", (int)event->jbutton.button);
+ break;
+ }
controllerlist = SDL_gamecontrollers;
while (controllerlist) {
@@ -223,9 +261,12 @@ int SDL_GameControllerEventWatcher(void *userdata, SDL_Event * event)
while (controllerlist) {
if (controllerlist->joystick->instance_id == event->jdevice.which) {
SDL_Event deviceevent;
+
deviceevent.type = SDL_CONTROLLERDEVICEREMOVED;
deviceevent.cdevice.which = event->jdevice.which;
SDL_PushEvent(&deviceevent);
+
+ UpdateEventsForDeviceRemoval();
break;
}
controllerlist = controllerlist->next;
@@ -861,7 +902,6 @@ SDL_GameControllerInit(void)
{
int i = 0;
const char *pMappingString = NULL;
- s_pSupportedControllers = NULL;
pMappingString = s_ControllerMappings[i];
while (pMappingString) {
SDL_GameControllerAddMapping(pMappingString);
@@ -971,6 +1011,20 @@ SDL_GameControllerOpen(int device_index)
SDL_PrivateLoadButtonMapping(&gamecontroller->mapping, pSupportedController->guid, pSupportedController->name, pSupportedController->mapping);
+ /* The triggers are mapped from -32768 to 32767, where -32768 is the 'unpressed' value */
+ {
+ int leftTriggerMapping = gamecontroller->mapping.axes[SDL_CONTROLLER_AXIS_TRIGGERLEFT];
+ int rightTriggerMapping = gamecontroller->mapping.axes[SDL_CONTROLLER_AXIS_TRIGGERRIGHT];
+ if (leftTriggerMapping >= 0) {
+ gamecontroller->joystick->axes[leftTriggerMapping] =
+ gamecontroller->joystick->axes_zero[leftTriggerMapping] = (Sint16)-32768;
+ }
+ if (rightTriggerMapping >= 0) {
+ gamecontroller->joystick->axes[rightTriggerMapping] =
+ gamecontroller->joystick->axes_zero[rightTriggerMapping] = (Sint16)-32768;
+ }
+ }
+
/* Add joystick to list */
++gamecontroller->ref_count;
/* Link the joystick in the list */
@@ -1007,7 +1061,7 @@ SDL_GameControllerGetAxis(SDL_GameController * gamecontroller, SDL_GameControlle
switch (axis) {
case SDL_CONTROLLER_AXIS_TRIGGERLEFT:
case SDL_CONTROLLER_AXIS_TRIGGERRIGHT:
- /* Shift it to be 0 - 32767. */
+ /* Shift it to be 0 - 32767 */
value = value / 2 + 16384;
default:
break;
diff --git a/Engine/lib/sdl/src/joystick/SDL_gamecontrollerdb.h b/Engine/lib/sdl/src/joystick/SDL_gamecontrollerdb.h
index 211d00d01..1e623cbb8 100644
--- a/Engine/lib/sdl/src/joystick/SDL_gamecontrollerdb.h
+++ b/Engine/lib/sdl/src/joystick/SDL_gamecontrollerdb.h
@@ -35,6 +35,7 @@ static const char *s_ControllerMappings [] =
"xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
#endif
#if SDL_JOYSTICK_DINPUT
+ "10280900000000000000504944564944,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,",
"341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
"e8206058000000000000504944564944,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,",
"ffff0000000000000000504944564944,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
@@ -48,6 +49,7 @@ static const char *s_ControllerMappings [] =
"4c05c405000000000000504944564944,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
#endif
#if defined(__MACOSX__)
+ "10280000000000000900000000000000,8Bitdo SFC30 GamePad Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,",
"830500000000000031b0000000000000,Cideko AK08b,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
"6d0400000000000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* Guide button doesn't seem to be sent in DInput mode. */
@@ -56,11 +58,14 @@ static const char *s_ControllerMappings [] =
"6d0400000000000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* This includes F710 in DInput mode and the "Logitech Cordless RumblePad 2", at the very least. */
"4c050000000000006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,",
"4c05000000000000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
+ "351200000000000021ab000000000000,SFC30 Joystick,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,",
"11010000000000002014000000000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,",
"11010000000000001714000000000000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b12,x:b2,y:b3,",
"5e040000000000008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,",
#endif
#if defined(__LINUX__)
+ "05000000102800000900000000010000,8Bitdo SFC30 GamePad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,",
+ "03000000100000008200000011010000,Akishop Customs PS360+ v1.66,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,",
"03000000e82000006058000001010000,Cideko AK08b,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,",
"0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
"030000006f0e00000104000000010000,Gamestop Logic3 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
@@ -71,6 +76,12 @@ static const char *s_ControllerMappings [] =
"030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* Guide button doesn't seem to be sent in DInput mode. */
"030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"030000006d04000018c2000010010000,Logitech RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
+ "03000000380700008433000011010000,Mad Catz FightStick TE S+ PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
+ "03000000380700008483000011010000,Mad Catz FightStick TE S+ PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
+ "03000000380700003847000090040000,Mad Catz Wired Xbox 360 Controller (SFIV),a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
+ "03000000380700008034000011010000,Mad Catz fightstick (PS3),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
+ "03000000380700008084000011010000,Mad Catz fightstick (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
+ "03000000380700001888000010010000,MadCatz PC USB Wired Stick 8818,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
"03000000550900001072000011010000,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,",
"050000007e0500003003000001000000,Nintendo Wii Remote Pro Controller,a:b1,b:b0,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,",
"050000003620000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,",
@@ -78,12 +89,15 @@ static const char *s_ControllerMappings [] =
"03000000341a00003608000011010000,PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,",
"030000004c050000c405000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
"050000004c050000c405000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
+ "030000004c050000cc09000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
+ "050000004c050000cc09000000010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,",
"03000000c6240000045d000025010000,Razer Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"03000000321500000009000011010000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,",
"050000003215000000090000163a0000,Razer Serval,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,",
"03000000de280000fc11000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"03000000de280000ff11000001000000,Valve Streaming Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
+ "050000005e040000e002000003090000,Xbox One Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
"030000005e040000d102000001010000,Xbox One Wireless Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,",
#endif
#if defined(__ANDROID__)
diff --git a/Engine/lib/sdl/src/joystick/SDL_joystick.c b/Engine/lib/sdl/src/joystick/SDL_joystick.c
index dc910a82b..c426a39e5 100644
--- a/Engine/lib/sdl/src/joystick/SDL_joystick.c
+++ b/Engine/lib/sdl/src/joystick/SDL_joystick.c
@@ -142,8 +142,8 @@ SDL_JoystickOpen(int device_index)
joystick->name = NULL;
if (joystick->naxes > 0) {
- joystick->axes = (Sint16 *) SDL_malloc
- (joystick->naxes * sizeof(Sint16));
+ joystick->axes = (Sint16 *) SDL_malloc(joystick->naxes * sizeof(Sint16));
+ joystick->axes_zero = (Sint16 *) SDL_malloc(joystick->naxes * sizeof(Sint16));
}
if (joystick->nhats > 0) {
joystick->hats = (Uint8 *) SDL_malloc
@@ -167,6 +167,7 @@ SDL_JoystickOpen(int device_index)
}
if (joystick->axes) {
SDL_memset(joystick->axes, 0, joystick->naxes * sizeof(Sint16));
+ SDL_memset(joystick->axes_zero, 0, joystick->naxes * sizeof(Sint16));
}
if (joystick->hats) {
SDL_memset(joystick->hats, 0, joystick->nhats * sizeof(Uint8));
@@ -497,6 +498,71 @@ SDL_PrivateJoystickShouldIgnoreEvent()
/* These are global for SDL_sysjoystick.c and SDL_events.c */
+void SDL_PrivateJoystickAdded(int device_index)
+{
+#if !SDL_EVENTS_DISABLED
+ SDL_Event event;
+
+ event.type = SDL_JOYDEVICEADDED;
+
+ if (SDL_GetEventState(event.type) == SDL_ENABLE) {
+ event.jdevice.which = device_index;
+ if ( (SDL_EventOK == NULL) ||
+ (*SDL_EventOK) (SDL_EventOKParam, &event) ) {
+ SDL_PushEvent(&event);
+ }
+ }
+#endif /* !SDL_EVENTS_DISABLED */
+}
+
+/*
+ * If there is an existing add event in the queue, it needs to be modified
+ * to have the right value for which, because the number of controllers in
+ * the system is now one less.
+ */
+static void UpdateEventsForDeviceRemoval()
+{
+ int i, num_events;
+ SDL_Event *events;
+
+ num_events = SDL_PeepEvents(NULL, 0, SDL_PEEKEVENT, SDL_JOYDEVICEADDED, SDL_JOYDEVICEADDED);
+ if (num_events <= 0) {
+ return;
+ }
+
+ events = SDL_stack_alloc(SDL_Event, num_events);
+ if (!events) {
+ return;
+ }
+
+ num_events = SDL_PeepEvents(events, num_events, SDL_GETEVENT, SDL_JOYDEVICEADDED, SDL_JOYDEVICEADDED);
+ for (i = 0; i < num_events; ++i) {
+ --events[i].jdevice.which;
+ }
+ SDL_PeepEvents(events, num_events, SDL_ADDEVENT, 0, 0);
+
+ SDL_stack_free(events);
+}
+
+void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance)
+{
+#if !SDL_EVENTS_DISABLED
+ SDL_Event event;
+
+ event.type = SDL_JOYDEVICEREMOVED;
+
+ if (SDL_GetEventState(event.type) == SDL_ENABLE) {
+ event.jdevice.which = device_instance;
+ if ( (SDL_EventOK == NULL) ||
+ (*SDL_EventOK) (SDL_EventOKParam, &event) ) {
+ SDL_PushEvent(&event);
+ }
+ }
+
+ UpdateEventsForDeviceRemoval();
+#endif /* !SDL_EVENTS_DISABLED */
+}
+
int
SDL_PrivateJoystickAxis(SDL_Joystick * joystick, Uint8 axis, Sint16 value)
{
@@ -514,8 +580,8 @@ SDL_PrivateJoystickAxis(SDL_Joystick * joystick, Uint8 axis, Sint16 value)
* events.
*/
if (SDL_PrivateJoystickShouldIgnoreEvent()) {
- if ((value > 0 && value >= joystick->axes[axis]) ||
- (value < 0 && value <= joystick->axes[axis])) {
+ if ((value > joystick->axes_zero[axis] && value >= joystick->axes[axis]) ||
+ (value < joystick->axes_zero[axis] && value <= joystick->axes[axis])) {
return 0;
}
}
@@ -688,7 +754,7 @@ SDL_JoystickUpdate(void)
/* Tell the app that everything is centered/unpressed... */
for (i = 0; i < joystick->naxes; i++) {
- SDL_PrivateJoystickAxis(joystick, i, 0);
+ SDL_PrivateJoystickAxis(joystick, i, joystick->axes_zero[i]);
}
for (i = 0; i < joystick->nbuttons; i++) {
diff --git a/Engine/lib/sdl/src/joystick/SDL_joystick_c.h b/Engine/lib/sdl/src/joystick/SDL_joystick_c.h
index 4a076f6d6..cb9c92544 100644
--- a/Engine/lib/sdl/src/joystick/SDL_joystick_c.h
+++ b/Engine/lib/sdl/src/joystick/SDL_joystick_c.h
@@ -33,6 +33,8 @@ extern void SDL_GameControllerQuit(void);
/* Internal event queueing functions */
+extern void SDL_PrivateJoystickAdded(int device_index);
+extern void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance);
extern int SDL_PrivateJoystickAxis(SDL_Joystick * joystick,
Uint8 axis, Sint16 value);
extern int SDL_PrivateJoystickBall(SDL_Joystick * joystick,
@@ -41,8 +43,8 @@ extern int SDL_PrivateJoystickHat(SDL_Joystick * joystick,
Uint8 hat, Uint8 value);
extern int SDL_PrivateJoystickButton(SDL_Joystick * joystick,
Uint8 button, Uint8 state);
-extern void SDL_PrivateJoystickBatteryLevel( SDL_Joystick * joystick,
- SDL_JoystickPowerLevel ePowerLevel );
+extern void SDL_PrivateJoystickBatteryLevel(SDL_Joystick * joystick,
+ SDL_JoystickPowerLevel ePowerLevel);
/* Internal sanity checking functions */
extern int SDL_PrivateJoystickValid(SDL_Joystick * joystick);
diff --git a/Engine/lib/sdl/src/joystick/SDL_sysjoystick.h b/Engine/lib/sdl/src/joystick/SDL_sysjoystick.h
index 1015840af..f4cad05ec 100644
--- a/Engine/lib/sdl/src/joystick/SDL_sysjoystick.h
+++ b/Engine/lib/sdl/src/joystick/SDL_sysjoystick.h
@@ -36,6 +36,7 @@ struct _SDL_Joystick
int naxes; /* Number of axis controls on the joystick */
Sint16 *axes; /* Current axis states */
+ Sint16 *axes_zero; /* Zero point on the axis (-32768 for triggers) */
int nhats; /* Number of hats on the joystick */
Uint8 *hats; /* Current hat states */
diff --git a/Engine/lib/sdl/src/joystick/android/SDL_sysjoystick.c b/Engine/lib/sdl/src/joystick/android/SDL_sysjoystick.c
index 8656a5322..a09e9a12c 100644
--- a/Engine/lib/sdl/src/joystick/android/SDL_sysjoystick.c
+++ b/Engine/lib/sdl/src/joystick/android/SDL_sysjoystick.c
@@ -27,10 +27,6 @@
#include "SDL_error.h"
#include "SDL_events.h"
-#if !SDL_EVENTS_DISABLED
-#include "../../events/SDL_events_c.h"
-#endif
-
#include "SDL_joystick.h"
#include "SDL_hints.h"
#include "SDL_assert.h"
@@ -191,8 +187,8 @@ Android_OnPadDown(int device_id, int keycode)
item = JoystickByDeviceId(device_id);
if (item && item->joystick) {
SDL_PrivateJoystickButton(item->joystick, button , SDL_PRESSED);
- return 0;
}
+ return 0;
}
return -1;
@@ -207,8 +203,8 @@ Android_OnPadUp(int device_id, int keycode)
item = JoystickByDeviceId(device_id);
if (item && item->joystick) {
SDL_PrivateJoystickButton(item->joystick, button, SDL_RELEASED);
- return 0;
}
+ return 0;
}
return -1;
@@ -252,9 +248,6 @@ Android_AddJoystick(int device_id, const char *name, SDL_bool is_accelerometer,
{
SDL_JoystickGUID guid;
SDL_joylist_item *item;
-#if !SDL_EVENTS_DISABLED
- SDL_Event event;
-#endif
if(JoystickByDeviceId(device_id) != NULL || name == NULL) {
return -1;
@@ -299,17 +292,7 @@ Android_AddJoystick(int device_id, const char *name, SDL_bool is_accelerometer,
/* Need to increment the joystick count before we post the event */
++numjoysticks;
-#if !SDL_EVENTS_DISABLED
- event.type = SDL_JOYDEVICEADDED;
-
- if (SDL_GetEventState(event.type) == SDL_ENABLE) {
- event.jdevice.which = (numjoysticks - 1);
- if ( (SDL_EventOK == NULL) ||
- (*SDL_EventOK) (SDL_EventOKParam, &event) ) {
- SDL_PushEvent(&event);
- }
- }
-#endif /* !SDL_EVENTS_DISABLED */
+ SDL_PrivateJoystickAdded(numjoysticks - 1);
#ifdef DEBUG_JOYSTICK
SDL_Log("Added joystick %s with device_id %d", name, device_id);
@@ -323,9 +306,6 @@ Android_RemoveJoystick(int device_id)
{
SDL_joylist_item *item = SDL_joylist;
SDL_joylist_item *prev = NULL;
-#if !SDL_EVENTS_DISABLED
- SDL_Event event;
-#endif
/* Don't call JoystickByDeviceId here or there'll be an infinite loop! */
while (item != NULL) {
@@ -340,7 +320,6 @@ Android_RemoveJoystick(int device_id)
return -1;
}
- const int retval = item->device_instance;
if (item->joystick) {
item->joystick->hwdata = NULL;
}
@@ -358,17 +337,7 @@ Android_RemoveJoystick(int device_id)
/* Need to decrement the joystick count before we post the event */
--numjoysticks;
-#if !SDL_EVENTS_DISABLED
- event.type = SDL_JOYDEVICEREMOVED;
-
- if (SDL_GetEventState(event.type) == SDL_ENABLE) {
- event.jdevice.which = item->device_instance;
- if ( (SDL_EventOK == NULL) ||
- (*SDL_EventOK) (SDL_EventOKParam, &event) ) {
- SDL_PushEvent(&event);
- }
- }
-#endif /* !SDL_EVENTS_DISABLED */
+ SDL_PrivateJoystickRemoved(item->device_instance);
#ifdef DEBUG_JOYSTICK
SDL_Log("Removed joystick with device_id %d", device_id);
@@ -376,18 +345,16 @@ Android_RemoveJoystick(int device_id)
SDL_free(item->name);
SDL_free(item);
- return retval;
+ return numjoysticks;
}
int
SDL_SYS_JoystickInit(void)
{
- const char *hint;
SDL_SYS_JoystickDetect();
- hint = SDL_GetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK);
- if (!hint || SDL_atoi(hint)) {
+ if (SDL_GetHintBoolean(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, SDL_TRUE)) {
/* Default behavior, accelerometer as joystick */
Android_AddJoystick(ANDROID_ACCELEROMETER_DEVICE_ID, ANDROID_ACCELEROMETER_NAME, SDL_TRUE, 0, 3, 0, 0);
}
@@ -539,6 +506,10 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
void
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
{
+ SDL_joylist_item *item = (SDL_joylist_item *) joystick->hwdata;
+ if (item) {
+ item->joystick = NULL;
+ }
}
/* Function to perform any system-specific joystick related cleanup */
diff --git a/Engine/lib/sdl/src/joystick/android/SDL_sysjoystick_c.h b/Engine/lib/sdl/src/joystick/android/SDL_sysjoystick_c.h
index 49b494c54..51803db35 100644
--- a/Engine/lib/sdl/src/joystick/android/SDL_sysjoystick_c.h
+++ b/Engine/lib/sdl/src/joystick/android/SDL_sysjoystick_c.h
@@ -1,23 +1,23 @@
/*
- Simple DirectMedia Layer
- Copyright (C) 1997-2016 Sam Lantinga
-
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
-
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
-
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2016 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
#include "../../SDL_internal.h"
diff --git a/Engine/lib/sdl/src/joystick/bsd/SDL_sysjoystick.c b/Engine/lib/sdl/src/joystick/bsd/SDL_sysjoystick.c
index 509d43f75..ddc899f6e 100644
--- a/Engine/lib/sdl/src/joystick/bsd/SDL_sysjoystick.c
+++ b/Engine/lib/sdl/src/joystick/bsd/SDL_sysjoystick.c
@@ -179,7 +179,7 @@ SDL_SYS_JoystickInit(void)
SDL_snprintf(s, SDL_arraysize(s), "/dev/uhid%d", i);
- joynames[SDL_SYS_numjoysticks] = strdup(s);
+ joynames[SDL_SYS_numjoysticks] = SDL_strdup(s);
if (SDL_SYS_JoystickOpen(&nj, SDL_SYS_numjoysticks) == 0) {
SDL_SYS_JoystickClose(&nj);
@@ -193,7 +193,7 @@ SDL_SYS_JoystickInit(void)
SDL_snprintf(s, SDL_arraysize(s), "/dev/joy%d", i);
fd = open(s, O_RDONLY);
if (fd != -1) {
- joynames[SDL_SYS_numjoysticks++] = strdup(s);
+ joynames[SDL_SYS_numjoysticks++] = SDL_strdup(s);
close(fd);
}
}
@@ -304,14 +304,14 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joy, int device_index)
}
joy->hwdata = hw;
hw->fd = fd;
- hw->path = strdup(path);
+ hw->path = SDL_strdup(path);
if (!SDL_strncmp(path, "/dev/joy", 8)) {
hw->type = BSDJOY_JOY;
joy->naxes = 2;
joy->nbuttons = 2;
joy->nhats = 0;
joy->nballs = 0;
- joydevnames[device_index] = strdup("Gameport joystick");
+ joydevnames[device_index] = SDL_strdup("Gameport joystick");
goto usbend;
} else {
hw->type = BSDJOY_UHID;
@@ -363,7 +363,7 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joy, int device_index)
str[i] = '\0';
asprintf(&new_name, "%s @ %s", str, path);
if (new_name != NULL) {
- free(joydevnames[SDL_SYS_numjoysticks]);
+ SDL_free(joydevnames[SDL_SYS_numjoysticks]);
joydevnames[SDL_SYS_numjoysticks] = new_name;
}
}
diff --git a/Engine/lib/sdl/src/joystick/darwin/SDL_sysjoystick.c b/Engine/lib/sdl/src/joystick/darwin/SDL_sysjoystick.c
index 6dd306aa8..da10fbac5 100644
--- a/Engine/lib/sdl/src/joystick/darwin/SDL_sysjoystick.c
+++ b/Engine/lib/sdl/src/joystick/darwin/SDL_sysjoystick.c
@@ -34,9 +34,6 @@
#include "SDL_sysjoystick_c.h"
#include "SDL_events.h"
#include "../../haptic/darwin/SDL_syshaptic_c.h" /* For haptic hot plugging */
-#if !SDL_EVENTS_DISABLED
-#include "../../events/SDL_events_c.h"
-#endif
#define SDL_JOYSTICK_RUNLOOP_MODE CFSTR("SDLJoystick")
@@ -154,21 +151,7 @@ JoystickDeviceWasRemovedCallback(void *ctx, IOReturn result, void *sender)
MacHaptic_MaybeRemoveDevice(device->ffservice);
#endif
-/* !!! FIXME: why isn't there an SDL_PrivateJoyDeviceRemoved()? */
-#if !SDL_EVENTS_DISABLED
- {
- SDL_Event event;
- event.type = SDL_JOYDEVICEREMOVED;
-
- if (SDL_GetEventState(event.type) == SDL_ENABLE) {
- event.jdevice.which = device->instance_id;
- if ((SDL_EventOK == NULL)
- || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
- SDL_PushEvent(&event);
- }
- }
- }
-#endif /* !SDL_EVENTS_DISABLED */
+ SDL_PrivateJoystickRemoved(device->instance_id);
}
@@ -249,6 +232,7 @@ AddHIDElement(const void *value, void *parameter)
case kHIDUsage_GD_DPadLeft:
case kHIDUsage_GD_Start:
case kHIDUsage_GD_Select:
+ case kHIDUsage_GD_SystemMainMenu:
if (!ElementAlreadyAdded(cookie, pDevice->firstButton)) {
element = (recElement *) SDL_calloc(1, sizeof (recElement));
if (element) {
@@ -422,6 +406,7 @@ JoystickDeviceWasAddedCallback(void *ctx, IOReturn res, void *sender, IOHIDDevic
{
recDevice *device;
int device_index = 0;
+ io_service_t ioservice;
if (res != kIOReturnSuccess) {
return;
@@ -451,20 +436,11 @@ JoystickDeviceWasAddedCallback(void *ctx, IOReturn res, void *sender, IOHIDDevic
device->instance_id = ++s_joystick_instance_id;
/* We have to do some storage of the io_service_t for SDL_HapticOpenFromJoystick */
-
-#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
- if (IOHIDDeviceGetService != NULL) { /* weak reference: available in 10.6 and later. */
-#endif
-
- const io_service_t ioservice = IOHIDDeviceGetService(ioHIDDeviceObject);
+ ioservice = IOHIDDeviceGetService(ioHIDDeviceObject);
#if SDL_HAPTIC_IOKIT
- if ((ioservice) && (FFIsForceFeedback(ioservice) == FF_OK)) {
- device->ffservice = ioservice;
- MacHaptic_MaybeAddDevice(ioservice);
- }
-#endif
-
-#if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
+ if ((ioservice) && (FFIsForceFeedback(ioservice) == FF_OK)) {
+ device->ffservice = ioservice;
+ MacHaptic_MaybeAddDevice(ioservice);
}
#endif
@@ -483,21 +459,7 @@ JoystickDeviceWasAddedCallback(void *ctx, IOReturn res, void *sender, IOHIDDevic
++device_index; /* bump by one since we counted by pNext. */
}
-/* !!! FIXME: why isn't there an SDL_PrivateJoyDeviceAdded()? */
-#if !SDL_EVENTS_DISABLED
- {
- SDL_Event event;
- event.type = SDL_JOYDEVICEADDED;
-
- if (SDL_GetEventState(event.type) == SDL_ENABLE) {
- event.jdevice.which = device_index;
- if ((SDL_EventOK == NULL)
- || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
- SDL_PushEvent(&event);
- }
- }
- }
-#endif /* !SDL_EVENTS_DISABLED */
+ SDL_PrivateJoystickAdded(device_index);
}
static SDL_bool
diff --git a/Engine/lib/sdl/src/joystick/emscripten/SDL_sysjoystick.c b/Engine/lib/sdl/src/joystick/emscripten/SDL_sysjoystick.c
index e0c5833bf..6b203667a 100644
--- a/Engine/lib/sdl/src/joystick/emscripten/SDL_sysjoystick.c
+++ b/Engine/lib/sdl/src/joystick/emscripten/SDL_sysjoystick.c
@@ -27,10 +27,6 @@
#include "SDL_error.h"
#include "SDL_events.h"
-#if !SDL_EVENTS_DISABLED
-#include "../../events/SDL_events_c.h"
-#endif
-
#include "SDL_joystick.h"
#include "SDL_hints.h"
#include "SDL_assert.h"
@@ -57,10 +53,6 @@ Emscripten_JoyStickConnected(int eventType, const EmscriptenGamepadEvent *gamepa
return 1;
}
-#if !SDL_EVENTS_DISABLED
- SDL_Event event;
-#endif
-
item = (SDL_joylist_item *) SDL_malloc(sizeof (SDL_joylist_item));
if (item == NULL) {
return 1;
@@ -105,20 +97,12 @@ Emscripten_JoyStickConnected(int eventType, const EmscriptenGamepadEvent *gamepa
}
++numjoysticks;
+
+ SDL_PrivateJoystickAdded(numjoysticks - 1);
+
#ifdef DEBUG_JOYSTICK
SDL_Log("Number of joysticks is %d", numjoysticks);
#endif
-#if !SDL_EVENTS_DISABLED
- event.type = SDL_JOYDEVICEADDED;
-
- if (SDL_GetEventState(event.type) == SDL_ENABLE) {
- event.jdevice.which = numjoysticks - 1;
- if ( (SDL_EventOK == NULL) ||
- (*SDL_EventOK) (SDL_EventOKParam, &event) ) {
- SDL_PushEvent(&event);
- }
- }
-#endif /* !SDL_EVENTS_DISABLED */
#ifdef DEBUG_JOYSTICK
SDL_Log("Added joystick with index %d", item->index);
@@ -132,9 +116,6 @@ Emscripten_JoyStickDisconnected(int eventType, const EmscriptenGamepadEvent *gam
{
SDL_joylist_item *item = SDL_joylist;
SDL_joylist_item *prev = NULL;
-#if !SDL_EVENTS_DISABLED
- SDL_Event event;
-#endif
while (item != NULL) {
if (item->index == gamepadEvent->index) {
@@ -165,17 +146,7 @@ Emscripten_JoyStickDisconnected(int eventType, const EmscriptenGamepadEvent *gam
/* Need to decrement the joystick count before we post the event */
--numjoysticks;
-#if !SDL_EVENTS_DISABLED
- event.type = SDL_JOYDEVICEREMOVED;
-
- if (SDL_GetEventState(event.type) == SDL_ENABLE) {
- event.jdevice.which = item->device_instance;
- if ( (SDL_EventOK == NULL) ||
- (*SDL_EventOK) (SDL_EventOKParam, &event) ) {
- SDL_PushEvent(&event);
- }
- }
-#endif /* !SDL_EVENTS_DISABLED */
+ SDL_PrivateJoystickRemoved(item->device_instance);
#ifdef DEBUG_JOYSTICK
SDL_Log("Removed joystick with id %d", item->device_instance);
@@ -377,6 +348,10 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
void
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
{
+ SDL_joylist_item *item = (SDL_joylist_item *) joystick->hwdata;
+ if (item) {
+ item->joystick = NULL;
+ }
}
/* Function to perform any system-specific joystick related cleanup */
diff --git a/Engine/lib/sdl/src/joystick/emscripten/SDL_sysjoystick_c.h b/Engine/lib/sdl/src/joystick/emscripten/SDL_sysjoystick_c.h
index c7103c56a..41f613e11 100644
--- a/Engine/lib/sdl/src/joystick/emscripten/SDL_sysjoystick_c.h
+++ b/Engine/lib/sdl/src/joystick/emscripten/SDL_sysjoystick_c.h
@@ -1,23 +1,23 @@
/*
- Simple DirectMedia Layer
- Copyright (C) 1997-2016 Sam Lantinga
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2016 Sam Lantinga
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
#include "../../SDL_internal.h"
diff --git a/Engine/lib/sdl/src/joystick/haiku/SDL_haikujoystick.cc b/Engine/lib/sdl/src/joystick/haiku/SDL_haikujoystick.cc
index 3ec9ae107..a680189c7 100644
--- a/Engine/lib/sdl/src/joystick/haiku/SDL_haikujoystick.cc
+++ b/Engine/lib/sdl/src/joystick/haiku/SDL_haikujoystick.cc
@@ -74,8 +74,8 @@ extern "C"
if (joystick.Open(name) != B_ERROR) {
BString stick_name;
joystick.GetControllerName(&stick_name);
- SDL_joyport[SDL_SYS_numjoysticks] = strdup(name);
- SDL_joyname[SDL_SYS_numjoysticks] = strdup(stick_name.String());
+ SDL_joyport[SDL_SYS_numjoysticks] = SDL_strdup(name);
+ SDL_joyname[SDL_SYS_numjoysticks] = SDL_strdup(stick_name.String());
SDL_SYS_numjoysticks++;
joystick.Close();
}
diff --git a/Engine/lib/sdl/src/joystick/iphoneos/SDL_sysjoystick.m b/Engine/lib/sdl/src/joystick/iphoneos/SDL_sysjoystick.m
index c8a42af05..eb7e00032 100644
--- a/Engine/lib/sdl/src/joystick/iphoneos/SDL_sysjoystick.m
+++ b/Engine/lib/sdl/src/joystick/iphoneos/SDL_sysjoystick.m
@@ -26,6 +26,7 @@
/* needed for SDL_IPHONE_MAX_GFORCE macro */
#include "SDL_config_iphoneos.h"
+#include "SDL_events.h"
#include "SDL_joystick.h"
#include "SDL_hints.h"
#include "SDL_stdinc.h"
@@ -36,7 +37,9 @@
#include "../../events/SDL_events_c.h"
#endif
+#if !TARGET_OS_TV
#import
+#endif
#ifdef SDL_JOYSTICK_MFI
#import
@@ -45,8 +48,10 @@ static id connectObserver = nil;
static id disconnectObserver = nil;
#endif /* SDL_JOYSTICK_MFI */
+#if !TARGET_OS_TV
static const char *accelerometerName = "iOS Accelerometer";
static CMMotionManager *motionManager = nil;
+#endif /* !TARGET_OS_TV */
static SDL_JoystickDeviceItem *deviceList = NULL;
@@ -105,6 +110,11 @@ SDL_SYS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCController *contr
} else if (controller.gamepad) {
device->guid.data[10] = 2;
}
+#if TARGET_OS_TV
+ else if (controller.microGamepad) {
+ device->guid.data[10] = 3;
+ }
+#endif /* TARGET_OS_TV */
if (controller.extendedGamepad) {
device->naxes = 6; /* 2 thumbsticks and 2 triggers */
@@ -115,21 +125,27 @@ SDL_SYS_AddMFIJoystickDevice(SDL_JoystickDeviceItem *device, GCController *contr
device->nhats = 1; /* d-pad */
device->nbuttons = 7; /* ABXY, shoulder buttons, pause button */
}
- /* TODO: Handle micro profiles on tvOS. */
+#if TARGET_OS_TV
+ else if (controller.microGamepad) {
+ device->naxes = 2; /* treat the touch surface as two axes */
+ device->nhats = 0; /* apparently the touch surface-as-dpad is buggy */
+ device->nbuttons = 3; /* AX, pause button */
+
+ controller.microGamepad.allowsRotation = SDL_GetHintBoolean(SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION, SDL_FALSE);
+ }
+#endif /* TARGET_OS_TV */
/* This will be set when the first button press of the controller is
* detected. */
controller.playerIndex = -1;
-#endif
+
+#endif /* SDL_JOYSTICK_MFI */
}
static void
SDL_SYS_AddJoystickDevice(GCController *controller, SDL_bool accelerometer)
{
SDL_JoystickDeviceItem *device = deviceList;
-#if !SDL_EVENTS_DISABLED
- SDL_Event event;
-#endif
while (device != NULL) {
if (device->controller == controller) {
@@ -149,6 +165,10 @@ SDL_SYS_AddJoystickDevice(GCController *controller, SDL_bool accelerometer)
device->instance_id = instancecounter++;
if (accelerometer) {
+#if TARGET_OS_TV
+ SDL_free(device);
+ return;
+#else
device->name = SDL_strdup(accelerometerName);
device->naxes = 3; /* Device acceleration in the x, y, and z axes. */
device->nhats = 0;
@@ -156,6 +176,7 @@ SDL_SYS_AddJoystickDevice(GCController *controller, SDL_bool accelerometer)
/* Use the accelerometer name as a GUID. */
SDL_memcpy(&device->guid.data, device->name, SDL_min(sizeof(SDL_JoystickGUID), SDL_strlen(device->name)));
+#endif /* TARGET_OS_TV */
} else if (controller) {
SDL_SYS_AddMFIJoystickDevice(device, controller);
}
@@ -172,17 +193,7 @@ SDL_SYS_AddJoystickDevice(GCController *controller, SDL_bool accelerometer)
++numjoysticks;
-#if !SDL_EVENTS_DISABLED
- event.type = SDL_JOYDEVICEADDED;
-
- if (SDL_GetEventState(event.type) == SDL_ENABLE) {
- event.jdevice.which = numjoysticks - 1;
- if ((SDL_EventOK == NULL) ||
- (*SDL_EventOK)(SDL_EventOKParam, &event)) {
- SDL_PushEvent(&event);
- }
- }
-#endif /* !SDL_EVENTS_DISABLED */
+ SDL_PrivateJoystickAdded(numjoysticks - 1);
}
static SDL_JoystickDeviceItem *
@@ -191,9 +202,6 @@ SDL_SYS_RemoveJoystickDevice(SDL_JoystickDeviceItem *device)
SDL_JoystickDeviceItem *prev = NULL;
SDL_JoystickDeviceItem *next = NULL;
SDL_JoystickDeviceItem *item = deviceList;
-#if !SDL_EVENTS_DISABLED
- SDL_Event event;
-#endif
if (device == NULL) {
return NULL;
@@ -234,17 +242,7 @@ SDL_SYS_RemoveJoystickDevice(SDL_JoystickDeviceItem *device)
--numjoysticks;
-#if !SDL_EVENTS_DISABLED
- event.type = SDL_JOYDEVICEREMOVED;
-
- if (SDL_GetEventState(event.type) == SDL_ENABLE) {
- event.jdevice.which = device->instance_id;
- if ((SDL_EventOK == NULL) ||
- (*SDL_EventOK)(SDL_EventOKParam, &event)) {
- SDL_PushEvent(&event);
- }
- }
-#endif /* !SDL_EVENTS_DISABLED */
+ SDL_PrivateJoystickRemoved(device->instance_id);
SDL_free(device->name);
SDL_free(device);
@@ -252,6 +250,22 @@ SDL_SYS_RemoveJoystickDevice(SDL_JoystickDeviceItem *device)
return next;
}
+#if TARGET_OS_TV
+static void
+SDL_AppleTVRemoteRotationHintChanged(void *udata, const char *name, const char *oldValue, const char *newValue)
+{
+ BOOL allowRotation = newValue != NULL && *newValue != '0';
+
+ @autoreleasepool {
+ for (GCController *controller in [GCController controllers]) {
+ if (controller.microGamepad) {
+ controller.microGamepad.allowsRotation = allowRotation;
+ }
+ }
+ }
+}
+#endif /* TARGET_OS_TV */
+
/* Function to scan the system for joysticks.
* Joystick 0 should be the system default joystick.
* It should return 0, or -1 on an unrecoverable fatal error.
@@ -261,12 +275,13 @@ SDL_SYS_JoystickInit(void)
{
@autoreleasepool {
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
- const char *hint = SDL_GetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK);
- if (!hint || SDL_atoi(hint)) {
+#if !TARGET_OS_TV
+ if (SDL_GetHintBoolean(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, SDL_TRUE)) {
/* Default behavior, accelerometer as joystick */
SDL_SYS_AddJoystickDevice(nil, SDL_TRUE);
}
+#endif /* !TARGET_OS_TV */
#ifdef SDL_JOYSTICK_MFI
/* GameController.framework was added in iOS 7. */
@@ -278,6 +293,11 @@ SDL_SYS_JoystickInit(void)
SDL_SYS_AddJoystickDevice(controller, SDL_FALSE);
}
+#if TARGET_OS_TV
+ SDL_AddHintCallback(SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION,
+ SDL_AppleTVRemoteRotationHintChanged, NULL);
+#endif /* TARGET_OS_TV */
+
connectObserver = [center addObserverForName:GCControllerDidConnectNotification
object:nil
queue:nil
@@ -355,6 +375,7 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
@autoreleasepool {
if (device->accelerometer) {
+#if !TARGET_OS_TV
if (motionManager == nil) {
motionManager = [[CMMotionManager alloc] init];
}
@@ -362,6 +383,7 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index)
/* Shorter times between updates can significantly increase CPU usage. */
motionManager.accelerometerUpdateInterval = 0.1;
[motionManager startAccelerometerUpdates];
+#endif /* !TARGET_OS_TV */
} else {
#ifdef SDL_JOYSTICK_MFI
GCController *controller = device->controller;
@@ -387,6 +409,7 @@ SDL_SYS_JoystickAttached(SDL_Joystick *joystick)
static void
SDL_SYS_AccelerometerUpdate(SDL_Joystick * joystick)
{
+#if !TARGET_OS_TV
const float maxgforce = SDL_IPHONE_MAX_GFORCE;
const SInt16 maxsint16 = 0x7FFF;
CMAcceleration accel;
@@ -424,6 +447,7 @@ SDL_SYS_AccelerometerUpdate(SDL_Joystick * joystick)
SDL_PrivateJoystickAxis(joystick, 0, (accel.x / maxgforce) * maxsint16);
SDL_PrivateJoystickAxis(joystick, 1, -(accel.y / maxgforce) * maxsint16);
SDL_PrivateJoystickAxis(joystick, 2, (accel.z / maxgforce) * maxsint16);
+#endif /* !TARGET_OS_TV */
}
#ifdef SDL_JOYSTICK_MFI
@@ -455,7 +479,7 @@ SDL_SYS_MFIJoystickHatStateForDPad(GCControllerDirectionPad *dpad)
static void
SDL_SYS_MFIJoystickUpdate(SDL_Joystick * joystick)
{
-#ifdef SDL_JOYSTICK_MFI
+#if SDL_JOYSTICK_MFI
@autoreleasepool {
GCController *controller = joystick->hwdata->controller;
Uint8 hatstate = SDL_HAT_CENTERED;
@@ -517,7 +541,36 @@ SDL_SYS_MFIJoystickUpdate(SDL_Joystick * joystick)
SDL_PrivateJoystickButton(joystick, i, buttons[i]);
}
}
- /* TODO: Handle micro profiles on tvOS. */
+#if TARGET_OS_TV
+ else if (controller.microGamepad) {
+ GCMicroGamepad *gamepad = controller.microGamepad;
+
+ Sint16 axes[] = {
+ (Sint16) (gamepad.dpad.xAxis.value * 32767),
+ (Sint16) (gamepad.dpad.yAxis.value * -32767),
+ };
+
+ for (i = 0; i < SDL_arraysize(axes); i++) {
+ updateplayerindex |= (joystick->axes[i] != axes[i]);
+ SDL_PrivateJoystickAxis(joystick, i, axes[i]);
+ }
+
+ /* Apparently the dpad values are not accurate enough to be useful. */
+ /* hatstate = SDL_SYS_MFIJoystickHatStateForDPad(gamepad.dpad); */
+
+ Uint8 buttons[] = {
+ gamepad.buttonA.isPressed,
+ gamepad.buttonX.isPressed,
+ };
+
+ for (i = 0; i < SDL_arraysize(buttons); i++) {
+ updateplayerindex |= (joystick->buttons[i] != buttons[i]);
+ SDL_PrivateJoystickButton(joystick, i, buttons[i]);
+ }
+
+ /* TODO: Figure out what to do with reportsAbsoluteDpadValues */
+ }
+#endif /* TARGET_OS_TV */
if (joystick->nhats > 0) {
updateplayerindex |= (joystick->hats[0] != hatstate);
@@ -557,7 +610,7 @@ SDL_SYS_MFIJoystickUpdate(SDL_Joystick * joystick)
}
}
}
-#endif
+#endif /* SDL_JOYSTICK_MFI */
}
/* Function to update the state of a joystick - called as a device poll.
@@ -595,7 +648,9 @@ SDL_SYS_JoystickClose(SDL_Joystick * joystick)
@autoreleasepool {
if (device->accelerometer) {
+#if !TARGET_OS_TV
[motionManager stopAccelerometerUpdates];
+#endif /* !TARGET_OS_TV */
} else if (device->controller) {
#ifdef SDL_JOYSTICK_MFI
GCController *controller = device->controller;
@@ -623,13 +678,20 @@ SDL_SYS_JoystickQuit(void)
[center removeObserver:disconnectObserver name:GCControllerDidDisconnectNotification object:nil];
disconnectObserver = nil;
}
+
+#if TARGET_OS_TV
+ SDL_DelHintCallback(SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION,
+ SDL_AppleTVRemoteRotationHintChanged, NULL);
+#endif /* TARGET_OS_TV */
#endif /* SDL_JOYSTICK_MFI */
while (deviceList != NULL) {
SDL_SYS_RemoveJoystickDevice(deviceList);
}
+#if !TARGET_OS_TV
motionManager = nil;
+#endif /* !TARGET_OS_TV */
}
numjoysticks = 0;
diff --git a/Engine/lib/sdl/src/joystick/linux/SDL_sysjoystick.c b/Engine/lib/sdl/src/joystick/linux/SDL_sysjoystick.c
index 8c73859ea..bd52b1808 100644
--- a/Engine/lib/sdl/src/joystick/linux/SDL_sysjoystick.c
+++ b/Engine/lib/sdl/src/joystick/linux/SDL_sysjoystick.c
@@ -42,11 +42,6 @@
#include "../SDL_joystick_c.h"
#include "SDL_sysjoystick_c.h"
-/* !!! FIXME: move this somewhere else. */
-#if !SDL_EVENTS_DISABLED
-#include "../../events/SDL_events_c.h"
-#endif
-
/* This isn't defined in older Linux kernel headers */
#ifndef SYN_DROPPED
#define SYN_DROPPED 3
@@ -176,9 +171,6 @@ MaybeAddDevice(const char *path)
char namebuf[128];
SDL_JoystickGUID guid;
SDL_joylist_item *item;
-#if !SDL_EVENTS_DISABLED
- SDL_Event event;
-#endif
if (path == NULL) {
return -1;
@@ -239,18 +231,7 @@ MaybeAddDevice(const char *path)
/* Need to increment the joystick count before we post the event */
++numjoysticks;
- /* !!! FIXME: Move this to an SDL_PrivateJoyDeviceAdded() function? */
-#if !SDL_EVENTS_DISABLED
- event.type = SDL_JOYDEVICEADDED;
-
- if (SDL_GetEventState(event.type) == SDL_ENABLE) {
- event.jdevice.which = (numjoysticks - 1);
- if ( (SDL_EventOK == NULL) ||
- (*SDL_EventOK) (SDL_EventOKParam, &event) ) {
- SDL_PushEvent(&event);
- }
- }
-#endif /* !SDL_EVENTS_DISABLED */
+ SDL_PrivateJoystickAdded(numjoysticks - 1);
return numjoysticks;
}
@@ -262,9 +243,6 @@ MaybeRemoveDevice(const char *path)
{
SDL_joylist_item *item;
SDL_joylist_item *prev = NULL;
-#if !SDL_EVENTS_DISABLED
- SDL_Event event;
-#endif
if (path == NULL) {
return -1;
@@ -290,18 +268,7 @@ MaybeRemoveDevice(const char *path)
/* Need to decrement the joystick count before we post the event */
--numjoysticks;
- /* !!! FIXME: Move this to an SDL_PrivateJoyDeviceRemoved() function? */
-#if !SDL_EVENTS_DISABLED
- event.type = SDL_JOYDEVICEREMOVED;
-
- if (SDL_GetEventState(event.type) == SDL_ENABLE) {
- event.jdevice.which = item->device_instance;
- if ( (SDL_EventOK == NULL) ||
- (*SDL_EventOK) (SDL_EventOKParam, &event) ) {
- SDL_PushEvent(&event);
- }
- }
-#endif /* !SDL_EVENTS_DISABLED */
+ SDL_PrivateJoystickRemoved(item->device_instance);
SDL_free(item->path);
SDL_free(item->name);
diff --git a/Engine/lib/sdl/src/joystick/psp/SDL_sysjoystick.c b/Engine/lib/sdl/src/joystick/psp/SDL_sysjoystick.c
index e5247254f..352960edf 100644
--- a/Engine/lib/sdl/src/joystick/psp/SDL_sysjoystick.c
+++ b/Engine/lib/sdl/src/joystick/psp/SDL_sysjoystick.c
@@ -34,9 +34,9 @@
#include "SDL_events.h"
#include "SDL_error.h"
-#include "SDL_thread.h"
#include "SDL_mutex.h"
#include "SDL_timer.h"
+#include "../../thread/SDL_systhread.h"
/* Current pad state */
static SceCtrlData pad = { .Lx = 0, .Ly = 0, .Buttons = 0 };
@@ -116,7 +116,7 @@ int SDL_SYS_JoystickInit(void)
return SDL_SetError("Can't create input semaphore");
}
running = 1;
- if((thread = SDL_CreateThread(JoystickUpdate, "JoySitckThread",NULL)) == NULL) {
+ if((thread = SDL_CreateThreadInternal(JoystickUpdate, "JoystickThread", 4096, NULL)) == NULL) {
return SDL_SetError("Can't create input thread");
}
diff --git a/Engine/lib/sdl/src/joystick/sort_controllers.py b/Engine/lib/sdl/src/joystick/sort_controllers.py
old mode 100644
new mode 100755
diff --git a/Engine/lib/sdl/src/joystick/windows/SDL_dinputjoystick.c b/Engine/lib/sdl/src/joystick/windows/SDL_dinputjoystick.c
index f6b0cc88d..7166075b1 100644
--- a/Engine/lib/sdl/src/joystick/windows/SDL_dinputjoystick.c
+++ b/Engine/lib/sdl/src/joystick/windows/SDL_dinputjoystick.c
@@ -214,7 +214,7 @@ static DIOBJECTDATAFORMAT dfDIJoystick2[] = {
{ &GUID_Slider, FIELD_OFFSET(DIJOYSTATE2, rglFSlider[1]), DIDFT_OPTIONAL | DIDFT_AXIS | DIDFT_ANYINSTANCE, 0 },
};
-const DIDATAFORMAT c_dfDIJoystick2 = {
+const DIDATAFORMAT SDL_c_dfDIJoystick2 = {
sizeof(DIDATAFORMAT),
sizeof(DIOBJECTDATAFORMAT),
DIDF_ABSAXIS,
@@ -240,11 +240,23 @@ SDL_IsXInputDevice(const GUID* pGuidProductFromDirectInput)
static GUID IID_ValveStreamingGamepad = { MAKELONG(0x28DE, 0x11FF), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
static GUID IID_X360WiredGamepad = { MAKELONG(0x045E, 0x02A1), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
static GUID IID_X360WirelessGamepad = { MAKELONG(0x045E, 0x028E), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
+ static GUID IID_XOneWiredGamepad = { MAKELONG(0x045E, 0x02FF), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
+ static GUID IID_XOneWirelessGamepad = { MAKELONG(0x045E, 0x02DD), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
+ static GUID IID_XOneNewWirelessGamepad = { MAKELONG(0x045E, 0x02D1), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
+ static GUID IID_XOneSWirelessGamepad = { MAKELONG(0x045E, 0x02EA), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
+ static GUID IID_XOneSBluetoothGamepad = { MAKELONG(0x045E, 0x02E0), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
+ static GUID IID_XOneEliteWirelessGamepad = { MAKELONG(0x045E, 0x02E3), 0x0000, 0x0000, { 0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44 } };
static const GUID *s_XInputProductGUID[] = {
&IID_ValveStreamingGamepad,
- &IID_X360WiredGamepad, /* Microsoft's wired X360 controller for Windows. */
- &IID_X360WirelessGamepad /* Microsoft's wireless X360 controller for Windows. */
+ &IID_X360WiredGamepad, /* Microsoft's wired X360 controller for Windows. */
+ &IID_X360WirelessGamepad, /* Microsoft's wireless X360 controller for Windows. */
+ &IID_XOneWiredGamepad, /* Microsoft's wired Xbox One controller for Windows. */
+ &IID_XOneWirelessGamepad, /* Microsoft's wireless Xbox One controller for Windows. */
+ &IID_XOneNewWirelessGamepad, /* Microsoft's updated wireless Xbox One controller (w/ 3.5 mm jack) for Windows. */
+ &IID_XOneSWirelessGamepad, /* Microsoft's wireless Xbox One S controller for Windows. */
+ &IID_XOneSBluetoothGamepad, /* Microsoft's Bluetooth Xbox One S controller for Windows. */
+ &IID_XOneEliteWirelessGamepad /* Microsoft's wireless Xbox One Elite controller for Windows. */
};
size_t iDevice;
@@ -582,7 +594,7 @@ SDL_DINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickde
/* Use the extended data structure: DIJOYSTATE2. */
result =
IDirectInputDevice8_SetDataFormat(joystick->hwdata->InputDevice,
- &c_dfDIJoystick2);
+ &SDL_c_dfDIJoystick2);
if (FAILED(result)) {
return SetDIerror("IDirectInputDevice8::SetDataFormat", result);
}
diff --git a/Engine/lib/sdl/src/joystick/windows/SDL_windowsjoystick.c b/Engine/lib/sdl/src/joystick/windows/SDL_windowsjoystick.c
index 7123c6151..e528afa7f 100644
--- a/Engine/lib/sdl/src/joystick/windows/SDL_windowsjoystick.c
+++ b/Engine/lib/sdl/src/joystick/windows/SDL_windowsjoystick.c
@@ -35,16 +35,13 @@
#include "SDL_error.h"
#include "SDL_assert.h"
#include "SDL_events.h"
-#include "SDL_thread.h"
#include "SDL_timer.h"
#include "SDL_mutex.h"
#include "SDL_events.h"
#include "SDL_hints.h"
#include "SDL_joystick.h"
#include "../SDL_sysjoystick.h"
-#if !SDL_EVENTS_DISABLED
-#include "../../events/SDL_events_c.h"
-#endif
+#include "../../thread/SDL_systhread.h"
#include "../../core/windows/SDL_windows.h"
#if !defined(__WINRT__)
#include
@@ -301,18 +298,9 @@ SDL_SYS_JoystickInit(void)
SDL_SYS_JoystickDetect();
if (!s_threadJoystick) {
- s_bJoystickThreadQuit = SDL_FALSE;
/* spin up the thread to detect hotplug of devices */
-#if defined(__WIN32__) && !defined(HAVE_LIBC)
-#undef SDL_CreateThread
-#if SDL_DYNAMIC_API
- s_threadJoystick= SDL_CreateThread_REAL(SDL_JoystickThread, "SDL_joystick", NULL, NULL, NULL);
-#else
- s_threadJoystick= SDL_CreateThread(SDL_JoystickThread, "SDL_joystick", NULL, NULL, NULL);
-#endif
-#else
- s_threadJoystick = SDL_CreateThread(SDL_JoystickThread, "SDL_joystick", NULL);
-#endif
+ s_bJoystickThreadQuit = SDL_FALSE;
+ s_threadJoystick = SDL_CreateThreadInternal(SDL_JoystickThread, "SDL_joystick", 64 * 1024, NULL);
}
return SDL_SYS_NumJoysticks();
}
@@ -336,9 +324,6 @@ void
SDL_SYS_JoystickDetect()
{
JoyStick_DeviceData *pCurList = NULL;
-#if !SDL_EVENTS_DISABLED
- SDL_Event event;
-#endif
/* only enum the devices if the joystick thread told us something changed */
if (!s_bDeviceAdded && !s_bDeviceRemoved) {
@@ -370,17 +355,7 @@ SDL_SYS_JoystickDetect()
SDL_DINPUT_MaybeRemoveDevice(&pCurList->dxdevice);
}
-#if !SDL_EVENTS_DISABLED
- SDL_zero(event);
- event.type = SDL_JOYDEVICEREMOVED;
-
- if (SDL_GetEventState(event.type) == SDL_ENABLE) {
- event.jdevice.which = pCurList->nInstanceID;
- if ((!SDL_EventOK) || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
- SDL_PushEvent(&event);
- }
- }
-#endif /* !SDL_EVENTS_DISABLED */
+ SDL_PrivateJoystickRemoved(pCurList->nInstanceID);
pListNext = pCurList->pNext;
SDL_free(pCurList->joystickname);
@@ -401,17 +376,8 @@ SDL_SYS_JoystickDetect()
SDL_DINPUT_MaybeAddDevice(&pNewJoystick->dxdevice);
}
-#if !SDL_EVENTS_DISABLED
- SDL_zero(event);
- event.type = SDL_JOYDEVICEADDED;
+ SDL_PrivateJoystickAdded(device_index);
- if (SDL_GetEventState(event.type) == SDL_ENABLE) {
- event.jdevice.which = device_index;
- if ((!SDL_EventOK) || (*SDL_EventOK) (SDL_EventOKParam, &event)) {
- SDL_PushEvent(&event);
- }
- }
-#endif /* !SDL_EVENTS_DISABLED */
pNewJoystick->send_add_event = SDL_FALSE;
}
device_index++;
@@ -543,6 +509,9 @@ SDL_SYS_JoystickQuit(void)
SDL_DINPUT_JoystickQuit();
SDL_XINPUT_JoystickQuit();
+
+ s_bDeviceAdded = SDL_FALSE;
+ s_bDeviceRemoved = SDL_FALSE;
}
/* return the stable device guid for this device index */
diff --git a/Engine/lib/sdl/src/joystick/windows/SDL_windowsjoystick_c.h b/Engine/lib/sdl/src/joystick/windows/SDL_windowsjoystick_c.h
index ab946b4f7..d3c5fcaab 100644
--- a/Engine/lib/sdl/src/joystick/windows/SDL_windowsjoystick_c.h
+++ b/Engine/lib/sdl/src/joystick/windows/SDL_windowsjoystick_c.h
@@ -83,6 +83,10 @@ struct joystick_hwdata
DWORD dwPacketNumber;
};
+#if SDL_JOYSTICK_DINPUT
+extern const DIDATAFORMAT SDL_c_dfDIJoystick2;
+#endif
+
extern void SDL_SYS_AddJoystickDevice(JoyStick_DeviceData *device);
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/joystick/windows/SDL_xinputjoystick.c b/Engine/lib/sdl/src/joystick/windows/SDL_xinputjoystick.c
index 2f27c47dc..d581d45b9 100644
--- a/Engine/lib/sdl/src/joystick/windows/SDL_xinputjoystick.c
+++ b/Engine/lib/sdl/src/joystick/windows/SDL_xinputjoystick.c
@@ -40,8 +40,7 @@ SDL_XInputUseOldJoystickMapping()
{
static int s_XInputUseOldJoystickMapping = -1;
if (s_XInputUseOldJoystickMapping < 0) {
- const char *hint = SDL_GetHint(SDL_HINT_XINPUT_USE_OLD_JOYSTICK_MAPPING);
- s_XInputUseOldJoystickMapping = (hint && *hint == '1') ? 1 : 0;
+ s_XInputUseOldJoystickMapping = SDL_GetHintBoolean(SDL_HINT_XINPUT_USE_OLD_JOYSTICK_MAPPING, SDL_FALSE);
}
return (s_XInputUseOldJoystickMapping > 0);
}
@@ -54,10 +53,7 @@ SDL_bool SDL_XINPUT_Enabled(void)
int
SDL_XINPUT_JoystickInit(void)
{
- const char *env = SDL_GetHint(SDL_HINT_XINPUT_ENABLED);
- if (env && !SDL_atoi(env)) {
- s_bXInputEnabled = SDL_FALSE;
- }
+ s_bXInputEnabled = SDL_GetHintBoolean(SDL_HINT_XINPUT_ENABLED, SDL_TRUE);
if (s_bXInputEnabled && WIN_LoadXInputDLL() < 0) {
s_bXInputEnabled = SDL_FALSE; /* oh well. */
@@ -376,7 +372,7 @@ SDL_SYS_IsXInputGamepad_DeviceIndex(int device_index)
for (index = device_index; index > 0; index--)
device = device->pNext;
- return (device->SubType == XINPUT_DEVSUBTYPE_GAMEPAD);
+ return device->bXInputDevice;
}
#else /* !SDL_JOYSTICK_XINPUT */
diff --git a/Engine/lib/sdl/src/loadso/dlopen/SDL_sysloadso.c b/Engine/lib/sdl/src/loadso/dlopen/SDL_sysloadso.c
index 03ffae129..7b30b7735 100644
--- a/Engine/lib/sdl/src/loadso/dlopen/SDL_sysloadso.c
+++ b/Engine/lib/sdl/src/loadso/dlopen/SDL_sysloadso.c
@@ -30,11 +30,25 @@
#include "SDL_loadso.h"
+#if SDL_VIDEO_DRIVER_UIKIT
+#include "../../video/uikit/SDL_uikitvideo.h"
+#endif
+
void *
SDL_LoadObject(const char *sofile)
{
- void *handle = dlopen(sofile, RTLD_NOW|RTLD_LOCAL);
- const char *loaderror = (char *) dlerror();
+ void *handle;
+ const char *loaderror;
+
+#if SDL_VIDEO_DRIVER_UIKIT
+ if (!UIKit_IsSystemVersionAtLeast(8.0)) {
+ SDL_SetError("SDL_LoadObject requires iOS 8+");
+ return NULL;
+ }
+#endif
+
+ handle = dlopen(sofile, RTLD_NOW|RTLD_LOCAL);
+ loaderror = (char *) dlerror();
if (handle == NULL) {
SDL_SetError("Failed loading %s: %s", sofile, loaderror);
}
diff --git a/Engine/lib/sdl/src/main/android/SDL_android_main.c b/Engine/lib/sdl/src/main/android/SDL_android_main.c
index 4173bcb1d..671d9328e 100644
--- a/Engine/lib/sdl/src/main/android/SDL_android_main.c
+++ b/Engine/lib/sdl/src/main/android/SDL_android_main.c
@@ -16,12 +16,17 @@
/* Called before SDL_main() to initialize JNI bindings in SDL library */
extern void SDL_Android_Init(JNIEnv* env, jclass cls);
+/* This prototype is needed to prevent a warning about the missing prototype for global function below */
+JNIEXPORT int JNICALL Java_org_libsdl_app_SDLActivity_nativeInit(JNIEnv* env, jclass cls, jobject array);
+
/* Start up the SDL app */
JNIEXPORT int JNICALL Java_org_libsdl_app_SDLActivity_nativeInit(JNIEnv* env, jclass cls, jobject array)
{
int i;
int argc;
int status;
+ int len;
+ char** argv;
/* This interface could expand with ABI negotiation, callbacks, etc. */
SDL_Android_Init(env, cls);
@@ -30,8 +35,8 @@ JNIEXPORT int JNICALL Java_org_libsdl_app_SDLActivity_nativeInit(JNIEnv* env, jc
/* Prepare the arguments. */
- int len = (*env)->GetArrayLength(env, array);
- char* argv[1 + len + 1];
+ len = (*env)->GetArrayLength(env, array);
+ argv = SDL_stack_alloc(char*, 1 + len + 1);
argc = 0;
/* Use the name "app_process" so PHYSFS_platformCalcBaseDir() works.
https://bitbucket.org/MartinFelis/love-android-sdl2/issue/23/release-build-crash-on-start
@@ -66,7 +71,7 @@ JNIEXPORT int JNICALL Java_org_libsdl_app_SDLActivity_nativeInit(JNIEnv* env, jc
for (i = 0; i < argc; ++i) {
SDL_free(argv[i]);
}
-
+ SDL_stack_free(argv);
/* Do not issue an exit or the whole application will terminate instead of just the SDL thread */
/* exit(status); */
diff --git a/Engine/lib/sdl/src/main/haiku/SDL_BApp.h b/Engine/lib/sdl/src/main/haiku/SDL_BApp.h
index 157c23635..9672d462c 100644
--- a/Engine/lib/sdl/src/main/haiku/SDL_BApp.h
+++ b/Engine/lib/sdl/src/main/haiku/SDL_BApp.h
@@ -193,7 +193,8 @@ public:
if(_current_context)
_current_context->UnlockGL();
_current_context = newContext;
- _current_context->LockGL();
+ if (_current_context)
+ _current_context->LockGL();
}
private:
/* Event management */
@@ -272,6 +273,17 @@ private:
}
BE_SetKeyState(scancode, state);
SDL_SendKeyboardKey(state, BE_GetScancodeFromBeKey(scancode));
+
+ if (state == SDL_PRESSED && SDL_EventState(SDL_TEXTINPUT, SDL_QUERY)) {
+ const int8 *keyUtf8;
+ ssize_t count;
+ if (msg->FindData("key-utf8", B_INT8_TYPE, (const void**)&keyUtf8, &count) == B_OK) {
+ char text[SDL_TEXTINPUTEVENT_TEXT_SIZE];
+ SDL_zero(text);
+ SDL_memcpy(text, keyUtf8, count);
+ SDL_SendKeyboardText(text);
+ }
+ }
}
void _HandleMouseFocus(BMessage *msg) {
diff --git a/Engine/lib/sdl/src/main/haiku/SDL_BeApp.cc b/Engine/lib/sdl/src/main/haiku/SDL_BeApp.cc
index 36c2a1ab8..4c5df0954 100644
--- a/Engine/lib/sdl/src/main/haiku/SDL_BeApp.cc
+++ b/Engine/lib/sdl/src/main/haiku/SDL_BeApp.cc
@@ -31,7 +31,6 @@
#include "SDL_BApp.h" /* SDL_BApp class definition */
#include "SDL_BeApp.h"
-#include "SDL_thread.h"
#include "SDL_timer.h"
#include "SDL_error.h"
@@ -40,6 +39,9 @@
#ifdef __cplusplus
extern "C" {
#endif
+
+#include "../../thread/SDL_systhread.h"
+
/* Flag to tell whether or not the Be application is active or not */
int SDL_BeAppActive = 0;
static SDL_Thread *SDL_AppThread = NULL;
@@ -62,7 +64,7 @@ SDL_InitBeApp(void)
{
/* Create the BApplication that handles appserver interaction */
if (SDL_BeAppActive <= 0) {
- SDL_AppThread = SDL_CreateThread(StartBeApp, "SDLApplication", NULL);
+ SDL_AppThread = SDL_CreateThreadInternal(StartBeApp, "SDLApplication", 0, NULL);
if (SDL_AppThread == NULL) {
return SDL_SetError("Couldn't create BApplication thread");
}
diff --git a/Engine/lib/sdl/src/main/windows/SDL_windows_main.c b/Engine/lib/sdl/src/main/windows/SDL_windows_main.c
index e6378081f..b502ed50e 100644
--- a/Engine/lib/sdl/src/main/windows/SDL_windows_main.c
+++ b/Engine/lib/sdl/src/main/windows/SDL_windows_main.c
@@ -126,44 +126,15 @@ main_utf8(int argc, char *argv[])
return SDL_main(argc, argv);
}
-/* This is where execution begins [console apps, ansi] */
-int
-console_ansi_main(int argc, char *argv[])
-{
- /* !!! FIXME: are these in the system codepage? We need to convert to UTF-8. */
- return main_utf8(argc, argv);
-}
-
-
-#if UNICODE
-/* This is where execution begins [console apps, unicode] */
-int
-console_wmain(int argc, wchar_t *wargv[], wchar_t *wenvp)
-{
- int retval = 0;
- char **argv = SDL_stack_alloc(char*, argc);
- int i;
-
- for (i = 0; i < argc; ++i) {
- argv[i] = WIN_StringToUTF8(wargv[i]);
- }
-
- retval = main_utf8(argc, argv);
-
- /* !!! FIXME: we are leaking all the elements of argv we allocated. */
- SDL_stack_free(argv);
-
- return retval;
-}
-#endif
-
-/* This is where execution begins [windowed apps] */
-int WINAPI
-WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
+/* Gets the arguments with GetCommandLine, converts them to argc and argv
+ and calls main_utf8 */
+static int
+main_getcmdline()
{
char **argv;
int argc;
char *cmdline;
+ int retval = 0;
/* Grab the command line */
TCHAR *text = GetCommandLine();
@@ -185,15 +156,50 @@ WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
}
ParseCommandLine(cmdline, argv);
- /* Run the main program */
- main_utf8(argc, argv);
+ retval = main_utf8(argc, argv);
SDL_stack_free(argv);
-
SDL_free(cmdline);
- /* Hush little compiler, don't you cry... */
- return 0;
+ return retval;
+}
+
+/* This is where execution begins [console apps, ansi] */
+int
+console_ansi_main(int argc, char *argv[])
+{
+ return main_getcmdline();
+}
+
+
+#if UNICODE
+/* This is where execution begins [console apps, unicode] */
+int
+console_wmain(int argc, wchar_t *wargv[], wchar_t *wenvp)
+{
+ int retval = 0;
+ char **argv = SDL_stack_alloc(char*, argc + 1);
+ int i;
+
+ for (i = 0; i < argc; ++i) {
+ argv[i] = WIN_StringToUTF8(wargv[i]);
+ }
+ argv[argc] = NULL;
+
+ retval = main_utf8(argc, argv);
+
+ /* !!! FIXME: we are leaking all the elements of argv we allocated. */
+ SDL_stack_free(argv);
+
+ return retval;
+}
+#endif
+
+/* This is where execution begins [windowed apps] */
+int WINAPI
+WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
+{
+ return main_getcmdline();
}
#endif /* __WIN32__ */
diff --git a/Engine/lib/sdl/src/main/windows/version.rc b/Engine/lib/sdl/src/main/windows/version.rc
index 8597154aa..e10443b06 100644
--- a/Engine/lib/sdl/src/main/windows/version.rc
+++ b/Engine/lib/sdl/src/main/windows/version.rc
@@ -9,8 +9,8 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,0,4,0
- PRODUCTVERSION 2,0,4,0
+ FILEVERSION 2,0,5,0
+ PRODUCTVERSION 2,0,5,0
FILEFLAGSMASK 0x3fL
FILEFLAGS 0x0L
FILEOS 0x40004L
@@ -23,12 +23,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "\0"
VALUE "FileDescription", "SDL\0"
- VALUE "FileVersion", "2, 0, 4, 0\0"
+ VALUE "FileVersion", "2, 0, 5, 0\0"
VALUE "InternalName", "SDL\0"
VALUE "LegalCopyright", "Copyright © 2016 Sam Lantinga\0"
VALUE "OriginalFilename", "SDL2.dll\0"
VALUE "ProductName", "Simple DirectMedia Layer\0"
- VALUE "ProductVersion", "2, 0, 4, 0\0"
+ VALUE "ProductVersion", "2, 0, 5, 0\0"
END
END
BLOCK "VarFileInfo"
diff --git a/Engine/lib/sdl/src/main/winrt/SDL2-WinRTResource_BlankCursor.cur b/Engine/lib/sdl/src/main/winrt/SDL2-WinRTResource_BlankCursor.cur
new file mode 100644
index 000000000..c6556b8a7
Binary files /dev/null and b/Engine/lib/sdl/src/main/winrt/SDL2-WinRTResource_BlankCursor.cur differ
diff --git a/Engine/lib/sdl/src/main/winrt/SDL2-WinRTResources.rc b/Engine/lib/sdl/src/main/winrt/SDL2-WinRTResources.rc
new file mode 100644
index 000000000..988a8d57d
--- /dev/null
+++ b/Engine/lib/sdl/src/main/winrt/SDL2-WinRTResources.rc
@@ -0,0 +1,3 @@
+#include "winres.h"
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+5000 CURSOR "SDL2-WinRTResource_BlankCursor.cur"
diff --git a/Engine/lib/sdl/src/power/uikit/SDL_syspower.m b/Engine/lib/sdl/src/power/uikit/SDL_syspower.m
index 14ce3576a..7186b219c 100644
--- a/Engine/lib/sdl/src/power/uikit/SDL_syspower.m
+++ b/Engine/lib/sdl/src/power/uikit/SDL_syspower.m
@@ -30,6 +30,7 @@
#include "SDL_assert.h"
#include "SDL_syspower.h"
+#if !TARGET_OS_TV
/* turn off the battery monitor if it's been more than X ms since last check. */
static const int BATTERY_MONITORING_TIMEOUT = 3000;
static Uint32 SDL_UIKitLastPowerInfoQuery = 0;
@@ -46,10 +47,22 @@ SDL_UIKit_UpdateBatteryMonitoring(void)
}
}
}
+#else
+void
+SDL_UIKit_UpdateBatteryMonitoring(void)
+{
+ /* Do nothing. */
+}
+#endif /* !TARGET_OS_TV */
SDL_bool
SDL_GetPowerInfo_UIKit(SDL_PowerState * state, int *seconds, int *percent)
{
+#if TARGET_OS_TV
+ *state = SDL_POWERSTATE_NO_BATTERY;
+ *seconds = -1;
+ *percent = -1;
+#else /* TARGET_OS_TV */
@autoreleasepool {
UIDevice *uidev = [UIDevice currentDevice];
@@ -88,8 +101,10 @@ SDL_GetPowerInfo_UIKit(SDL_PowerState * state, int *seconds, int *percent)
const float level = uidev.batteryLevel;
*percent = ( (level < 0.0f) ? -1 : ((int) ((level * 100) + 0.5f)) );
- return SDL_TRUE; /* always the definitive answer on iOS. */
}
+#endif /* TARGET_OS_TV */
+
+ return SDL_TRUE; /* always the definitive answer on iOS. */
}
#endif /* SDL_POWER_UIKIT */
diff --git a/Engine/lib/sdl/src/render/SDL_render.c b/Engine/lib/sdl/src/render/SDL_render.c
index 923973ec7..94750810d 100644
--- a/Engine/lib/sdl/src/render/SDL_render.c
+++ b/Engine/lib/sdl/src/render/SDL_render.c
@@ -234,12 +234,11 @@ SDL_CreateRenderer(SDL_Window * window, int index, Uint32 flags)
return NULL;
}
- hint = SDL_GetHint(SDL_HINT_RENDER_VSYNC);
- if (hint) {
- if (*hint == '0') {
- flags &= ~SDL_RENDERER_PRESENTVSYNC;
- } else {
+ if (SDL_GetHint(SDL_HINT_RENDER_VSYNC)) {
+ if (SDL_GetHintBoolean(SDL_HINT_RENDER_VSYNC, SDL_TRUE)) {
flags |= SDL_RENDERER_PRESENTVSYNC;
+ } else {
+ flags &= ~SDL_RENDERER_PRESENTVSYNC;
}
}
@@ -1106,6 +1105,8 @@ SDL_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
renderer->viewport.y = 0;
renderer->viewport.w = texture->w;
renderer->viewport.h = texture->h;
+ SDL_zero(renderer->clip_rect);
+ renderer->clipping_enabled = SDL_FALSE;
renderer->scale.x = 1.0f;
renderer->scale.y = 1.0f;
renderer->logical_w = texture->w;
@@ -1144,6 +1145,9 @@ UpdateLogicalSize(SDL_Renderer *renderer)
float scale;
SDL_Rect viewport;
+ if (!renderer->logical_w || !renderer->logical_h) {
+ return 0;
+ }
if (SDL_GetRendererOutputSize(renderer, &w, &h) < 0) {
return -1;
}
@@ -1154,7 +1158,19 @@ UpdateLogicalSize(SDL_Renderer *renderer)
/* Clear the scale because we're setting viewport in output coordinates */
SDL_RenderSetScale(renderer, 1.0f, 1.0f);
- if (SDL_fabs(want_aspect-real_aspect) < 0.0001) {
+ if (renderer->integer_scale) {
+ if (want_aspect > real_aspect) {
+ scale = (float)(w / renderer->logical_w);
+ } else {
+ scale = (float)(h / renderer->logical_h);
+ }
+ viewport.w = (int)SDL_ceil(renderer->logical_w * scale);
+ viewport.x = (w - viewport.w) / 2;
+ viewport.h = (int)SDL_ceil(renderer->logical_h * scale);
+ viewport.y = (h - viewport.h) / 2;
+
+ SDL_RenderSetViewport(renderer, &viewport);
+ } else if (SDL_fabs(want_aspect-real_aspect) < 0.0001) {
/* The aspect ratios are the same, just scale appropriately */
scale = (float)w / renderer->logical_w;
SDL_RenderSetViewport(renderer, NULL);
@@ -1215,6 +1231,24 @@ SDL_RenderGetLogicalSize(SDL_Renderer * renderer, int *w, int *h)
}
}
+int
+SDL_RenderSetIntegerScale(SDL_Renderer * renderer, SDL_bool enable)
+{
+ CHECK_RENDERER_MAGIC(renderer, -1);
+
+ renderer->integer_scale = enable;
+
+ return UpdateLogicalSize(renderer);
+}
+
+SDL_bool
+SDLCALL SDL_RenderGetIntegerScale(SDL_Renderer * renderer)
+{
+ CHECK_RENDERER_MAGIC(renderer, SDL_FALSE);
+
+ return renderer->integer_scale;
+}
+
int
SDL_RenderSetViewport(SDL_Renderer * renderer, const SDL_Rect * rect)
{
@@ -1425,6 +1459,7 @@ SDL_RenderDrawPoints(SDL_Renderer * renderer,
if (count < 1) {
return 0;
}
+
/* Don't draw while we're hidden */
if (renderer->hidden) {
return 0;
@@ -1534,6 +1569,7 @@ SDL_RenderDrawLines(SDL_Renderer * renderer,
if (count < 2) {
return 0;
}
+
/* Don't draw while we're hidden */
if (renderer->hidden) {
return 0;
@@ -1607,6 +1643,7 @@ SDL_RenderDrawRects(SDL_Renderer * renderer,
if (renderer->hidden) {
return 0;
}
+
for (i = 0; i < count; ++i) {
if (SDL_RenderDrawRect(renderer, &rects[i]) < 0) {
return -1;
@@ -1648,6 +1685,7 @@ SDL_RenderFillRects(SDL_Renderer * renderer,
if (count < 1) {
return 0;
}
+
/* Don't draw while we're hidden */
if (renderer->hidden) {
return 0;
@@ -1686,6 +1724,11 @@ SDL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
return SDL_SetError("Texture was not created with this renderer");
}
+ /* Don't draw while we're hidden */
+ if (renderer->hidden) {
+ return 0;
+ }
+
real_srcrect.x = 0;
real_srcrect.y = 0;
real_srcrect.w = texture->w;
@@ -1710,11 +1753,6 @@ SDL_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
texture = texture->native;
}
- /* Don't draw while we're hidden */
- if (renderer->hidden) {
- return 0;
- }
-
frect.x = real_dstrect.x * renderer->scale.x;
frect.y = real_dstrect.y * renderer->scale.y;
frect.w = real_dstrect.w * renderer->scale.x;
@@ -1735,7 +1773,7 @@ SDL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
SDL_FRect frect;
SDL_FPoint fcenter;
- if (flip == SDL_FLIP_NONE && angle == 0) { /* fast path when we don't need rotation or flipping */
+ if (flip == SDL_FLIP_NONE && (int)(angle/360) == angle/360) { /* fast path when we don't need rotation or flipping */
return SDL_RenderCopy(renderer, texture, srcrect, dstrect);
}
@@ -1749,6 +1787,11 @@ SDL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
return SDL_SetError("Renderer does not support RenderCopyEx");
}
+ /* Don't draw while we're hidden */
+ if (renderer->hidden) {
+ return 0;
+ }
+
real_srcrect.x = 0;
real_srcrect.y = 0;
real_srcrect.w = texture->w;
@@ -1772,8 +1815,9 @@ SDL_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
texture = texture->native;
}
- if(center) real_center = *center;
- else {
+ if (center) {
+ real_center = *center;
+ } else {
real_center.x = real_dstrect.w/2;
real_center.y = real_dstrect.h/2;
}
diff --git a/Engine/lib/sdl/src/render/SDL_sysrender.h b/Engine/lib/sdl/src/render/SDL_sysrender.h
index 19dfe8e64..378fc4d97 100644
--- a/Engine/lib/sdl/src/render/SDL_sysrender.h
+++ b/Engine/lib/sdl/src/render/SDL_sysrender.h
@@ -135,6 +135,9 @@ struct SDL_Renderer
int logical_w_backup;
int logical_h_backup;
+ /* Whether or not to force the viewport to even integer intervals */
+ SDL_bool integer_scale;
+
/* The drawable area within the window */
SDL_Rect viewport;
SDL_Rect viewport_backup;
diff --git a/Engine/lib/sdl/src/render/direct3d/SDL_render_d3d.c b/Engine/lib/sdl/src/render/direct3d/SDL_render_d3d.c
index 9d7564224..151dbbf04 100644
--- a/Engine/lib/sdl/src/render/direct3d/SDL_render_d3d.c
+++ b/Engine/lib/sdl/src/render/direct3d/SDL_render_d3d.c
@@ -512,7 +512,6 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
D3D_RenderData *data;
SDL_SysWMinfo windowinfo;
HRESULT result;
- const char *hint;
D3DPRESENT_PARAMETERS pparams;
IDirect3DSwapChain9 *chain;
D3DCAPS9 caps;
@@ -607,8 +606,7 @@ D3D_CreateRenderer(SDL_Window * window, Uint32 flags)
device_flags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
}
- hint = SDL_GetHint(SDL_HINT_RENDER_DIRECT3D_THREADSAFE);
- if (hint && SDL_atoi(hint)) {
+ if (SDL_GetHintBoolean(SDL_HINT_RENDER_DIRECT3D_THREADSAFE, SDL_FALSE)) {
device_flags |= D3DCREATE_MULTITHREADED;
}
@@ -1004,6 +1002,10 @@ D3D_RecreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
D3D_RenderData *data = (D3D_RenderData *)renderer->driverdata;
D3D_TextureData *texturedata = (D3D_TextureData *)texture->driverdata;
+ if (!texturedata) {
+ return 0;
+ }
+
if (D3D_RecreateTextureRep(data->device, &texturedata->texture, texture->format, texture->w, texture->h) < 0) {
return -1;
}
@@ -1307,6 +1309,10 @@ D3D_RenderClear(SDL_Renderer * renderer)
BackBufferHeight = data->pparams.BackBufferHeight;
}
+ if (renderer->clipping_enabled) {
+ IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, FALSE);
+ }
+
/* Don't reset the viewport if we don't have to! */
if (!renderer->viewport.x && !renderer->viewport.y &&
renderer->viewport.w == BackBufferWidth &&
@@ -1336,6 +1342,10 @@ D3D_RenderClear(SDL_Renderer * renderer)
IDirect3DDevice9_SetViewport(data->device, &viewport);
}
+ if (renderer->clipping_enabled) {
+ IDirect3DDevice9_SetRenderState(data->device, D3DRS_SCISSORTESTENABLE, TRUE);
+ }
+
if (FAILED(result)) {
return D3D_SetError("Clear()", result);
}
diff --git a/Engine/lib/sdl/src/render/direct3d11/SDL_render_d3d11.c b/Engine/lib/sdl/src/render/direct3d11/SDL_render_d3d11.c
index a48eacee7..df0f1558a 100644
--- a/Engine/lib/sdl/src/render/direct3d11/SDL_render_d3d11.c
+++ b/Engine/lib/sdl/src/render/direct3d11/SDL_render_d3d11.c
@@ -51,6 +51,8 @@ extern ISwapChainBackgroundPanelNative * WINRT_GlobalSwapChainBackgroundPanelNat
#endif /* __WINRT__ */
+#define SDL_COMPOSE_ERROR(str) SDL_STRINGIFY_ARG(__FUNCTION__) ", " str
+
#define SAFE_RELEASE(X) if ((X)) { IUnknown_Release(SDL_static_cast(IUnknown*, X)); X = NULL; }
@@ -136,14 +138,31 @@ typedef struct
} D3D11_RenderData;
-/* Defined here so we don't have to include uuid.lib */
-static const GUID IID_IDXGIFactory2 = { 0x50c83a1c, 0xe072, 0x4c48, { 0x87, 0xb0, 0x36, 0x30, 0xfa, 0x36, 0xa6, 0xd0 } };
-static const GUID IID_IDXGIDevice1 = { 0x77db970f, 0x6276, 0x48ba, { 0xba, 0x28, 0x07, 0x01, 0x43, 0xb4, 0x39, 0x2c } };
-static const GUID IID_IDXGIDevice3 = { 0x6007896c, 0x3244, 0x4afd, { 0xbf, 0x18, 0xa6, 0xd3, 0xbe, 0xda, 0x50, 0x23 } };
-static const GUID IID_ID3D11Texture2D = { 0x6f15aaf2, 0xd208, 0x4e89, { 0x9a, 0xb4, 0x48, 0x95, 0x35, 0xd3, 0x4f, 0x9c } };
-static const GUID IID_ID3D11Device1 = { 0xa04bfb29, 0x08ef, 0x43d6, { 0xa4, 0x9c, 0xa9, 0xbd, 0xbd, 0xcb, 0xe6, 0x86 } };
-static const GUID IID_ID3D11DeviceContext1 = { 0xbb2c6faa, 0xb5fb, 0x4082, { 0x8e, 0x6b, 0x38, 0x8b, 0x8c, 0xfa, 0x90, 0xe1 } };
-static const GUID IID_ID3D11Debug = { 0x79cf2233, 0x7536, 0x4948, { 0x9d, 0x36, 0x1e, 0x46, 0x92, 0xdc, 0x57, 0x60 } };
+/* Define D3D GUIDs here so we don't have to include uuid.lib.
+*
+* Fix for SDL bug https://bugzilla.libsdl.org/show_bug.cgi?id=3437:
+* The extra 'SDL_' was added to the start of each IID's name, in order
+* to prevent build errors on both MinGW-w64 and WinRT/UWP.
+* (SDL bug https://bugzilla.libsdl.org/show_bug.cgi?id=3336 led to
+* linker errors in WinRT/UWP builds.)
+*/
+
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-const-variable"
+#endif
+
+static const GUID SDL_IID_IDXGIFactory2 = { 0x50c83a1c, 0xe072, 0x4c48, { 0x87, 0xb0, 0x36, 0x30, 0xfa, 0x36, 0xa6, 0xd0 } };
+static const GUID SDL_IID_IDXGIDevice1 = { 0x77db970f, 0x6276, 0x48ba, { 0xba, 0x28, 0x07, 0x01, 0x43, 0xb4, 0x39, 0x2c } };
+static const GUID SDL_IID_IDXGIDevice3 = { 0x6007896c, 0x3244, 0x4afd, { 0xbf, 0x18, 0xa6, 0xd3, 0xbe, 0xda, 0x50, 0x23 } };
+static const GUID SDL_IID_ID3D11Texture2D = { 0x6f15aaf2, 0xd208, 0x4e89, { 0x9a, 0xb4, 0x48, 0x95, 0x35, 0xd3, 0x4f, 0x9c } };
+static const GUID SDL_IID_ID3D11Device1 = { 0xa04bfb29, 0x08ef, 0x43d6, { 0xa4, 0x9c, 0xa9, 0xbd, 0xbd, 0xcb, 0xe6, 0x86 } };
+static const GUID SDL_IID_ID3D11DeviceContext1 = { 0xbb2c6faa, 0xb5fb, 0x4082, { 0x8e, 0x6b, 0x38, 0x8b, 0x8c, 0xfa, 0x90, 0xe1 } };
+static const GUID SDL_IID_ID3D11Debug = { 0x79cf2233, 0x7536, 0x4948, { 0x9d, 0x36, 0x1e, 0x46, 0x92, 0xdc, 0x57, 0x60 } };
+
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
/* Direct3D 11.x shaders
@@ -961,7 +980,7 @@ D3D11_CreateBlendMode(SDL_Renderer * renderer,
blendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
result = ID3D11Device_CreateBlendState(data->d3dDevice, &blendDesc, blendStateOutput);
if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateBlendState", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateBlendState"), result);
return result;
}
@@ -976,13 +995,11 @@ D3D11_CreateDeviceResources(SDL_Renderer * renderer)
PFN_CREATE_DXGI_FACTORY CreateDXGIFactoryFunc;
D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
PFN_D3D11_CREATE_DEVICE D3D11CreateDeviceFunc;
- IDXGIAdapter *d3dAdapter = NULL;
ID3D11Device *d3dDevice = NULL;
ID3D11DeviceContext *d3dContext = NULL;
IDXGIDevice1 *dxgiDevice = NULL;
HRESULT result = S_OK;
UINT creationFlags;
- const char *hint;
/* This array defines the set of DirectX hardware feature levels this app will support.
* Note the ordering should be preserved.
@@ -1041,16 +1058,16 @@ D3D11_CreateDeviceResources(SDL_Renderer * renderer)
}
#endif /* __WINRT__ */
- result = CreateDXGIFactoryFunc(&IID_IDXGIFactory2, &data->dxgiFactory);
+ result = CreateDXGIFactoryFunc(&SDL_IID_IDXGIFactory2, (void **)&data->dxgiFactory);
if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", CreateDXGIFactory", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("CreateDXGIFactory"), result);
goto done;
}
/* FIXME: Should we use the default adapter? */
result = IDXGIFactory2_EnumAdapters(data->dxgiFactory, 0, &data->dxgiAdapter);
if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", D3D11CreateDevice", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("D3D11CreateDevice"), result);
goto done;
}
@@ -1060,8 +1077,7 @@ D3D11_CreateDeviceResources(SDL_Renderer * renderer)
creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
/* Make sure Direct3D's debugging feature gets used, if the app requests it. */
- hint = SDL_GetHint(SDL_HINT_RENDER_DIRECT3D11_DEBUG);
- if (hint && SDL_atoi(hint) > 0) {
+ if (SDL_GetHintBoolean(SDL_HINT_RENDER_DIRECT3D11_DEBUG, SDL_FALSE)) {
creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
}
@@ -1079,25 +1095,25 @@ D3D11_CreateDeviceResources(SDL_Renderer * renderer)
&d3dContext /* Returns the device immediate context. */
);
if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", D3D11CreateDevice", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("D3D11CreateDevice"), result);
goto done;
}
- result = ID3D11Device_QueryInterface(d3dDevice, &IID_ID3D11Device1, &data->d3dDevice);
+ result = ID3D11Device_QueryInterface(d3dDevice, &SDL_IID_ID3D11Device1, (void **)&data->d3dDevice);
if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device to ID3D11Device1", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device to ID3D11Device1"), result);
goto done;
}
- result = ID3D11DeviceContext_QueryInterface(d3dContext, &IID_ID3D11DeviceContext1, &data->d3dContext);
+ result = ID3D11DeviceContext_QueryInterface(d3dContext, &SDL_IID_ID3D11DeviceContext1, (void **)&data->d3dContext);
if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11DeviceContext to ID3D11DeviceContext1", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11DeviceContext to ID3D11DeviceContext1"), result);
goto done;
}
- result = ID3D11Device_QueryInterface(d3dDevice, &IID_IDXGIDevice1, &dxgiDevice);
+ result = ID3D11Device_QueryInterface(d3dDevice, &SDL_IID_IDXGIDevice1, (void **)&dxgiDevice);
if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device to IDXGIDevice1", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device to IDXGIDevice1"), result);
goto done;
}
@@ -1106,7 +1122,7 @@ D3D11_CreateDeviceResources(SDL_Renderer * renderer)
*/
result = IDXGIDevice1_SetMaximumFrameLatency(dxgiDevice, 1);
if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIDevice1::SetMaximumFrameLatency", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGIDevice1::SetMaximumFrameLatency"), result);
goto done;
}
@@ -1135,7 +1151,7 @@ D3D11_CreateDeviceResources(SDL_Renderer * renderer)
break;
default:
- SDL_SetError(__FUNCTION__ ", Unexpected feature level: %d", data->featureLevel);
+ SDL_SetError("%s, Unexpected feature level: %d", __FUNCTION__, data->featureLevel);
result = E_FAIL;
goto done;
}
@@ -1148,7 +1164,7 @@ D3D11_CreateDeviceResources(SDL_Renderer * renderer)
&data->vertexShader
);
if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateVertexShader", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateVertexShader"), result);
goto done;
}
@@ -1161,7 +1177,7 @@ D3D11_CreateDeviceResources(SDL_Renderer * renderer)
&data->inputLayout
);
if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateInputLayout", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateInputLayout"), result);
goto done;
}
@@ -1173,7 +1189,7 @@ D3D11_CreateDeviceResources(SDL_Renderer * renderer)
&data->colorPixelShader
);
if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreatePixelShader ['color' shader]", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreatePixelShader ['color' shader]"), result);
goto done;
}
@@ -1184,7 +1200,7 @@ D3D11_CreateDeviceResources(SDL_Renderer * renderer)
&data->texturePixelShader
);
if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreatePixelShader ['textures' shader]", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreatePixelShader ['textures' shader]"), result);
goto done;
}
@@ -1195,7 +1211,7 @@ D3D11_CreateDeviceResources(SDL_Renderer * renderer)
&data->yuvPixelShader
);
if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreatePixelShader ['yuv' shader]", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreatePixelShader ['yuv' shader]"), result);
goto done;
}
@@ -1210,7 +1226,7 @@ D3D11_CreateDeviceResources(SDL_Renderer * renderer)
&data->vertexShaderConstants
);
if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateBuffer [vertex shader constants]", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateBuffer [vertex shader constants]"), result);
goto done;
}
@@ -1230,7 +1246,7 @@ D3D11_CreateDeviceResources(SDL_Renderer * renderer)
&data->nearestPixelSampler
);
if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateSamplerState [nearest-pixel filter]", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateSamplerState [nearest-pixel filter]"), result);
goto done;
}
@@ -1240,7 +1256,7 @@ D3D11_CreateDeviceResources(SDL_Renderer * renderer)
&data->linearSampler
);
if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateSamplerState [linear filter]", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateSamplerState [linear filter]"), result);
goto done;
}
@@ -1258,14 +1274,14 @@ D3D11_CreateDeviceResources(SDL_Renderer * renderer)
rasterDesc.SlopeScaledDepthBias = 0.0f;
result = ID3D11Device_CreateRasterizerState(data->d3dDevice, &rasterDesc, &data->mainRasterizer);
if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateRasterizerState [main rasterizer]", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateRasterizerState [main rasterizer]"), result);
goto done;
}
rasterDesc.ScissorEnable = TRUE;
result = ID3D11Device_CreateRasterizerState(data->d3dDevice, &rasterDesc, &data->clippedRasterizer);
if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateRasterizerState [clipped rasterizer]", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateRasterizerState [clipped rasterizer]"), result);
goto done;
}
@@ -1358,7 +1374,6 @@ D3D11_GetRotationForCurrentRenderTarget(SDL_Renderer * renderer)
static int
D3D11_GetViewportAlignedD3DRect(SDL_Renderer * renderer, const SDL_Rect * sdlRect, D3D11_RECT * outRect, BOOL includeViewportOffset)
{
- D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
const int rotation = D3D11_GetRotationForCurrentRenderTarget(renderer);
switch (rotation) {
case DXGI_MODE_ROTATION_IDENTITY:
@@ -1444,7 +1459,7 @@ D3D11_CreateSwapChain(SDL_Renderer * renderer, int w, int h)
&data->swapChain
);
if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIFactory2::CreateSwapChainForCoreWindow", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGIFactory2::CreateSwapChainForCoreWindow"), result);
goto done;
}
} else if (usingXAML) {
@@ -1454,18 +1469,18 @@ D3D11_CreateSwapChain(SDL_Renderer * renderer, int w, int h)
NULL,
&data->swapChain);
if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIFactory2::CreateSwapChainForComposition", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGIFactory2::CreateSwapChainForComposition"), result);
goto done;
}
#if WINAPI_FAMILY == WINAPI_FAMILY_APP
result = ISwapChainBackgroundPanelNative_SetSwapChain(WINRT_GlobalSwapChainBackgroundPanelNative, (IDXGISwapChain *) data->swapChain);
if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", ISwapChainBackgroundPanelNative::SetSwapChain", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ISwapChainBackgroundPanelNative::SetSwapChain"), result);
goto done;
}
#else
- SDL_SetError(__FUNCTION__ ", XAML support is not yet available for Windows Phone");
+ SDL_SetError(SDL_COMPOSE_ERROR("XAML support is not yet available for Windows Phone"));
result = E_FAIL;
goto done;
#endif
@@ -1484,7 +1499,7 @@ D3D11_CreateSwapChain(SDL_Renderer * renderer, int w, int h)
&data->swapChain
);
if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGIFactory2::CreateSwapChainForHwnd", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGIFactory2::CreateSwapChainForHwnd"), result);
goto done;
}
@@ -1545,7 +1560,7 @@ D3D11_CreateWindowSizeDependentResources(SDL_Renderer * renderer)
*/
goto done;
} else if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGISwapChain::ResizeBuffers", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain::ResizeBuffers"), result);
goto done;
}
#endif
@@ -1576,7 +1591,7 @@ D3D11_CreateWindowSizeDependentResources(SDL_Renderer * renderer)
if (data->swapEffect == DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL) {
result = IDXGISwapChain1_SetRotation(data->swapChain, data->rotation);
if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGISwapChain1::SetRotation", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain1::SetRotation"), result);
goto done;
}
}
@@ -1584,11 +1599,11 @@ D3D11_CreateWindowSizeDependentResources(SDL_Renderer * renderer)
result = IDXGISwapChain_GetBuffer(data->swapChain,
0,
- &IID_ID3D11Texture2D,
- &backBuffer
+ &SDL_IID_ID3D11Texture2D,
+ (void **)&backBuffer
);
if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGISwapChain::GetBuffer [back-buffer]", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain::GetBuffer [back-buffer]"), result);
goto done;
}
@@ -1599,7 +1614,7 @@ D3D11_CreateWindowSizeDependentResources(SDL_Renderer * renderer)
&data->mainRenderTargetView
);
if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device::CreateRenderTargetView", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device::CreateRenderTargetView"), result);
goto done;
}
@@ -1618,14 +1633,12 @@ done:
static HRESULT
D3D11_UpdateForWindowSizeChange(SDL_Renderer * renderer)
{
- D3D11_RenderData *data = (D3D11_RenderData *)renderer->driverdata;
return D3D11_CreateWindowSizeDependentResources(renderer);
}
HRESULT
D3D11_HandleDeviceLost(SDL_Renderer * renderer)
{
- D3D11_RenderData *data = (D3D11_RenderData *) renderer->driverdata;
HRESULT result = S_OK;
D3D11_ReleaseAll(renderer);
@@ -1661,7 +1674,7 @@ D3D11_Trim(SDL_Renderer * renderer)
HRESULT result = S_OK;
IDXGIDevice3 *dxgiDevice = NULL;
- result = ID3D11Device_QueryInterface(data->d3dDevice, &IID_IDXGIDevice3, &dxgiDevice);
+ result = ID3D11Device_QueryInterface(data->d3dDevice, &SDL_IID_IDXGIDevice3, &dxgiDevice);
if (FAILED(result)) {
//WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device to IDXGIDevice3", result);
return;
@@ -1702,7 +1715,7 @@ D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
D3D11_TEXTURE2D_DESC textureDesc;
D3D11_SHADER_RESOURCE_VIEW_DESC resourceViewDesc;
- if (textureFormat == SDL_PIXELFORMAT_UNKNOWN) {
+ if (textureFormat == DXGI_FORMAT_UNKNOWN) {
return SDL_SetError("%s, An unsupported SDL pixel format (0x%x) was specified",
__FUNCTION__, texture->format);
}
@@ -1747,7 +1760,7 @@ D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
);
if (FAILED(result)) {
D3D11_DestroyTexture(renderer, texture);
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateTexture2D", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result);
return -1;
}
@@ -1765,7 +1778,7 @@ D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
);
if (FAILED(result)) {
D3D11_DestroyTexture(renderer, texture);
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateTexture2D", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result);
return -1;
}
@@ -1776,7 +1789,7 @@ D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
);
if (FAILED(result)) {
D3D11_DestroyTexture(renderer, texture);
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateTexture2D", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D"), result);
return -1;
}
}
@@ -1792,7 +1805,7 @@ D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
);
if (FAILED(result)) {
D3D11_DestroyTexture(renderer, texture);
- WIN_SetErrorFromHRESULT(__FUNCTION__ "ID3D11Device1::CreateShaderResourceView", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateShaderResourceView"), result);
return -1;
}
@@ -1804,7 +1817,7 @@ D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
);
if (FAILED(result)) {
D3D11_DestroyTexture(renderer, texture);
- WIN_SetErrorFromHRESULT(__FUNCTION__ "ID3D11Device1::CreateShaderResourceView", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateShaderResourceView"), result);
return -1;
}
result = ID3D11Device_CreateShaderResourceView(rendererData->d3dDevice,
@@ -1814,7 +1827,7 @@ D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
);
if (FAILED(result)) {
D3D11_DestroyTexture(renderer, texture);
- WIN_SetErrorFromHRESULT(__FUNCTION__ "ID3D11Device1::CreateShaderResourceView", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateShaderResourceView"), result);
return -1;
}
}
@@ -1831,7 +1844,7 @@ D3D11_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
&textureData->mainTextureRenderTargetView);
if (FAILED(result)) {
D3D11_DestroyTexture(renderer, texture);
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateRenderTargetView", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateRenderTargetView"), result);
return -1;
}
}
@@ -1887,7 +1900,7 @@ D3D11_UpdateTextureInternal(D3D11_RenderData *rendererData, ID3D11Texture2D *tex
NULL,
&stagingTexture);
if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateTexture2D [create staging texture]", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D [create staging texture]"), result);
return -1;
}
@@ -1900,7 +1913,7 @@ D3D11_UpdateTextureInternal(D3D11_RenderData *rendererData, ID3D11Texture2D *tex
&textureMemory
);
if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11DeviceContext1::Map [map staging texture]", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11DeviceContext1::Map [map staging texture]"), result);
SAFE_RELEASE(stagingTexture);
return -1;
}
@@ -2062,7 +2075,7 @@ D3D11_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
NULL,
&textureData->stagingTexture);
if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateTexture2D [create staging texture]", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D [create staging texture]"), result);
return -1;
}
@@ -2075,7 +2088,7 @@ D3D11_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture,
&textureMemory
);
if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11DeviceContext1::Map [map staging texture]", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11DeviceContext1::Map [map staging texture]"), result);
SAFE_RELEASE(textureData->stagingTexture);
return -1;
}
@@ -2359,7 +2372,7 @@ D3D11_UpdateVertexBuffer(SDL_Renderer *renderer,
&mappedResource
);
if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11DeviceContext1::Map [vertex buffer]", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11DeviceContext1::Map [vertex buffer]"), result);
return -1;
}
SDL_memcpy(mappedResource.pData, vertexData, dataSizeInBytes);
@@ -2383,7 +2396,7 @@ D3D11_UpdateVertexBuffer(SDL_Renderer *renderer,
&rendererData->vertexBuffer
);
if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateBuffer [vertex buffer]", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateBuffer [vertex buffer]"), result);
return -1;
}
@@ -2842,18 +2855,18 @@ D3D11_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
HRESULT result;
int status = -1;
D3D11_TEXTURE2D_DESC stagingTextureDesc;
- D3D11_RECT srcRect;
+ D3D11_RECT srcRect = {0, 0, 0, 0};
D3D11_BOX srcBox;
D3D11_MAPPED_SUBRESOURCE textureMemory;
/* Retrieve a pointer to the back buffer: */
result = IDXGISwapChain_GetBuffer(data->swapChain,
0,
- &IID_ID3D11Texture2D,
- &backBuffer
+ &SDL_IID_ID3D11Texture2D,
+ (void **)&backBuffer
);
if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGISwapChain1::GetBuffer [get back buffer]", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain1::GetBuffer [get back buffer]"), result);
goto done;
}
@@ -2870,7 +2883,7 @@ D3D11_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
NULL,
&stagingTexture);
if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11Device1::CreateTexture2D [create staging texture]", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11Device1::CreateTexture2D [create staging texture]"), result);
goto done;
}
@@ -2902,7 +2915,7 @@ D3D11_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
0,
&textureMemory);
if (FAILED(result)) {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", ID3D11DeviceContext1::Map [map staging texture]", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("ID3D11DeviceContext1::Map [map staging texture]"), result);
goto done;
}
@@ -2921,7 +2934,7 @@ D3D11_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
* Get the error message, and attach some extra data to it.
*/
char errorMessage[1024];
- SDL_snprintf(errorMessage, sizeof(errorMessage), __FUNCTION__ ", Convert Pixels failed: %s", SDL_GetError());
+ SDL_snprintf(errorMessage, sizeof(errorMessage), "%s, Convert Pixels failed: %s", __FUNCTION__, SDL_GetError());
SDL_SetError("%s", errorMessage);
goto done;
}
@@ -2991,7 +3004,7 @@ D3D11_RenderPresent(SDL_Renderer * renderer)
/* We probably went through a fullscreen <-> windowed transition */
D3D11_CreateWindowSizeDependentResources(renderer);
} else {
- WIN_SetErrorFromHRESULT(__FUNCTION__ ", IDXGISwapChain::Present", result);
+ WIN_SetErrorFromHRESULT(SDL_COMPOSE_ERROR("IDXGISwapChain::Present"), result);
}
}
}
diff --git a/Engine/lib/sdl/src/render/opengl/SDL_render_gl.c b/Engine/lib/sdl/src/render/opengl/SDL_render_gl.c
index 6a4fa3ecf..1ca2cb5c4 100644
--- a/Engine/lib/sdl/src/render/opengl/SDL_render_gl.c
+++ b/Engine/lib/sdl/src/render/opengl/SDL_render_gl.c
@@ -390,7 +390,6 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
{
SDL_Renderer *renderer;
GL_RenderData *data;
- const char *hint;
GLint value;
Uint32 window_flags;
int profile_mask = 0, major = 0, minor = 0;
@@ -450,7 +449,7 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
renderer->GL_BindTexture = GL_BindTexture;
renderer->GL_UnbindTexture = GL_UnbindTexture;
renderer->info = GL_RenderDriver.info;
- renderer->info.flags = (SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);
+ renderer->info.flags = SDL_RENDERER_ACCELERATED;
renderer->driverdata = data;
renderer->window = window;
@@ -528,8 +527,7 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags)
}
/* Check for shader support */
- hint = SDL_GetHint(SDL_HINT_RENDER_OPENGL_SHADERS);
- if (!hint || *hint != '0') {
+ if (SDL_GetHintBoolean(SDL_HINT_RENDER_OPENGL_SHADERS, SDL_TRUE)) {
data->shaders = GL_CreateShaderContext();
}
SDL_LogInfo(SDL_LOG_CATEGORY_RENDER, "OpenGL shaders: %s",
@@ -594,7 +592,6 @@ static int
GL_GetOutputSize(SDL_Renderer * renderer, int *w, int *h)
{
SDL_GL_GetDrawableSize(renderer->window, w, h);
-
return 0;
}
@@ -664,6 +661,11 @@ GL_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
GL_ActivateRenderer(renderer);
+ if (texture->access == SDL_TEXTUREACCESS_TARGET &&
+ !renderdata->GL_EXT_framebuffer_object_supported) {
+ return SDL_SetError("Render targets not supported by OpenGL");
+ }
+
if (!convert_format(renderdata, texture->format, &internalFormat,
&format, &type)) {
return SDL_SetError("Texture format %s not supported by OpenGL",
@@ -980,6 +982,10 @@ GL_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture)
GL_ActivateRenderer(renderer);
+ if (!data->GL_EXT_framebuffer_object_supported) {
+ return SDL_SetError("Render targets not supported by OpenGL");
+ }
+
if (texture == NULL) {
data->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
return 0;
@@ -1013,7 +1019,7 @@ GL_UpdateViewport(SDL_Renderer * renderer)
} else {
int w, h;
- SDL_GetRendererOutputSize(renderer, &w, &h);
+ SDL_GL_GetDrawableSize(renderer->window, &w, &h);
data->glViewport(renderer->viewport.x, (h - renderer->viewport.y - renderer->viewport.h),
renderer->viewport.w, renderer->viewport.h);
}
@@ -1051,7 +1057,7 @@ GL_UpdateClipRect(SDL_Renderer * renderer)
} else {
int w, h;
- SDL_GetRendererOutputSize(renderer, &w, &h);
+ SDL_GL_GetDrawableSize(renderer->window, &w, &h);
data->glScissor(renderer->viewport.x + rect->x, h - renderer->viewport.y - rect->y - rect->h, rect->w, rect->h);
}
} else {
@@ -1089,21 +1095,17 @@ GL_SetBlendMode(GL_RenderData * data, int blendMode)
if (blendMode != data->current.blendMode) {
switch (blendMode) {
case SDL_BLENDMODE_NONE:
- data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
data->glDisable(GL_BLEND);
break;
case SDL_BLENDMODE_BLEND:
- data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
data->glEnable(GL_BLEND);
data->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
break;
case SDL_BLENDMODE_ADD:
- data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
data->glEnable(GL_BLEND);
data->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
break;
case SDL_BLENDMODE_MOD:
- data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
data->glEnable(GL_BLEND);
data->glBlendFuncSeparate(GL_ZERO, GL_SRC_COLOR, GL_ZERO, GL_ONE);
break;
@@ -1141,8 +1143,16 @@ GL_RenderClear(SDL_Renderer * renderer)
(GLfloat) renderer->b * inv255f,
(GLfloat) renderer->a * inv255f);
+ if (renderer->clipping_enabled) {
+ data->glDisable(GL_SCISSOR_TEST);
+ }
+
data->glClear(GL_COLOR_BUFFER_BIT);
+ if (renderer->clipping_enabled) {
+ data->glEnable(GL_SCISSOR_TEST);
+ }
+
return 0;
}
@@ -1409,7 +1419,7 @@ GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
Uint32 pixel_format, void * pixels, int pitch)
{
GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
- Uint32 temp_format = SDL_PIXELFORMAT_ARGB8888;
+ Uint32 temp_format = renderer->target ? renderer->target->format : SDL_PIXELFORMAT_ARGB8888;
void *temp_pixels;
int temp_pitch;
GLint internalFormat;
@@ -1426,7 +1436,11 @@ GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
return SDL_OutOfMemory();
}
- convert_format(data, temp_format, &internalFormat, &format, &type);
+ if (!convert_format(data, temp_format, &internalFormat, &format, &type)) {
+ SDL_free(temp_pixels);
+ return SDL_SetError("Texture format %s not supported by OpenGL",
+ SDL_GetPixelFormatName(temp_format));
+ }
SDL_GetRendererOutputSize(renderer, &w, &h);
@@ -1434,28 +1448,30 @@ GL_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
data->glPixelStorei(GL_PACK_ROW_LENGTH,
(temp_pitch / SDL_BYTESPERPIXEL(temp_format)));
- data->glReadPixels(rect->x, (h-rect->y)-rect->h, rect->w, rect->h,
- format, type, temp_pixels);
+ data->glReadPixels(rect->x, renderer->target ? rect->y : (h-rect->y)-rect->h,
+ rect->w, rect->h, format, type, temp_pixels);
if (GL_CheckError("glReadPixels()", renderer) < 0) {
SDL_free(temp_pixels);
return -1;
}
- /* Flip the rows to be top-down */
- length = rect->w * SDL_BYTESPERPIXEL(temp_format);
- src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch;
- dst = (Uint8*)temp_pixels;
- tmp = SDL_stack_alloc(Uint8, length);
- rows = rect->h / 2;
- while (rows--) {
- SDL_memcpy(tmp, dst, length);
- SDL_memcpy(dst, src, length);
- SDL_memcpy(src, tmp, length);
- dst += temp_pitch;
- src -= temp_pitch;
+ /* Flip the rows to be top-down if necessary */
+ if (!renderer->target) {
+ length = rect->w * SDL_BYTESPERPIXEL(temp_format);
+ src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch;
+ dst = (Uint8*)temp_pixels;
+ tmp = SDL_stack_alloc(Uint8, length);
+ rows = rect->h / 2;
+ while (rows--) {
+ SDL_memcpy(tmp, dst, length);
+ SDL_memcpy(dst, src, length);
+ SDL_memcpy(src, tmp, length);
+ dst += temp_pitch;
+ src -= temp_pitch;
+ }
+ SDL_stack_free(tmp);
}
- SDL_stack_free(tmp);
status = SDL_ConvertPixels(rect->w, rect->h,
temp_format, temp_pixels, temp_pitch,
diff --git a/Engine/lib/sdl/src/render/opengles/SDL_render_gles.c b/Engine/lib/sdl/src/render/opengles/SDL_render_gles.c
index 0d59da360..71f5b3a7a 100644
--- a/Engine/lib/sdl/src/render/opengles/SDL_render_gles.c
+++ b/Engine/lib/sdl/src/render/opengles/SDL_render_gles.c
@@ -129,8 +129,6 @@ typedef struct
GLES_FBOList *framebuffers;
GLuint window_framebuffer;
- SDL_bool useDrawTexture;
- SDL_bool GL_OES_draw_texture_supported;
SDL_bool GL_OES_blend_func_separate_supported;
} GLES_RenderData;
@@ -369,19 +367,6 @@ GLES_CreateRenderer(SDL_Window * window, Uint32 flags)
renderer->info.flags |= SDL_RENDERER_PRESENTVSYNC;
}
-#if SDL_VIDEO_DRIVER_PANDORA
- data->GL_OES_draw_texture_supported = SDL_FALSE;
- data->useDrawTexture = SDL_FALSE;
-#else
- if (SDL_GL_ExtensionSupported("GL_OES_draw_texture")) {
- data->GL_OES_draw_texture_supported = SDL_TRUE;
- data->useDrawTexture = SDL_TRUE;
- } else {
- data->GL_OES_draw_texture_supported = SDL_FALSE;
- data->useDrawTexture = SDL_FALSE;
- }
-#endif
-
value = 0;
data->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &value);
renderer->info.max_texture_width = value;
@@ -605,6 +590,7 @@ GLES_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
data->format,
data->formattype,
src);
+ renderdata->glDisable(data->type);
SDL_free(blob);
if (renderdata->glGetError() != GL_NO_ERROR) {
@@ -686,18 +672,27 @@ GLES_UpdateViewport(SDL_Renderer * renderer)
} else {
int w, h;
- SDL_GetRendererOutputSize(renderer, &w, &h);
+ SDL_GL_GetDrawableSize(renderer->window, &w, &h);
data->glViewport(renderer->viewport.x, (h - renderer->viewport.y - renderer->viewport.h),
renderer->viewport.w, renderer->viewport.h);
}
+ data->glMatrixMode(GL_PROJECTION);
+ data->glLoadIdentity();
if (renderer->viewport.w && renderer->viewport.h) {
- data->glMatrixMode(GL_PROJECTION);
- data->glLoadIdentity();
- data->glOrthof((GLfloat) 0,
- (GLfloat) renderer->viewport.w,
- (GLfloat) renderer->viewport.h,
- (GLfloat) 0, 0.0, 1.0);
+ if (renderer->target) {
+ data->glOrthof((GLfloat) 0,
+ (GLfloat) renderer->viewport.w,
+ (GLfloat) 0,
+ (GLfloat) renderer->viewport.h,
+ 0.0, 1.0);
+ } else {
+ data->glOrthof((GLfloat) 0,
+ (GLfloat) renderer->viewport.w,
+ (GLfloat) renderer->viewport.h,
+ (GLfloat) 0,
+ 0.0, 1.0);
+ }
}
return 0;
}
@@ -720,7 +715,7 @@ GLES_UpdateClipRect(SDL_Renderer * renderer)
} else {
int w, h;
- SDL_GetRendererOutputSize(renderer, &w, &h);
+ SDL_GL_GetDrawableSize(renderer->window, &w, &h);
data->glScissor(renderer->viewport.x + rect->x, h - renderer->viewport.y - rect->y - rect->h, rect->w, rect->h);
}
} else {
@@ -749,11 +744,9 @@ GLES_SetBlendMode(GLES_RenderData * data, int blendMode)
if (blendMode != data->current.blendMode) {
switch (blendMode) {
case SDL_BLENDMODE_NONE:
- data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
data->glDisable(GL_BLEND);
break;
case SDL_BLENDMODE_BLEND:
- data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
data->glEnable(GL_BLEND);
if (data->GL_OES_blend_func_separate_supported) {
data->glBlendFuncSeparateOES(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
@@ -762,7 +755,6 @@ GLES_SetBlendMode(GLES_RenderData * data, int blendMode)
}
break;
case SDL_BLENDMODE_ADD:
- data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
data->glEnable(GL_BLEND);
if (data->GL_OES_blend_func_separate_supported) {
data->glBlendFuncSeparateOES(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
@@ -771,7 +763,6 @@ GLES_SetBlendMode(GLES_RenderData * data, int blendMode)
}
break;
case SDL_BLENDMODE_MOD:
- data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
data->glEnable(GL_BLEND);
if (data->GL_OES_blend_func_separate_supported) {
data->glBlendFuncSeparateOES(GL_ZERO, GL_SRC_COLOR, GL_ZERO, GL_ONE);
@@ -825,9 +816,17 @@ GLES_RenderClear(SDL_Renderer * renderer)
(GLfloat) renderer->g * inv255f,
(GLfloat) renderer->b * inv255f,
(GLfloat) renderer->a * inv255f);
+
+ if (renderer->clipping_enabled) {
+ data->glDisable(GL_SCISSOR_TEST);
+ }
data->glClear(GL_COLOR_BUFFER_BIT);
+ if (renderer->clipping_enabled) {
+ data->glEnable(GL_SCISSOR_TEST);
+ }
+
return 0;
}
@@ -952,71 +951,42 @@ GLES_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
GLES_SetTexCoords(data, SDL_TRUE);
- if (data->GL_OES_draw_texture_supported && data->useDrawTexture) {
- /* this code is a little funny because the viewport is upside down vs SDL's coordinate system */
- GLint cropRect[4];
- int w, h;
- SDL_Window *window = renderer->window;
+ minx = dstrect->x;
+ miny = dstrect->y;
+ maxx = dstrect->x + dstrect->w;
+ maxy = dstrect->y + dstrect->h;
- SDL_GetWindowSize(window, &w, &h);
- if (renderer->target) {
- cropRect[0] = srcrect->x;
- cropRect[1] = srcrect->y;
- cropRect[2] = srcrect->w;
- cropRect[3] = srcrect->h;
- data->glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES,
- cropRect);
- data->glDrawTexfOES(renderer->viewport.x + dstrect->x, renderer->viewport.y + dstrect->y, 0,
- dstrect->w, dstrect->h);
- } else {
- cropRect[0] = srcrect->x;
- cropRect[1] = srcrect->y + srcrect->h;
- cropRect[2] = srcrect->w;
- cropRect[3] = -srcrect->h;
- data->glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES,
- cropRect);
- data->glDrawTexfOES(renderer->viewport.x + dstrect->x,
- h - (renderer->viewport.y + dstrect->y) - dstrect->h, 0,
- dstrect->w, dstrect->h);
- }
- } else {
+ minu = (GLfloat) srcrect->x / texture->w;
+ minu *= texturedata->texw;
+ maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
+ maxu *= texturedata->texw;
+ minv = (GLfloat) srcrect->y / texture->h;
+ minv *= texturedata->texh;
+ maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
+ maxv *= texturedata->texh;
- minx = dstrect->x;
- miny = dstrect->y;
- maxx = dstrect->x + dstrect->w;
- maxy = dstrect->y + dstrect->h;
+ vertices[0] = minx;
+ vertices[1] = miny;
+ vertices[2] = maxx;
+ vertices[3] = miny;
+ vertices[4] = minx;
+ vertices[5] = maxy;
+ vertices[6] = maxx;
+ vertices[7] = maxy;
- minu = (GLfloat) srcrect->x / texture->w;
- minu *= texturedata->texw;
- maxu = (GLfloat) (srcrect->x + srcrect->w) / texture->w;
- maxu *= texturedata->texw;
- minv = (GLfloat) srcrect->y / texture->h;
- minv *= texturedata->texh;
- maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
- maxv *= texturedata->texh;
+ texCoords[0] = minu;
+ texCoords[1] = minv;
+ texCoords[2] = maxu;
+ texCoords[3] = minv;
+ texCoords[4] = minu;
+ texCoords[5] = maxv;
+ texCoords[6] = maxu;
+ texCoords[7] = maxv;
- vertices[0] = minx;
- vertices[1] = miny;
- vertices[2] = maxx;
- vertices[3] = miny;
- vertices[4] = minx;
- vertices[5] = maxy;
- vertices[6] = maxx;
- vertices[7] = maxy;
+ data->glVertexPointer(2, GL_FLOAT, 0, vertices);
+ data->glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
+ data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
- texCoords[0] = minu;
- texCoords[1] = minv;
- texCoords[2] = maxu;
- texCoords[3] = minv;
- texCoords[4] = minu;
- texCoords[5] = maxv;
- texCoords[6] = maxu;
- texCoords[7] = maxv;
-
- data->glVertexPointer(2, GL_FLOAT, 0, vertices);
- data->glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
- data->glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
- }
data->glDisable(GL_TEXTURE_2D);
return 0;
@@ -1117,7 +1087,7 @@ GLES_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
Uint32 pixel_format, void * pixels, int pitch)
{
GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
- Uint32 temp_format = SDL_PIXELFORMAT_ABGR8888;
+ Uint32 temp_format = renderer->target ? renderer->target->format : SDL_PIXELFORMAT_ABGR8888;
void *temp_pixels;
int temp_pitch;
Uint8 *src, *dst, *tmp;
@@ -1136,23 +1106,25 @@ GLES_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
data->glPixelStorei(GL_PACK_ALIGNMENT, 1);
- data->glReadPixels(rect->x, (h-rect->y)-rect->h, rect->w, rect->h,
- GL_RGBA, GL_UNSIGNED_BYTE, temp_pixels);
+ data->glReadPixels(rect->x, renderer->target ? rect->y : (h-rect->y)-rect->h,
+ rect->w, rect->h, GL_RGBA, GL_UNSIGNED_BYTE, temp_pixels);
- /* Flip the rows to be top-down */
- length = rect->w * SDL_BYTESPERPIXEL(temp_format);
- src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch;
- dst = (Uint8*)temp_pixels;
- tmp = SDL_stack_alloc(Uint8, length);
- rows = rect->h / 2;
- while (rows--) {
- SDL_memcpy(tmp, dst, length);
- SDL_memcpy(dst, src, length);
- SDL_memcpy(src, tmp, length);
- dst += temp_pitch;
- src -= temp_pitch;
+ /* Flip the rows to be top-down if necessary */
+ if (!renderer->target) {
+ length = rect->w * SDL_BYTESPERPIXEL(temp_format);
+ src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch;
+ dst = (Uint8*)temp_pixels;
+ tmp = SDL_stack_alloc(Uint8, length);
+ rows = rect->h / 2;
+ while (rows--) {
+ SDL_memcpy(tmp, dst, length);
+ SDL_memcpy(dst, src, length);
+ SDL_memcpy(src, tmp, length);
+ dst += temp_pitch;
+ src -= temp_pitch;
+ }
+ SDL_stack_free(tmp);
}
- SDL_stack_free(tmp);
status = SDL_ConvertPixels(rect->w, rect->h,
temp_format, temp_pixels, temp_pitch,
diff --git a/Engine/lib/sdl/src/render/opengles2/SDL_render_gles2.c b/Engine/lib/sdl/src/render/opengles2/SDL_render_gles2.c
index e41ab6231..c846a7b39 100644
--- a/Engine/lib/sdl/src/render/opengles2/SDL_render_gles2.c
+++ b/Engine/lib/sdl/src/render/opengles2/SDL_render_gles2.c
@@ -388,7 +388,7 @@ GLES2_UpdateViewport(SDL_Renderer * renderer)
} else {
int w, h;
- SDL_GetRendererOutputSize(renderer, &w, &h);
+ SDL_GL_GetDrawableSize(renderer->window, &w, &h);
data->glViewport(renderer->viewport.x, (h - renderer->viewport.y - renderer->viewport.h),
renderer->viewport.w, renderer->viewport.h);
}
@@ -417,7 +417,7 @@ GLES2_UpdateClipRect(SDL_Renderer * renderer)
} else {
int w, h;
- SDL_GetRendererOutputSize(renderer, &w, &h);
+ SDL_GL_GetDrawableSize(renderer->window, &w, &h);
data->glScissor(renderer->viewport.x + rect->x, h - renderer->viewport.y - rect->y - rect->h, rect->w, rect->h);
}
} else {
@@ -1327,8 +1327,16 @@ GLES2_RenderClear(SDL_Renderer * renderer)
data->clear_a = renderer->a;
}
+ if (renderer->clipping_enabled) {
+ data->glDisable(GL_SCISSOR_TEST);
+ }
+
data->glClear(GL_COLOR_BUFFER_BIT);
+ if (renderer->clipping_enabled) {
+ data->glEnable(GL_SCISSOR_TEST);
+ }
+
return 0;
}
@@ -1817,7 +1825,7 @@ GLES2_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
Uint32 pixel_format, void * pixels, int pitch)
{
GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
- Uint32 temp_format = SDL_PIXELFORMAT_ABGR8888;
+ Uint32 temp_format = renderer->target ? renderer->target->format : SDL_PIXELFORMAT_ABGR8888;
void *temp_pixels;
int temp_pitch;
Uint8 *src, *dst, *tmp;
@@ -1834,26 +1842,28 @@ GLES2_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
SDL_GetRendererOutputSize(renderer, &w, &h);
- data->glReadPixels(rect->x, (h-rect->y)-rect->h, rect->w, rect->h,
- GL_RGBA, GL_UNSIGNED_BYTE, temp_pixels);
+ data->glReadPixels(rect->x, renderer->target ? rect->y : (h-rect->y)-rect->h,
+ rect->w, rect->h, GL_RGBA, GL_UNSIGNED_BYTE, temp_pixels);
if (GL_CheckError("glReadPixels()", renderer) < 0) {
return -1;
}
- /* Flip the rows to be top-down */
- length = rect->w * SDL_BYTESPERPIXEL(temp_format);
- src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch;
- dst = (Uint8*)temp_pixels;
- tmp = SDL_stack_alloc(Uint8, length);
- rows = rect->h / 2;
- while (rows--) {
- SDL_memcpy(tmp, dst, length);
- SDL_memcpy(dst, src, length);
- SDL_memcpy(src, tmp, length);
- dst += temp_pitch;
- src -= temp_pitch;
+ /* Flip the rows to be top-down if necessary */
+ if (!renderer->target) {
+ length = rect->w * SDL_BYTESPERPIXEL(temp_format);
+ src = (Uint8*)temp_pixels + (rect->h-1)*temp_pitch;
+ dst = (Uint8*)temp_pixels;
+ tmp = SDL_stack_alloc(Uint8, length);
+ rows = rect->h / 2;
+ while (rows--) {
+ SDL_memcpy(tmp, dst, length);
+ SDL_memcpy(dst, src, length);
+ SDL_memcpy(src, tmp, length);
+ dst += temp_pitch;
+ src -= temp_pitch;
+ }
+ SDL_stack_free(tmp);
}
- SDL_stack_free(tmp);
status = SDL_ConvertPixels(rect->w, rect->h,
temp_format, temp_pixels, temp_pitch,
@@ -1959,9 +1969,15 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
int profile_mask = 0, major = 0, minor = 0;
SDL_bool changed_window = SDL_FALSE;
- SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile_mask);
- SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major);
- SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor);
+ if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile_mask) < 0) {
+ goto error;
+ }
+ if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major) < 0) {
+ goto error;
+ }
+ if (SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor) < 0) {
+ goto error;
+ }
window_flags = SDL_GetWindowFlags(window);
if (!(window_flags & SDL_WINDOW_OPENGL) ||
diff --git a/Engine/lib/sdl/src/render/psp/SDL_render_psp.c b/Engine/lib/sdl/src/render/psp/SDL_render_psp.c
index 8e8c87353..f2851319e 100644
--- a/Engine/lib/sdl/src/render/psp/SDL_render_psp.c
+++ b/Engine/lib/sdl/src/render/psp/SDL_render_psp.c
@@ -50,6 +50,8 @@ static SDL_Renderer *PSP_CreateRenderer(SDL_Window * window, Uint32 flags);
static void PSP_WindowEvent(SDL_Renderer * renderer,
const SDL_WindowEvent *event);
static int PSP_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture);
+static int PSP_SetTextureColorMod(SDL_Renderer * renderer,
+ SDL_Texture * texture);
static int PSP_UpdateTexture(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * rect, const void *pixels,
int pitch);
@@ -359,6 +361,7 @@ PSP_CreateRenderer(SDL_Window * window, Uint32 flags)
renderer->WindowEvent = PSP_WindowEvent;
renderer->CreateTexture = PSP_CreateTexture;
+ renderer->SetTextureColorMod = PSP_SetTextureColorMod;
renderer->UpdateTexture = PSP_UpdateTexture;
renderer->LockTexture = PSP_LockTexture;
renderer->UnlockTexture = PSP_UnlockTexture;
@@ -501,6 +504,11 @@ PSP_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
return 0;
}
+static int
+PSP_SetTextureColorMod(SDL_Renderer * renderer, SDL_Texture * texture)
+{
+ return SDL_Unsupported();
+}
void
TextureActivate(SDL_Texture * texture)
@@ -853,7 +861,7 @@ PSP_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
Uint32 pixel_format, void * pixels, int pitch)
{
- return 0;
+ return SDL_Unsupported();
}
diff --git a/Engine/lib/sdl/src/render/software/SDL_render_sw.c b/Engine/lib/sdl/src/render/software/SDL_render_sw.c
index dadd2442f..e7a6cd88d 100644
--- a/Engine/lib/sdl/src/render/software/SDL_render_sw.c
+++ b/Engine/lib/sdl/src/render/software/SDL_render_sw.c
@@ -677,8 +677,8 @@ SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture,
}
if (!retval) {
- SDLgfx_rotozoomSurfaceSizeTrig(tmp_rect.w, tmp_rect.h, -angle, &dstwidth, &dstheight, &cangle, &sangle);
- surface_rotated = SDLgfx_rotateSurface(surface_scaled, -angle, dstwidth/2, dstheight/2, GetScaleQuality(), flip & SDL_FLIP_HORIZONTAL, flip & SDL_FLIP_VERTICAL, dstwidth, dstheight, cangle, sangle);
+ SDLgfx_rotozoomSurfaceSizeTrig(tmp_rect.w, tmp_rect.h, angle, &dstwidth, &dstheight, &cangle, &sangle);
+ surface_rotated = SDLgfx_rotateSurface(surface_scaled, angle, dstwidth/2, dstheight/2, GetScaleQuality(), flip & SDL_FLIP_HORIZONTAL, flip & SDL_FLIP_VERTICAL, dstwidth, dstheight, cangle, sangle);
if(surface_rotated) {
/* Find out where the new origin is by rotating the four final_rect points around the center and then taking the extremes */
abscenterx = final_rect.x + (int)center->x;
diff --git a/Engine/lib/sdl/src/render/software/SDL_rotate.c b/Engine/lib/sdl/src/render/software/SDL_rotate.c
index 8d92758f8..0141d174d 100644
--- a/Engine/lib/sdl/src/render/software/SDL_rotate.c
+++ b/Engine/lib/sdl/src/render/software/SDL_rotate.c
@@ -110,31 +110,105 @@ SDLgfx_rotozoomSurfaceSizeTrig(int width, int height, double angle,
int *dstwidth, int *dstheight,
double *cangle, double *sangle)
{
- double x, y, cx, cy, sx, sy;
- double radangle;
- int dstwidthhalf, dstheighthalf;
-
- /*
- * Determine destination width and height by rotating a centered source box
- */
- radangle = angle * (M_PI / 180.0);
- *sangle = SDL_sin(radangle);
- *cangle = SDL_cos(radangle);
- x = (double)(width / 2);
- y = (double)(height / 2);
- cx = *cangle * x;
- cy = *cangle * y;
- sx = *sangle * x;
- sy = *sangle * y;
-
- dstwidthhalf = MAX((int)
- SDL_ceil(MAX(MAX(MAX(SDL_fabs(cx + sy), SDL_fabs(cx - sy)), SDL_fabs(-cx + sy)), SDL_fabs(-cx - sy))), 1);
- dstheighthalf = MAX((int)
- SDL_ceil(MAX(MAX(MAX(SDL_fabs(sx + cy), SDL_fabs(sx - cy)), SDL_fabs(-sx + cy)), SDL_fabs(-sx - cy))), 1);
- *dstwidth = 2 * dstwidthhalf;
- *dstheight = 2 * dstheighthalf;
+ /* The trig code below gets the wrong size (due to FP inaccuracy?) when angle is a multiple of 90 degrees */
+ int angle90 = (int)(angle/90);
+ if(angle90 == angle/90) { /* if the angle is a multiple of 90 degrees */
+ angle90 %= 4;
+ if(angle90 < 0) angle90 += 4; /* 0:0 deg, 1:90 deg, 2:180 deg, 3:270 deg */
+ if(angle90 & 1) {
+ *dstwidth = height;
+ *dstheight = width;
+ *cangle = 0;
+ *sangle = angle90 == 1 ? -1 : 1; /* reversed because our rotations are clockwise */
+ } else {
+ *dstwidth = width;
+ *dstheight = height;
+ *cangle = angle90 == 0 ? 1 : -1;
+ *sangle = 0;
+ }
+ } else {
+ double x, y, cx, cy, sx, sy;
+ double radangle;
+ int dstwidthhalf, dstheighthalf;
+ /*
+ * Determine destination width and height by rotating a centered source box
+ */
+ radangle = angle * (M_PI / -180.0); /* reverse the angle because our rotations are clockwise */
+ *sangle = SDL_sin(radangle);
+ *cangle = SDL_cos(radangle);
+ x = (double)(width / 2);
+ y = (double)(height / 2);
+ cx = *cangle * x;
+ cy = *cangle * y;
+ sx = *sangle * x;
+ sy = *sangle * y;
+
+ dstwidthhalf = MAX((int)
+ SDL_ceil(MAX(MAX(MAX(SDL_fabs(cx + sy), SDL_fabs(cx - sy)), SDL_fabs(-cx + sy)), SDL_fabs(-cx - sy))), 1);
+ dstheighthalf = MAX((int)
+ SDL_ceil(MAX(MAX(MAX(SDL_fabs(sx + cy), SDL_fabs(sx - cy)), SDL_fabs(-sx + cy)), SDL_fabs(-sx - cy))), 1);
+ *dstwidth = 2 * dstwidthhalf;
+ *dstheight = 2 * dstheighthalf;
+ }
}
+/* Computes source pointer X/Y increments for a rotation that's a multiple of 90 degrees. */
+static void
+computeSourceIncrements90(SDL_Surface * src, int bpp, int angle, int flipx, int flipy,
+ int *sincx, int *sincy, int *signx, int *signy)
+{
+ int pitch = flipy ? -src->pitch : src->pitch;
+ if (flipx) {
+ bpp = -bpp;
+ }
+ switch (angle) { /* 0:0 deg, 1:90 deg, 2:180 deg, 3:270 deg */
+ case 0: *sincx = bpp; *sincy = pitch - src->w * *sincx; *signx = *signy = 1; break;
+ case 1: *sincx = -pitch; *sincy = bpp - *sincx * src->h; *signx = 1; *signy = -1; break;
+ case 2: *sincx = -bpp; *sincy = -src->w * *sincx - pitch; *signx = *signy = -1; break;
+ case 3: default: *sincx = pitch; *sincy = -*sincx * src->h - bpp; *signx = -1; *signy = 1; break;
+ }
+ if (flipx) {
+ *signx = -*signx;
+ }
+ if (flipy) {
+ *signy = -*signy;
+ }
+}
+
+/* Performs a relatively fast rotation/flip when the angle is a multiple of 90 degrees. */
+#define TRANSFORM_SURFACE_90(pixelType) \
+ int dy, dincy = dst->pitch - dst->w*sizeof(pixelType), sincx, sincy, signx, signy; \
+ Uint8 *sp = (Uint8*)src->pixels, *dp = (Uint8*)dst->pixels, *de; \
+ \
+ computeSourceIncrements90(src, sizeof(pixelType), angle, flipx, flipy, &sincx, &sincy, &signx, &signy); \
+ if (signx < 0) sp += (src->w-1)*sizeof(pixelType); \
+ if (signy < 0) sp += (src->h-1)*src->pitch; \
+ \
+ for (dy = 0; dy < dst->h; sp += sincy, dp += dincy, dy++) { \
+ if (sincx == sizeof(pixelType)) { /* if advancing src and dest equally, use memcpy */ \
+ SDL_memcpy(dp, sp, dst->w*sizeof(pixelType)); \
+ sp += dst->w*sizeof(pixelType); \
+ dp += dst->w*sizeof(pixelType); \
+ } else { \
+ for (de = dp + dst->w*sizeof(pixelType); dp != de; sp += sincx, dp += sizeof(pixelType)) { \
+ *(pixelType*)dp = *(pixelType*)sp; \
+ } \
+ } \
+ }
+
+static void
+transformSurfaceRGBA90(SDL_Surface * src, SDL_Surface * dst, int angle, int flipx, int flipy)
+{
+ TRANSFORM_SURFACE_90(tColorRGBA);
+}
+
+static void
+transformSurfaceY90(SDL_Surface * src, SDL_Surface * dst, int angle, int flipx, int flipy)
+{
+ TRANSFORM_SURFACE_90(tColorY);
+}
+
+#undef TRANSFORM_SURFACE_90
/* !
\brief Internal 32 bit rotozoomer with optional anti-aliasing.
@@ -341,9 +415,9 @@ SDLgfx_rotateSurface(SDL_Surface * src, double angle, int centerx, int centery,
{
SDL_Surface *rz_src;
SDL_Surface *rz_dst;
- int is32bit;
+ int is32bit, angle90;
int i;
- Uint8 r,g,b;
+ Uint8 r = 0, g = 0, b = 0;
Uint32 colorkey = 0;
int colorKeyAvailable = 0;
double sangleinv, cangleinv;
@@ -370,18 +444,13 @@ SDLgfx_rotateSurface(SDL_Surface * src, double angle, int centerx, int centery,
*/
rz_src = src;
} else {
- Uint32 format = SDL_MasksToPixelFormatEnum(32,
-#if SDL_BYTEORDER == SDL_LIL_ENDIAN
- 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
-#else
- 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
-#endif
- );
- rz_src = SDL_ConvertSurfaceFormat(src, format, src->flags);
+ rz_src = SDL_ConvertSurfaceFormat(src, SDL_PIXELFORMAT_ARGB32, src->flags);
+ if (rz_src == NULL) {
+ return NULL;
+ }
is32bit = 1;
}
-
/* Determine target size */
/* _rotozoomSurfaceSizeTrig(rz_src->w, rz_src->h, angle, &dstwidth, &dstheight, &cangle, &sangle); */
@@ -394,7 +463,6 @@ SDLgfx_rotateSurface(SDL_Surface * src, double angle, int centerx, int centery,
/*
* Alloc space to completely contain the rotated surface
*/
- rz_dst = NULL;
if (is32bit) {
/*
* Target surface is 32bit with source RGBA/ABGR ordering
@@ -430,6 +498,18 @@ SDLgfx_rotateSurface(SDL_Surface * src, double angle, int centerx, int centery,
SDL_LockSurface(rz_src);
}
+ /* check if the rotation is a multiple of 90 degrees so we can take a fast path and also somewhat reduce
+ * the off-by-one problem in _transformSurfaceRGBA that expresses itself when the rotation is near
+ * multiples of 90 degrees.
+ */
+ angle90 = (int)(angle/90);
+ if (angle90 == angle/90) {
+ angle90 %= 4;
+ if (angle90 < 0) angle90 += 4; /* 0:0 deg, 1:90 deg, 2:180 deg, 3:270 deg */
+ } else {
+ angle90 = -1;
+ }
+
/*
* Check which kind of surface we have
*/
@@ -437,10 +517,11 @@ SDLgfx_rotateSurface(SDL_Surface * src, double angle, int centerx, int centery,
/*
* Call the 32bit transformation routine to do the rotation (using alpha)
*/
- _transformSurfaceRGBA(rz_src, rz_dst, centerx, centery,
- (int) (sangleinv), (int) (cangleinv),
- flipx, flipy,
- smooth);
+ if (angle90 >= 0) {
+ transformSurfaceRGBA90(rz_src, rz_dst, angle90, flipx, flipy);
+ } else {
+ _transformSurfaceRGBA(rz_src, rz_dst, centerx, centery, (int) (sangleinv), (int) (cangleinv), flipx, flipy, smooth);
+ }
/*
* Turn on source-alpha support
*/
@@ -457,9 +538,11 @@ SDLgfx_rotateSurface(SDL_Surface * src, double angle, int centerx, int centery,
/*
* Call the 8bit transformation routine to do the rotation
*/
- transformSurfaceY(rz_src, rz_dst, centerx, centery,
- (int) (sangleinv), (int) (cangleinv),
- flipx, flipy);
+ if(angle90 >= 0) {
+ transformSurfaceY90(rz_src, rz_dst, angle90, flipx, flipy);
+ } else {
+ transformSurfaceY(rz_src, rz_dst, centerx, centery, (int)(sangleinv), (int)(cangleinv), flipx, flipy);
+ }
SDL_SetColorKey(rz_dst, /* SDL_SRCCOLORKEY */ SDL_TRUE | SDL_RLEACCEL, _colorkey(rz_src));
}
diff --git a/Engine/lib/sdl/src/stdlib/SDL_iconv.c b/Engine/lib/sdl/src/stdlib/SDL_iconv.c
index 8f0403734..34bcd8431 100644
--- a/Engine/lib/sdl/src/stdlib/SDL_iconv.c
+++ b/Engine/lib/sdl/src/stdlib/SDL_iconv.c
@@ -30,7 +30,8 @@
#include "SDL_stdinc.h"
#include "SDL_endian.h"
-#ifdef HAVE_ICONV
+#if defined(HAVE_ICONV) && defined(HAVE_ICONV_H)
+#include
/* Depending on which standard the iconv() was implemented with,
iconv() may or may not use const char ** for the inbuf param.
diff --git a/Engine/lib/sdl/src/stdlib/SDL_qsort.c b/Engine/lib/sdl/src/stdlib/SDL_qsort.c
index 0d1978424..2ef33b15e 100644
--- a/Engine/lib/sdl/src/stdlib/SDL_qsort.c
+++ b/Engine/lib/sdl/src/stdlib/SDL_qsort.c
@@ -1,46 +1,23 @@
-/* qsort.c
- * (c) 1998 Gareth McCaughan
- *
- * This is a drop-in replacement for the C library's |qsort()| routine.
- *
- * Features:
- * - Median-of-three pivoting (and more)
- * - Truncation and final polishing by a single insertion sort
- * - Early truncation when no swaps needed in pivoting step
- * - Explicit recursion, guaranteed not to overflow
- * - A few little wrinkles stolen from the GNU |qsort()|.
- * - separate code for non-aligned / aligned / word-size objects
- *
- * This code may be reproduced freely provided
- * - this file is retained unaltered apart from minor
- * changes for portability and efficiency
- * - no changes are made to this comment
- * - any changes that *are* made are clearly flagged
- * - the _ID string below is altered by inserting, after
- * the date, the string " altered" followed at your option
- * by other material. (Exceptions: you may change the name
- * of the exported routine without changing the ID string.
- * You may change the values of the macros TRUNC_* and
- * PIVOT_THRESHOLD without changing the ID string, provided
- * they remain constants with TRUNC_nonaligned, TRUNC_aligned
- * and TRUNC_words/WORD_BYTES between 8 and 24, and
- * PIVOT_THRESHOLD between 32 and 200.)
- *
- * You may use it in anything you like; you may make money
- * out of it; you may distribute it in object form or as
- * part of an executable without including source code;
- * you don't have to credit me. (But it would be nice if
- * you did.)
- *
- * If you find problems with this code, or find ways of
- * making it significantly faster, please let me know!
- * My e-mail address, valid as of early 1998 and certainly
- * OK for at least the next 18 months, is
- * gjm11@dpmms.cam.ac.uk
- * Thanks!
- *
- * Gareth McCaughan Peterhouse Cambridge 1998
- */
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2016 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
#if defined(__clang_analyzer__) && !defined(SDL_DISABLE_ANALYZE_MACROS)
#define SDL_DISABLE_ANALYZE_MACROS 1
@@ -48,11 +25,6 @@
#include "../SDL_internal.h"
-/*
-#include
-#include
-#include
-*/
#include "SDL_stdinc.h"
#include "SDL_assert.h"
@@ -62,34 +34,128 @@ SDL_qsort(void *base, size_t nmemb, size_t size, int (*compare) (const void *, c
{
qsort(base, nmemb, size, compare);
}
+
#else
#ifdef assert
#undef assert
#endif
-#define assert(X) SDL_assert(X)
+#define assert SDL_assert
#ifdef malloc
#undef malloc
#endif
-#define malloc SDL_malloc
+#define malloc SDL_malloc
#ifdef free
#undef free
#endif
-#define free SDL_free
+#define free SDL_free
#ifdef memcpy
#undef memcpy
#endif
-#define memcpy SDL_memcpy
+#define memcpy SDL_memcpy
#ifdef memmove
#undef memmove
#endif
-#define memmove SDL_memmove
-#ifdef qsort
-#undef qsort
+#define memmove SDL_memmove
+#ifdef qsortG
+#undef qsortG
#endif
-#define qsort SDL_qsort
+#define qsortG SDL_qsort
-static const char _ID[] = "";
+/*
+This code came from Gareth McCaughan, under the zlib license.
+Specifically this: https://www.mccaughan.org.uk/software/qsort.c-1.14
+
+Everything below this comment until the HAVE_QSORT #endif was from Gareth
+(any minor changes will be noted inline).
+
+Thank you to Gareth for relicensing this code under the zlib license for our
+benefit!
+
+--ryan.
+*/
+
+/* This is a drop-in replacement for the C library's |qsort()| routine.
+ *
+ * It is intended for use where you know or suspect that your
+ * platform's qsort is bad. If that isn't the case, then you
+ * should probably use the qsort your system gives you in preference
+ * to mine -- it will likely have been tested and tuned better.
+ *
+ * Features:
+ * - Median-of-three pivoting (and more)
+ * - Truncation and final polishing by a single insertion sort
+ * - Early truncation when no swaps needed in pivoting step
+ * - Explicit recursion, guaranteed not to overflow
+ * - A few little wrinkles stolen from the GNU |qsort()|.
+ * (For the avoidance of doubt, no code was stolen, only
+ * broad ideas.)
+ * - separate code for non-aligned / aligned / word-size objects
+ *
+ * Earlier releases of this code used an idiosyncratic licence
+ * I wrote myself, because I'm an idiot. The code is now released
+ * under the "zlib/libpng licence"; you will find the actual
+ * terms in the next comment. I request (but do not require)
+ * that if you make any changes beyond the name of the exported
+ * routine and reasonable tweaks to the TRUNC_* and
+ * PIVOT_THRESHOLD values, you modify the _ID string so as
+ * to make it clear that you have changed the code.
+ *
+ * If you find problems with this code, or find ways of
+ * making it significantly faster, please let me know!
+ * My e-mail address, valid as of early 2016 and for the
+ * foreseeable future, is
+ * gareth.mccaughan@pobox.com
+ * Thanks!
+ *
+ * Gareth McCaughan
+ */
+
+/* Copyright (c) 1998-2016 Gareth McCaughan
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any
+ * damages arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented;
+ * you must not claim that you wrote the original software.
+ * If you use this software in a product, an acknowledgment
+ * in the product documentation would be appreciated but
+ * is not required.
+ *
+ * 2. Altered source versions must be plainly marked as such,
+ * and must not be misrepresented as being the original software.
+ *
+ * 3. This notice may not be removed or altered from any source
+ * distribution.
+ */
+
+/* Revision history since release:
+ * 1998-03-19 v1.12 First release I have any records of.
+ * 2007-09-02 v1.13 Fix bug kindly reported by Dan Bodoh
+ * (premature termination of recursion).
+ * Add a few clarifying comments.
+ * Minor improvements to debug output.
+ * 2016-02-21 v1.14 Replace licence with 2-clause BSD,
+ * and clarify a couple of things in
+ * comments. No code changes.
+ */
+
+/* BEGIN SDL CHANGE ... commented this out with an #if 0 block. --ryan. */
+#if 0
+#include
+#include
+#include
+
+#define DEBUG_QSORT
+
+static char _ID[]="";
+#endif
+/* END SDL CHANGE ... commented this out with an #if 0 block. --ryan. */
/* How many bytes are there per word? (Must be a power of 2,
* and must in fact equal sizeof(int).)
@@ -110,7 +176,7 @@ static const char _ID[] = "";
*/
#define TRUNC_nonaligned 12
#define TRUNC_aligned 12
-#define TRUNC_words 12*WORD_BYTES /* nb different meaning */
+#define TRUNC_words 12*WORD_BYTES /* nb different meaning */
/* We use a simple pivoting algorithm for shortish sub-arrays
* and a more complicated one for larger ones. The threshold
@@ -118,11 +184,7 @@ static const char _ID[] = "";
*/
#define PIVOT_THRESHOLD 40
-typedef struct
-{
- char *first;
- char *last;
-} stack_entry;
+typedef struct { char * first; char * last; } stack_entry;
#define pushLeft {stack[stacktop].first=ffirst;stack[stacktop++].last=last;}
#define pushRight {stack[stacktop].first=first;stack[stacktop++].last=llast;}
#define doLeft {first=ffirst;llast=last;continue;}
@@ -197,7 +259,9 @@ typedef struct
* 16-bit |int|s and 4096-bit |size_t|s. :-)
*/
-/* The recursion logic is the same in each case: */
+/* The recursion logic is the same in each case.
+ * We keep chopping up until we reach subarrays of size
+ * strictly less than Trunc; we leave these unsorted. */
#define Recurse(Trunc) \
{ size_t l=last-ffirst,r=llast-first; \
if (lPIVOT_THRESHOLD*sz) mid=pivot_big(first,mid,last,sz,compare);\
+ if (last-first>PIVOT_THRESHOLD*sz) mid=pivot_big(first,mid,last,sz,compare);\
else { \
if (compare(first,mid)<0) { \
if (compare(mid,last)>0) { \
@@ -235,26 +299,28 @@ typedef struct
/* and so is the partitioning logic: */
#define Partition(swapper,sz) { \
- int swapped=0; \
do { \
while (compare(first,pivot)<0) first+=sz; \
while (compare(pivot,last)<0) last-=sz; \
if (firstlimit ? limit : nmemb-1)*sz;\
+ last=first + ((nmemb>limit ? limit : nmemb)-1)*sz;\
while (last!=base) { \
if (compare(first,last)>0) first=last; \
last-=sz; } \
@@ -294,188 +360,175 @@ typedef struct
/* ---------------------------------------------------------------------- */
-static char *
-pivot_big(char *first, char *mid, char *last, size_t size,
- int compare(const void *, const void *))
-{
- size_t d = (((last - first) / size) >> 3) * size;
- char *m1, *m2, *m3;
- {
- char *a = first, *b = first + d, *c = first + 2 * d;
+static char * pivot_big(char *first, char *mid, char *last, size_t size,
+ int compare(const void *, const void *)) {
+ int d=(((last-first)/size)>>3)*size;
#ifdef DEBUG_QSORT
- fprintf(stderr, "< %d %d %d\n", *(int *) a, *(int *) b, *(int *) c);
+fprintf(stderr, "pivot_big: first=%p last=%p size=%lu n=%lu\n", first, (unsigned long)last, size, (unsigned long)((last-first+1)/size));
#endif
- m1 = compare(a, b) < 0 ?
- (compare(b, c) < 0 ? b : (compare(a, c) < 0 ? c : a))
- : (compare(a, c) < 0 ? a : (compare(b, c) < 0 ? c : b));
- }
- {
- char *a = mid - d, *b = mid, *c = mid + d;
+ char *m1,*m2,*m3;
+ { char *a=first, *b=first+d, *c=first+2*d;
#ifdef DEBUG_QSORT
- fprintf(stderr, ". %d %d %d\n", *(int *) a, *(int *) b, *(int *) c);
+fprintf(stderr,"< %d %d %d @ %p %p %p\n",*(int*)a,*(int*)b,*(int*)c, a,b,c);
#endif
- m2 = compare(a, b) < 0 ?
- (compare(b, c) < 0 ? b : (compare(a, c) < 0 ? c : a))
- : (compare(a, c) < 0 ? a : (compare(b, c) < 0 ? c : b));
- }
- {
- char *a = last - 2 * d, *b = last - d, *c = last;
+ m1 = compare(a,b)<0 ?
+ (compare(b,c)<0 ? b : (compare(a,c)<0 ? c : a))
+ : (compare(a,c)<0 ? a : (compare(b,c)<0 ? c : b));
+ }
+ { char *a=mid-d, *b=mid, *c=mid+d;
#ifdef DEBUG_QSORT
- fprintf(stderr, "> %d %d %d\n", *(int *) a, *(int *) b, *(int *) c);
+fprintf(stderr,". %d %d %d @ %p %p %p\n",*(int*)a,*(int*)b,*(int*)c, a,b,c);
#endif
- m3 = compare(a, b) < 0 ?
- (compare(b, c) < 0 ? b : (compare(a, c) < 0 ? c : a))
- : (compare(a, c) < 0 ? a : (compare(b, c) < 0 ? c : b));
- }
+ m2 = compare(a,b)<0 ?
+ (compare(b,c)<0 ? b : (compare(a,c)<0 ? c : a))
+ : (compare(a,c)<0 ? a : (compare(b,c)<0 ? c : b));
+ }
+ { char *a=last-2*d, *b=last-d, *c=last;
#ifdef DEBUG_QSORT
- fprintf(stderr, "-> %d %d %d\n", *(int *) m1, *(int *) m2, *(int *) m3);
+fprintf(stderr,"> %d %d %d @ %p %p %p\n",*(int*)a,*(int*)b,*(int*)c, a,b,c);
#endif
- return compare(m1, m2) < 0 ?
- (compare(m2, m3) < 0 ? m2 : (compare(m1, m3) < 0 ? m3 : m1))
- : (compare(m1, m3) < 0 ? m1 : (compare(m2, m3) < 0 ? m3 : m2));
+ m3 = compare(a,b)<0 ?
+ (compare(b,c)<0 ? b : (compare(a,c)<0 ? c : a))
+ : (compare(a,c)<0 ? a : (compare(b,c)<0 ? c : b));
+ }
+#ifdef DEBUG_QSORT
+fprintf(stderr,"-> %d %d %d @ %p %p %p\n",*(int*)m1,*(int*)m2,*(int*)m3, m1,m2,m3);
+#endif
+ return compare(m1,m2)<0 ?
+ (compare(m2,m3)<0 ? m2 : (compare(m1,m3)<0 ? m3 : m1))
+ : (compare(m1,m3)<0 ? m1 : (compare(m2,m3)<0 ? m3 : m2));
}
/* ---------------------------------------------------------------------- */
-static void
-qsort_nonaligned(void *base, size_t nmemb, size_t size,
- int (*compare) (const void *, const void *))
-{
+static void qsort_nonaligned(void *base, size_t nmemb, size_t size,
+ int (*compare)(const void *, const void *)) {
- stack_entry stack[STACK_SIZE];
- int stacktop = 0;
- char *first, *last;
- char *pivot = malloc(size);
- size_t trunc = TRUNC_nonaligned * size;
- assert(pivot != 0);
+ stack_entry stack[STACK_SIZE];
+ int stacktop=0;
+ char *first,*last;
+ char *pivot=malloc(size);
+ size_t trunc=TRUNC_nonaligned*size;
+ assert(pivot!=0);
- first = (char *) base;
- last = first + (nmemb - 1) * size;
+ first=(char*)base; last=first+(nmemb-1)*size;
- if ((size_t) (last - first) > trunc) {
- char *ffirst = first, *llast = last;
- while (1) {
- /* Select pivot */
- {
- char *mid = first + size * ((last - first) / size >> 1);
- Pivot(SWAP_nonaligned, size);
- memcpy(pivot, mid, size);
- }
- /* Partition. */
- Partition(SWAP_nonaligned, size);
- /* Prepare to recurse/iterate. */
- Recurse(trunc)}
+ if (last-first>=trunc) {
+ char *ffirst=first, *llast=last;
+ while (1) {
+ /* Select pivot */
+ { char * mid=first+size*((last-first)/size >> 1);
+ Pivot(SWAP_nonaligned,size);
+ memcpy(pivot,mid,size);
+ }
+ /* Partition. */
+ Partition(SWAP_nonaligned,size);
+ /* Prepare to recurse/iterate. */
+ Recurse(trunc)
}
- PreInsertion(SWAP_nonaligned, TRUNC_nonaligned, size);
- Insertion(SWAP_nonaligned);
- free(pivot);
+ }
+ PreInsertion(SWAP_nonaligned,TRUNC_nonaligned,size);
+ Insertion(SWAP_nonaligned);
+ free(pivot);
}
-static void
-qsort_aligned(void *base, size_t nmemb, size_t size,
- int (*compare) (const void *, const void *))
-{
+static void qsort_aligned(void *base, size_t nmemb, size_t size,
+ int (*compare)(const void *, const void *)) {
- stack_entry stack[STACK_SIZE];
- int stacktop = 0;
- char *first, *last;
- char *pivot = malloc(size);
- size_t trunc = TRUNC_aligned * size;
- assert(pivot != 0);
+ stack_entry stack[STACK_SIZE];
+ int stacktop=0;
+ char *first,*last;
+ char *pivot=malloc(size);
+ size_t trunc=TRUNC_aligned*size;
+ assert(pivot!=0);
- first = (char *) base;
- last = first + (nmemb - 1) * size;
+ first=(char*)base; last=first+(nmemb-1)*size;
- if ((size_t) (last - first) > trunc) {
- char *ffirst = first, *llast = last;
- while (1) {
- /* Select pivot */
- {
- char *mid = first + size * ((last - first) / size >> 1);
- Pivot(SWAP_aligned, size);
- memcpy(pivot, mid, size);
- }
- /* Partition. */
- Partition(SWAP_aligned, size);
- /* Prepare to recurse/iterate. */
- Recurse(trunc)}
+ if (last-first>=trunc) {
+ char *ffirst=first,*llast=last;
+ while (1) {
+ /* Select pivot */
+ { char * mid=first+size*((last-first)/size >> 1);
+ Pivot(SWAP_aligned,size);
+ memcpy(pivot,mid,size);
+ }
+ /* Partition. */
+ Partition(SWAP_aligned,size);
+ /* Prepare to recurse/iterate. */
+ Recurse(trunc)
}
- PreInsertion(SWAP_aligned, TRUNC_aligned, size);
- Insertion(SWAP_aligned);
- free(pivot);
+ }
+ PreInsertion(SWAP_aligned,TRUNC_aligned,size);
+ Insertion(SWAP_aligned);
+ free(pivot);
}
-static void
-qsort_words(void *base, size_t nmemb,
- int (*compare) (const void *, const void *))
-{
+static void qsort_words(void *base, size_t nmemb,
+ int (*compare)(const void *, const void *)) {
- stack_entry stack[STACK_SIZE];
- int stacktop = 0;
- char *first, *last;
- char *pivot = malloc(WORD_BYTES);
- assert(pivot != 0);
+ stack_entry stack[STACK_SIZE];
+ int stacktop=0;
+ char *first,*last;
+ char *pivot=malloc(WORD_BYTES);
+ assert(pivot!=0);
- first = (char *) base;
- last = first + (nmemb - 1) * WORD_BYTES;
+ first=(char*)base; last=first+(nmemb-1)*WORD_BYTES;
- if (last - first > TRUNC_words) {
- char *ffirst = first, *llast = last;
- while (1) {
+ if (last-first>=TRUNC_words) {
+ char *ffirst=first, *llast=last;
+ while (1) {
#ifdef DEBUG_QSORT
- fprintf(stderr, "Doing %d:%d: ",
- (first - (char *) base) / WORD_BYTES,
- (last - (char *) base) / WORD_BYTES);
+fprintf(stderr,"Doing %d:%d: ",
+ (first-(char*)base)/WORD_BYTES,
+ (last-(char*)base)/WORD_BYTES);
#endif
- /* Select pivot */
- {
- char *mid =
- first + WORD_BYTES * ((last - first) / (2 * WORD_BYTES));
- Pivot(SWAP_words, WORD_BYTES);
- *(int *) pivot = *(int *) mid;
- }
+ /* Select pivot */
+ { char * mid=first+WORD_BYTES*((last-first) / (2*WORD_BYTES));
+ Pivot(SWAP_words,WORD_BYTES);
+ *(int*)pivot=*(int*)mid;
#ifdef DEBUG_QSORT
- fprintf(stderr, "pivot=%d\n", *(int *) pivot);
+fprintf(stderr,"pivot = %p = #%lu = %d\n", mid, (unsigned long)(((int*)mid)-((int*)base)), *(int*)mid);
#endif
- /* Partition. */
- Partition(SWAP_words, WORD_BYTES);
- /* Prepare to recurse/iterate. */
- Recurse(TRUNC_words)}
+ }
+ /* Partition. */
+ Partition(SWAP_words,WORD_BYTES);
+#ifdef DEBUG_QSORT
+fprintf(stderr, "after partitioning first=#%lu last=#%lu\n", (first-(char*)base)/4lu, (last-(char*)base)/4lu);
+#endif
+ /* Prepare to recurse/iterate. */
+ Recurse(TRUNC_words)
}
- PreInsertion(SWAP_words, (TRUNC_words / WORD_BYTES), WORD_BYTES);
- /* Now do insertion sort. */
- last = ((char *) base) + nmemb * WORD_BYTES;
- for (first = ((char *) base) + WORD_BYTES; first != last;
- first += WORD_BYTES) {
- /* Find the right place for |first|. My apologies for var reuse */
- int *pl = (int *) (first - WORD_BYTES), *pr = (int *) first;
- *(int *) pivot = *(int *) first;
- for (; compare(pl, pivot) > 0; pr = pl, --pl) {
- *pr = *pl;
- }
- if (pr != (int *) first)
- *pr = *(int *) pivot;
- }
- free(pivot);
+ }
+ PreInsertion(SWAP_words,(TRUNC_words/WORD_BYTES),WORD_BYTES);
+ /* Now do insertion sort. */
+ last=((char*)base)+nmemb*WORD_BYTES;
+ for (first=((char*)base)+WORD_BYTES;first!=last;first+=WORD_BYTES) {
+ /* Find the right place for |first|. My apologies for var reuse */
+ int *pl=(int*)(first-WORD_BYTES),*pr=(int*)first;
+ *(int*)pivot=*(int*)first;
+ for (;compare(pl,pivot)>0;pr=pl,--pl) {
+ *pr=*pl; }
+ if (pr!=(int*)first) *pr=*(int*)pivot;
+ }
+ free(pivot);
}
/* ---------------------------------------------------------------------- */
-void
-qsort(void *base, size_t nmemb, size_t size,
- int (*compare) (const void *, const void *))
-{
+extern void qsortG(void *base, size_t nmemb, size_t size,
+ int (*compare)(const void *, const void *)) {
- if (nmemb <= 1)
- return;
- if (((uintptr_t) base | size) & (WORD_BYTES - 1))
- qsort_nonaligned(base, nmemb, size, compare);
- else if (size != WORD_BYTES)
- qsort_aligned(base, nmemb, size, compare);
- else
- qsort_words(base, nmemb, compare);
+ if (nmemb<=1) return;
+ if (((int)base|size)&(WORD_BYTES-1))
+ qsort_nonaligned(base,nmemb,size,compare);
+ else if (size!=WORD_BYTES)
+ qsort_aligned(base,nmemb,size,compare);
+ else
+ qsort_words(base,nmemb,compare);
}
-#endif /* !SDL_qsort */
+
+#endif /* HAVE_QSORT */
/* vi: set ts=4 sw=4 expandtab: */
+
diff --git a/Engine/lib/sdl/src/stdlib/SDL_stdlib.c b/Engine/lib/sdl/src/stdlib/SDL_stdlib.c
index 6723d4e2c..f5a152b49 100644
--- a/Engine/lib/sdl/src/stdlib/SDL_stdlib.c
+++ b/Engine/lib/sdl/src/stdlib/SDL_stdlib.c
@@ -34,7 +34,7 @@
double
SDL_atan(double x)
{
-#ifdef HAVE_ATAN
+#if defined(HAVE_ATAN)
return atan(x);
#else
return SDL_uclibc_atan(x);
@@ -90,7 +90,7 @@ SDL_asin(double val)
double
SDL_ceil(double x)
{
-#ifdef HAVE_CEIL
+#if defined(HAVE_CEIL)
return ceil(x);
#else
double integer = SDL_floor(x);
@@ -127,7 +127,7 @@ SDL_cos(double x)
float
SDL_cosf(float x)
{
-#ifdef HAVE_COSF
+#if defined(HAVE_COSF)
return cosf(x);
#else
return (float)SDL_cos((double)x);
@@ -199,7 +199,7 @@ SDL_sin(double x)
float
SDL_sinf(float x)
{
-#ifdef HAVE_SINF
+#if defined(HAVE_SINF)
return sinf(x);
#else
return (float)SDL_sin((double)x);
@@ -248,14 +248,14 @@ SDL_tanf(float x)
int SDL_abs(int x)
{
-#ifdef HAVE_ABS
+#if defined(HAVE_ABS)
return abs(x);
#else
return ((x) < 0 ? -(x) : (x));
#endif
}
-#ifdef HAVE_CTYPE_H
+#if defined(HAVE_CTYPE_H)
int SDL_isdigit(int x) { return isdigit(x); }
int SDL_isspace(int x) { return isspace(x); }
int SDL_toupper(int x) { return toupper(x); }
@@ -279,7 +279,7 @@ __declspec(selectany) int _fltused = 1;
#endif
/* The optimizer on Visual Studio 2005 and later generates memcpy() calls */
-#if (_MSC_VER >= 1400) && defined(_WIN64) && !defined(_DEBUG)
+#if (_MSC_VER >= 1400) && defined(_WIN64) && !defined(_DEBUG) && !(_MSC_VER >= 1900 && defined(_MT))
#include
#pragma function(memcpy)
diff --git a/Engine/lib/sdl/src/stdlib/SDL_string.c b/Engine/lib/sdl/src/stdlib/SDL_string.c
index 5debb2285..debbebaed 100644
--- a/Engine/lib/sdl/src/stdlib/SDL_string.c
+++ b/Engine/lib/sdl/src/stdlib/SDL_string.c
@@ -1315,6 +1315,7 @@ static size_t
SDL_PrintString(char *text, size_t maxlen, SDL_FormatInfo *info, const char *string)
{
size_t length = 0;
+ size_t slen;
if (info && info->width && (size_t)info->width > SDL_strlen(string)) {
char fill = info->pad_zeroes ? '0' : ' ';
@@ -1326,7 +1327,8 @@ SDL_PrintString(char *text, size_t maxlen, SDL_FormatInfo *info, const char *str
}
}
- length += SDL_strlcpy(text, string, maxlen);
+ slen = SDL_strlcpy(text, string, maxlen);
+ length += SDL_min(slen, maxlen);
if (info) {
if (info->force_case == SDL_CASE_LOWER) {
@@ -1402,10 +1404,11 @@ SDL_PrintFloat(char *text, size_t maxlen, SDL_FormatInfo *info, double arg)
}
value = (unsigned long) arg;
len = SDL_PrintUnsignedLong(text, left, NULL, value);
- text += len;
if (len >= left) {
+ text += (left > 1) ? left - 1 : 0;
left = SDL_min(left, 1);
} else {
+ text += len;
left -= len;
}
arg -= value;
@@ -1422,10 +1425,11 @@ SDL_PrintFloat(char *text, size_t maxlen, SDL_FormatInfo *info, double arg)
while (info->precision-- > 0) {
value = (unsigned long) (arg * mult);
len = SDL_PrintUnsignedLong(text, left, NULL, value);
- text += len;
if (len >= left) {
+ text += (left > 1) ? left - 1 : 0;
left = SDL_min(left, 1);
} else {
+ text += len;
left -= len;
}
arg -= (double) value / mult;
@@ -1458,10 +1462,11 @@ SDL_PrintFloat(char *text, size_t maxlen, SDL_FormatInfo *info, double arg)
}
}
len = (size_t)width;
- text += len;
if (len >= left) {
+ text += (left > 1) ? left - 1 : 0;
left = SDL_min(left, 1);
} else {
+ text += len;
left -= len;
}
while (len--) {
@@ -1637,10 +1642,11 @@ SDL_vsnprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, const char *fmt,
}
++fmt;
}
- text += len;
if (len >= left) {
+ text += (left > 1) ? left - 1 : 0;
left = SDL_min(left, 1);
} else {
+ text += len;
left -= len;
}
} else {
diff --git a/Engine/lib/sdl/src/test/SDL_test_assert.c b/Engine/lib/sdl/src/test/SDL_test_assert.c
index 98a84d386..ee2f13248 100644
--- a/Engine/lib/sdl/src/test/SDL_test_assert.c
+++ b/Engine/lib/sdl/src/test/SDL_test_assert.c
@@ -30,10 +30,10 @@
#include "SDL_test.h"
/* Assert check message format */
-const char *SDLTest_AssertCheckFormat = "Assert '%s': %s";
+#define SDLTEST_ASSERT_CHECK_FORMAT "Assert '%s': %s"
/* Assert summary message format */
-const char *SDLTest_AssertSummaryFormat = "Assert Summary: Total=%d Passed=%d Failed=%d";
+#define SDLTEST_ASSERT_SUMMARY_FORMAT "Assert Summary: Total=%d Passed=%d Failed=%d"
/* ! \brief counts the failed asserts */
static Uint32 SDLTest_AssertsFailed = 0;
@@ -77,12 +77,12 @@ int SDLTest_AssertCheck(int assertCondition, SDL_PRINTF_FORMAT_STRING const char
if (assertCondition == ASSERT_FAIL)
{
SDLTest_AssertsFailed++;
- SDLTest_LogError(SDLTest_AssertCheckFormat, logMessage, "Failed");
+ SDLTest_LogError(SDLTEST_ASSERT_CHECK_FORMAT, logMessage, "Failed");
}
else
{
SDLTest_AssertsPassed++;
- SDLTest_Log(SDLTest_AssertCheckFormat, logMessage, "Passed");
+ SDLTest_Log(SDLTEST_ASSERT_CHECK_FORMAT, logMessage, "Passed");
}
return assertCondition;
@@ -104,7 +104,7 @@ void SDLTest_AssertPass(SDL_PRINTF_FORMAT_STRING const char *assertDescription,
/* Log pass message */
SDLTest_AssertsPassed++;
- SDLTest_Log(SDLTest_AssertCheckFormat, logMessage, "Pass");
+ SDLTest_Log(SDLTEST_ASSERT_CHECK_FORMAT, logMessage, "Pass");
}
/*
@@ -125,11 +125,11 @@ void SDLTest_LogAssertSummary()
Uint32 totalAsserts = SDLTest_AssertsPassed + SDLTest_AssertsFailed;
if (SDLTest_AssertsFailed == 0)
{
- SDLTest_Log(SDLTest_AssertSummaryFormat, totalAsserts, SDLTest_AssertsPassed, SDLTest_AssertsFailed);
+ SDLTest_Log(SDLTEST_ASSERT_SUMMARY_FORMAT, totalAsserts, SDLTest_AssertsPassed, SDLTest_AssertsFailed);
}
else
{
- SDLTest_LogError(SDLTest_AssertSummaryFormat, totalAsserts, SDLTest_AssertsPassed, SDLTest_AssertsFailed);
+ SDLTest_LogError(SDLTEST_ASSERT_SUMMARY_FORMAT, totalAsserts, SDLTest_AssertsPassed, SDLTest_AssertsFailed);
}
}
diff --git a/Engine/lib/sdl/src/test/SDL_test_common.c b/Engine/lib/sdl/src/test/SDL_test_common.c
index fee249cb9..1d0b005b5 100644
--- a/Engine/lib/sdl/src/test/SDL_test_common.c
+++ b/Engine/lib/sdl/src/test/SDL_test_common.c
@@ -1064,6 +1064,12 @@ SDLTest_PrintEvent(SDL_Event * event)
case SDL_WINDOWEVENT_CLOSE:
SDL_Log("SDL EVENT: Window %d closed", event->window.windowID);
break;
+ case SDL_WINDOWEVENT_TAKE_FOCUS:
+ SDL_Log("SDL EVENT: Window %d take focus", event->window.windowID);
+ break;
+ case SDL_WINDOWEVENT_HIT_TEST:
+ SDL_Log("SDL EVENT: Window %d hit test", event->window.windowID);
+ break;
default:
SDL_Log("SDL EVENT: Window %d got unknown event %d",
event->window.windowID, event->window.event);
@@ -1368,6 +1374,24 @@ SDLTest_CommonEvent(SDLTest_CommonState * state, SDL_Event * event, int *done)
}
}
break;
+ case SDLK_o:
+ if (withControl) {
+ /* Ctrl-O (or Ctrl-Shift-O) changes window opacity. */
+ SDL_Window *window = SDL_GetWindowFromID(event->key.windowID);
+ if (window) {
+ float opacity;
+ if (SDL_GetWindowOpacity(window, &opacity) == 0) {
+ if (withShift) {
+ opacity += 0.20f;
+ } else {
+ opacity -= 0.20f;
+ }
+ SDL_SetWindowOpacity(window, opacity);
+ }
+ }
+ }
+ break;
+
case SDLK_c:
if (withControl) {
/* Ctrl-C copy awesome text! */
diff --git a/Engine/lib/sdl/src/test/SDL_test_compare.c b/Engine/lib/sdl/src/test/SDL_test_compare.c
index 45eb3c689..d06ead9f7 100644
--- a/Engine/lib/sdl/src/test/SDL_test_compare.c
+++ b/Engine/lib/sdl/src/test/SDL_test_compare.c
@@ -43,7 +43,7 @@ int SDLTest_CompareSurfaces(SDL_Surface *surface, SDL_Surface *referenceSurface,
int bpp, bpp_reference;
Uint8 *p, *p_reference;
int dist;
- int sampleErrorX, sampleErrorY, sampleDist;
+ int sampleErrorX = 0, sampleErrorY = 0, sampleDist = 0;
Uint8 R, G, B, A;
Uint8 Rd, Gd, Bd, Ad;
char imageFilename[128];
diff --git a/Engine/lib/sdl/src/test/SDL_test_harness.c b/Engine/lib/sdl/src/test/SDL_test_harness.c
index fec34164c..4b86c7a0d 100644
--- a/Engine/lib/sdl/src/test/SDL_test_harness.c
+++ b/Engine/lib/sdl/src/test/SDL_test_harness.c
@@ -29,13 +29,13 @@
#include
/* Invalid test name/description message format */
-const char *SDLTest_InvalidNameFormat = "(Invalid)";
+#define SDLTEST_INVALID_NAME_FORMAT "(Invalid)"
/* Log summary message format */
-const char *SDLTest_LogSummaryFormat = "%s Summary: Total=%d Passed=%d Failed=%d Skipped=%d";
+#define SDLTEST_LOG_SUMMARY_FORMAT "%s Summary: Total=%d Passed=%d Failed=%d Skipped=%d"
/* Final result message format */
-const char *SDLTest_FinalResultFormat = ">>> %s '%s': %s\n";
+#define SDLTEST_FINAL_RESULT_FORMAT ">>> %s '%s': %s\n"
/* ! \brief Timeout for single test case execution */
static Uint32 SDLTest_TestCaseTimeout = 3600;
@@ -239,7 +239,7 @@ SDLTest_RunTest(SDLTest_TestSuiteReference *testSuite, SDLTest_TestCaseReference
if (!testCase->enabled && forceTestRun == SDL_FALSE)
{
- SDLTest_Log((char *)SDLTest_FinalResultFormat, "Test", testCase->name, "Skipped (Disabled)");
+ SDLTest_Log(SDLTEST_FINAL_RESULT_FORMAT, "Test", testCase->name, "Skipped (Disabled)");
return TEST_RESULT_SKIPPED;
}
@@ -256,7 +256,7 @@ SDLTest_RunTest(SDLTest_TestSuiteReference *testSuite, SDLTest_TestCaseReference
if (testSuite->testSetUp) {
testSuite->testSetUp(0x0);
if (SDLTest_AssertSummaryToTestResult() == TEST_RESULT_FAILED) {
- SDLTest_LogError((char *)SDLTest_FinalResultFormat, "Suite Setup", testSuite->name, "Failed");
+ SDLTest_LogError(SDLTEST_FINAL_RESULT_FORMAT, "Suite Setup", testSuite->name, "Failed");
return TEST_RESULT_SETUP_FAILURE;
}
}
@@ -298,13 +298,13 @@ SDLTest_RunTest(SDLTest_TestSuiteReference *testSuite, SDLTest_TestCaseReference
/* Final log based on test execution result */
if (testCaseResult == TEST_SKIPPED) {
/* Test was programatically skipped */
- SDLTest_Log((char *)SDLTest_FinalResultFormat, "Test", testCase->name, "Skipped (Programmatically)");
+ SDLTest_Log(SDLTEST_FINAL_RESULT_FORMAT, "Test", testCase->name, "Skipped (Programmatically)");
} else if (testCaseResult == TEST_STARTED) {
/* Test did not return a TEST_COMPLETED value; assume it failed */
- SDLTest_LogError((char *)SDLTest_FinalResultFormat, "Test", testCase->name, "Failed (test started, but did not return TEST_COMPLETED)");
+ SDLTest_LogError(SDLTEST_FINAL_RESULT_FORMAT, "Test", testCase->name, "Failed (test started, but did not return TEST_COMPLETED)");
} else if (testCaseResult == TEST_ABORTED) {
/* Test was aborted early; assume it failed */
- SDLTest_LogError((char *)SDLTest_FinalResultFormat, "Test", testCase->name, "Failed (Aborted)");
+ SDLTest_LogError(SDLTEST_FINAL_RESULT_FORMAT, "Test", testCase->name, "Failed (Aborted)");
} else {
SDLTest_LogAssertSummary();
}
@@ -326,7 +326,7 @@ void SDLTest_LogTestSuiteSummary(SDLTest_TestSuiteReference *testSuites)
testSuite=&testSuites[suiteCounter];
suiteCounter++;
SDLTest_Log("Test Suite %i - %s\n", suiteCounter,
- (testSuite->name) ? testSuite->name : SDLTest_InvalidNameFormat);
+ (testSuite->name) ? testSuite->name : SDLTEST_INVALID_NAME_FORMAT);
/* Loop over all test cases */
testCounter = 0;
@@ -335,8 +335,8 @@ void SDLTest_LogTestSuiteSummary(SDLTest_TestSuiteReference *testSuites)
testCase=(SDLTest_TestCaseReference *)testSuite->testCases[testCounter];
testCounter++;
SDLTest_Log(" Test Case %i - %s: %s", testCounter,
- (testCase->name) ? testCase->name : SDLTest_InvalidNameFormat,
- (testCase->description) ? testCase->description : SDLTest_InvalidNameFormat);
+ (testCase->name) ? testCase->name : SDLTEST_INVALID_NAME_FORMAT,
+ (testCase->description) ? testCase->description : SDLTEST_INVALID_NAME_FORMAT);
}
}
}
@@ -396,7 +396,6 @@ int SDLTest_RunSuites(SDLTest_TestSuiteReference *testSuites[], const char *user
Uint32 testPassedCount = 0;
Uint32 testSkippedCount = 0;
Uint32 countSum = 0;
- char *logFormat = (char *)SDLTest_LogSummaryFormat;
SDLTest_TestCaseReference **failedTests;
/* Sanitize test iterations */
@@ -493,7 +492,7 @@ int SDLTest_RunSuites(SDLTest_TestSuiteReference *testSuites[], const char *user
suiteCounter = 0;
while(testSuites[suiteCounter]) {
testSuite=(SDLTest_TestSuiteReference *)testSuites[suiteCounter];
- currentSuiteName = (char *)((testSuite->name) ? testSuite->name : SDLTest_InvalidNameFormat);
+ currentSuiteName = (char *)((testSuite->name) ? testSuite->name : SDLTEST_INVALID_NAME_FORMAT);
suiteCounter++;
/* Filter suite if flag set and we have a name */
@@ -523,7 +522,7 @@ int SDLTest_RunSuites(SDLTest_TestSuiteReference *testSuites[], const char *user
while(testSuite->testCases[testCounter])
{
testCase=(SDLTest_TestCaseReference *)testSuite->testCases[testCounter];
- currentTestName = (char *)((testCase->name) ? testCase->name : SDLTest_InvalidNameFormat);
+ currentTestName = (char *)((testCase->name) ? testCase->name : SDLTEST_INVALID_NAME_FORMAT);
testCounter++;
/* Filter tests if flag set and we have a name */
@@ -551,7 +550,7 @@ int SDLTest_RunSuites(SDLTest_TestSuiteReference *testSuites[], const char *user
currentTestName);
if (testCase->description != NULL && testCase->description[0] != '\0') {
SDLTest_Log("Test Description: '%s'",
- (testCase->description) ? testCase->description : SDLTest_InvalidNameFormat);
+ (testCase->description) ? testCase->description : SDLTEST_INVALID_NAME_FORMAT);
}
/* Loop over all iterations */
@@ -598,13 +597,13 @@ int SDLTest_RunSuites(SDLTest_TestSuiteReference *testSuites[], const char *user
/* Log final test result */
switch (testResult) {
case TEST_RESULT_PASSED:
- SDLTest_Log((char *)SDLTest_FinalResultFormat, "Test", currentTestName, "Passed");
+ SDLTest_Log(SDLTEST_FINAL_RESULT_FORMAT, "Test", currentTestName, "Passed");
break;
case TEST_RESULT_FAILED:
- SDLTest_LogError((char *)SDLTest_FinalResultFormat, "Test", currentTestName, "Failed");
+ SDLTest_LogError(SDLTEST_FINAL_RESULT_FORMAT, "Test", currentTestName, "Failed");
break;
case TEST_RESULT_NO_ASSERT:
- SDLTest_LogError((char *)SDLTest_FinalResultFormat,"Test", currentTestName, "No Asserts");
+ SDLTest_LogError(SDLTEST_FINAL_RESULT_FORMAT,"Test", currentTestName, "No Asserts");
break;
}
@@ -628,13 +627,13 @@ int SDLTest_RunSuites(SDLTest_TestSuiteReference *testSuites[], const char *user
countSum = testPassedCount + testFailedCount + testSkippedCount;
if (testFailedCount == 0)
{
- SDLTest_Log(logFormat, "Suite", countSum, testPassedCount, testFailedCount, testSkippedCount);
- SDLTest_Log((char *)SDLTest_FinalResultFormat, "Suite", currentSuiteName, "Passed");
+ SDLTest_Log(SDLTEST_LOG_SUMMARY_FORMAT, "Suite", countSum, testPassedCount, testFailedCount, testSkippedCount);
+ SDLTest_Log(SDLTEST_FINAL_RESULT_FORMAT, "Suite", currentSuiteName, "Passed");
}
else
{
- SDLTest_LogError(logFormat, "Suite", countSum, testPassedCount, testFailedCount, testSkippedCount);
- SDLTest_LogError((char *)SDLTest_FinalResultFormat, "Suite", currentSuiteName, "Failed");
+ SDLTest_LogError(SDLTEST_LOG_SUMMARY_FORMAT, "Suite", countSum, testPassedCount, testFailedCount, testSkippedCount);
+ SDLTest_LogError(SDLTEST_FINAL_RESULT_FORMAT, "Suite", currentSuiteName, "Failed");
}
}
@@ -653,14 +652,14 @@ int SDLTest_RunSuites(SDLTest_TestSuiteReference *testSuites[], const char *user
if (totalTestFailedCount == 0)
{
runResult = 0;
- SDLTest_Log(logFormat, "Run", countSum, totalTestPassedCount, totalTestFailedCount, totalTestSkippedCount);
- SDLTest_Log((char *)SDLTest_FinalResultFormat, "Run /w seed", runSeed, "Passed");
+ SDLTest_Log(SDLTEST_LOG_SUMMARY_FORMAT, "Run", countSum, totalTestPassedCount, totalTestFailedCount, totalTestSkippedCount);
+ SDLTest_Log(SDLTEST_FINAL_RESULT_FORMAT, "Run /w seed", runSeed, "Passed");
}
else
{
runResult = 1;
- SDLTest_LogError(logFormat, "Run", countSum, totalTestPassedCount, totalTestFailedCount, totalTestSkippedCount);
- SDLTest_LogError((char *)SDLTest_FinalResultFormat, "Run /w seed", runSeed, "Failed");
+ SDLTest_LogError(SDLTEST_LOG_SUMMARY_FORMAT, "Run", countSum, totalTestPassedCount, totalTestFailedCount, totalTestSkippedCount);
+ SDLTest_LogError(SDLTEST_FINAL_RESULT_FORMAT, "Run /w seed", runSeed, "Failed");
}
/* Print repro steps for failed tests */
diff --git a/Engine/lib/sdl/src/test/SDL_test_log.c b/Engine/lib/sdl/src/test/SDL_test_log.c
index 097372e7a..a2f857f26 100644
--- a/Engine/lib/sdl/src/test/SDL_test_log.c
+++ b/Engine/lib/sdl/src/test/SDL_test_log.c
@@ -55,12 +55,11 @@ char *SDLTest_TimestampToString(const time_t timestamp)
time_t copy;
static char buffer[64];
struct tm *local;
- const char *fmt = "%x %X";
SDL_memset(buffer, 0, sizeof(buffer));
copy = timestamp;
local = localtime(©);
- strftime(buffer, sizeof(buffer), fmt, local);
+ strftime(buffer, sizeof(buffer), "%x %X", local);
return buffer;
}
diff --git a/Engine/lib/sdl/src/thread/SDL_systhread.h b/Engine/lib/sdl/src/thread/SDL_systhread.h
index f13f3e203..05a012536 100644
--- a/Engine/lib/sdl/src/thread/SDL_systhread.h
+++ b/Engine/lib/sdl/src/thread/SDL_systhread.h
@@ -60,6 +60,11 @@ extern SDL_TLSData *SDL_SYS_GetTLSData();
/* Set the thread local storage for this thread */
extern int SDL_SYS_SetTLSData(SDL_TLSData *data);
+/* This is for internal SDL use, so we don't need #ifdefs everywhere. */
+extern SDL_Thread *
+SDL_CreateThreadInternal(int (SDLCALL * fn) (void *), const char *name,
+ const size_t stacksize, void *data);
+
#endif /* _SDL_systhread_h */
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/thread/SDL_thread.c b/Engine/lib/sdl/src/thread/SDL_thread.c
index e66c5819c..ae865790a 100644
--- a/Engine/lib/sdl/src/thread/SDL_thread.c
+++ b/Engine/lib/sdl/src/thread/SDL_thread.c
@@ -26,6 +26,7 @@
#include "SDL_thread.h"
#include "SDL_thread_c.h"
#include "SDL_systhread.h"
+#include "SDL_hints.h"
#include "../SDL_error_c.h"
@@ -304,15 +305,15 @@ SDL_RunThread(void *data)
#endif
#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
-DECLSPEC SDL_Thread *SDLCALL
-SDL_CreateThread(int (SDLCALL * fn) (void *),
- const char *name, void *data,
+static SDL_Thread *
+SDL_CreateThreadWithStackSize(int (SDLCALL * fn) (void *),
+ const char *name, const size_t stacksize, void *data,
pfnSDL_CurrentBeginThread pfnBeginThread,
pfnSDL_CurrentEndThread pfnEndThread)
#else
-DECLSPEC SDL_Thread *SDLCALL
-SDL_CreateThread(int (SDLCALL * fn) (void *),
- const char *name, void *data)
+static SDL_Thread *
+SDL_CreateThreadWithStackSize(int (SDLCALL * fn) (void *),
+ const char *name, const size_t stacksize, void *data)
#endif
{
SDL_Thread *thread;
@@ -362,6 +363,8 @@ SDL_CreateThread(int (SDLCALL * fn) (void *),
return (NULL);
}
+ thread->stacksize = stacksize;
+
/* Create the thread and go! */
#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
ret = SDL_SYS_CreateThread(thread, args, pfnBeginThread, pfnEndThread);
@@ -386,6 +389,50 @@ SDL_CreateThread(int (SDLCALL * fn) (void *),
return (thread);
}
+#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
+DECLSPEC SDL_Thread *SDLCALL
+SDL_CreateThread(int (SDLCALL * fn) (void *),
+ const char *name, void *data,
+ pfnSDL_CurrentBeginThread pfnBeginThread,
+ pfnSDL_CurrentEndThread pfnEndThread)
+#else
+DECLSPEC SDL_Thread *SDLCALL
+SDL_CreateThread(int (SDLCALL * fn) (void *),
+ const char *name, void *data)
+#endif
+{
+ /* !!! FIXME: in 2.1, just make stackhint part of the usual API. */
+ const char *stackhint = SDL_GetHint(SDL_HINT_THREAD_STACK_SIZE);
+ size_t stacksize = 0;
+
+ /* If the SDL_HINT_THREAD_STACK_SIZE exists, use it */
+ if (stackhint != NULL) {
+ char *endp = NULL;
+ const Sint64 hintval = SDL_strtoll(stackhint, &endp, 10);
+ if ((*stackhint != '\0') && (*endp == '\0')) { /* a valid number? */
+ if (hintval > 0) { /* reject bogus values. */
+ stacksize = (size_t) hintval;
+ }
+ }
+ }
+
+#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
+ return SDL_CreateThreadWithStackSize(fn, name, stacksize, data, pfnBeginThread, pfnEndThread);
+#else
+ return SDL_CreateThreadWithStackSize(fn, name, stacksize, data);
+#endif
+}
+
+SDL_Thread *
+SDL_CreateThreadInternal(int (SDLCALL * fn) (void *), const char *name,
+ const size_t stacksize, void *data) {
+#ifdef SDL_PASSED_BEGINTHREAD_ENDTHREAD
+ return SDL_CreateThreadWithStackSize(fn, name, stacksize, data, NULL, NULL);
+#else
+ return SDL_CreateThreadWithStackSize(fn, name, stacksize, data);
+#endif
+}
+
SDL_threadID
SDL_GetThreadID(SDL_Thread * thread)
{
diff --git a/Engine/lib/sdl/src/thread/SDL_thread_c.h b/Engine/lib/sdl/src/thread/SDL_thread_c.h
index a283a0e2c..554325d6d 100644
--- a/Engine/lib/sdl/src/thread/SDL_thread_c.h
+++ b/Engine/lib/sdl/src/thread/SDL_thread_c.h
@@ -59,6 +59,7 @@ struct SDL_Thread
SDL_atomic_t state; /* SDL_THREAD_STATE_* */
SDL_error errbuf;
char *name;
+ size_t stacksize; /* 0 for default, >0 for user-specified stack size. */
void *data;
};
diff --git a/Engine/lib/sdl/src/thread/psp/SDL_systhread.c b/Engine/lib/sdl/src/thread/psp/SDL_systhread.c
index ab8aff376..c6003b8ed 100644
--- a/Engine/lib/sdl/src/thread/psp/SDL_systhread.c
+++ b/Engine/lib/sdl/src/thread/psp/SDL_systhread.c
@@ -52,8 +52,8 @@ int SDL_SYS_CreateThread(SDL_Thread *thread, void *args)
priority = status.currentPriority;
}
- thread->handle = sceKernelCreateThread("SDL thread", ThreadEntry,
- priority, 0x8000,
+ thread->handle = sceKernelCreateThread(thread->name, ThreadEntry,
+ priority, thread->stacksize ? ((int) thread->stacksize) : 0x8000,
PSP_THREAD_ATTR_VFPU, NULL);
if (thread->handle < 0) {
return SDL_SetError("sceKernelCreateThread() failed");
diff --git a/Engine/lib/sdl/src/thread/pthread/SDL_systhread.c b/Engine/lib/sdl/src/thread/pthread/SDL_systhread.c
index 22f7bd57b..4958f6fb9 100644
--- a/Engine/lib/sdl/src/thread/pthread/SDL_systhread.c
+++ b/Engine/lib/sdl/src/thread/pthread/SDL_systhread.c
@@ -45,7 +45,6 @@
#include "SDL_platform.h"
#include "SDL_thread.h"
-#include "SDL_hints.h"
#include "../SDL_thread_c.h"
#include "../SDL_systhread.h"
#ifdef __ANDROID__
@@ -87,7 +86,6 @@ int
SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
{
pthread_attr_t type;
- const char *hint = SDL_GetHint(SDL_HINT_THREAD_STACK_SIZE);
/* do this here before any threads exist, so there's no race condition. */
#if defined(__MACOSX__) || defined(__IPHONEOS__) || defined(__LINUX__)
@@ -108,12 +106,9 @@ SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
}
pthread_attr_setdetachstate(&type, PTHREAD_CREATE_JOINABLE);
- /* If the SDL_HINT_THREAD_STACK_SIZE exists and it seems to be a positive number, use it */
- if (hint && hint[0] >= '0' && hint[0] <= '9') {
- const size_t stacksize = (size_t) SDL_atoi(hint);
- if (stacksize > 0) {
- pthread_attr_setstacksize(&type, stacksize);
- }
+ /* Set caller-requested stack size. Otherwise: use the system default. */
+ if (thread->stacksize) {
+ pthread_attr_setstacksize(&type, (size_t) thread->stacksize);
}
/* Create the thread and go! */
@@ -127,10 +122,10 @@ SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
void
SDL_SYS_SetupThread(const char *name)
{
-#if !defined(__ANDROID__) && !defined(__NACL__)
+#if !defined(__NACL__)
int i;
sigset_t mask;
-#endif /* !__ANDROID__ && !__NACL__ */
+#endif /* !__NACL__ */
if (name != NULL) {
#if defined(__MACOSX__) || defined(__IPHONEOS__) || defined(__LINUX__)
@@ -160,14 +155,14 @@ SDL_SYS_SetupThread(const char *name)
}
/* NativeClient does not yet support signals.*/
-#if !defined(__ANDROID__) && !defined(__NACL__)
+#if !defined(__NACL__)
/* Mask asynchronous signals for this thread */
sigemptyset(&mask);
for (i = 0; sig_list[i]; ++i) {
sigaddset(&mask, sig_list[i]);
}
pthread_sigmask(SIG_BLOCK, &mask, 0);
-#endif /* !__ANDROID__ && !__NACL__ */
+#endif /* !__NACL__ */
#ifdef PTHREAD_CANCEL_ASYNCHRONOUS
@@ -204,6 +199,10 @@ SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
if (setpriority(PRIO_PROCESS, syscall(SYS_gettid), value) < 0) {
/* Note that this fails if you're trying to set high priority
and you don't have root permission. BUT DON'T RUN AS ROOT!
+
+ You can grant the ability to increase thread priority by
+ running the following command on your application binary:
+ sudo setcap 'cap_sys_nice=eip'
*/
return SDL_SetError("setpriority() failed");
}
diff --git a/Engine/lib/sdl/src/thread/stdcpp/SDL_systhread.cpp b/Engine/lib/sdl/src/thread/stdcpp/SDL_systhread.cpp
index 219c67e93..6e5ef473e 100644
--- a/Engine/lib/sdl/src/thread/stdcpp/SDL_systhread.cpp
+++ b/Engine/lib/sdl/src/thread/stdcpp/SDL_systhread.cpp
@@ -48,6 +48,7 @@ int
SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
{
try {
+ // !!! FIXME: no way to set a thread stack size here.
std::thread cpp_thread(RunThread, args);
thread->handle = (void *) new std::thread(std::move(cpp_thread));
return 0;
diff --git a/Engine/lib/sdl/src/thread/windows/SDL_systhread.c b/Engine/lib/sdl/src/thread/windows/SDL_systhread.c
index 308145e30..20a4bd6e2 100644
--- a/Engine/lib/sdl/src/thread/windows/SDL_systhread.c
+++ b/Engine/lib/sdl/src/thread/windows/SDL_systhread.c
@@ -24,6 +24,7 @@
/* Win32 thread management routines for SDL */
+#include "SDL_hints.h"
#include "SDL_thread.h"
#include "../SDL_thread_c.h"
#include "../SDL_systhread.h"
@@ -33,6 +34,10 @@
/* We'll use the C library from this DLL */
#include
+#ifndef STACK_SIZE_PARAM_IS_A_RESERVATION
+#define STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000
+#endif
+
/* Cygwin gcc-3 ... MingW64 (even with a i386 host) does this like MSVC. */
#if (defined(__MINGW32__) && (__GNUC__ < 4))
typedef unsigned long (__cdecl *pfnSDL_CurrentBeginThread) (void *, unsigned,
@@ -121,6 +126,7 @@ SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
#endif /* SDL_PASSED_BEGINTHREAD_ENDTHREAD */
pThreadStartParms pThreadParms =
(pThreadStartParms) SDL_malloc(sizeof(tThreadStartParms));
+ const DWORD flags = thread->stacksize ? STACK_SIZE_PARAM_IS_A_RESERVATION : 0;
if (!pThreadParms) {
return SDL_OutOfMemory();
}
@@ -129,15 +135,18 @@ SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
/* Also save the real parameters we have to pass to thread function */
pThreadParms->args = args;
+ /* thread->stacksize == 0 means "system default", same as win32 expects */
if (pfnBeginThread) {
unsigned threadid = 0;
thread->handle = (SYS_ThreadHandle)
- ((size_t) pfnBeginThread(NULL, 0, RunThreadViaBeginThreadEx,
- pThreadParms, 0, &threadid));
+ ((size_t) pfnBeginThread(NULL, (unsigned int) thread->stacksize,
+ RunThreadViaBeginThreadEx,
+ pThreadParms, flags, &threadid));
} else {
DWORD threadid = 0;
- thread->handle = CreateThread(NULL, 0, RunThreadViaCreateThread,
- pThreadParms, 0, &threadid);
+ thread->handle = CreateThread(NULL, thread->stacksize,
+ RunThreadViaCreateThread,
+ pThreadParms, flags, &threadid);
}
if (thread->handle == NULL) {
return SDL_SetError("Not enough resources to create thread");
@@ -145,9 +154,6 @@ SDL_SYS_CreateThread(SDL_Thread * thread, void *args)
return 0;
}
-#if 0 /* !!! FIXME: revisit this later. See https://bugzilla.libsdl.org/show_bug.cgi?id=2089 */
-#ifdef _MSC_VER
-#pragma warning(disable : 4733)
#pragma pack(push,8)
typedef struct tagTHREADNAME_INFO
{
@@ -158,48 +164,26 @@ typedef struct tagTHREADNAME_INFO
} THREADNAME_INFO;
#pragma pack(pop)
-static EXCEPTION_DISPOSITION
-ignore_exception(void *a, void *b, void *c, void *d)
-{
- return ExceptionContinueExecution;
-}
-#endif
-#endif
-
void
SDL_SYS_SetupThread(const char *name)
{
- if (name != NULL) {
- #if 0 /* !!! FIXME: revisit this later. See https://bugzilla.libsdl.org/show_bug.cgi?id=2089 */
- #if (defined(_MSC_VER) && defined(_M_IX86))
- /* This magic tells the debugger to name a thread if it's listening.
- The inline asm sets up SEH (__try/__except) without C runtime
- support. See Microsoft Systems Journal, January 1997:
- http://www.microsoft.com/msj/0197/exception/exception.aspx */
- INT_PTR handler = (INT_PTR) ignore_exception;
+ if ((name != NULL) && IsDebuggerPresent()) {
THREADNAME_INFO inf;
+ /* C# and friends will try to catch this Exception, let's avoid it. */
+ if (SDL_GetHintBoolean(SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING, SDL_FALSE)) {
+ return;
+ }
+
+ /* This magic tells the debugger to name a thread if it's listening. */
+ SDL_zero(inf);
inf.dwType = 0x1000;
inf.szName = name;
inf.dwThreadID = (DWORD) -1;
inf.dwFlags = 0;
- __asm { /* set up SEH */
- push handler
- push fs:[0]
- mov fs:[0],esp
- }
-
- /* The program itself should ignore this bogus exception. */
- RaiseException(0x406D1388, 0, sizeof(inf)/sizeof(DWORD), (DWORD*)&inf);
-
- __asm { /* tear down SEH. */
- mov eax,[esp]
- mov fs:[0], eax
- add esp, 8
- }
- #endif
- #endif
+ /* The debugger catches this, renames the thread, continues on. */
+ RaiseException(0x406D1388, 0, sizeof(inf) / sizeof(ULONG), (const ULONG_PTR*) &inf);
}
}
@@ -230,11 +214,7 @@ SDL_SYS_SetThreadPriority(SDL_ThreadPriority priority)
void
SDL_SYS_WaitThread(SDL_Thread * thread)
{
-#if __WINRT__
WaitForSingleObjectEx(thread->handle, INFINITE, FALSE);
-#else
- WaitForSingleObject(thread->handle, INFINITE);
-#endif
CloseHandle(thread->handle);
}
diff --git a/Engine/lib/sdl/src/timer/SDL_timer.c b/Engine/lib/sdl/src/timer/SDL_timer.c
index 6189ab8b5..abe968e86 100644
--- a/Engine/lib/sdl/src/timer/SDL_timer.c
+++ b/Engine/lib/sdl/src/timer/SDL_timer.c
@@ -24,7 +24,7 @@
#include "SDL_timer_c.h"
#include "SDL_atomic.h"
#include "SDL_cpuinfo.h"
-#include "SDL_thread.h"
+#include "../thread/SDL_systhread.h"
/* #define DEBUG_TIMERS */
@@ -35,7 +35,7 @@ typedef struct _SDL_Timer
void *param;
Uint32 interval;
Uint32 scheduled;
- volatile SDL_bool canceled;
+ SDL_atomic_t canceled;
struct _SDL_Timer *next;
} SDL_Timer;
@@ -60,9 +60,9 @@ typedef struct {
/* Data used to communicate with the timer thread */
SDL_SpinLock lock;
SDL_sem *sem;
- SDL_Timer * volatile pending;
- SDL_Timer * volatile freelist;
- volatile SDL_bool active;
+ SDL_Timer *pending;
+ SDL_Timer *freelist;
+ SDL_atomic_t active;
/* List of timers - this is only touched by the timer thread */
SDL_Timer *timers;
@@ -138,7 +138,7 @@ SDL_TimerThread(void *_data)
freelist_tail = NULL;
/* Check to see if we're still running, after maintenance */
- if (!data->active) {
+ if (!SDL_AtomicGet(&data->active)) {
break;
}
@@ -160,7 +160,7 @@ SDL_TimerThread(void *_data)
/* We're going to do something with this timer */
data->timers = current->next;
- if (current->canceled) {
+ if (SDL_AtomicGet(¤t->canceled)) {
interval = 0;
} else {
interval = current->callback(current->interval, current->param);
@@ -179,7 +179,7 @@ SDL_TimerThread(void *_data)
}
freelist_tail = current;
- current->canceled = SDL_TRUE;
+ SDL_AtomicSet(¤t->canceled, 1);
}
}
@@ -207,7 +207,7 @@ SDL_TimerInit(void)
{
SDL_TimerData *data = &SDL_timer_data;
- if (!data->active) {
+ if (!SDL_AtomicGet(&data->active)) {
const char *name = "SDLTimer";
data->timermap_lock = SDL_CreateMutex();
if (!data->timermap_lock) {
@@ -220,18 +220,10 @@ SDL_TimerInit(void)
return -1;
}
- data->active = SDL_TRUE;
- /* !!! FIXME: this is nasty. */
-#if defined(__WIN32__) && !defined(HAVE_LIBC)
-#undef SDL_CreateThread
-#if SDL_DYNAMIC_API
- data->thread = SDL_CreateThread_REAL(SDL_TimerThread, name, data, NULL, NULL);
-#else
- data->thread = SDL_CreateThread(SDL_TimerThread, name, data, NULL, NULL);
-#endif
-#else
- data->thread = SDL_CreateThread(SDL_TimerThread, name, data);
-#endif
+ SDL_AtomicSet(&data->active, 1);
+
+ /* Timer threads use a callback into the app, so we can't set a limited stack size here. */
+ data->thread = SDL_CreateThreadInternal(SDL_TimerThread, name, 0, data);
if (!data->thread) {
SDL_TimerQuit();
return -1;
@@ -249,9 +241,7 @@ SDL_TimerQuit(void)
SDL_Timer *timer;
SDL_TimerMap *entry;
- if (data->active) {
- data->active = SDL_FALSE;
-
+ if (SDL_AtomicCAS(&data->active, 1, 0)) { /* active? Move to inactive. */
/* Shutdown the timer thread */
if (data->thread) {
SDL_SemPost(data->sem);
@@ -291,21 +281,14 @@ SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *param)
SDL_Timer *timer;
SDL_TimerMap *entry;
- if (!data->active) {
- int status = 0;
-
- SDL_AtomicLock(&data->lock);
- if (!data->active) {
- status = SDL_TimerInit();
- }
- SDL_AtomicUnlock(&data->lock);
-
- if (status < 0) {
+ SDL_AtomicLock(&data->lock);
+ if (!SDL_AtomicGet(&data->active)) {
+ if (SDL_TimerInit() < 0) {
+ SDL_AtomicUnlock(&data->lock);
return 0;
}
}
- SDL_AtomicLock(&data->lock);
timer = data->freelist;
if (timer) {
data->freelist = timer->next;
@@ -326,7 +309,7 @@ SDL_AddTimer(Uint32 interval, SDL_TimerCallback callback, void *param)
timer->param = param;
timer->interval = interval;
timer->scheduled = SDL_GetTicks() + interval;
- timer->canceled = SDL_FALSE;
+ SDL_AtomicSet(&timer->canceled, 0);
entry = (SDL_TimerMap *)SDL_malloc(sizeof(*entry));
if (!entry) {
@@ -377,8 +360,8 @@ SDL_RemoveTimer(SDL_TimerID id)
SDL_UnlockMutex(data->timermap_lock);
if (entry) {
- if (!entry->timer->canceled) {
- entry->timer->canceled = SDL_TRUE;
+ if (!SDL_AtomicGet(&entry->timer->canceled)) {
+ SDL_AtomicSet(&entry->timer->canceled, 1);
canceled = SDL_TRUE;
}
SDL_free(entry);
diff --git a/Engine/lib/sdl/src/timer/windows/SDL_systimer.c b/Engine/lib/sdl/src/timer/windows/SDL_systimer.c
index abfbcb99a..5c9121a51 100644
--- a/Engine/lib/sdl/src/timer/windows/SDL_systimer.c
+++ b/Engine/lib/sdl/src/timer/windows/SDL_systimer.c
@@ -107,10 +107,8 @@ SDL_TicksInit(void)
void
SDL_TicksQuit(void)
{
- if (!hires_timer_available) {
- SDL_DelHintCallback(SDL_HINT_TIMER_RESOLUTION,
- SDL_TimerResolutionChanged, NULL);
- }
+ SDL_DelHintCallback(SDL_HINT_TIMER_RESOLUTION,
+ SDL_TimerResolutionChanged, NULL);
SDL_SetSystemTimerResolution(0); /* always release our timer resolution request. */
@@ -189,6 +187,10 @@ SDL_Delay(Uint32 ms)
}
WaitForSingleObjectEx(mutex, ms, FALSE);
#else
+ if (!ticks_started) {
+ SDL_TicksInit();
+ }
+
Sleep(ms);
#endif
}
diff --git a/Engine/lib/sdl/src/video/SDL_blit_copy.c b/Engine/lib/sdl/src/video/SDL_blit_copy.c
index 7b9a91ffd..674650dd9 100644
--- a/Engine/lib/sdl/src/video/SDL_blit_copy.c
+++ b/Engine/lib/sdl/src/video/SDL_blit_copy.c
@@ -109,10 +109,20 @@ SDL_BlitCopy(SDL_BlitInfo * info)
overlap = (src < (dst + h*dstskip));
}
if (overlap) {
- while (h--) {
- SDL_memmove(dst, src, w);
- src += srcskip;
- dst += dstskip;
+ if ( dst < src ) {
+ while ( h-- ) {
+ SDL_memmove(dst, src, w);
+ src += srcskip;
+ dst += dstskip;
+ }
+ } else {
+ src += ((h-1) * srcskip);
+ dst += ((h-1) * dstskip);
+ while ( h-- ) {
+ SDL_memmove(dst, src, w);
+ src -= srcskip;
+ dst -= dstskip;
+ }
}
return;
}
diff --git a/Engine/lib/sdl/src/video/SDL_blit_slow.c b/Engine/lib/sdl/src/video/SDL_blit_slow.c
index 3a462f6e2..02ab41de7 100644
--- a/Engine/lib/sdl/src/video/SDL_blit_slow.c
+++ b/Engine/lib/sdl/src/video/SDL_blit_slow.c
@@ -46,6 +46,8 @@ SDL_Blit_Slow(SDL_BlitInfo * info)
SDL_PixelFormat *dst_fmt = info->dst_fmt;
int srcbpp = src_fmt->BytesPerPixel;
int dstbpp = dst_fmt->BytesPerPixel;
+ Uint32 rgbmask = ~src_fmt->Amask;
+ Uint32 ckey = info->colorkey & rgbmask;
srcy = 0;
posy = 0;
@@ -85,7 +87,7 @@ SDL_Blit_Slow(SDL_BlitInfo * info)
srcpixel = (srcR << src_fmt->Rshift) |
(srcG << src_fmt->Gshift) | (srcB << src_fmt->Bshift);
}
- if (srcpixel == info->colorkey) {
+ if ((srcpixel & rgbmask) == ckey) {
posx += incx;
dst += dstbpp;
continue;
@@ -127,6 +129,7 @@ SDL_Blit_Slow(SDL_BlitInfo * info)
dstR = srcR + ((255 - srcA) * dstR) / 255;
dstG = srcG + ((255 - srcA) * dstG) / 255;
dstB = srcB + ((255 - srcA) * dstB) / 255;
+ dstA = srcA + ((255 - srcA) * dstA) / 255;
break;
case SDL_COPY_ADD:
dstR = srcR + dstR;
diff --git a/Engine/lib/sdl/src/video/SDL_bmp.c b/Engine/lib/sdl/src/video/SDL_bmp.c
index f80f93696..2d9cf240b 100644
--- a/Engine/lib/sdl/src/video/SDL_bmp.c
+++ b/Engine/lib/sdl/src/video/SDL_bmp.c
@@ -32,6 +32,7 @@
This code currently supports Win32 DIBs in uncompressed 8 and 24 bpp.
*/
+#include "SDL_hints.h"
#include "SDL_video.h"
#include "SDL_assert.h"
#include "SDL_endian.h"
@@ -47,6 +48,11 @@
#define BI_BITFIELDS 3
#endif
+/* Logical color space values for BMP files */
+#ifndef LCS_WINDOWS_COLOR_SPACE
+/* 0x57696E20 == "Win " */
+#define LCS_WINDOWS_COLOR_SPACE 0x57696E20
+#endif
static void CorrectAlphaChannel(SDL_Surface *surface)
{
@@ -457,6 +463,8 @@ SDL_SaveBMP_RW(SDL_Surface * saveme, SDL_RWops * dst, int freedst)
int i, pad;
SDL_Surface *surface;
Uint8 *bits;
+ SDL_bool save32bit = SDL_FALSE;
+ SDL_bool saveLegacyBMP = SDL_FALSE;
/* The Win32 BMP file header (14 bytes) */
char magic[2] = { 'B', 'M' };
@@ -478,14 +486,24 @@ SDL_SaveBMP_RW(SDL_Surface * saveme, SDL_RWops * dst, int freedst)
Uint32 biClrUsed;
Uint32 biClrImportant;
+ /* The additional header members from the Win32 BITMAPV4HEADER struct (108 bytes in total) */
+ Uint32 bV4RedMask = 0;
+ Uint32 bV4GreenMask = 0;
+ Uint32 bV4BlueMask = 0;
+ Uint32 bV4AlphaMask = 0;
+ Uint32 bV4CSType = 0;
+ Sint32 bV4Endpoints[3 * 3] = {0};
+ Uint32 bV4GammaRed = 0;
+ Uint32 bV4GammaGreen = 0;
+ Uint32 bV4GammaBlue = 0;
+
/* Make sure we have somewhere to save */
surface = NULL;
if (dst) {
- SDL_bool save32bit = SDL_FALSE;
#ifdef SAVE_32BIT_BMP
/* We can save alpha information in a 32-bit BMP */
- if (saveme->map->info.flags & SDL_COPY_COLORKEY ||
- saveme->format->Amask) {
+ if (saveme->format->BitsPerPixel >= 8 && (saveme->format->Amask ||
+ saveme->map->info.flags & SDL_COPY_COLORKEY)) {
save32bit = SDL_TRUE;
}
#endif /* SAVE_32BIT_BMP */
@@ -497,7 +515,7 @@ SDL_SaveBMP_RW(SDL_Surface * saveme, SDL_RWops * dst, int freedst)
SDL_SetError("%d bpp BMP files not supported",
saveme->format->BitsPerPixel);
}
- } else if ((saveme->format->BitsPerPixel == 24) &&
+ } else if ((saveme->format->BitsPerPixel == 24) && !save32bit &&
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
(saveme->format->Rmask == 0x00FF0000) &&
(saveme->format->Gmask == 0x0000FF00) &&
@@ -515,13 +533,7 @@ SDL_SaveBMP_RW(SDL_Surface * saveme, SDL_RWops * dst, int freedst)
/* If the surface has a colorkey or alpha channel we'll save a
32-bit BMP with alpha channel, otherwise save a 24-bit BMP. */
if (save32bit) {
- SDL_InitFormat(&format,
-#if SDL_BYTEORDER == SDL_LIL_ENDIAN
- SDL_PIXELFORMAT_ARGB8888
-#else
- SDL_PIXELFORMAT_BGRA8888
-#endif
- );
+ SDL_InitFormat(&format, SDL_PIXELFORMAT_BGRA32);
} else {
SDL_InitFormat(&format, SDL_PIXELFORMAT_BGR24);
}
@@ -537,6 +549,10 @@ SDL_SaveBMP_RW(SDL_Surface * saveme, SDL_RWops * dst, int freedst)
return -1;
}
+ if (save32bit) {
+ saveLegacyBMP = SDL_GetHintBoolean(SDL_HINT_BMP_SAVE_LEGACY_FORMAT, SDL_FALSE);
+ }
+
if (surface && (SDL_LockSurface(surface) == 0)) {
const int bw = surface->w * surface->format->BytesPerPixel;
@@ -572,6 +588,21 @@ SDL_SaveBMP_RW(SDL_Surface * saveme, SDL_RWops * dst, int freedst)
}
biClrImportant = 0;
+ /* Set the BMP info values for the version 4 header */
+ if (save32bit && !saveLegacyBMP) {
+ biSize = 108;
+ biCompression = BI_BITFIELDS;
+ /* The BMP format is always little endian, these masks stay the same */
+ bV4RedMask = 0x00ff0000;
+ bV4GreenMask = 0x0000ff00;
+ bV4BlueMask = 0x000000ff;
+ bV4AlphaMask = 0xff000000;
+ bV4CSType = LCS_WINDOWS_COLOR_SPACE;
+ bV4GammaRed = 0;
+ bV4GammaGreen = 0;
+ bV4GammaBlue = 0;
+ }
+
/* Write the BMP info values */
SDL_WriteLE32(dst, biSize);
SDL_WriteLE32(dst, biWidth);
@@ -585,6 +616,21 @@ SDL_SaveBMP_RW(SDL_Surface * saveme, SDL_RWops * dst, int freedst)
SDL_WriteLE32(dst, biClrUsed);
SDL_WriteLE32(dst, biClrImportant);
+ /* Write the BMP info values for the version 4 header */
+ if (save32bit && !saveLegacyBMP) {
+ SDL_WriteLE32(dst, bV4RedMask);
+ SDL_WriteLE32(dst, bV4GreenMask);
+ SDL_WriteLE32(dst, bV4BlueMask);
+ SDL_WriteLE32(dst, bV4AlphaMask);
+ SDL_WriteLE32(dst, bV4CSType);
+ for (i = 0; i < 3 * 3; i++) {
+ SDL_WriteLE32(dst, bV4Endpoints[i]);
+ }
+ SDL_WriteLE32(dst, bV4GammaRed);
+ SDL_WriteLE32(dst, bV4GammaGreen);
+ SDL_WriteLE32(dst, bV4GammaBlue);
+ }
+
/* Write the palette (in BGR color order) */
if (surface->format->palette) {
SDL_Color *colors;
diff --git a/Engine/lib/sdl/src/video/SDL_egl.c b/Engine/lib/sdl/src/video/SDL_egl.c
index bfd4affb9..c90380566 100644
--- a/Engine/lib/sdl/src/video/SDL_egl.c
+++ b/Engine/lib/sdl/src/video/SDL_egl.c
@@ -161,7 +161,7 @@ int
SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_display)
{
void *dll_handle = NULL, *egl_dll_handle = NULL; /* The naming is counter intuitive, but hey, I just work here -- Gabriel */
- char *path = NULL;
+ const char *path = NULL;
#if SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_WINRT
const char *d3dcompiler;
#endif
@@ -558,7 +558,8 @@ int
SDL_EGL_GetSwapInterval(_THIS)
{
if (!_this->egl_data) {
- return SDL_SetError("EGL not initialized");
+ SDL_SetError("EGL not initialized");
+ return 0;
}
return _this->egl_data->egl_swapinterval;
diff --git a/Engine/lib/sdl/src/video/SDL_surface.c b/Engine/lib/sdl/src/video/SDL_surface.c
index dae07f285..9d52e5ca4 100644
--- a/Engine/lib/sdl/src/video/SDL_surface.c
+++ b/Engine/lib/sdl/src/video/SDL_surface.c
@@ -27,27 +27,20 @@
#include "SDL_pixels_c.h"
/* Public routines */
+
/*
- * Create an empty RGB surface of the appropriate depth
+ * Create an empty RGB surface of the appropriate depth using the given
+ * enum SDL_PIXELFORMAT_* format
*/
SDL_Surface *
-SDL_CreateRGBSurface(Uint32 flags,
- int width, int height, int depth,
- Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
+SDL_CreateRGBSurfaceWithFormat(Uint32 flags, int width, int height, int depth,
+ Uint32 format)
{
SDL_Surface *surface;
- Uint32 format;
/* The flags are no longer used, make the compiler happy */
(void)flags;
- /* Get the pixel format */
- format = SDL_MasksToPixelFormatEnum(depth, Rmask, Gmask, Bmask, Amask);
- if (format == SDL_PIXELFORMAT_UNKNOWN) {
- SDL_SetError("Unknown pixel format");
- return NULL;
- }
-
/* Allocate the surface */
surface = (SDL_Surface *) SDL_calloc(1, sizeof(*surface));
if (surface == NULL) {
@@ -105,7 +98,7 @@ SDL_CreateRGBSurface(Uint32 flags,
}
/* By default surface with an alpha mask are set up for blending */
- if (Amask) {
+ if (surface->format->Amask) {
SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_BLEND);
}
@@ -114,6 +107,26 @@ SDL_CreateRGBSurface(Uint32 flags,
return surface;
}
+/*
+ * Create an empty RGB surface of the appropriate depth
+ */
+SDL_Surface *
+SDL_CreateRGBSurface(Uint32 flags,
+ int width, int height, int depth,
+ Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask)
+{
+ Uint32 format;
+
+ /* Get the pixel format */
+ format = SDL_MasksToPixelFormatEnum(depth, Rmask, Gmask, Bmask, Amask);
+ if (format == SDL_PIXELFORMAT_UNKNOWN) {
+ SDL_SetError("Unknown pixel format");
+ return NULL;
+ }
+
+ return SDL_CreateRGBSurfaceWithFormat(flags, width, height, depth, format);
+}
+
/*
* Create an RGB surface from an existing memory buffer
*/
@@ -125,8 +138,30 @@ SDL_CreateRGBSurfaceFrom(void *pixels,
{
SDL_Surface *surface;
- surface =
- SDL_CreateRGBSurface(0, 0, 0, depth, Rmask, Gmask, Bmask, Amask);
+ surface = SDL_CreateRGBSurface(0, 0, 0, depth, Rmask, Gmask, Bmask, Amask);
+ if (surface != NULL) {
+ surface->flags |= SDL_PREALLOC;
+ surface->pixels = pixels;
+ surface->w = width;
+ surface->h = height;
+ surface->pitch = pitch;
+ SDL_SetClipRect(surface, NULL);
+ }
+ return surface;
+}
+
+/*
+ * Create an RGB surface from an existing memory buffer using the given given
+ * enum SDL_PIXELFORMAT_* format
+ */
+SDL_Surface *
+SDL_CreateRGBSurfaceWithFormatFrom(void *pixels,
+ int width, int height, int depth, int pitch,
+ Uint32 format)
+{
+ SDL_Surface *surface;
+
+ surface = SDL_CreateRGBSurfaceWithFormat(0, 0, 0, depth, format);
if (surface != NULL) {
surface->flags |= SDL_PREALLOC;
surface->pixels = pixels;
diff --git a/Engine/lib/sdl/src/video/SDL_sysvideo.h b/Engine/lib/sdl/src/video/SDL_sysvideo.h
index 77426c3eb..cd2ed2a7e 100644
--- a/Engine/lib/sdl/src/video/SDL_sysvideo.h
+++ b/Engine/lib/sdl/src/video/SDL_sysvideo.h
@@ -86,6 +86,8 @@ struct SDL_Window
SDL_DisplayMode fullscreen_mode;
+ float opacity;
+
float brightness;
Uint16 *gamma;
Uint16 *saved_gamma; /* (just offset into gamma) */
@@ -95,6 +97,7 @@ struct SDL_Window
SDL_bool is_hiding;
SDL_bool is_destroying;
+ SDL_bool is_dropping; /* drag/drop in progress, expecting SDL_SendDropComplete(). */
SDL_WindowShaper *shaper;
@@ -175,6 +178,11 @@ struct SDL_VideoDevice
*/
int (*GetDisplayDPI) (_THIS, SDL_VideoDisplay * display, float * ddpi, float * hdpi, float * vdpi);
+ /*
+ * Get the usable bounds of a display (bounds minus menubar or whatever)
+ */
+ int (*GetDisplayUsableBounds) (_THIS, SDL_VideoDisplay * display, SDL_Rect * rect);
+
/*
* Get a list of the available display modes for a display.
*/
@@ -200,6 +208,10 @@ struct SDL_VideoDevice
void (*SetWindowSize) (_THIS, SDL_Window * window);
void (*SetWindowMinimumSize) (_THIS, SDL_Window * window);
void (*SetWindowMaximumSize) (_THIS, SDL_Window * window);
+ int (*GetWindowBordersSize) (_THIS, SDL_Window * window, int *top, int *left, int *bottom, int *right);
+ int (*SetWindowOpacity) (_THIS, SDL_Window * window, float opacity);
+ int (*SetWindowModalFor) (_THIS, SDL_Window * modal_window, SDL_Window * parent_window);
+ int (*SetWindowInputFocus) (_THIS, SDL_Window * window);
void (*ShowWindow) (_THIS, SDL_Window * window);
void (*HideWindow) (_THIS, SDL_Window * window);
void (*RaiseWindow) (_THIS, SDL_Window * window);
@@ -207,6 +219,7 @@ struct SDL_VideoDevice
void (*MinimizeWindow) (_THIS, SDL_Window * window);
void (*RestoreWindow) (_THIS, SDL_Window * window);
void (*SetWindowBordered) (_THIS, SDL_Window * window, SDL_bool bordered);
+ void (*SetWindowResizable) (_THIS, SDL_Window * window, SDL_bool resizable);
void (*SetWindowFullscreen) (_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
int (*SetWindowGammaRamp) (_THIS, SDL_Window * window, const Uint16 * ramp);
int (*GetWindowGammaRamp) (_THIS, SDL_Window * window, Uint16 * ramp);
diff --git a/Engine/lib/sdl/src/video/SDL_video.c b/Engine/lib/sdl/src/video/SDL_video.c
index 511b4c087..0a21ef5fc 100644
--- a/Engine/lib/sdl/src/video/SDL_video.c
+++ b/Engine/lib/sdl/src/video/SDL_video.c
@@ -55,6 +55,10 @@
#undef CreateWindow
#endif
+#ifdef __EMSCRIPTEN__
+#include
+#endif
+
/* Available video drivers */
static VideoBootStrap *bootstrap[] = {
#if SDL_VIDEO_DRIVER_COCOA
@@ -177,7 +181,7 @@ ShouldUseTextureFramebuffer()
/* See if the user or application wants a specific behavior */
hint = SDL_GetHint(SDL_HINT_FRAMEBUFFER_ACCELERATION);
if (hint) {
- if (*hint == '0') {
+ if (*hint == '0' || SDL_strcasecmp(hint, "false") == 0) {
return SDL_FALSE;
} else {
return SDL_TRUE;
@@ -254,6 +258,8 @@ SDL_CreateWindowTexture(SDL_VideoDevice *unused, SDL_Window * window, Uint32 * f
/* Check to see if there's a specific driver requested */
if (hint && *hint != '0' && *hint != '1' &&
+ SDL_strcasecmp(hint, "true") != 0 &&
+ SDL_strcasecmp(hint, "false") != 0 &&
SDL_strcasecmp(hint, "software") != 0) {
for (i = 0; i < SDL_GetNumRenderDrivers(); ++i) {
SDL_RendererInfo info;
@@ -443,10 +449,8 @@ int
SDL_VideoInit(const char *driver_name)
{
SDL_VideoDevice *video;
- const char *hint;
int index;
int i;
- SDL_bool allow_screensaver;
/* Check to make sure we don't overwrite '_this' */
if (_this != NULL) {
@@ -534,13 +538,7 @@ SDL_VideoInit(const char *driver_name)
joystick, or passively watching a movie. Things that use SDL but
function more like a normal desktop app should explicitly reenable the
screensaver. */
- hint = SDL_GetHint(SDL_HINT_VIDEO_ALLOW_SCREENSAVER);
- if (hint) {
- allow_screensaver = SDL_atoi(hint) ? SDL_TRUE : SDL_FALSE;
- } else {
- allow_screensaver = SDL_FALSE;
- }
- if (!allow_screensaver) {
+ if (!SDL_GetHintBoolean(SDL_HINT_VIDEO_ALLOW_SCREENSAVER, SDL_FALSE)) {
SDL_DisableScreenSaver();
}
@@ -684,7 +682,26 @@ SDL_GetDisplayBounds(int displayIndex, SDL_Rect * rect)
rect->w = display->current_mode.w;
rect->h = display->current_mode.h;
}
- return 0;
+ return 0; /* !!! FIXME: should this be an error if (rect==NULL) ? */
+}
+
+int SDL_GetDisplayUsableBounds(int displayIndex, SDL_Rect * rect)
+{
+ CHECK_DISPLAY_INDEX(displayIndex, -1);
+
+ if (rect) {
+ SDL_VideoDisplay *display = &_this->displays[displayIndex];
+
+ if (_this->GetDisplayUsableBounds) {
+ if (_this->GetDisplayUsableBounds(_this, display, rect) == 0) {
+ return 0;
+ }
+ }
+
+ /* Oh well, just give the entire display bounds. */
+ return SDL_GetDisplayBounds(displayIndex, rect);
+ }
+ return 0; /* !!! FIXME: should this be an error if (rect==NULL) ? */
}
int
@@ -700,7 +717,9 @@ SDL_GetDisplayDPI(int displayIndex, float * ddpi, float * hdpi, float * vdpi)
if (_this->GetDisplayDPI(_this, display, ddpi, hdpi, vdpi) == 0) {
return 0;
}
- }
+ } else {
+ return SDL_Unsupported();
+ }
return -1;
}
@@ -1285,16 +1304,11 @@ SDL_UpdateFullscreenMode(SDL_Window * window, SDL_bool fullscreen)
}
#define CREATE_FLAGS \
- (SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI)
+ (SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_ALWAYS_ON_TOP | SDL_WINDOW_SKIP_TASKBAR | SDL_WINDOW_POPUP_MENU | SDL_WINDOW_UTILITY | SDL_WINDOW_TOOLTIP)
static void
SDL_FinishWindowCreation(SDL_Window *window, Uint32 flags)
{
- window->windowed.x = window->x;
- window->windowed.y = window->y;
- window->windowed.w = window->w;
- window->windowed.h = window->h;
-
if (flags & SDL_WINDOW_MAXIMIZED) {
SDL_MaximizeWindow(window);
}
@@ -1316,7 +1330,6 @@ SDL_Window *
SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags)
{
SDL_Window *window;
- const char *hint;
if (!_this) {
/* Initialize the video system if needed */
@@ -1325,6 +1338,11 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags)
}
}
+ if ( (((flags & SDL_WINDOW_UTILITY) != 0) + ((flags & SDL_WINDOW_TOOLTIP) != 0) + ((flags & SDL_WINDOW_POPUP_MENU) != 0)) > 1 ) {
+ SDL_SetError("Conflicting window flags specified");
+ return NULL;
+ }
+
/* Some platforms can't create zero-sized windows */
if (w < 1) {
w = 1;
@@ -1341,7 +1359,9 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags)
/* Some platforms have OpenGL enabled by default */
#if (SDL_VIDEO_OPENGL && __MACOSX__) || __IPHONEOS__ || __ANDROID__ || __NACL__
- flags |= SDL_WINDOW_OPENGL;
+ if (SDL_strcmp(_this->name, "dummy") != 0) {
+ flags |= SDL_WINDOW_OPENGL;
+ }
#endif
if (flags & SDL_WINDOW_OPENGL) {
if (!_this->GL_CreateContext) {
@@ -1357,8 +1377,7 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags)
* SDL_WINDOW_ALLOW_HIGHDPI flag.
*/
if (flags & SDL_WINDOW_ALLOW_HIGHDPI) {
- hint = SDL_GetHint(SDL_HINT_VIDEO_HIGHDPI_DISABLED);
- if (hint && SDL_atoi(hint) > 0) {
+ if (SDL_GetHintBoolean(SDL_HINT_VIDEO_HIGHDPI_DISABLED, SDL_FALSE)) {
flags &= ~SDL_WINDOW_ALLOW_HIGHDPI;
}
}
@@ -1389,8 +1408,28 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags)
window->y = bounds.y + (bounds.h - h) / 2;
}
}
+ window->windowed.x = window->x;
+ window->windowed.y = window->y;
+ window->windowed.w = window->w;
+ window->windowed.h = window->h;
+
+ if (flags & SDL_WINDOW_FULLSCREEN) {
+ SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
+ int displayIndex;
+ SDL_Rect bounds;
+
+ displayIndex = SDL_GetIndexOfDisplay(display);
+ SDL_GetDisplayBounds(displayIndex, &bounds);
+
+ window->x = bounds.x;
+ window->y = bounds.y;
+ window->w = bounds.w;
+ window->h = bounds.h;
+ }
+
window->flags = ((flags & CREATE_FLAGS) | SDL_WINDOW_HIDDEN);
window->last_fullscreen_flags = window->flags;
+ window->opacity = 1.0f;
window->brightness = 1.0f;
window->next = _this->windows;
window->is_destroying = SDL_FALSE;
@@ -1451,6 +1490,7 @@ SDL_CreateWindowFrom(const void *data)
window->flags = SDL_WINDOW_FOREIGN;
window->last_fullscreen_flags = window->flags;
window->is_destroying = SDL_FALSE;
+ window->opacity = 1.0f;
window->brightness = 1.0f;
window->next = _this->windows;
if (_this->windows) {
@@ -1795,6 +1835,24 @@ SDL_SetWindowBordered(SDL_Window * window, SDL_bool bordered)
}
}
+void
+SDL_SetWindowResizable(SDL_Window * window, SDL_bool resizable)
+{
+ CHECK_WINDOW_MAGIC(window,);
+ if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
+ const int want = (resizable != SDL_FALSE); /* normalize the flag. */
+ const int have = ((window->flags & SDL_WINDOW_RESIZABLE) != 0);
+ if ((want != have) && (_this->SetWindowResizable)) {
+ if (want) {
+ window->flags |= SDL_WINDOW_RESIZABLE;
+ } else {
+ window->flags &= ~SDL_WINDOW_RESIZABLE;
+ }
+ _this->SetWindowResizable(_this, window, (SDL_bool) want);
+ }
+ }
+}
+
void
SDL_SetWindowSize(SDL_Window * window, int w, int h)
{
@@ -1883,6 +1941,28 @@ SDL_SetWindowMinimumSize(SDL_Window * window, int min_w, int min_h)
}
}
+int
+SDL_GetWindowBordersSize(SDL_Window * window, int *top, int *left, int *bottom, int *right)
+{
+ int dummy = 0;
+
+ if (!top) { top = &dummy; }
+ if (!left) { left = &dummy; }
+ if (!right) { right = &dummy; }
+ if (!bottom) { bottom = &dummy; }
+
+ /* Always initialize, so applications don't have to care */
+ *top = *left = *bottom = *right = 0;
+
+ CHECK_WINDOW_MAGIC(window, -1);
+
+ if (!_this->GetWindowBordersSize) {
+ return SDL_Unsupported();
+ }
+
+ return _this->GetWindowBordersSize(_this, window, top, left, bottom, right);
+}
+
void
SDL_GetWindowMinimumSize(SDL_Window * window, int *min_w, int *min_h)
{
@@ -2144,6 +2224,68 @@ SDL_GetWindowBrightness(SDL_Window * window)
return window->brightness;
}
+int
+SDL_SetWindowOpacity(SDL_Window * window, float opacity)
+{
+ int retval;
+ CHECK_WINDOW_MAGIC(window, -1);
+
+ if (!_this->SetWindowOpacity) {
+ return SDL_Unsupported();
+ }
+
+ if (opacity < 0.0f) {
+ opacity = 0.0f;
+ } else if (opacity > 1.0f) {
+ opacity = 1.0f;
+ }
+
+ retval = _this->SetWindowOpacity(_this, window, opacity);
+ if (retval == 0) {
+ window->opacity = opacity;
+ }
+
+ return retval;
+}
+
+int
+SDL_GetWindowOpacity(SDL_Window * window, float * out_opacity)
+{
+ CHECK_WINDOW_MAGIC(window, -1);
+
+ if (out_opacity) {
+ *out_opacity = window->opacity;
+ }
+
+ return 0;
+}
+
+int
+SDL_SetWindowModalFor(SDL_Window * modal_window, SDL_Window * parent_window)
+{
+ CHECK_WINDOW_MAGIC(modal_window, -1);
+ CHECK_WINDOW_MAGIC(parent_window, -1);
+
+ if (!_this->SetWindowModalFor) {
+ return SDL_Unsupported();
+ }
+
+ return _this->SetWindowModalFor(_this, modal_window, parent_window);
+}
+
+int
+SDL_SetWindowInputFocus(SDL_Window * window)
+{
+ CHECK_WINDOW_MAGIC(window, -1);
+
+ if (!_this->SetWindowInputFocus) {
+ return SDL_Unsupported();
+ }
+
+ return _this->SetWindowInputFocus(_this, window);
+}
+
+
int
SDL_SetWindowGammaRamp(SDL_Window * window, const Uint16 * red,
const Uint16 * green,
@@ -2359,8 +2501,6 @@ SDL_OnWindowFocusGained(SDL_Window * window)
static SDL_bool
ShouldMinimizeOnFocusLoss(SDL_Window * window)
{
- const char *hint;
-
if (!(window->flags & SDL_WINDOW_FULLSCREEN) || window->is_destroying) {
return SDL_FALSE;
}
@@ -2371,16 +2511,7 @@ ShouldMinimizeOnFocusLoss(SDL_Window * window)
}
#endif
- hint = SDL_GetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS);
- if (hint) {
- if (*hint == '0') {
- return SDL_FALSE;
- } else {
- return SDL_TRUE;
- }
- }
-
- return SDL_TRUE;
+ return SDL_GetHintBoolean(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, SDL_TRUE);
}
void
@@ -3596,6 +3727,16 @@ SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
int
SDL_ShowSimpleMessageBox(Uint32 flags, const char *title, const char *message, SDL_Window *window)
{
+#ifdef __EMSCRIPTEN__
+ /* !!! FIXME: propose a browser API for this, get this #ifdef out of here? */
+ /* Web browsers don't (currently) have an API for a custom message box
+ that can block, but for the most common case (SDL_ShowSimpleMessageBox),
+ we can use the standard Javascript alert() function. */
+ EM_ASM_({
+ alert(UTF8ToString($0) + "\n\n" + UTF8ToString($1));
+ }, title, message);
+ return 0;
+#else
SDL_MessageBoxData data;
SDL_MessageBoxButtonData button;
@@ -3613,20 +3754,13 @@ SDL_ShowSimpleMessageBox(Uint32 flags, const char *title, const char *message, S
button.text = "OK";
return SDL_ShowMessageBox(&data, NULL);
+#endif
}
SDL_bool
SDL_ShouldAllowTopmost(void)
{
- const char *hint = SDL_GetHint(SDL_HINT_ALLOW_TOPMOST);
- if (hint) {
- if (*hint == '0') {
- return SDL_FALSE;
- } else {
- return SDL_TRUE;
- }
- }
- return SDL_TRUE;
+ return SDL_GetHintBoolean(SDL_HINT_ALLOW_TOPMOST, SDL_TRUE);
}
int
diff --git a/Engine/lib/sdl/src/video/android/SDL_androidevents.c b/Engine/lib/sdl/src/video/android/SDL_androidevents.c
index 326361af0..c3cd4cc1b 100644
--- a/Engine/lib/sdl/src/video/android/SDL_androidevents.c
+++ b/Engine/lib/sdl/src/video/android/SDL_androidevents.c
@@ -34,11 +34,11 @@ void android_egl_context_backup();
void android_egl_context_restore();
#if SDL_AUDIO_DRIVER_ANDROID
-void AndroidAUD_ResumeDevices(void);
-void AndroidAUD_PauseDevices(void);
+void ANDROIDAUDIO_ResumeDevices(void);
+void ANDROIDAUDIO_PauseDevices(void);
#else
-static void AndroidAUD_ResumeDevices(void) {}
-static void AndroidAUD_PauseDevices(void) {}
+static void ANDROIDAUDIO_ResumeDevices(void) {}
+static void ANDROIDAUDIO_PauseDevices(void) {}
#endif
void
@@ -83,14 +83,14 @@ Android_PumpEvents(_THIS)
if (isPaused && !isPausing) {
/* Make sure this is the last thing we do before pausing */
android_egl_context_backup();
- AndroidAUD_PauseDevices();
+ ANDROIDAUDIO_PauseDevices();
if(SDL_SemWait(Android_ResumeSem) == 0) {
#else
if (isPaused) {
if(SDL_SemTryWait(Android_ResumeSem) == 0) {
#endif
isPaused = 0;
- AndroidAUD_ResumeDevices();
+ ANDROIDAUDIO_ResumeDevices();
/* Restore the GL Context from here, as this operation is thread dependent */
if (!SDL_HasEvent(SDL_QUIT)) {
android_egl_context_restore();
@@ -113,7 +113,7 @@ Android_PumpEvents(_THIS)
#else
if(SDL_SemTryWait(Android_PauseSem) == 0) {
android_egl_context_backup();
- AndroidAUD_PauseDevices();
+ ANDROIDAUDIO_PauseDevices();
isPaused = 1;
}
#endif
diff --git a/Engine/lib/sdl/src/video/android/SDL_androidkeyboard.c b/Engine/lib/sdl/src/video/android/SDL_androidkeyboard.c
index dc8951ff9..652e0cca7 100644
--- a/Engine/lib/sdl/src/video/android/SDL_androidkeyboard.c
+++ b/Engine/lib/sdl/src/video/android/SDL_androidkeyboard.c
@@ -304,18 +304,22 @@ static SDL_Scancode Android_Keycodes[] = {
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_NAVIGATE_NEXT */
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_NAVIGATE_IN */
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_NAVIGATE_OUT */
- SDL_SCANCODE_UNKNOWN,
- SDL_SCANCODE_UNKNOWN,
- SDL_SCANCODE_UNKNOWN,
- SDL_SCANCODE_UNKNOWN,
- SDL_SCANCODE_UNKNOWN,
- SDL_SCANCODE_UNKNOWN,
- SDL_SCANCODE_UNKNOWN,
- SDL_SCANCODE_UNKNOWN,
+ SDL_SCANCODE_UNKNOWN, /* AKEYCODE_STEM_PRIMARY */
+ SDL_SCANCODE_UNKNOWN, /* AKEYCODE_STEM_1 */
+ SDL_SCANCODE_UNKNOWN, /* AKEYCODE_STEM_2 */
+ SDL_SCANCODE_UNKNOWN, /* AKEYCODE_STEM_3 */
+ SDL_SCANCODE_UNKNOWN, /* AKEYCODE_DPAD_UP_LEFT */
+ SDL_SCANCODE_UNKNOWN, /* AKEYCODE_DPAD_DOWN_LEFT */
+ SDL_SCANCODE_UNKNOWN, /* AKEYCODE_DPAD_UP_RIGHT */
+ SDL_SCANCODE_UNKNOWN, /* AKEYCODE_DPAD_DOWN_RIGHT */
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_MEDIA_SKIP_FORWARD */
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_MEDIA_SKIP_BACKWARD */
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_MEDIA_STEP_FORWARD */
SDL_SCANCODE_UNKNOWN, /* AKEYCODE_MEDIA_STEP_BACKWARD */
+ SDL_SCANCODE_UNKNOWN, /* AKEYCODE_SOFT_SLEEP */
+ SDL_SCANCODE_CUT, /* AKEYCODE_CUT */
+ SDL_SCANCODE_COPY, /* AKEYCODE_COPY */
+ SDL_SCANCODE_PASTE, /* AKEYCODE_PASTE */
};
static SDL_Scancode
diff --git a/Engine/lib/sdl/src/video/android/SDL_androidmouse.c b/Engine/lib/sdl/src/video/android/SDL_androidmouse.c
index 3e9c0aff5..883fa8d22 100644
--- a/Engine/lib/sdl/src/video/android/SDL_androidmouse.c
+++ b/Engine/lib/sdl/src/video/android/SDL_androidmouse.c
@@ -32,15 +32,24 @@
#define ACTION_DOWN 0
#define ACTION_UP 1
+#define ACTION_MOVE 2
#define ACTION_HOVER_MOVE 7
#define ACTION_SCROLL 8
#define BUTTON_PRIMARY 1
#define BUTTON_SECONDARY 2
#define BUTTON_TERTIARY 4
+#define BUTTON_BACK 8
+#define BUTTON_FORWARD 16
+
+static Uint8 SDLButton;
+
+void
+Android_InitMouse(void)
+{
+ SDLButton = 0;
+}
void Android_OnMouse( int androidButton, int action, float x, float y) {
- static Uint8 SDLButton;
-
if (!Android_Window) {
return;
}
@@ -53,6 +62,10 @@ void Android_OnMouse( int androidButton, int action, float x, float y) {
SDLButton = SDL_BUTTON_RIGHT;
} else if (androidButton == BUTTON_TERTIARY) {
SDLButton = SDL_BUTTON_MIDDLE;
+ } else if (androidButton == BUTTON_FORWARD) {
+ SDLButton = SDL_BUTTON_X1;
+ } else if (androidButton == BUTTON_BACK) {
+ SDLButton = SDL_BUTTON_X2;
}
SDL_SendMouseMotion(Android_Window, 0, 0, x, y);
SDL_SendMouseButton(Android_Window, 0, SDL_PRESSED, SDLButton);
@@ -65,6 +78,7 @@ void Android_OnMouse( int androidButton, int action, float x, float y) {
SDL_SendMouseButton(Android_Window, 0, SDL_RELEASED, SDLButton);
break;
+ case ACTION_MOVE:
case ACTION_HOVER_MOVE:
SDL_SendMouseMotion(Android_Window, 0, 0, x, y);
break;
diff --git a/Engine/lib/sdl/src/video/android/SDL_androidmouse.h b/Engine/lib/sdl/src/video/android/SDL_androidmouse.h
index 9b68eed57..a64e06d51 100644
--- a/Engine/lib/sdl/src/video/android/SDL_androidmouse.h
+++ b/Engine/lib/sdl/src/video/android/SDL_androidmouse.h
@@ -24,6 +24,7 @@
#include "SDL_androidvideo.h"
+extern void Android_InitMouse(void);
extern void Android_OnMouse( int button, int action, float x, float y);
#endif /* _SDL_androidmouse_h */
diff --git a/Engine/lib/sdl/src/video/android/SDL_androidtouch.c b/Engine/lib/sdl/src/video/android/SDL_androidtouch.c
index a6e0b896a..0ff11ef57 100644
--- a/Engine/lib/sdl/src/video/android/SDL_androidtouch.c
+++ b/Engine/lib/sdl/src/video/android/SDL_androidtouch.c
@@ -50,7 +50,7 @@ static void Android_GetWindowCoordinates(float x, float y,
*window_y = (int)(y * window_h);
}
-static volatile SDL_bool separate_mouse_and_touch = SDL_FALSE;
+static SDL_bool separate_mouse_and_touch = SDL_FALSE;
static void
SeparateEventsHintWatcher(void *userdata, const char *name,
diff --git a/Engine/lib/sdl/src/video/android/SDL_androidvideo.c b/Engine/lib/sdl/src/video/android/SDL_androidvideo.c
index e14b96641..178a3e691 100644
--- a/Engine/lib/sdl/src/video/android/SDL_androidvideo.c
+++ b/Engine/lib/sdl/src/video/android/SDL_androidvideo.c
@@ -36,6 +36,7 @@
#include "SDL_androidclipboard.h"
#include "SDL_androidevents.h"
#include "SDL_androidkeyboard.h"
+#include "SDL_androidmouse.h"
#include "SDL_androidtouch.h"
#include "SDL_androidwindow.h"
@@ -181,6 +182,8 @@ Android_VideoInit(_THIS)
Android_InitTouch();
+ Android_InitMouse();
+
/* We're done! */
return 0;
}
@@ -191,7 +194,6 @@ Android_VideoQuit(_THIS)
Android_QuitTouch();
}
-/* This function gets called before VideoInit() */
void
Android_SetScreenResolution(int width, int height, Uint32 format, float rate)
{
@@ -200,8 +202,33 @@ Android_SetScreenResolution(int width, int height, Uint32 format, float rate)
Android_ScreenFormat = format;
Android_ScreenRate = rate;
+ /*
+ Update the resolution of the desktop mode, so that the window
+ can be properly resized. The screen resolution change can for
+ example happen when the Activity enters or exists immersive mode,
+ which can happen after VideoInit().
+ */
+ SDL_VideoDevice* device = SDL_GetVideoDevice();
+ if (device && device->num_displays > 0)
+ {
+ SDL_VideoDisplay* display = &device->displays[0];
+ display->desktop_mode.format = Android_ScreenFormat;
+ display->desktop_mode.w = Android_ScreenWidth;
+ display->desktop_mode.h = Android_ScreenHeight;
+ display->desktop_mode.refresh_rate = Android_ScreenRate;
+ }
+
if (Android_Window) {
SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_RESIZED, width, height);
+
+ /* Force the current mode to match the resize otherwise the SDL_WINDOWEVENT_RESTORED event
+ * will fall back to the old mode */
+ SDL_VideoDisplay *display = SDL_GetDisplayForWindow(Android_Window);
+
+ display->current_mode.format = format;
+ display->current_mode.w = width;
+ display->current_mode.h = height;
+ display->current_mode.refresh_rate = rate;
}
}
diff --git a/Engine/lib/sdl/src/video/cocoa/SDL_cocoaclipboard.m b/Engine/lib/sdl/src/video/cocoa/SDL_cocoaclipboard.m
index 015d77106..fd8680925 100644
--- a/Engine/lib/sdl/src/video/cocoa/SDL_cocoaclipboard.m
+++ b/Engine/lib/sdl/src/video/cocoa/SDL_cocoaclipboard.m
@@ -25,23 +25,13 @@
#include "SDL_cocoavideo.h"
#include "../../events/SDL_clipboardevents_c.h"
-static NSString *
-GetTextFormat(_THIS)
-{
- if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_5) {
- return NSPasteboardTypeString;
- } else {
- return NSStringPboardType;
- }
-}
-
int
Cocoa_SetClipboardText(_THIS, const char *text)
{ @autoreleasepool
{
SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
NSPasteboard *pasteboard;
- NSString *format = GetTextFormat(_this);
+ NSString *format = NSPasteboardTypeString;
pasteboard = [NSPasteboard generalPasteboard];
data->clipboard_count = [pasteboard declareTypes:[NSArray arrayWithObject:format] owner:nil];
@@ -55,12 +45,12 @@ Cocoa_GetClipboardText(_THIS)
{ @autoreleasepool
{
NSPasteboard *pasteboard;
- NSString *format = GetTextFormat(_this);
+ NSString *format = NSPasteboardTypeString;
NSString *available;
char *text;
pasteboard = [NSPasteboard generalPasteboard];
- available = [pasteboard availableTypeFromArray: [NSArray arrayWithObject:format]];
+ available = [pasteboard availableTypeFromArray:[NSArray arrayWithObject:format]];
if ([available isEqualToString:format]) {
NSString* string;
const char *utf8;
diff --git a/Engine/lib/sdl/src/video/cocoa/SDL_cocoaevents.m b/Engine/lib/sdl/src/video/cocoa/SDL_cocoaevents.m
index e0da11fd4..17a3183b7 100644
--- a/Engine/lib/sdl/src/video/cocoa/SDL_cocoaevents.m
+++ b/Engine/lib/sdl/src/video/cocoa/SDL_cocoaevents.m
@@ -36,6 +36,7 @@
@interface SDLApplication : NSApplication
- (void)terminate:(id)sender;
+- (void)sendEvent:(NSEvent *)theEvent;
@end
@@ -47,6 +48,48 @@
SDL_SendQuit();
}
+static SDL_bool s_bShouldHandleEventsInSDLApplication = SDL_FALSE;
+
+static void Cocoa_DispatchEvent(NSEvent *theEvent)
+{
+ SDL_VideoDevice *_this = SDL_GetVideoDevice();
+
+ switch ([theEvent type]) {
+ case NSLeftMouseDown:
+ case NSOtherMouseDown:
+ case NSRightMouseDown:
+ case NSLeftMouseUp:
+ case NSOtherMouseUp:
+ case NSRightMouseUp:
+ case NSLeftMouseDragged:
+ case NSRightMouseDragged:
+ case NSOtherMouseDragged: /* usually middle mouse dragged */
+ case NSMouseMoved:
+ case NSScrollWheel:
+ Cocoa_HandleMouseEvent(_this, theEvent);
+ break;
+ case NSKeyDown:
+ case NSKeyUp:
+ case NSFlagsChanged:
+ Cocoa_HandleKeyEvent(_this, theEvent);
+ break;
+ default:
+ break;
+ }
+}
+
+// Dispatch events here so that we can handle events caught by
+// nextEventMatchingMask in SDL, as well as events caught by other
+// processes (such as CEF) that are passed down to NSApp.
+- (void)sendEvent:(NSEvent *)theEvent
+{
+ if (s_bShouldHandleEventsInSDLApplication) {
+ Cocoa_DispatchEvent(theEvent);
+ }
+
+ [super sendEvent:theEvent];
+}
+
@end // SDLApplication
/* setAppleMenu disappeared from the headers in 10.4 */
@@ -114,28 +157,23 @@
*/
for (NSWindow *window in [NSApp orderedWindows]) {
if (window != win && [window canBecomeKeyWindow]) {
- if ([window respondsToSelector:@selector(isOnActiveSpace)]) {
- if (![window isOnActiveSpace]) {
- continue;
- }
+ if (![window isOnActiveSpace]) {
+ continue;
}
[window makeKeyAndOrderFront:self];
return;
}
}
- /* If a window wasn't found above, iterate through all visible windows
- * (including the 'About' window, if it's shown) and make the first one key.
- * Note that +[NSWindow windowNumbersWithOptions:] was added in 10.6.
+ /* If a window wasn't found above, iterate through all visible windows in
+ * the active Space in z-order (including the 'About' window, if it's shown)
+ * and make the first one key.
*/
- if ([NSWindow respondsToSelector:@selector(windowNumbersWithOptions:)]) {
- /* Get all visible windows in the active Space, in z-order. */
- for (NSNumber *num in [NSWindow windowNumbersWithOptions:0]) {
- NSWindow *window = [NSApp windowWithWindowNumber:[num integerValue]];
- if (window && window != win && [window canBecomeKeyWindow]) {
- [window makeKeyAndOrderFront:self];
- return;
- }
+ for (NSNumber *num in [NSWindow windowNumbersWithOptions:0]) {
+ NSWindow *window = [NSApp windowWithWindowNumber:[num integerValue]];
+ if (window && window != win && [window canBecomeKeyWindow]) {
+ [window makeKeyAndOrderFront:self];
+ return;
}
}
}
@@ -176,7 +214,7 @@
- (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
{
- return (BOOL)SDL_SendDropFile([filename UTF8String]);
+ return (BOOL)SDL_SendDropFile(NULL, [filename UTF8String]) && SDL_SendDropComplete(NULL);
}
@end
@@ -291,7 +329,7 @@ CreateApplicationMenus(void)
/* Add the fullscreen view toggle menu option, if supported */
- if ([NSApp respondsToSelector:@selector(setPresentationOptions:)]) {
+ if (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6) {
/* Create the view menu */
viewMenu = [[NSMenu alloc] initWithTitle:@"View"];
@@ -319,18 +357,10 @@ Cocoa_RegisterApp(void)
[SDLApplication sharedApplication];
SDL_assert(NSApp != nil);
- const char *hint = SDL_GetHint(SDL_HINT_MAC_BACKGROUND_APP);
- if (!hint || *hint == '0') {
-#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6
- if ([NSApp respondsToSelector:@selector(setActivationPolicy:)]) {
-#endif
- [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
-#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_6
- } else {
- ProcessSerialNumber psn = {0, kCurrentProcess};
- TransformProcessType(&psn, kProcessTransformToForegroundApplication);
- }
-#endif
+ s_bShouldHandleEventsInSDLApplication = SDL_TRUE;
+
+ if (!SDL_GetHintBoolean(SDL_HINT_MAC_BACKGROUND_APP, SDL_FALSE)) {
+ [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
[NSApp activateIgnoringOtherApps:YES];
}
@@ -381,29 +411,11 @@ Cocoa_PumpEvents(_THIS)
break;
}
- switch ([event type]) {
- case NSLeftMouseDown:
- case NSOtherMouseDown:
- case NSRightMouseDown:
- case NSLeftMouseUp:
- case NSOtherMouseUp:
- case NSRightMouseUp:
- case NSLeftMouseDragged:
- case NSRightMouseDragged:
- case NSOtherMouseDragged: /* usually middle mouse dragged */
- case NSMouseMoved:
- case NSScrollWheel:
- Cocoa_HandleMouseEvent(_this, event);
- break;
- case NSKeyDown:
- case NSKeyUp:
- case NSFlagsChanged:
- Cocoa_HandleKeyEvent(_this, event);
- break;
- default:
- break;
+ if (!s_bShouldHandleEventsInSDLApplication) {
+ Cocoa_DispatchEvent(event);
}
- /* Pass through to NSApp to make sure everything stays in sync */
+
+ // Pass events down to SDLApplication to be handled in sendEvent:
[NSApp sendEvent:event];
}
}}
diff --git a/Engine/lib/sdl/src/video/cocoa/SDL_cocoakeyboard.m b/Engine/lib/sdl/src/video/cocoa/SDL_cocoakeyboard.m
index 7f1d2308f..8b2ed91c2 100644
--- a/Engine/lib/sdl/src/video/cocoa/SDL_cocoakeyboard.m
+++ b/Engine/lib/sdl/src/video/cocoa/SDL_cocoakeyboard.m
@@ -29,6 +29,7 @@
#include "../../events/scancodes_darwin.h"
#include
+#include
/*#define DEBUG_IME NSLog */
#define DEBUG_IME(...)
@@ -69,14 +70,6 @@
SDL_SendKeyboardText(str);
}
-- (void)insertText:(id)insertString
-{
- /* This method is part of NSTextInput and not NSTextInputClient, but
- * apparently it still might be called in OS X 10.5 and can cause beeps if
- * the implementation is missing: http://crbug.com/47890 */
- [self insertText:insertString replacementRange:NSMakeRange(0, 0)];
-}
-
- (void)doCommandBySelector:(SEL)myselector
{
/* No need to do anything since we are not using Cocoa
@@ -102,7 +95,7 @@
- (void)setMarkedText:(id)aString selectedRange:(NSRange)selectedRange replacementRange:(NSRange)replacementRange;
{
- if ([aString isKindOfClass: [NSAttributedString class]]) {
+ if ([aString isKindOfClass:[NSAttributedString class]]) {
aString = [aString string];
}
@@ -120,7 +113,7 @@
_markedRange = NSMakeRange(0, [aString length]);
SDL_SendEditingText([aString UTF8String],
- selectedRange.location, selectedRange.length);
+ (int) selectedRange.location, (int) selectedRange.length);
DEBUG_IME(@"setMarkedText: %@, (%d, %d)", _markedText,
selRange.location, selRange.length);
@@ -150,10 +143,10 @@
aRange.location, aRange.length, windowHeight,
NSStringFromRect(rect));
- if ([[self window] respondsToSelector:@selector(convertRectToScreen:)]) {
- rect = [[self window] convertRectToScreen:rect];
+ if ([window respondsToSelector:@selector(convertRectToScreen:)]) {
+ rect = [window convertRectToScreen:rect];
} else {
- rect.origin = [[self window] convertBaseToScreen:rect.origin];
+ rect.origin = [window convertBaseToScreen:rect.origin];
}
return rect;
@@ -191,6 +184,116 @@
@end
+/*------------------------------------------------------------------------------
+Set up a HID callback to properly detect Caps Lock up/down events.
+Derived from:
+http://stackoverflow.com/questions/7190852/using-iohidmanager-to-get-modifier-key-events
+*/
+
+static IOHIDManagerRef s_hidManager = NULL;
+
+static void
+HIDCallback(void *context, IOReturn result, void *sender, IOHIDValueRef value)
+{
+ if (context != s_hidManager) {
+ /* An old callback, ignore it (related to bug 2157 below) */
+ return;
+ }
+
+ IOHIDElementRef elem = IOHIDValueGetElement(value);
+ if (IOHIDElementGetUsagePage(elem) != kHIDPage_KeyboardOrKeypad
+ || IOHIDElementGetUsage(elem) != kHIDUsage_KeyboardCapsLock) {
+ return;
+ }
+ CFIndex pressed = IOHIDValueGetIntegerValue(value);
+ SDL_SendKeyboardKey(pressed ? SDL_PRESSED : SDL_RELEASED, SDL_SCANCODE_CAPSLOCK);
+}
+
+static CFDictionaryRef
+CreateHIDDeviceMatchingDictionary(UInt32 usagePage, UInt32 usage)
+{
+ CFMutableDictionaryRef dict = CFDictionaryCreateMutable(kCFAllocatorDefault,
+ 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+ if (dict) {
+ CFNumberRef number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usagePage);
+ if (number) {
+ CFDictionarySetValue(dict, CFSTR(kIOHIDDeviceUsagePageKey), number);
+ CFRelease(number);
+ number = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage);
+ if (number) {
+ CFDictionarySetValue(dict, CFSTR(kIOHIDDeviceUsageKey), number);
+ CFRelease(number);
+ return dict;
+ }
+ }
+ CFRelease(dict);
+ }
+ return NULL;
+}
+
+static void
+QuitHIDCallback()
+{
+ if (!s_hidManager) {
+ return;
+ }
+
+#if 0 /* Releasing here causes a crash on Mac OS X 10.10 and earlier,
+ * so just leak it for now. See bug 2157 for details.
+ */
+ IOHIDManagerUnscheduleFromRunLoop(s_hidManager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
+ IOHIDManagerRegisterInputValueCallback(s_hidManager, NULL, NULL);
+ IOHIDManagerClose(s_hidManager, 0);
+
+ CFRelease(s_hidManager);
+#endif
+ s_hidManager = NULL;
+}
+
+static void
+InitHIDCallback()
+{
+ s_hidManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
+ if (!s_hidManager) {
+ return;
+ }
+ CFDictionaryRef keyboard = NULL, keypad = NULL;
+ CFArrayRef matches = NULL;
+ keyboard = CreateHIDDeviceMatchingDictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_Keyboard);
+ if (!keyboard) {
+ goto fail;
+ }
+ keypad = CreateHIDDeviceMatchingDictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_Keypad);
+ if (!keypad) {
+ goto fail;
+ }
+ CFDictionaryRef matchesList[] = { keyboard, keypad };
+ matches = CFArrayCreate(kCFAllocatorDefault, (const void **)matchesList, 2, NULL);
+ if (!matches) {
+ goto fail;
+ }
+ IOHIDManagerSetDeviceMatchingMultiple(s_hidManager, matches);
+ IOHIDManagerRegisterInputValueCallback(s_hidManager, HIDCallback, s_hidManager);
+ IOHIDManagerScheduleWithRunLoop(s_hidManager, CFRunLoopGetMain(), kCFRunLoopDefaultMode);
+ if (IOHIDManagerOpen(s_hidManager, kIOHIDOptionsTypeNone) == kIOReturnSuccess) {
+ goto cleanup;
+ }
+
+fail:
+ QuitHIDCallback();
+
+cleanup:
+ if (matches) {
+ CFRelease(matches);
+ }
+ if (keypad) {
+ CFRelease(keypad);
+ }
+ if (keyboard) {
+ CFRelease(keyboard);
+ }
+}
+
/* This is a helper function for HandleModifierSide. This
* function reverts back to behavior before the distinction between
* sides was made.
@@ -328,24 +431,6 @@ ReleaseModifierSide(unsigned int device_independent_mask,
}
}
-/* This is a helper function for DoSidedModifiers.
- * This function handles the CapsLock case.
- */
-static void
-HandleCapsLock(unsigned short scancode,
- unsigned int oldMods, unsigned int newMods)
-{
- unsigned int oldMask, newMask;
-
- oldMask = oldMods & NSAlphaShiftKeyMask;
- newMask = newMods & NSAlphaShiftKeyMask;
-
- if (oldMask != newMask) {
- SDL_SendKeyboardKey(SDL_PRESSED, SDL_SCANCODE_CAPSLOCK);
- SDL_SendKeyboardKey(SDL_RELEASED, SDL_SCANCODE_CAPSLOCK);
- }
-}
-
/* This function will handle the modifier keys and also determine the
* correct side of the key.
*/
@@ -374,9 +459,6 @@ DoSidedModifiers(unsigned short scancode,
unsigned int i, bit;
- /* Handle CAPSLOCK separately because it doesn't have a left/right side */
- HandleCapsLock(scancode, oldMods, newMods);
-
/* Iterate through the bits, testing each against the old modifiers */
for (i = 0, bit = NSShiftKeyMask; bit <= NSCommandKeyMask; bit <<= 1, ++i) {
unsigned int oldMask, newMask;
@@ -498,11 +580,10 @@ Cocoa_InitKeyboard(_THIS)
SDL_SetScancodeName(SDL_SCANCODE_RALT, "Right Option");
SDL_SetScancodeName(SDL_SCANCODE_RGUI, "Right Command");
- /* On pre-10.6, you might have the initial capslock key state wrong. */
- if (floor(NSAppKitVersionNumber) >= NSAppKitVersionNumber10_6) {
- data->modifierFlags = [NSEvent modifierFlags];
- SDL_ToggleModState(KMOD_CAPS, (data->modifierFlags & NSAlphaShiftKeyMask) != 0);
- }
+ data->modifierFlags = [NSEvent modifierFlags];
+ SDL_ToggleModState(KMOD_CAPS, (data->modifierFlags & NSAlphaShiftKeyMask) != 0);
+
+ InitHIDCallback();
}
void
@@ -628,6 +709,7 @@ Cocoa_HandleKeyEvent(_THIS, NSEvent *event)
void
Cocoa_QuitKeyboard(_THIS)
{
+ QuitHIDCallback();
}
#endif /* SDL_VIDEO_DRIVER_COCOA */
diff --git a/Engine/lib/sdl/src/video/cocoa/SDL_cocoamodes.h b/Engine/lib/sdl/src/video/cocoa/SDL_cocoamodes.h
index a0a29f501..ce8601cba 100644
--- a/Engine/lib/sdl/src/video/cocoa/SDL_cocoamodes.h
+++ b/Engine/lib/sdl/src/video/cocoa/SDL_cocoamodes.h
@@ -30,12 +30,14 @@ typedef struct
typedef struct
{
- const void *moderef;
+ CGDisplayModeRef moderef;
} SDL_DisplayModeData;
extern void Cocoa_InitModes(_THIS);
extern int Cocoa_GetDisplayBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect);
+extern int Cocoa_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect);
extern void Cocoa_GetDisplayModes(_THIS, SDL_VideoDisplay * display);
+extern int Cocoa_GetDisplayDPI(_THIS, SDL_VideoDisplay * display, float * ddpi, float * hpdi, float * vdpi);
extern int Cocoa_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);
extern void Cocoa_QuitModes(_THIS);
diff --git a/Engine/lib/sdl/src/video/cocoa/SDL_cocoamodes.m b/Engine/lib/sdl/src/video/cocoa/SDL_cocoamodes.m
index 7d98264a7..6ae9decbc 100644
--- a/Engine/lib/sdl/src/video/cocoa/SDL_cocoamodes.m
+++ b/Engine/lib/sdl/src/video/cocoa/SDL_cocoamodes.m
@@ -19,6 +19,7 @@
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
+#include "SDL_assert.h"
#if SDL_VIDEO_DRIVER_COCOA
@@ -55,25 +56,6 @@ Cocoa_ToggleMenuBar(const BOOL show)
#endif
}
-
-/* !!! FIXME: clean out the pre-10.6 code when it makes sense to do so. */
-#define FORCE_OLD_API 0
-
-#if FORCE_OLD_API
-#undef MAC_OS_X_VERSION_MIN_REQUIRED
-#define MAC_OS_X_VERSION_MIN_REQUIRED 1050
-#endif
-
-static BOOL
-IS_SNOW_LEOPARD_OR_LATER()
-{
-#if FORCE_OLD_API
- return NO;
-#else
- return floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_5;
-#endif
-}
-
static int
CG_SetError(const char *prefix, CGDisplayErr result)
{
@@ -118,65 +100,46 @@ CG_SetError(const char *prefix, CGDisplayErr result)
}
static SDL_bool
-GetDisplayMode(_THIS, const void *moderef, CVDisplayLinkRef link, SDL_DisplayMode *mode)
+GetDisplayMode(_THIS, CGDisplayModeRef vidmode, CVDisplayLinkRef link, SDL_DisplayMode *mode)
{
SDL_DisplayModeData *data;
- long width = 0;
- long height = 0;
- long bpp = 0;
- long refreshRate = 0;
+ int width = 0;
+ int height = 0;
+ int bpp = 0;
+ int refreshRate = 0;
+ CFStringRef fmt;
data = (SDL_DisplayModeData *) SDL_malloc(sizeof(*data));
if (!data) {
return SDL_FALSE;
}
- data->moderef = moderef;
+ data->moderef = vidmode;
- if (IS_SNOW_LEOPARD_OR_LATER()) {
- CGDisplayModeRef vidmode = (CGDisplayModeRef) moderef;
- CFStringRef fmt = CGDisplayModeCopyPixelEncoding(vidmode);
- width = (long) CGDisplayModeGetWidth(vidmode);
- height = (long) CGDisplayModeGetHeight(vidmode);
- refreshRate = (long) (CGDisplayModeGetRefreshRate(vidmode) + 0.5);
+ fmt = CGDisplayModeCopyPixelEncoding(vidmode);
+ width = (int) CGDisplayModeGetWidth(vidmode);
+ height = (int) CGDisplayModeGetHeight(vidmode);
+ refreshRate = (int) (CGDisplayModeGetRefreshRate(vidmode) + 0.5);
- if (CFStringCompare(fmt, CFSTR(IO32BitDirectPixels),
- kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
- bpp = 32;
- } else if (CFStringCompare(fmt, CFSTR(IO16BitDirectPixels),
- kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
- bpp = 16;
- } else if (CFStringCompare(fmt, CFSTR(kIO30BitDirectPixels),
- kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
- bpp = 30;
- } else {
- bpp = 0; /* ignore 8-bit and such for now. */
- }
-
- CFRelease(fmt);
+ if (CFStringCompare(fmt, CFSTR(IO32BitDirectPixels),
+ kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
+ bpp = 32;
+ } else if (CFStringCompare(fmt, CFSTR(IO16BitDirectPixels),
+ kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
+ bpp = 16;
+ } else if (CFStringCompare(fmt, CFSTR(kIO30BitDirectPixels),
+ kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
+ bpp = 30;
+ } else {
+ bpp = 0; /* ignore 8-bit and such for now. */
}
- #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
- if (!IS_SNOW_LEOPARD_OR_LATER()) {
- CFNumberRef number;
- double refresh;
- CFDictionaryRef vidmode = (CFDictionaryRef) moderef;
- number = CFDictionaryGetValue(vidmode, kCGDisplayWidth);
- CFNumberGetValue(number, kCFNumberLongType, &width);
- number = CFDictionaryGetValue(vidmode, kCGDisplayHeight);
- CFNumberGetValue(number, kCFNumberLongType, &height);
- number = CFDictionaryGetValue(vidmode, kCGDisplayBitsPerPixel);
- CFNumberGetValue(number, kCFNumberLongType, &bpp);
- number = CFDictionaryGetValue(vidmode, kCGDisplayRefreshRate);
- CFNumberGetValue(number, kCFNumberDoubleType, &refresh);
- refreshRate = (long) (refresh + 0.5);
- }
- #endif
+ CFRelease(fmt);
/* CGDisplayModeGetRefreshRate returns 0 for many non-CRT displays. */
if (refreshRate == 0 && link != NULL) {
CVTime time = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(link);
if ((time.flags & kCVTimeIsIndefinite) == 0 && time.timeValue != 0) {
- refreshRate = (long) ((time.timeScale / (double) time.timeValue) + 0.5);
+ refreshRate = (int) ((time.timeScale / (double) time.timeValue) + 0.5);
}
}
@@ -203,22 +166,6 @@ GetDisplayMode(_THIS, const void *moderef, CVDisplayLinkRef link, SDL_DisplayMod
return SDL_TRUE;
}
-static void
-Cocoa_ReleaseDisplayMode(_THIS, const void *moderef)
-{
- if (IS_SNOW_LEOPARD_OR_LATER()) {
- CGDisplayModeRelease((CGDisplayModeRef) moderef); /* NULL is ok */
- }
-}
-
-static void
-Cocoa_ReleaseDisplayModeList(_THIS, CFArrayRef modelist)
-{
- if (IS_SNOW_LEOPARD_OR_LATER()) {
- CFRelease(modelist); /* NULL is ok */
- }
-}
-
static const char *
Cocoa_GetDisplayName(CGDirectDisplayID displayID)
{
@@ -261,7 +208,7 @@ Cocoa_InitModes(_THIS)
SDL_VideoDisplay display;
SDL_DisplayData *displaydata;
SDL_DisplayMode mode;
- const void *moderef = NULL;
+ CGDisplayModeRef moderef = NULL;
CVDisplayLinkRef link = NULL;
if (pass == 0) {
@@ -278,15 +225,7 @@ Cocoa_InitModes(_THIS)
continue;
}
- if (IS_SNOW_LEOPARD_OR_LATER()) {
- moderef = CGDisplayCopyDisplayMode(displays[i]);
- }
-
- #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
- if (!IS_SNOW_LEOPARD_OR_LATER()) {
- moderef = CGDisplayCurrentMode(displays[i]);
- }
- #endif
+ moderef = CGDisplayCopyDisplayMode(displays[i]);
if (!moderef) {
continue;
@@ -294,7 +233,7 @@ Cocoa_InitModes(_THIS)
displaydata = (SDL_DisplayData *) SDL_malloc(sizeof(*displaydata));
if (!displaydata) {
- Cocoa_ReleaseDisplayMode(_this, moderef);
+ CGDisplayModeRelease(moderef);
continue;
}
displaydata->display = displays[i];
@@ -306,7 +245,7 @@ Cocoa_InitModes(_THIS)
display.name = (char *)Cocoa_GetDisplayName(displays[i]);
if (!GetDisplayMode(_this, moderef, link, &mode)) {
CVDisplayLinkRelease(link);
- Cocoa_ReleaseDisplayMode(_this, moderef);
+ CGDisplayModeRelease(moderef);
SDL_free(display.name);
SDL_free(displaydata);
continue;
@@ -338,21 +277,70 @@ Cocoa_GetDisplayBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect)
return 0;
}
+int
+Cocoa_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect)
+{
+ SDL_DisplayData *displaydata = (SDL_DisplayData *) display->driverdata;
+ const CGDirectDisplayID cgdisplay = displaydata->display;
+ NSArray *screens = [NSScreen screens];
+ NSScreen *screen = nil;
+
+ /* !!! FIXME: maybe track the NSScreen in SDL_DisplayData? */
+ for (NSScreen *i in screens) {
+ const CGDirectDisplayID thisDisplay = (CGDirectDisplayID) [[[i deviceDescription] objectForKey:@"NSScreenNumber"] unsignedIntValue];
+ if (thisDisplay == cgdisplay) {
+ screen = i;
+ break;
+ }
+ }
+
+ SDL_assert(screen != nil); /* didn't find it?! */
+ if (screen == nil) {
+ return -1;
+ }
+
+ const CGRect cgrect = CGDisplayBounds(cgdisplay);
+ const NSRect frame = [screen visibleFrame];
+
+ // !!! FIXME: I assume -[NSScreen visibleFrame] is relative to the origin of the screen in question and not the whole desktop.
+ // !!! FIXME: The math vs CGDisplayBounds might be incorrect if that's not the case, though. Check this.
+ rect->x = (int)(cgrect.origin.x + frame.origin.x);
+ rect->y = (int)(cgrect.origin.y + frame.origin.y);
+ rect->w = (int)frame.size.width;
+ rect->h = (int)frame.size.height;
+
+ return 0;
+}
+
+int
+Cocoa_GetDisplayDPI(_THIS, SDL_VideoDisplay * display, float * ddpi, float * hdpi, float * vdpi)
+{
+ const float MM_IN_INCH = 25.4f;
+
+ SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
+
+ CGSize displaySize = CGDisplayScreenSize(data->display);
+ int pixelWidth = (int) CGDisplayPixelsWide(data->display);
+ int pixelHeight = (int) CGDisplayPixelsHigh(data->display);
+
+ if (ddpi) {
+ *ddpi = SDL_ComputeDiagonalDPI(pixelWidth, pixelHeight, displaySize.width / MM_IN_INCH, displaySize.height / MM_IN_INCH);
+ }
+ if (hdpi) {
+ *hdpi = pixelWidth * MM_IN_INCH / displaySize.width;
+ }
+ if (vdpi) {
+ *vdpi = pixelHeight * MM_IN_INCH / displaySize.height;
+ }
+
+ return 0;
+}
+
void
Cocoa_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
{
SDL_DisplayData *data = (SDL_DisplayData *) display->driverdata;
- CFArrayRef modes = NULL;
-
- if (IS_SNOW_LEOPARD_OR_LATER()) {
- modes = CGDisplayCopyAllDisplayModes(data->display, NULL);
- }
-
- #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
- if (!IS_SNOW_LEOPARD_OR_LATER()) {
- modes = CGDisplayAvailableModes(data->display);
- }
- #endif
+ CFArrayRef modes = CGDisplayCopyAllDisplayModes(data->display, NULL);
if (modes) {
CVDisplayLinkRef link = NULL;
@@ -362,37 +350,19 @@ Cocoa_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
CVDisplayLinkCreateWithCGDisplay(data->display, &link);
for (i = 0; i < count; i++) {
- const void *moderef = CFArrayGetValueAtIndex(modes, i);
+ CGDisplayModeRef moderef = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
SDL_DisplayMode mode;
if (GetDisplayMode(_this, moderef, link, &mode)) {
- if (IS_SNOW_LEOPARD_OR_LATER()) {
- CGDisplayModeRetain((CGDisplayModeRef) moderef);
- }
+ CGDisplayModeRetain(moderef);
SDL_AddDisplayMode(display, &mode);
}
}
CVDisplayLinkRelease(link);
- Cocoa_ReleaseDisplayModeList(_this, modes);
+ CFRelease(modes);
}
}
-static CGError
-Cocoa_SwitchMode(_THIS, CGDirectDisplayID display, const void *mode)
-{
- if (IS_SNOW_LEOPARD_OR_LATER()) {
- return CGDisplaySetDisplayMode(display, (CGDisplayModeRef) mode, NULL);
- }
-
- #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
- if (!IS_SNOW_LEOPARD_OR_LATER()) {
- return CGDisplaySwitchToMode(display, (CFDictionaryRef) mode);
- }
- #endif
-
- return kCGErrorFailure;
-}
-
int
Cocoa_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
{
@@ -408,7 +378,7 @@ Cocoa_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
if (data == display->desktop_mode.driverdata) {
/* Restoring desktop mode */
- Cocoa_SwitchMode(_this, displaydata->display, data->moderef);
+ CGDisplaySetDisplayMode(displaydata->display, data->moderef, NULL);
if (CGDisplayIsMain(displaydata->display)) {
CGReleaseAllDisplays();
@@ -433,7 +403,7 @@ Cocoa_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
}
/* Do the physical switch */
- result = Cocoa_SwitchMode(_this, displaydata->display, data->moderef);
+ result = CGDisplaySetDisplayMode(displaydata->display, data->moderef, NULL);
if (result != kCGErrorSuccess) {
CG_SetError("CGDisplaySwitchToMode()", result);
goto ERR_NO_SWITCH;
@@ -478,11 +448,11 @@ Cocoa_QuitModes(_THIS)
}
mode = (SDL_DisplayModeData *) display->desktop_mode.driverdata;
- Cocoa_ReleaseDisplayMode(_this, mode->moderef);
+ CGDisplayModeRelease(mode->moderef);
for (j = 0; j < display->num_display_modes; j++) {
mode = (SDL_DisplayModeData*) display->display_modes[j].driverdata;
- Cocoa_ReleaseDisplayMode(_this, mode->moderef);
+ CGDisplayModeRelease(mode->moderef);
}
}
diff --git a/Engine/lib/sdl/src/video/cocoa/SDL_cocoamouse.m b/Engine/lib/sdl/src/video/cocoa/SDL_cocoamouse.m
index c76833123..0a27549ae 100644
--- a/Engine/lib/sdl/src/video/cocoa/SDL_cocoamouse.m
+++ b/Engine/lib/sdl/src/video/cocoa/SDL_cocoamouse.m
@@ -226,13 +226,15 @@ Cocoa_WarpMouseGlobal(int x, int y)
Cocoa_HandleMouseWarp(point.x, point.y);
- /* According to the docs, this was deprecated in 10.6, but it's still
- * around. The substitute requires a CGEventSource, but I'm not entirely
- * sure how we'd procure the right one for this event.
- */
- CGSetLocalEventsSuppressionInterval(0.0);
CGWarpMouseCursorPosition(point);
- CGSetLocalEventsSuppressionInterval(0.25);
+
+ /* CGWarpMouse causes a short delay by default, which is preventable by
+ * Calling this directly after. CGSetLocalEventsSuppressionInterval can also
+ * prevent it, but it's deprecated as of OS X 10.6.
+ */
+ if (!mouse->relative_mode) {
+ CGAssociateMouseAndMouseCursorPosition(YES);
+ }
/* CGWarpMouseCursorPosition doesn't generate a window event, unlike our
* other implementations' APIs. Send what's appropriate.
@@ -314,7 +316,7 @@ Cocoa_GetGlobalMouseState(int *x, int *y)
for (NSScreen *screen in [NSScreen screens]) {
NSRect frame = [screen frame];
- if (NSPointInRect(cocoaLocation, frame)) {
+ if (NSMouseInRect(cocoaLocation, frame, NO)) {
*x = (int) cocoaLocation.x;
*y = (int) ((frame.origin.y + frame.size.height) - cocoaLocation.y);
break;
@@ -396,7 +398,7 @@ Cocoa_HandleMouseEvent(_THIS, NSEvent *event)
/* Ignore events that aren't inside the client area (i.e. title bar.) */
if ([event window]) {
NSRect windowRect = [[[event window] contentView] frame];
- if (!NSPointInRect([event locationInWindow], windowRect)) {
+ if (!NSMouseInRect([event locationInWindow], windowRect, NO)) {
return;
}
}
@@ -419,8 +421,8 @@ Cocoa_HandleMouseWheel(SDL_Window *window, NSEvent *event)
{
SDL_Mouse *mouse = SDL_GetMouse();
- float x = -[event deltaX];
- float y = [event deltaY];
+ CGFloat x = -[event deltaX];
+ CGFloat y = [event deltaY];
SDL_MouseWheelDirection direction = SDL_MOUSEWHEEL_NORMAL;
if ([event respondsToSelector:@selector(isDirectionInvertedFromDevice)]) {
@@ -430,14 +432,14 @@ Cocoa_HandleMouseWheel(SDL_Window *window, NSEvent *event)
}
if (x > 0) {
- x += 0.9f;
+ x = SDL_ceil(x);
} else if (x < 0) {
- x -= 0.9f;
+ x = SDL_floor(x);
}
if (y > 0) {
- y += 0.9f;
+ y = SDL_ceil(y);
} else if (y < 0) {
- y -= 0.9f;
+ y = SDL_floor(y);
}
SDL_SendMouseWheel(window, mouse->mouseID, (int)x, (int)y, direction);
}
diff --git a/Engine/lib/sdl/src/video/cocoa/SDL_cocoamousetap.m b/Engine/lib/sdl/src/video/cocoa/SDL_cocoamousetap.m
index ed70f3ca3..48abbca9c 100644
--- a/Engine/lib/sdl/src/video/cocoa/SDL_cocoamousetap.m
+++ b/Engine/lib/sdl/src/video/cocoa/SDL_cocoamousetap.m
@@ -32,8 +32,8 @@
#if SDL_MAC_NO_SANDBOX
#include "SDL_keyboard.h"
-#include "SDL_thread.h"
#include "SDL_cocoavideo.h"
+#include "../../thread/SDL_systhread.h"
#include "../../events/SDL_mouse_c.h"
@@ -96,7 +96,7 @@ Cocoa_MouseTapCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event
eventLocation = CGEventGetUnflippedLocation(event);
windowRect = [nswindow contentRectForFrameRect:[nswindow frame]];
- if (!NSPointInRect(NSPointFromCGPoint(eventLocation), windowRect)) {
+ if (!NSMouseInRect(NSPointFromCGPoint(eventLocation), windowRect, NO)) {
/* This is in CGs global screenspace coordinate system, which has a
* flipped Y.
@@ -109,15 +109,14 @@ Cocoa_MouseTapCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event
newLocation.x = NSMaxX(windowRect) - 1.0;
}
- if (eventLocation.y < NSMinY(windowRect)) {
+ if (eventLocation.y <= NSMinY(windowRect)) {
newLocation.y -= (NSMinY(windowRect) - eventLocation.y + 1);
- } else if (eventLocation.y >= NSMaxY(windowRect)) {
- newLocation.y += (eventLocation.y - NSMaxY(windowRect) + 1);
+ } else if (eventLocation.y > NSMaxY(windowRect)) {
+ newLocation.y += (eventLocation.y - NSMaxY(windowRect));
}
- CGSetLocalEventsSuppressionInterval(0);
CGWarpMouseCursorPosition(newLocation);
- CGSetLocalEventsSuppressionInterval(0.25);
+ CGAssociateMouseAndMouseCursorPosition(YES);
if ((CGEventMaskBit(type) & movementEventsMask) == 0) {
/* For click events, we just constrain the event to the window, so
@@ -203,7 +202,7 @@ Cocoa_InitMouseEventTap(SDL_MouseData* driverdata)
tapdata->runloopStartedSemaphore = SDL_CreateSemaphore(0);
if (tapdata->runloopStartedSemaphore) {
- tapdata->thread = SDL_CreateThread(&Cocoa_MouseTapThread, "Event Tap Loop", tapdata);
+ tapdata->thread = SDL_CreateThreadInternal(&Cocoa_MouseTapThread, "Event Tap Loop", 512 * 1024, tapdata);
if (!tapdata->thread) {
SDL_DestroySemaphore(tapdata->runloopStartedSemaphore);
}
diff --git a/Engine/lib/sdl/src/video/cocoa/SDL_cocoaopengl.m b/Engine/lib/sdl/src/video/cocoa/SDL_cocoaopengl.m
index aa3609984..645e5ba45 100644
--- a/Engine/lib/sdl/src/video/cocoa/SDL_cocoaopengl.m
+++ b/Engine/lib/sdl/src/video/cocoa/SDL_cocoaopengl.m
@@ -173,6 +173,8 @@ Cocoa_GL_CreateContext(_THIS, SDL_Window * window)
return NULL;
}
+ attr[i++] = NSOpenGLPFAAllowOfflineRenderers;
+
/* specify a profile if we're on Lion (10.7) or later. */
if (lion_or_later) {
NSOpenGLPixelFormatAttribute profile = NSOpenGLProfileVersionLegacy;
diff --git a/Engine/lib/sdl/src/video/cocoa/SDL_cocoashape.m b/Engine/lib/sdl/src/video/cocoa/SDL_cocoashape.m
index cd5d97b70..fc8a2775c 100644
--- a/Engine/lib/sdl/src/video/cocoa/SDL_cocoashape.m
+++ b/Engine/lib/sdl/src/video/cocoa/SDL_cocoashape.m
@@ -35,9 +35,7 @@ Cocoa_CreateShaper(SDL_Window* window)
SDL_WindowData* windata = (SDL_WindowData*)window->driverdata;
[windata->nswindow setOpaque:NO];
- if ([windata->nswindow respondsToSelector:@selector(setStyleMask:)]) {
- [windata->nswindow setStyleMask:NSBorderlessWindowMask];
- }
+ [windata->nswindow setStyleMask:NSBorderlessWindowMask];
SDL_WindowShaper* result = result = malloc(sizeof(SDL_WindowShaper));
result->window = window;
diff --git a/Engine/lib/sdl/src/video/cocoa/SDL_cocoavideo.m b/Engine/lib/sdl/src/video/cocoa/SDL_cocoavideo.m
index b8f775ddb..e436e6521 100644
--- a/Engine/lib/sdl/src/video/cocoa/SDL_cocoavideo.m
+++ b/Engine/lib/sdl/src/video/cocoa/SDL_cocoavideo.m
@@ -73,6 +73,8 @@ Cocoa_CreateDevice(int devindex)
device->VideoInit = Cocoa_VideoInit;
device->VideoQuit = Cocoa_VideoQuit;
device->GetDisplayBounds = Cocoa_GetDisplayBounds;
+ device->GetDisplayUsableBounds = Cocoa_GetDisplayUsableBounds;
+ device->GetDisplayDPI = Cocoa_GetDisplayDPI;
device->GetDisplayModes = Cocoa_GetDisplayModes;
device->SetDisplayMode = Cocoa_SetDisplayMode;
device->PumpEvents = Cocoa_PumpEvents;
@@ -86,6 +88,7 @@ Cocoa_CreateDevice(int devindex)
device->SetWindowSize = Cocoa_SetWindowSize;
device->SetWindowMinimumSize = Cocoa_SetWindowMinimumSize;
device->SetWindowMaximumSize = Cocoa_SetWindowMaximumSize;
+ device->SetWindowOpacity = Cocoa_SetWindowOpacity;
device->ShowWindow = Cocoa_ShowWindow;
device->HideWindow = Cocoa_HideWindow;
device->RaiseWindow = Cocoa_RaiseWindow;
@@ -93,6 +96,7 @@ Cocoa_CreateDevice(int devindex)
device->MinimizeWindow = Cocoa_MinimizeWindow;
device->RestoreWindow = Cocoa_RestoreWindow;
device->SetWindowBordered = Cocoa_SetWindowBordered;
+ device->SetWindowResizable = Cocoa_SetWindowResizable;
device->SetWindowFullscreen = Cocoa_SetWindowFullscreen;
device->SetWindowGammaRamp = Cocoa_SetWindowGammaRamp;
device->GetWindowGammaRamp = Cocoa_GetWindowGammaRamp;
@@ -146,8 +150,7 @@ Cocoa_VideoInit(_THIS)
Cocoa_InitKeyboard(_this);
Cocoa_InitMouse(_this);
- const char *hint = SDL_GetHint(SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES);
- data->allow_spaces = ( (floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6) && (!hint || (*hint != '0')) );
+ data->allow_spaces = ((floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6) && SDL_GetHintBoolean(SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES, SDL_TRUE));
/* The IOPM assertion API can disable the screensaver as of 10.7. */
data->screensaver_use_iopm = floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6;
@@ -173,13 +176,7 @@ Cocoa_CreateImage(SDL_Surface * surface)
int i;
NSImage *img;
- converted = SDL_ConvertSurfaceFormat(surface,
-#if SDL_BYTEORDER == SDL_BIG_ENDIAN
- SDL_PIXELFORMAT_RGBA8888,
-#else
- SDL_PIXELFORMAT_ABGR8888,
-#endif
- 0);
+ converted = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_RGBA32, 0);
if (!converted) {
return nil;
}
diff --git a/Engine/lib/sdl/src/video/cocoa/SDL_cocoawindow.h b/Engine/lib/sdl/src/video/cocoa/SDL_cocoawindow.h
index 1037badfc..a32de8387 100644
--- a/Engine/lib/sdl/src/video/cocoa/SDL_cocoawindow.h
+++ b/Engine/lib/sdl/src/video/cocoa/SDL_cocoawindow.h
@@ -125,6 +125,7 @@ extern void Cocoa_SetWindowPosition(_THIS, SDL_Window * window);
extern void Cocoa_SetWindowSize(_THIS, SDL_Window * window);
extern void Cocoa_SetWindowMinimumSize(_THIS, SDL_Window * window);
extern void Cocoa_SetWindowMaximumSize(_THIS, SDL_Window * window);
+extern int Cocoa_SetWindowOpacity(_THIS, SDL_Window * window, float opacity);
extern void Cocoa_ShowWindow(_THIS, SDL_Window * window);
extern void Cocoa_HideWindow(_THIS, SDL_Window * window);
extern void Cocoa_RaiseWindow(_THIS, SDL_Window * window);
@@ -132,6 +133,7 @@ extern void Cocoa_MaximizeWindow(_THIS, SDL_Window * window);
extern void Cocoa_MinimizeWindow(_THIS, SDL_Window * window);
extern void Cocoa_RestoreWindow(_THIS, SDL_Window * window);
extern void Cocoa_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered);
+extern void Cocoa_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable);
extern void Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
extern int Cocoa_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp);
extern int Cocoa_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp);
diff --git a/Engine/lib/sdl/src/video/cocoa/SDL_cocoawindow.m b/Engine/lib/sdl/src/video/cocoa/SDL_cocoawindow.m
index a4da6cb2d..cfad54854 100644
--- a/Engine/lib/sdl/src/video/cocoa/SDL_cocoawindow.m
+++ b/Engine/lib/sdl/src/video/cocoa/SDL_cocoawindow.m
@@ -80,20 +80,20 @@
- (void)sendEvent:(NSEvent *)event
{
- [super sendEvent:event];
+ [super sendEvent:event];
- if ([event type] != NSLeftMouseUp) {
- return;
- }
+ if ([event type] != NSLeftMouseUp) {
+ return;
+ }
- id delegate = [self delegate];
- if (![delegate isKindOfClass:[Cocoa_WindowListener class]]) {
- return;
- }
+ id delegate = [self delegate];
+ if (![delegate isKindOfClass:[Cocoa_WindowListener class]]) {
+ return;
+ }
- if ([delegate isMoving]) {
- [delegate windowDidFinishMoving];
- }
+ if ([delegate isMoving]) {
+ [delegate windowDidFinishMoving];
+ }
}
/* We'll respond to selectors by doing nothing so we don't beep.
@@ -116,9 +116,12 @@
- (BOOL)performDragOperation:(id )sender
{ @autoreleasepool
{
+ SDL_VideoDevice *_this = SDL_GetVideoDevice();
NSPasteboard *pasteboard = [sender draggingPasteboard];
NSArray *types = [NSArray arrayWithObject:NSFilenamesPboardType];
NSString *desiredType = [pasteboard availableTypeFromArray:types];
+ SDL_Window *sdlwindow = nil;
+
if (desiredType == nil) {
return NO; /* can't accept anything that's being dropped here. */
}
@@ -132,13 +135,10 @@
NSArray *array = [pasteboard propertyListForType:@"NSFilenamesPboardType"];
for (NSString *path in array) {
- NSURL *fileURL = [[NSURL fileURLWithPath:path] autorelease];
+ NSURL *fileURL = [NSURL fileURLWithPath:path];
NSNumber *isAlias = nil;
- /* Functionality for resolving URL aliases was added with OS X 10.6. */
- if ([fileURL respondsToSelector:@selector(getResourceValue:forKey:error:)]) {
- [fileURL getResourceValue:&isAlias forKey:NSURLIsAliasFileKey error:nil];
- }
+ [fileURL getResourceValue:&isAlias forKey:NSURLIsAliasFileKey error:nil];
/* If the URL is an alias, resolve it. */
if ([isAlias boolValue]) {
@@ -157,11 +157,22 @@
}
}
- if (!SDL_SendDropFile([[fileURL path] UTF8String])) {
+ /* !!! FIXME: is there a better way to do this? */
+ if (_this) {
+ for (sdlwindow = _this->windows; sdlwindow; sdlwindow = sdlwindow->next) {
+ NSWindow *nswindow = ((SDL_WindowData *) sdlwindow->driverdata)->nswindow;
+ if (nswindow == self) {
+ break;
+ }
+ }
+ }
+
+ if (!SDL_SendDropFile(sdlwindow, [[fileURL path] UTF8String])) {
return NO;
}
}
+ SDL_SendDropComplete(sdlwindow);
return YES;
}}
@@ -196,17 +207,17 @@ ScheduleContextUpdates(SDL_WindowData *data)
}
}
+/* !!! FIXME: this should use a hint callback. */
static int
GetHintCtrlClickEmulateRightClick()
{
- const char *hint = SDL_GetHint( SDL_HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK );
- return hint != NULL && *hint != '0';
+ return SDL_GetHintBoolean(SDL_HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK, SDL_FALSE);
}
-static unsigned int
+static NSUInteger
GetWindowStyle(SDL_Window * window)
{
- unsigned int style;
+ NSUInteger style = 0;
if (window->flags & SDL_WINDOW_FULLSCREEN) {
style = NSBorderlessWindowMask;
@@ -224,21 +235,17 @@ GetWindowStyle(SDL_Window * window)
}
static SDL_bool
-SetWindowStyle(SDL_Window * window, unsigned int style)
+SetWindowStyle(SDL_Window * window, NSUInteger style)
{
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
NSWindow *nswindow = data->nswindow;
- if (![nswindow respondsToSelector: @selector(setStyleMask:)]) {
- return SDL_FALSE;
- }
-
/* The view responder chain gets messed with during setStyleMask */
if ([[nswindow contentView] nextResponder] == data->listener) {
[[nswindow contentView] setNextResponder:nil];
}
- [nswindow performSelector: @selector(setStyleMask:) withObject: (id)(uintptr_t)style];
+ [nswindow setStyleMask:style];
/* The view responder chain gets messed with during setStyleMask */
if ([[nswindow contentView] nextResponder] != data->listener) {
@@ -302,9 +309,7 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
[view setNextResponder:self];
- if ([view respondsToSelector:@selector(setAcceptsTouchEvents:)]) {
- [view setAcceptsTouchEvents:YES];
- }
+ [view setAcceptsTouchEvents:YES];
}
- (void)observeValueForKeyPath:(NSString *)keyPath
@@ -589,12 +594,9 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
[NSMenu setMenuBarVisible:NO];
}
- /* On pre-10.6, you might have the capslock key state wrong now because we can't check here. */
- if (floor(NSAppKitVersionNumber) >= NSAppKitVersionNumber10_6) {
- const unsigned int newflags = [NSEvent modifierFlags] & NSAlphaShiftKeyMask;
- _data->videodata->modifierFlags = (_data->videodata->modifierFlags & ~NSAlphaShiftKeyMask) | newflags;
- SDL_ToggleModState(KMOD_CAPS, newflags != 0);
- }
+ const unsigned int newflags = [NSEvent modifierFlags] & NSAlphaShiftKeyMask;
+ _data->videodata->modifierFlags = (_data->videodata->modifierFlags & ~NSAlphaShiftKeyMask) | newflags;
+ SDL_ToggleModState(KMOD_CAPS, newflags != 0);
}
- (void)windowDidResignKey:(NSNotification *)aNotification
@@ -820,23 +822,18 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
- (void)mouseDown:(NSEvent *)theEvent
{
int button;
+ int clicks;
/* Ignore events that aren't inside the client area (i.e. title bar.) */
if ([theEvent window]) {
NSRect windowRect = [[[theEvent window] contentView] frame];
-
- /* add one to size, since NSPointInRect is exclusive of the bottom
- edges, which mean it misses the top of the window by one pixel
- (as the origin is the bottom left). */
- windowRect.size.width += 1;
- windowRect.size.height += 1;
-
- if (!NSPointInRect([theEvent locationInWindow], windowRect)) {
+ if (!NSMouseInRect([theEvent locationInWindow], windowRect, NO)) {
return;
}
}
if ([self processHitTest:theEvent]) {
+ SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_HIT_TEST, 0, 0);
return; /* dragging, drop event. */
}
@@ -858,10 +855,12 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
button = SDL_BUTTON_MIDDLE;
break;
default:
- button = [theEvent buttonNumber] + 1;
+ button = (int) [theEvent buttonNumber] + 1;
break;
}
- SDL_SendMouseButton(_data->window, 0, SDL_PRESSED, button);
+
+ clicks = (int) [theEvent clickCount];
+ SDL_SendMouseButtonClicks(_data->window, 0, SDL_PRESSED, button, clicks);
}
- (void)rightMouseDown:(NSEvent *)theEvent
@@ -877,8 +876,10 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
- (void)mouseUp:(NSEvent *)theEvent
{
int button;
+ int clicks;
if ([self processHitTest:theEvent]) {
+ SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_HIT_TEST, 0, 0);
return; /* stopped dragging, drop event. */
}
@@ -898,10 +899,12 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
button = SDL_BUTTON_MIDDLE;
break;
default:
- button = [theEvent buttonNumber] + 1;
+ button = (int) [theEvent buttonNumber] + 1;
break;
}
- SDL_SendMouseButton(_data->window, 0, SDL_RELEASED, button);
+
+ clicks = (int) [theEvent clickCount];
+ SDL_SendMouseButtonClicks(_data->window, 0, SDL_RELEASED, button, clicks);
}
- (void)rightMouseUp:(NSEvent *)theEvent
@@ -922,6 +925,7 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
int x, y;
if ([self processHitTest:theEvent]) {
+ SDL_SendWindowEvent(window, SDL_WINDOWEVENT_HIT_TEST, 0, 0);
return; /* dragging, drop event. */
}
@@ -956,13 +960,8 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
cgpoint.x = window->x + x;
cgpoint.y = window->y + y;
- /* According to the docs, this was deprecated in 10.6, but it's still
- * around. The substitute requires a CGEventSource, but I'm not entirely
- * sure how we'd procure the right one for this event.
- */
- CGSetLocalEventsSuppressionInterval(0.0);
CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint);
- CGSetLocalEventsSuppressionInterval(0.25);
+ CGAssociateMouseAndMouseCursorPosition(YES);
Cocoa_HandleMouseWarp(cgpoint.x, cgpoint.y);
#endif
@@ -1075,6 +1074,7 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
- (void)rightMouseDown:(NSEvent *)theEvent;
- (BOOL)mouseDownCanMoveWindow;
- (void)drawRect:(NSRect)dirtyRect;
+- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent;
@end
@implementation SDLView
@@ -1114,6 +1114,15 @@ SetWindowStyle(SDL_Window * window, unsigned int style)
cursor:[NSCursor invisibleCursor]];
}
}
+
+- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
+{
+ if (SDL_GetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH)) {
+ return SDL_GetHintBoolean(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, SDL_FALSE);
+ } else {
+ return SDL_GetHintBoolean("SDL_MAC_MOUSE_FOCUS_CLICKTHROUGH", SDL_FALSE);
+ }
+}
@end
static int
@@ -1157,7 +1166,7 @@ SetupWindowData(_THIS, SDL_Window * window, NSWindow *nswindow, SDL_bool created
}
{
- unsigned int style = [nswindow styleMask];
+ unsigned long style = [nswindow styleMask];
if (style == NSBorderlessWindowMask) {
window->flags |= SDL_WINDOW_BORDERLESS;
@@ -1208,7 +1217,7 @@ Cocoa_CreateWindow(_THIS, SDL_Window * window)
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
NSRect rect;
SDL_Rect bounds;
- unsigned int style;
+ NSUInteger style;
NSArray *screens = [NSScreen screens];
Cocoa_GetDisplayBounds(_this, display, &bounds);
@@ -1263,7 +1272,7 @@ Cocoa_CreateWindow(_THIS, SDL_Window * window)
}
}
- [nswindow setContentView: contentView];
+ [nswindow setContentView:contentView];
[contentView release];
/* Allow files and folders to be dragged onto the window by users */
@@ -1470,27 +1479,6 @@ Cocoa_RestoreWindow(_THIS, SDL_Window * window)
}
}}
-static NSWindow *
-Cocoa_RebuildWindow(SDL_WindowData * data, NSWindow * nswindow, unsigned style)
-{
- if (!data->created) {
- /* Don't mess with other people's windows... */
- return nswindow;
- }
-
- [data->listener close];
- data->nswindow = [[SDLWindow alloc] initWithContentRect:[[nswindow contentView] frame] styleMask:style backing:NSBackingStoreBuffered defer:NO screen:[nswindow screen]];
- [data->nswindow setContentView:[nswindow contentView]];
- [data->nswindow registerForDraggedTypes:[NSArray arrayWithObject:(NSString *)kUTTypeFileURL]];
- /* See comment in SetupWindowData. */
- [data->nswindow setOneShot:NO];
- [data->listener listen:data];
-
- [nswindow close];
-
- return data->nswindow;
-}
-
void
Cocoa_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
{ @autoreleasepool
@@ -1502,6 +1490,20 @@ Cocoa_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
}
}}
+void
+Cocoa_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable)
+{ @autoreleasepool
+{
+ /* Don't set this if we're in a space!
+ * The window will get permanently stuck if resizable is false.
+ * -flibit
+ */
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ Cocoa_WindowListener *listener = data->listener;
+ if (![listener isInFullscreenSpace]) {
+ SetWindowStyle(window, GetWindowStyle(window));
+ }
+}}
void
Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen)
@@ -1532,11 +1534,7 @@ Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display
rect.origin.y += (screenRect.size.height - rect.size.height);
}
- if ([nswindow respondsToSelector: @selector(setStyleMask:)]) {
- [nswindow performSelector: @selector(setStyleMask:) withObject: (id)NSBorderlessWindowMask];
- } else {
- nswindow = Cocoa_RebuildWindow(data, nswindow, NSBorderlessWindowMask);
- }
+ [nswindow setStyleMask:NSBorderlessWindowMask];
} else {
rect.origin.x = window->windowed.x;
rect.origin.y = window->windowed.y;
@@ -1544,16 +1542,12 @@ Cocoa_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display
rect.size.height = window->windowed.h;
ConvertNSRect([nswindow screen], fullscreen, &rect);
- if ([nswindow respondsToSelector: @selector(setStyleMask:)]) {
- [nswindow performSelector: @selector(setStyleMask:) withObject: (id)(uintptr_t)GetWindowStyle(window)];
+ [nswindow setStyleMask:GetWindowStyle(window)];
- /* Hack to restore window decorations on Mac OS X 10.10 */
- NSRect frameRect = [nswindow frame];
- [nswindow setFrame:NSMakeRect(frameRect.origin.x, frameRect.origin.y, frameRect.size.width + 1, frameRect.size.height) display:NO];
- [nswindow setFrame:frameRect display:NO];
- } else {
- nswindow = Cocoa_RebuildWindow(data, nswindow, GetWindowStyle(window));
- }
+ /* Hack to restore window decorations on Mac OS X 10.10 */
+ NSRect frameRect = [nswindow frame];
+ [nswindow setFrame:NSMakeRect(frameRect.origin.x, frameRect.origin.y, frameRect.size.width + 1, frameRect.size.height) display:NO];
+ [nswindow setFrame:frameRect display:NO];
}
/* The view responder chain gets messed with during setStyleMask */
@@ -1767,6 +1761,14 @@ Cocoa_SetWindowHitTest(SDL_Window * window, SDL_bool enabled)
return 0; /* just succeed, the real work is done elsewhere. */
}
+int
+Cocoa_SetWindowOpacity(_THIS, SDL_Window * window, float opacity)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ [data->nswindow setAlphaValue:opacity];
+ return 0;
+}
+
#endif /* SDL_VIDEO_DRIVER_COCOA */
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/video/directfb/SDL_DirectFB_video.c b/Engine/lib/sdl/src/video/directfb/SDL_DirectFB_video.c
index 5579759eb..d339dd78e 100644
--- a/Engine/lib/sdl/src/video/directfb/SDL_DirectFB_video.c
+++ b/Engine/lib/sdl/src/video/directfb/SDL_DirectFB_video.c
@@ -121,6 +121,7 @@ DirectFB_CreateDevice(int devindex)
device->SetWindowIcon = DirectFB_SetWindowIcon;
device->SetWindowPosition = DirectFB_SetWindowPosition;
device->SetWindowSize = DirectFB_SetWindowSize;
+ device->SetWindowOpacity = DirectFB_SetWindowOpacity;
device->ShowWindow = DirectFB_ShowWindow;
device->HideWindow = DirectFB_HideWindow;
device->RaiseWindow = DirectFB_RaiseWindow;
diff --git a/Engine/lib/sdl/src/video/directfb/SDL_DirectFB_window.c b/Engine/lib/sdl/src/video/directfb/SDL_DirectFB_window.c
index 3b8b45d44..40bbe6aee 100644
--- a/Engine/lib/sdl/src/video/directfb/SDL_DirectFB_window.c
+++ b/Engine/lib/sdl/src/video/directfb/SDL_DirectFB_window.c
@@ -529,4 +529,17 @@ DirectFB_AdjustWindowSurface(SDL_Window * window)
return;
}
+int
+DirectFB_SetWindowOpacity(_THIS, SDL_Window * window, float opacity)
+{
+ const Uint8 alpha = (Uint8) ((unsigned int) (opacity * 255.0f));
+ SDL_DFB_WINDOWDATA(window);
+ SDL_DFB_CHECKERR(windata->dfbwin->SetOpacity(windata->dfbwin, alpha));
+ windata->opacity = alpha;
+ return 0;
+
+error:
+ return -1;
+}
+
#endif /* SDL_VIDEO_DRIVER_DIRECTFB */
diff --git a/Engine/lib/sdl/src/video/directfb/SDL_DirectFB_window.h b/Engine/lib/sdl/src/video/directfb/SDL_DirectFB_window.h
index 658cc8749..4b9970812 100644
--- a/Engine/lib/sdl/src/video/directfb/SDL_DirectFB_window.h
+++ b/Engine/lib/sdl/src/video/directfb/SDL_DirectFB_window.h
@@ -75,6 +75,7 @@ extern SDL_bool DirectFB_GetWindowWMInfo(_THIS, SDL_Window * window,
struct SDL_SysWMinfo *info);
extern void DirectFB_AdjustWindowSurface(SDL_Window * window);
+extern int DirectFB_SetWindowOpacity(_THIS, SDL_Window * window, float opacity);
#endif /* _SDL_directfb_window_h */
diff --git a/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenevents.c b/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenevents.c
index 0f915c6f3..a4720e402 100644
--- a/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenevents.c
+++ b/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenevents.c
@@ -217,16 +217,16 @@ static const SDL_Scancode emscripten_scancode_table[] = {
/* 171 */ SDL_SCANCODE_UNKNOWN,
/* 172 */ SDL_SCANCODE_UNKNOWN,
/* 173 */ SDL_SCANCODE_MINUS, /*FX*/
- /* 174 */ SDL_SCANCODE_UNKNOWN,
- /* 175 */ SDL_SCANCODE_UNKNOWN,
- /* 176 */ SDL_SCANCODE_UNKNOWN,
- /* 177 */ SDL_SCANCODE_UNKNOWN,
+ /* 174 */ SDL_SCANCODE_VOLUMEDOWN, /*IE, Chrome*/
+ /* 175 */ SDL_SCANCODE_VOLUMEUP, /*IE, Chrome*/
+ /* 176 */ SDL_SCANCODE_AUDIONEXT, /*IE, Chrome*/
+ /* 177 */ SDL_SCANCODE_AUDIOPREV, /*IE, Chrome*/
/* 178 */ SDL_SCANCODE_UNKNOWN,
- /* 179 */ SDL_SCANCODE_UNKNOWN,
+ /* 179 */ SDL_SCANCODE_AUDIOPLAY, /*IE, Chrome*/
/* 180 */ SDL_SCANCODE_UNKNOWN,
- /* 181 */ SDL_SCANCODE_UNKNOWN,
- /* 182 */ SDL_SCANCODE_UNKNOWN,
- /* 183 */ SDL_SCANCODE_UNKNOWN,
+ /* 181 */ SDL_SCANCODE_AUDIOMUTE, /*FX*/
+ /* 182 */ SDL_SCANCODE_VOLUMEDOWN, /*FX*/
+ /* 183 */ SDL_SCANCODE_VOLUMEUP, /*FX*/
/* 184 */ SDL_SCANCODE_UNKNOWN,
/* 185 */ SDL_SCANCODE_UNKNOWN,
/* 186 */ SDL_SCANCODE_SEMICOLON, /*IE, Chrome, D3E legacy*/
@@ -301,25 +301,34 @@ EM_BOOL
Emscripten_HandleMouseMove(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData)
{
SDL_WindowData *window_data = userData;
- int mx = mouseEvent->canvasX, my = mouseEvent->canvasY;
+ int mx, my;
+ static double residualx = 0, residualy = 0;
EmscriptenPointerlockChangeEvent pointerlock_status;
- /* check for pointer lock */
- emscripten_get_pointerlock_status(&pointerlock_status);
+ /* rescale (in case canvas is being scaled)*/
+ double client_w, client_h, xscale, yscale;
+ emscripten_get_element_css_size(NULL, &client_w, &client_h);
+ xscale = window_data->window->w / client_w;
+ yscale = window_data->window->h / client_h;
- if (pointerlock_status.isActive) {
- mx = mouseEvent->movementX;
- my = mouseEvent->movementY;
+ /* check for pointer lock */
+ int isPointerLockSupported = emscripten_get_pointerlock_status(&pointerlock_status);
+ int isPointerLocked = isPointerLockSupported == EMSCRIPTEN_RESULT_SUCCESS ? pointerlock_status.isActive : SDL_FALSE;
+
+ if (isPointerLocked) {
+ residualx += mouseEvent->movementX * xscale;
+ residualy += mouseEvent->movementY * yscale;
+ /* Let slow sub-pixel motion accumulate. Don't lose it. */
+ mx = residualx;
+ residualx -= mx;
+ my = residualy;
+ residualy -= my;
+ } else {
+ mx = mouseEvent->canvasX * xscale;
+ my = mouseEvent->canvasY * yscale;
}
- /* rescale (in case canvas is being scaled)*/
- double client_w, client_h;
- emscripten_get_element_css_size(NULL, &client_w, &client_h);
-
- mx = mx * (window_data->window->w / (client_w * window_data->pixel_ratio));
- my = my * (window_data->window->h / (client_h * window_data->pixel_ratio));
-
- SDL_SendMouseMotion(window_data->window, 0, pointerlock_status.isActive, mx, my);
+ SDL_SendMouseMotion(window_data->window, 0, isPointerLocked, mx, my);
return 0;
}
@@ -341,16 +350,36 @@ Emscripten_HandleMouseButton(int eventType, const EmscriptenMouseEvent *mouseEve
default:
return 0;
}
- SDL_SendMouseButton(window_data->window, 0, eventType == EMSCRIPTEN_EVENT_MOUSEDOWN ? SDL_PRESSED : SDL_RELEASED, sdl_button);
- return 1;
+
+ SDL_EventType sdl_event_type = (eventType == EMSCRIPTEN_EVENT_MOUSEDOWN ? SDL_PRESSED : SDL_RELEASED);
+ SDL_SendMouseButton(window_data->window, 0, sdl_event_type, sdl_button);
+ return SDL_GetEventState(sdl_event_type) == SDL_ENABLE;
}
EM_BOOL
Emscripten_HandleMouseFocus(int eventType, const EmscriptenMouseEvent *mouseEvent, void *userData)
{
SDL_WindowData *window_data = userData;
- SDL_SendWindowEvent(window_data->window, eventType == EMSCRIPTEN_EVENT_MOUSEENTER ? SDL_WINDOWEVENT_ENTER : SDL_WINDOWEVENT_LEAVE, 0, 0);
- return 1;
+
+ int mx = mouseEvent->canvasX, my = mouseEvent->canvasY;
+ EmscriptenPointerlockChangeEvent pointerlock_status;
+
+ /* check for pointer lock */
+ int isPointerLockSupported = emscripten_get_pointerlock_status(&pointerlock_status);
+ int isPointerLocked = isPointerLockSupported == EMSCRIPTEN_RESULT_SUCCESS ? pointerlock_status.isActive : SDL_FALSE;
+
+ if (!isPointerLocked) {
+ /* rescale (in case canvas is being scaled)*/
+ double client_w, client_h;
+ emscripten_get_element_css_size(NULL, &client_w, &client_h);
+
+ mx = mx * (window_data->window->w / client_w);
+ my = my * (window_data->window->h / client_h);
+ SDL_SendMouseMotion(window_data->window, 0, isPointerLocked, mx, my);
+ }
+
+ SDL_SetMouseFocus(eventType == EMSCRIPTEN_EVENT_MOUSEENTER ? window_data->window : NULL);
+ return SDL_GetEventState(SDL_WINDOWEVENT) == SDL_ENABLE;
}
EM_BOOL
@@ -358,15 +387,22 @@ Emscripten_HandleWheel(int eventType, const EmscriptenWheelEvent *wheelEvent, vo
{
SDL_WindowData *window_data = userData;
SDL_SendMouseWheel(window_data->window, 0, wheelEvent->deltaX, -wheelEvent->deltaY, SDL_MOUSEWHEEL_NORMAL);
- return 1;
+ return SDL_GetEventState(SDL_MOUSEWHEEL) == SDL_ENABLE;
}
EM_BOOL
Emscripten_HandleFocus(int eventType, const EmscriptenFocusEvent *wheelEvent, void *userData)
{
SDL_WindowData *window_data = userData;
+ /* If the user switches away while keys are pressed (such as
+ * via Alt+Tab), key release events won't be received. */
+ if (eventType == EMSCRIPTEN_EVENT_BLUR) {
+ SDL_ResetKeyboard();
+ }
+
+
SDL_SendWindowEvent(window_data->window, eventType == EMSCRIPTEN_EVENT_FOCUS ? SDL_WINDOWEVENT_FOCUS_GAINED : SDL_WINDOWEVENT_FOCUS_LOST, 0, 0);
- return 1;
+ return SDL_GetEventState(SDL_WINDOWEVENT) == SDL_ENABLE;
}
EM_BOOL
@@ -374,12 +410,16 @@ Emscripten_HandleTouch(int eventType, const EmscriptenTouchEvent *touchEvent, vo
{
SDL_WindowData *window_data = userData;
int i;
+ double client_w, client_h;
+ int preventDefault = 0;
SDL_TouchID deviceId = 1;
if (SDL_AddTouch(deviceId, "") < 0) {
return 0;
}
+ emscripten_get_element_css_size(NULL, &client_w, &client_h);
+
for (i = 0; i < touchEvent->numTouches; i++) {
SDL_FingerID id;
float x, y;
@@ -388,20 +428,44 @@ Emscripten_HandleTouch(int eventType, const EmscriptenTouchEvent *touchEvent, vo
continue;
id = touchEvent->touches[i].identifier;
- x = touchEvent->touches[i].canvasX / (float)window_data->windowed_width;
- y = touchEvent->touches[i].canvasY / (float)window_data->windowed_height;
+ x = touchEvent->touches[i].canvasX / client_w;
+ y = touchEvent->touches[i].canvasY / client_h;
- if (eventType == EMSCRIPTEN_EVENT_TOUCHMOVE) {
- SDL_SendTouchMotion(deviceId, id, x, y, 1.0f);
- } else if (eventType == EMSCRIPTEN_EVENT_TOUCHSTART) {
+ if (eventType == EMSCRIPTEN_EVENT_TOUCHSTART) {
+ if (!window_data->finger_touching) {
+ window_data->finger_touching = SDL_TRUE;
+ window_data->first_finger = id;
+ SDL_SendMouseMotion(window_data->window, SDL_TOUCH_MOUSEID, 0, x, y);
+ SDL_SendMouseButton(window_data->window, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT);
+ }
SDL_SendTouch(deviceId, id, SDL_TRUE, x, y, 1.0f);
+
+ if (!preventDefault && SDL_GetEventState(SDL_FINGERDOWN) == SDL_ENABLE) {
+ preventDefault = 1;
+ }
+ } else if (eventType == EMSCRIPTEN_EVENT_TOUCHMOVE) {
+ if ((window_data->finger_touching) && (window_data->first_finger == id)) {
+ SDL_SendMouseMotion(window_data->window, SDL_TOUCH_MOUSEID, 0, x, y);
+ }
+ SDL_SendTouchMotion(deviceId, id, x, y, 1.0f);
+
+ if (!preventDefault && SDL_GetEventState(SDL_FINGERMOTION) == SDL_ENABLE) {
+ preventDefault = 1;
+ }
} else {
+ if ((window_data->finger_touching) && (window_data->first_finger == id)) {
+ SDL_SendMouseButton(window_data->window, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT);
+ window_data->finger_touching = SDL_FALSE;
+ }
SDL_SendTouch(deviceId, id, SDL_FALSE, x, y, 1.0f);
+
+ if (!preventDefault && SDL_GetEventState(SDL_FINGERUP) == SDL_ENABLE) {
+ preventDefault = 1;
+ }
}
}
-
- return 1;
+ return preventDefault;
}
EM_BOOL
@@ -431,16 +495,19 @@ Emscripten_HandleKey(int eventType, const EmscriptenKeyboardEvent *keyEvent, voi
break;
}
}
- SDL_SendKeyboardKey(eventType == EMSCRIPTEN_EVENT_KEYDOWN ?
- SDL_PRESSED : SDL_RELEASED, scancode);
+ SDL_SendKeyboardKey(eventType == EMSCRIPTEN_EVENT_KEYDOWN ? SDL_PRESSED : SDL_RELEASED, scancode);
}
}
- /* if we prevent keydown, we won't get keypress
- * also we need to ALWAYS prevent backspace and tab otherwise chrome takes action and does bad navigation UX
+ SDL_bool prevent_default = SDL_GetEventState(eventType == EMSCRIPTEN_EVENT_KEYDOWN ? SDL_KEYDOWN : SDL_KEYUP) == SDL_ENABLE;
+
+ /* if TEXTINPUT events are enabled we can't prevent keydown or we won't get keypress
+ * we need to ALWAYS prevent backspace and tab otherwise chrome takes action and does bad navigation UX
*/
- return SDL_GetEventState(SDL_TEXTINPUT) != SDL_ENABLE || eventType != EMSCRIPTEN_EVENT_KEYDOWN
- || keyEvent->keyCode == 8 /* backspace */ || keyEvent->keyCode == 9 /* tab */;
+ if (eventType == EMSCRIPTEN_EVENT_KEYDOWN && SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE && keyEvent->keyCode != 8 /* backspace */ && keyEvent->keyCode != 9 /* tab */)
+ prevent_default = SDL_FALSE;
+
+ return prevent_default;
}
EM_BOOL
@@ -450,65 +517,24 @@ Emscripten_HandleKeyPress(int eventType, const EmscriptenKeyboardEvent *keyEvent
if (Emscripten_ConvertUTF32toUTF8(keyEvent->charCode, text)) {
SDL_SendKeyboardText(text);
}
- return 1;
+ return SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE;
}
EM_BOOL
Emscripten_HandleFullscreenChange(int eventType, const EmscriptenFullscreenChangeEvent *fullscreenChangeEvent, void *userData)
{
- /*make sure this is actually our element going fullscreen*/
- if(SDL_strcmp(fullscreenChangeEvent->id, "SDLFullscreenElement") != 0)
- return 0;
-
SDL_WindowData *window_data = userData;
if(fullscreenChangeEvent->isFullscreen)
{
- SDL_bool is_desktop_fullscreen;
window_data->window->flags |= window_data->requested_fullscreen_mode;
- if(!window_data->requested_fullscreen_mode)
- window_data->window->flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; /*we didn't reqest fullscreen*/
-
window_data->requested_fullscreen_mode = 0;
- is_desktop_fullscreen = (window_data->window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP;
-
- /*update size*/
- if(window_data->window->flags & SDL_WINDOW_RESIZABLE || is_desktop_fullscreen)
- {
- emscripten_set_canvas_size(fullscreenChangeEvent->screenWidth, fullscreenChangeEvent->screenHeight);
- SDL_SendWindowEvent(window_data->window, SDL_WINDOWEVENT_RESIZED, fullscreenChangeEvent->screenWidth, fullscreenChangeEvent->screenHeight);
- }
- else
- {
- /*preserve ratio*/
- double w = window_data->window->w;
- double h = window_data->window->h;
- double factor = SDL_min(fullscreenChangeEvent->screenWidth / w, fullscreenChangeEvent->screenHeight / h);
- emscripten_set_element_css_size(NULL, w * factor, h * factor);
- }
+ if(!window_data->requested_fullscreen_mode)
+ window_data->window->flags |= SDL_WINDOW_FULLSCREEN; /*we didn't reqest fullscreen*/
}
else
{
- EM_ASM({
- //un-reparent canvas (similar to Module.requestFullscreen)
- var canvas = Module['canvas'];
- if(canvas.parentNode.id == "SDLFullscreenElement") {
- var canvasContainer = canvas.parentNode;
- canvasContainer.parentNode.insertBefore(canvas, canvasContainer);
- canvasContainer.parentNode.removeChild(canvasContainer);
- }
- });
- double unscaled_w = window_data->windowed_width / window_data->pixel_ratio;
- double unscaled_h = window_data->windowed_height / window_data->pixel_ratio;
- emscripten_set_canvas_size(window_data->windowed_width, window_data->windowed_height);
-
- if (!window_data->external_size && window_data->pixel_ratio != 1.0f) {
- emscripten_set_element_css_size(NULL, unscaled_w, unscaled_h);
- }
-
- SDL_SendWindowEvent(window_data->window, SDL_WINDOWEVENT_RESIZED, unscaled_w, unscaled_h);
-
window_data->window->flags &= ~FULLSCREEN_MASK;
}
@@ -519,17 +545,11 @@ EM_BOOL
Emscripten_HandleResize(int eventType, const EmscriptenUiEvent *uiEvent, void *userData)
{
SDL_WindowData *window_data = userData;
- if(window_data->window->flags & FULLSCREEN_MASK)
- {
- SDL_bool is_desktop_fullscreen = (window_data->window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP;
- if(window_data->window->flags & SDL_WINDOW_RESIZABLE || is_desktop_fullscreen)
- {
- emscripten_set_canvas_size(uiEvent->windowInnerWidth * window_data->pixel_ratio, uiEvent->windowInnerHeight * window_data->pixel_ratio);
- SDL_SendWindowEvent(window_data->window, SDL_WINDOWEVENT_RESIZED, uiEvent->windowInnerWidth, uiEvent->windowInnerHeight);
- }
- }
- else
+ /* update pixel ratio */
+ window_data->pixel_ratio = emscripten_get_device_pixel_ratio();
+
+ if(!(window_data->window->flags & FULLSCREEN_MASK))
{
/* this will only work if the canvas size is set through css */
if(window_data->window->flags & SDL_WINDOW_RESIZABLE)
@@ -555,6 +575,22 @@ Emscripten_HandleResize(int eventType, const EmscriptenUiEvent *uiEvent, void *u
return 0;
}
+EM_BOOL
+Emscripten_HandleCanvasResize(int eventType, const void *reserved, void *userData)
+{
+ /*this is used during fullscreen changes*/
+ SDL_WindowData *window_data = userData;
+
+ if(window_data->fullscreen_resize)
+ {
+ double css_w, css_h;
+ emscripten_get_element_css_size(NULL, &css_w, &css_h);
+ SDL_SendWindowEvent(window_data->window, SDL_WINDOWEVENT_RESIZED, css_w, css_h);
+ }
+
+ return 0;
+}
+
EM_BOOL
Emscripten_HandleVisibilityChange(int eventType, const EmscriptenVisibilityChangeEvent *visEvent, void *userData)
{
@@ -570,15 +606,15 @@ Emscripten_RegisterEventHandlers(SDL_WindowData *data)
emscripten_set_mousemove_callback("#canvas", data, 0, Emscripten_HandleMouseMove);
emscripten_set_mousedown_callback("#canvas", data, 0, Emscripten_HandleMouseButton);
- emscripten_set_mouseup_callback("#canvas", data, 0, Emscripten_HandleMouseButton);
+ emscripten_set_mouseup_callback("#document", data, 0, Emscripten_HandleMouseButton);
emscripten_set_mouseenter_callback("#canvas", data, 0, Emscripten_HandleMouseFocus);
emscripten_set_mouseleave_callback("#canvas", data, 0, Emscripten_HandleMouseFocus);
emscripten_set_wheel_callback("#canvas", data, 0, Emscripten_HandleWheel);
- emscripten_set_focus_callback("#canvas", data, 0, Emscripten_HandleFocus);
- emscripten_set_blur_callback("#canvas", data, 0, Emscripten_HandleFocus);
+ emscripten_set_focus_callback("#window", data, 0, Emscripten_HandleFocus);
+ emscripten_set_blur_callback("#window", data, 0, Emscripten_HandleFocus);
emscripten_set_touchstart_callback("#canvas", data, 0, Emscripten_HandleTouch);
emscripten_set_touchend_callback("#canvas", data, 0, Emscripten_HandleTouch);
@@ -607,15 +643,15 @@ Emscripten_UnregisterEventHandlers(SDL_WindowData *data)
emscripten_set_mousemove_callback("#canvas", NULL, 0, NULL);
emscripten_set_mousedown_callback("#canvas", NULL, 0, NULL);
- emscripten_set_mouseup_callback("#canvas", NULL, 0, NULL);
+ emscripten_set_mouseup_callback("#document", NULL, 0, NULL);
emscripten_set_mouseenter_callback("#canvas", NULL, 0, NULL);
emscripten_set_mouseleave_callback("#canvas", NULL, 0, NULL);
emscripten_set_wheel_callback("#canvas", NULL, 0, NULL);
- emscripten_set_focus_callback("#canvas", NULL, 0, NULL);
- emscripten_set_blur_callback("#canvas", NULL, 0, NULL);
+ emscripten_set_focus_callback("#window", NULL, 0, NULL);
+ emscripten_set_blur_callback("#window", NULL, 0, NULL);
emscripten_set_touchstart_callback("#canvas", NULL, 0, NULL);
emscripten_set_touchend_callback("#canvas", NULL, 0, NULL);
diff --git a/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenevents.h b/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenevents.h
index d5b65f854..089ff60da 100644
--- a/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenevents.h
+++ b/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenevents.h
@@ -30,6 +30,9 @@ Emscripten_RegisterEventHandlers(SDL_WindowData *data);
extern void
Emscripten_UnregisterEventHandlers(SDL_WindowData *data);
+
+extern int
+Emscripten_HandleCanvasResize(int eventType, const void *reserved, void *userData);
#endif /* _SDL_emscriptenevents_h */
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenframebuffer.c b/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenframebuffer.c
index a26e23ae6..8a6a465d9 100644
--- a/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenframebuffer.c
+++ b/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenframebuffer.c
@@ -69,15 +69,25 @@ int Emscripten_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rec
/* Send the data to the display */
EM_ASM_INT({
- //TODO: don't create context every update
- var ctx = Module['canvas'].getContext('2d');
+ var w = $0;
+ var h = $1;
+ var pixels = $2;
- //library_sdl.js SDL_UnlockSurface
- var image = ctx.createImageData($0, $1);
- var data = image.data;
- var src = $2 >> 2;
+ if (!Module['SDL2']) Module['SDL2'] = {};
+ var SDL2 = Module['SDL2'];
+ if (SDL2.ctxCanvas !== Module['canvas']) {
+ SDL2.ctx = Module['createContext'](Module['canvas'], false, true);
+ SDL2.ctxCanvas = Module['canvas'];
+ }
+ if (SDL2.w !== w || SDL2.h !== h || SDL2.imageCtx !== SDL2.ctx) {
+ SDL2.image = SDL2.ctx.createImageData(w, h);
+ SDL2.w = w;
+ SDL2.h = h;
+ SDL2.imageCtx = SDL2.ctx;
+ }
+ var data = SDL2.image.data;
+ var src = pixels >> 2;
var dst = 0;
- var isScreen = true;
var num;
if (typeof CanvasPixelArray !== 'undefined' && data instanceof CanvasPixelArray) {
// IE10/IE11: ImageData objects are backed by the deprecated CanvasPixelArray,
@@ -90,26 +100,58 @@ int Emscripten_UpdateWindowFramebuffer(_THIS, SDL_Window * window, const SDL_Rec
data[dst ] = val & 0xff;
data[dst+1] = (val >> 8) & 0xff;
data[dst+2] = (val >> 16) & 0xff;
- data[dst+3] = isScreen ? 0xff : ((val >> 24) & 0xff);
+ data[dst+3] = 0xff;
src++;
dst += 4;
}
} else {
- var data32 = new Uint32Array(data.buffer);
+ if (SDL2.data32Data !== data) {
+ SDL2.data32 = new Int32Array(data.buffer);
+ SDL2.data8 = new Uint8Array(data.buffer);
+ }
+ var data32 = SDL2.data32;
num = data32.length;
- if (isScreen) {
- while (dst < num) {
- // HEAP32[src++] is an optimization. Instead, we could do {{{ makeGetValue('buffer', 'dst', 'i32') }}};
- data32[dst++] = HEAP32[src++] | 0xff000000;
+ // logically we need to do
+ // while (dst < num) {
+ // data32[dst++] = HEAP32[src++] | 0xff000000
+ // }
+ // the following code is faster though, because
+ // .set() is almost free - easily 10x faster due to
+ // native memcpy efficiencies, and the remaining loop
+ // just stores, not load + store, so it is faster
+ data32.set(HEAP32.subarray(src, src + num));
+ var data8 = SDL2.data8;
+ var i = 3;
+ var j = i + 4*num;
+ if (num % 8 == 0) {
+ // unrolling gives big speedups
+ while (i < j) {
+ data8[i] = 0xff;
+ i = i + 4 | 0;
+ data8[i] = 0xff;
+ i = i + 4 | 0;
+ data8[i] = 0xff;
+ i = i + 4 | 0;
+ data8[i] = 0xff;
+ i = i + 4 | 0;
+ data8[i] = 0xff;
+ i = i + 4 | 0;
+ data8[i] = 0xff;
+ i = i + 4 | 0;
+ data8[i] = 0xff;
+ i = i + 4 | 0;
+ data8[i] = 0xff;
+ i = i + 4 | 0;
}
- } else {
- while (dst < num) {
- data32[dst++] = HEAP32[src++];
+ } else {
+ while (i < j) {
+ data8[i] = 0xff;
+ i = i + 4 | 0;
}
}
}
- ctx.putImageData(image, 0, 0);
+ SDL2.ctx.putImageData(SDL2.image, 0, 0);
return 0;
}, surface->w, surface->h, surface->pixels);
diff --git a/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenmouse.c b/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenmouse.c
index 2a68dd95c..512ad2220 100644
--- a/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenmouse.c
+++ b/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenmouse.c
@@ -58,11 +58,13 @@ Emscripten_CreateDefaultCursor()
return cursor;
}
+/*
static SDL_Cursor*
Emscripten_CreateCursor(SDL_Surface* sruface, int hot_x, int hot_y)
{
return Emscripten_CreateDefaultCursor();
}
+*/
static SDL_Cursor*
Emscripten_CreateSystemCursor(SDL_SystemCursor id)
@@ -200,7 +202,9 @@ Emscripten_InitMouse()
{
SDL_Mouse* mouse = SDL_GetMouse();
+/*
mouse->CreateCursor = Emscripten_CreateCursor;
+*/
mouse->ShowCursor = Emscripten_ShowCursor;
mouse->FreeCursor = Emscripten_FreeCursor;
mouse->WarpMouse = Emscripten_WarpMouse;
diff --git a/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenvideo.c b/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenvideo.c
index 302ca8793..847bb4cf8 100644
--- a/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenvideo.c
+++ b/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenvideo.c
@@ -24,6 +24,7 @@
#include "SDL_video.h"
#include "SDL_mouse.h"
+#include "SDL_hints.h"
#include "../SDL_sysvideo.h"
#include "../SDL_pixels_c.h"
#include "../SDL_egl_c.h"
@@ -47,6 +48,7 @@ static void Emscripten_SetWindowSize(_THIS, SDL_Window * window);
static void Emscripten_DestroyWindow(_THIS, SDL_Window * window);
static void Emscripten_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
static void Emscripten_PumpEvents(_THIS);
+static void Emscripten_SetWindowTitle(_THIS, SDL_Window * window);
/* Emscripten driver bootstrap functions */
@@ -75,6 +77,12 @@ Emscripten_CreateDevice(int devindex)
return (0);
}
+ /* Firefox sends blur event which would otherwise prevent full screen
+ * when the user clicks to allow full screen.
+ * See https://bugzilla.mozilla.org/show_bug.cgi?id=1144964
+ */
+ SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0");
+
/* Set the function pointers */
device->VideoInit = Emscripten_VideoInit;
device->VideoQuit = Emscripten_VideoQuit;
@@ -84,9 +92,9 @@ Emscripten_CreateDevice(int devindex)
device->PumpEvents = Emscripten_PumpEvents;
device->CreateWindow = Emscripten_CreateWindow;
- /*device->CreateWindowFrom = Emscripten_CreateWindowFrom;
+ /*device->CreateWindowFrom = Emscripten_CreateWindowFrom;*/
device->SetWindowTitle = Emscripten_SetWindowTitle;
- device->SetWindowIcon = Emscripten_SetWindowIcon;
+ /*device->SetWindowIcon = Emscripten_SetWindowIcon;
device->SetWindowPosition = Emscripten_SetWindowPosition;*/
device->SetWindowSize = Emscripten_SetWindowSize;
/*device->ShowWindow = Emscripten_ShowWindow;
@@ -129,15 +137,17 @@ int
Emscripten_VideoInit(_THIS)
{
SDL_DisplayMode mode;
- double css_w, css_h;
/* Use a fake 32-bpp desktop mode */
mode.format = SDL_PIXELFORMAT_RGB888;
- emscripten_get_element_css_size(NULL, &css_w, &css_h);
+ mode.w = EM_ASM_INT_V({
+ return screen.width;
+ });
- mode.w = css_w;
- mode.h = css_h;
+ mode.h = EM_ASM_INT_V({
+ return screen.height;
+ });
mode.refresh_rate = 0;
mode.driverdata = NULL;
@@ -199,7 +209,7 @@ Emscripten_CreateWindow(_THIS, SDL_Window * window)
emscripten_get_element_css_size(NULL, &css_w, &css_h);
- wdata->external_size = css_w != scaled_w || css_h != scaled_h;
+ wdata->external_size = SDL_floor(css_w) != scaled_w || SDL_floor(css_h) != scaled_h;
if ((window->flags & SDL_WINDOW_RESIZABLE) && wdata->external_size) {
/* external css has resized us */
@@ -218,9 +228,6 @@ Emscripten_CreateWindow(_THIS, SDL_Window * window)
}
}
- wdata->windowed_width = scaled_w;
- wdata->windowed_height = scaled_h;
-
if (window->flags & SDL_WINDOW_OPENGL) {
if (!_this->egl_data) {
if (SDL_GL_LoadLibrary(NULL) < 0) {
@@ -255,6 +262,8 @@ static void Emscripten_SetWindowSize(_THIS, SDL_Window * window)
if (window->driverdata) {
data = (SDL_WindowData *) window->driverdata;
+ /* update pixel ratio */
+ data->pixel_ratio = emscripten_get_device_pixel_ratio();
emscripten_set_canvas_size(window->w * data->pixel_ratio, window->h * data->pixel_ratio);
/*scale canvas down*/
@@ -290,30 +299,49 @@ Emscripten_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * di
data = (SDL_WindowData *) window->driverdata;
if(fullscreen) {
+ EmscriptenFullscreenStrategy strategy;
+ SDL_bool is_desktop_fullscreen = (window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP;
+ int res;
+
+ strategy.scaleMode = is_desktop_fullscreen ? EMSCRIPTEN_FULLSCREEN_SCALE_STRETCH : EMSCRIPTEN_FULLSCREEN_SCALE_ASPECT;
+
+ if(!is_desktop_fullscreen) {
+ strategy.canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_NONE;
+ } else if(window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
+ strategy.canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_HIDEF;
+ } else {
+ strategy.canvasResolutionScaleMode = EMSCRIPTEN_FULLSCREEN_CANVAS_SCALE_STDDEF;
+ }
+
+ strategy.filteringMode = EMSCRIPTEN_FULLSCREEN_FILTERING_DEFAULT;
+
+ strategy.canvasResizedCallback = Emscripten_HandleCanvasResize;
+ strategy.canvasResizedCallbackUserData = data;
+
data->requested_fullscreen_mode = window->flags & (SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_FULLSCREEN);
- /*unset the fullscreen flags as we're not actually fullscreen yet*/
- window->flags &= ~(SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_FULLSCREEN);
+ data->fullscreen_resize = is_desktop_fullscreen;
- EM_ASM({
- //reparent canvas (similar to Module.requestFullscreen)
- var canvas = Module['canvas'];
- if(canvas.parentNode.id != "SDLFullscreenElement") {
- var canvasContainer = document.createElement("div");
- canvasContainer.id = "SDLFullscreenElement";
- canvas.parentNode.insertBefore(canvasContainer, canvas);
- canvasContainer.appendChild(canvas);
- }
- });
-
- int is_fullscreen;
- emscripten_get_canvas_size(&data->windowed_width, &data->windowed_height, &is_fullscreen);
- emscripten_request_fullscreen("SDLFullscreenElement", 1);
+ res = emscripten_request_fullscreen_strategy(NULL, 1, &strategy);
+ if(res != EMSCRIPTEN_RESULT_SUCCESS && res != EMSCRIPTEN_RESULT_DEFERRED) {
+ /* unset flags, fullscreen failed */
+ window->flags &= ~(SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_FULLSCREEN);
+ }
}
else
emscripten_exit_fullscreen();
}
}
+static void
+Emscripten_SetWindowTitle(_THIS, SDL_Window * window) {
+ EM_ASM_INT({
+ if (typeof Module['setWindowTitle'] !== 'undefined') {
+ Module['setWindowTitle'](Module['Pointer_stringify']($0));
+ }
+ return 0;
+ }, window->title);
+}
+
#endif /* SDL_VIDEO_DRIVER_EMSCRIPTEN */
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenvideo.h b/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenvideo.h
index e824de34f..7618ab6cc 100644
--- a/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenvideo.h
+++ b/Engine/lib/sdl/src/video/emscripten/SDL_emscriptenvideo.h
@@ -24,6 +24,7 @@
#define _SDL_emscriptenvideo_h
#include "../SDL_sysvideo.h"
+#include "../../events/SDL_touch_c.h"
#include
#include
@@ -37,14 +38,15 @@ typedef struct SDL_WindowData
SDL_Window *window;
SDL_Surface *surface;
- int windowed_width;
- int windowed_height;
-
float pixel_ratio;
SDL_bool external_size;
int requested_fullscreen_mode;
+ SDL_bool fullscreen_resize;
+
+ SDL_bool finger_touching; /* for mapping touch events to mice */
+ SDL_FingerID first_finger;
} SDL_WindowData;
#endif /* _SDL_emscriptenvideo_h */
diff --git a/Engine/lib/sdl/src/video/haiku/SDL_BWin.h b/Engine/lib/sdl/src/video/haiku/SDL_BWin.h
index dade664c3..a353e1aca 100644
--- a/Engine/lib/sdl/src/video/haiku/SDL_BWin.h
+++ b/Engine/lib/sdl/src/video/haiku/SDL_BWin.h
@@ -56,6 +56,7 @@ enum WinCommands {
BWIN_RESTORE_WINDOW,
BWIN_SET_TITLE,
BWIN_SET_BORDERED,
+ BWIN_SET_RESIZABLE,
BWIN_FULLSCREEN
};
@@ -336,16 +337,30 @@ class SDL_BWin:public BDirectWindow
break;
case B_KEY_DOWN:
+ {
+ int32 i = 0;
+ int8 byte;
+ int8 bytes[4] = { 0, 0, 0, 0 };
+ while (i < 4 && msg->FindInt8("byte", i, &byte) == B_OK) {
+ bytes[i] = byte;
+ i++;
+ }
+ if (msg->FindInt32("key", &key) == B_OK) {
+ _KeyEvent((SDL_Scancode)key, &bytes[0], i, SDL_PRESSED);
+ }
+ }
+ break;
+
case B_UNMAPPED_KEY_DOWN: /* modifier keys are unmapped */
if (msg->FindInt32("key", &key) == B_OK) {
- _KeyEvent((SDL_Scancode)key, SDL_PRESSED);
+ _KeyEvent((SDL_Scancode)key, NULL, 0, SDL_PRESSED);
}
break;
case B_KEY_UP:
case B_UNMAPPED_KEY_UP: /* modifier keys are unmapped */
if (msg->FindInt32("key", &key) == B_OK) {
- _KeyEvent(key, SDL_RELEASED);
+ _KeyEvent(key, NULL, 0, SDL_RELEASED);
}
break;
@@ -378,6 +393,9 @@ class SDL_BWin:public BDirectWindow
case BWIN_SET_BORDERED:
_SetBordered(message);
break;
+ case BWIN_SET_RESIZABLE:
+ _SetResizable(message);
+ break;
case BWIN_SHOW_WINDOW:
Show();
break;
@@ -508,13 +526,15 @@ private:
_PostWindowEvent(msg);
}
- void _KeyEvent(int32 keyCode, int32 keyState) {
+ void _KeyEvent(int32 keyCode, const int8 *keyUtf8, const ssize_t & len, int32 keyState) {
/* Create a message to pass along to the BeApp thread */
BMessage msg(BAPP_KEY);
msg.AddInt32("key-state", keyState);
msg.AddInt32("key-scancode", keyCode);
+ if (keyUtf8 != NULL) {
+ msg.AddData("key-utf8", B_INT8_TYPE, (const void*)keyUtf8, len);
+ }
be_app->PostMessage(&msg);
- /* Apparently SDL only uses the scancode */
}
void _RepaintEvent() {
@@ -568,6 +588,18 @@ private:
SetLook(bEnabled ? B_BORDERED_WINDOW_LOOK : B_NO_BORDER_WINDOW_LOOK);
}
+ void _SetResizable(BMessage *msg) {
+ bool bEnabled;
+ if(msg->FindBool("window-resizable", &bEnabled) != B_OK) {
+ return;
+ }
+ if (bEnabled) {
+ SetFlags(Flags() & ~(B_NOT_RESIZABLE | B_NOT_ZOOMABLE));
+ } else {
+ SetFlags(Flags() | (B_NOT_RESIZABLE | B_NOT_ZOOMABLE));
+ }
+ }
+
void _Restore() {
if(IsMinimized()) {
Minimize(false);
diff --git a/Engine/lib/sdl/src/video/haiku/SDL_bvideo.cc b/Engine/lib/sdl/src/video/haiku/SDL_bvideo.cc
index 8c243b7a0..8986c609c 100644
--- a/Engine/lib/sdl/src/video/haiku/SDL_bvideo.cc
+++ b/Engine/lib/sdl/src/video/haiku/SDL_bvideo.cc
@@ -81,6 +81,7 @@ BE_CreateDevice(int devindex)
device->MinimizeWindow = BE_MinimizeWindow;
device->RestoreWindow = BE_RestoreWindow;
device->SetWindowBordered = BE_SetWindowBordered;
+ device->SetWindowResizable = BE_SetWindowResizable;
device->SetWindowFullscreen = BE_SetWindowFullscreen;
device->SetWindowGammaRamp = BE_SetWindowGammaRamp;
device->GetWindowGammaRamp = BE_GetWindowGammaRamp;
diff --git a/Engine/lib/sdl/src/video/haiku/SDL_bwindow.cc b/Engine/lib/sdl/src/video/haiku/SDL_bwindow.cc
index 287eac965..a35471df5 100644
--- a/Engine/lib/sdl/src/video/haiku/SDL_bwindow.cc
+++ b/Engine/lib/sdl/src/video/haiku/SDL_bwindow.cc
@@ -145,6 +145,12 @@ void BE_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered) {
_ToBeWin(window)->PostMessage(&msg);
}
+void BE_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable) {
+ BMessage msg(BWIN_SET_RESIZABLE);
+ msg.AddBool("window-resizable", resizable != SDL_FALSE);
+ _ToBeWin(window)->PostMessage(&msg);
+}
+
void BE_ShowWindow(_THIS, SDL_Window * window) {
BMessage msg(BWIN_SHOW_WINDOW);
_ToBeWin(window)->PostMessage(&msg);
diff --git a/Engine/lib/sdl/src/video/haiku/SDL_bwindow.h b/Engine/lib/sdl/src/video/haiku/SDL_bwindow.h
index f64530ab7..388443dac 100644
--- a/Engine/lib/sdl/src/video/haiku/SDL_bwindow.h
+++ b/Engine/lib/sdl/src/video/haiku/SDL_bwindow.h
@@ -39,6 +39,7 @@ extern void BE_MaximizeWindow(_THIS, SDL_Window * window);
extern void BE_MinimizeWindow(_THIS, SDL_Window * window);
extern void BE_RestoreWindow(_THIS, SDL_Window * window);
extern void BE_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered);
+extern void BE_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable);
extern void BE_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
extern int BE_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp);
extern int BE_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp);
diff --git a/Engine/lib/sdl/src/video/mir/SDL_mirdyn.c b/Engine/lib/sdl/src/video/mir/SDL_mirdyn.c
index f9dfc0395..6bbe53759 100644
--- a/Engine/lib/sdl/src/video/mir/SDL_mirdyn.c
+++ b/Engine/lib/sdl/src/video/mir/SDL_mirdyn.c
@@ -84,9 +84,8 @@ MIR_GetSym(const char *fnname, int *pHasModule)
/* Define all the function pointers and wrappers... */
#define SDL_MIR_MODULE(modname) int SDL_MIR_HAVE_##modname = 0;
#define SDL_MIR_SYM(rc,fn,params) SDL_DYNMIRFN_##fn MIR_##fn = NULL;
+#define SDL_MIR_SYM_CONST(type,name) SDL_DYMMIRCONST_##name MIR_##name = NULL;
#include "SDL_mirsym.h"
-#undef SDL_MIR_MODULE
-#undef SDL_MIR_SYM
static int mir_load_refcount = 0;
@@ -103,9 +102,8 @@ SDL_MIR_UnloadSymbols(void)
/* set all the function pointers to NULL. */
#define SDL_MIR_MODULE(modname) SDL_MIR_HAVE_##modname = 0;
#define SDL_MIR_SYM(rc,fn,params) MIR_##fn = NULL;
+#define SDL_MIR_SYM_CONST(type,name) MIR_##name = NULL;
#include "SDL_mirsym.h"
-#undef SDL_MIR_MODULE
-#undef SDL_MIR_SYM
#ifdef SDL_VIDEO_DRIVER_MIR_DYNAMIC
@@ -138,16 +136,12 @@ SDL_MIR_LoadSymbols(void)
}
#define SDL_MIR_MODULE(modname) SDL_MIR_HAVE_##modname = 1; /* default yes */
-#define SDL_MIR_SYM(rc,fn,params)
#include "SDL_mirsym.h"
-#undef SDL_MIR_MODULE
-#undef SDL_MIR_SYM
#define SDL_MIR_MODULE(modname) thismod = &SDL_MIR_HAVE_##modname;
#define SDL_MIR_SYM(rc,fn,params) MIR_##fn = (SDL_DYNMIRFN_##fn) MIR_GetSym(#fn,thismod);
+#define SDL_MIR_SYM_CONST(type,name) MIR_##name = *(SDL_DYMMIRCONST_##name*) MIR_GetSym(#name,thismod);
#include "SDL_mirsym.h"
-#undef SDL_MIR_MODULE
-#undef SDL_MIR_SYM
if ((SDL_MIR_HAVE_MIR_CLIENT) && (SDL_MIR_HAVE_XKBCOMMON)) {
/* all required symbols loaded. */
@@ -162,9 +156,8 @@ SDL_MIR_LoadSymbols(void)
#define SDL_MIR_MODULE(modname) SDL_MIR_HAVE_##modname = 1; /* default yes */
#define SDL_MIR_SYM(rc,fn,params) MIR_##fn = fn;
+#define SDL_MIR_SYM_CONST(type,name) MIR_##name = name;
#include "SDL_mirsym.h"
-#undef SDL_MIR_MODULE
-#undef SDL_MIR_SYM
#endif
}
diff --git a/Engine/lib/sdl/src/video/mir/SDL_mirdyn.h b/Engine/lib/sdl/src/video/mir/SDL_mirdyn.h
index 48bf489c6..a3638cf05 100644
--- a/Engine/lib/sdl/src/video/mir/SDL_mirdyn.h
+++ b/Engine/lib/sdl/src/video/mir/SDL_mirdyn.h
@@ -36,13 +36,13 @@ int SDL_MIR_LoadSymbols(void);
void SDL_MIR_UnloadSymbols(void);
/* Declare all the function pointers and wrappers... */
-#define SDL_MIR_MODULE(modname)
#define SDL_MIR_SYM(rc,fn,params) \
typedef rc (*SDL_DYNMIRFN_##fn) params; \
extern SDL_DYNMIRFN_##fn MIR_##fn;
+#define SDL_MIR_SYM_CONST(type, name) \
+ typedef type SDL_DYMMIRCONST_##name; \
+ extern SDL_DYMMIRCONST_##name MIR_##name;
#include "SDL_mirsym.h"
-#undef SDL_MIR_MODULE
-#undef SDL_MIR_SYM
#ifdef __cplusplus
}
diff --git a/Engine/lib/sdl/src/video/mir/SDL_mirevents.c b/Engine/lib/sdl/src/video/mir/SDL_mirevents.c
index 708f8ffde..e36986835 100644
--- a/Engine/lib/sdl/src/video/mir/SDL_mirevents.c
+++ b/Engine/lib/sdl/src/video/mir/SDL_mirevents.c
@@ -53,73 +53,79 @@ HandleKeyText(int32_t key_code)
}
}
-static void
-CheckKeyboardFocus(SDL_Window* sdl_window)
-{
- SDL_Window* keyboard_window = SDL_GetKeyboardFocus();
-
- if (keyboard_window != sdl_window)
- SDL_SetKeyboardFocus(sdl_window);
-}
-
-
/* FIXME
Mir still needs to implement its IM API, for now we assume
a single key press produces a character.
*/
static void
-HandleKeyEvent(MirKeyEvent const ev, SDL_Window* window)
+HandleKeyEvent(MirKeyboardEvent const* key_event, SDL_Window* window)
{
- uint32_t scancode = SDL_SCANCODE_UNKNOWN;
- Uint8 key_state = ev.action == mir_key_action_up ? SDL_RELEASED : SDL_PRESSED;
+ xkb_keysym_t key_code;
+ Uint8 key_state;
+ int event_scancode;
+ uint32_t sdl_scancode = SDL_SCANCODE_UNKNOWN;
- CheckKeyboardFocus(window);
+ MirKeyboardAction action = MIR_mir_keyboard_event_action(key_event);
- if (ev.scan_code < SDL_arraysize(xfree86_scancode_table2))
- scancode = xfree86_scancode_table2[ev.scan_code];
+ key_state = SDL_PRESSED;
+ key_code = MIR_mir_keyboard_event_key_code(key_event);
+ event_scancode = MIR_mir_keyboard_event_scan_code(key_event);
- if (scancode != SDL_SCANCODE_UNKNOWN)
- SDL_SendKeyboardKey(key_state, scancode);
+ if (action == mir_keyboard_action_up)
+ key_state = SDL_RELEASED;
+
+ if (event_scancode < SDL_arraysize(xfree86_scancode_table2))
+ sdl_scancode = xfree86_scancode_table2[event_scancode];
+
+ if (sdl_scancode != SDL_SCANCODE_UNKNOWN)
+ SDL_SendKeyboardKey(key_state, sdl_scancode);
if (key_state == SDL_PRESSED)
- HandleKeyText(ev.key_code);
+ HandleKeyText(key_code);
}
static void
-HandleMouseButton(SDL_Window* sdl_window, Uint8 state, MirMotionButton button_state)
+HandleMouseButton(SDL_Window* sdl_window, Uint8 state, MirPointerEvent const* pointer)
{
- static uint32_t last_sdl_button;
- uint32_t sdl_button;
+ uint32_t sdl_button = SDL_BUTTON_LEFT;
+ MirPointerButton button_state = mir_pointer_button_primary;
+
+ static uint32_t old_button_states = 0;
+ uint32_t new_button_states = MIR_mir_pointer_event_buttons(pointer);
+
+ // XOR on our old button states vs our new states to get the newley pressed/released button
+ button_state = new_button_states ^ old_button_states;
switch (button_state) {
- case mir_motion_button_primary:
+ case mir_pointer_button_primary:
sdl_button = SDL_BUTTON_LEFT;
break;
- case mir_motion_button_secondary:
+ case mir_pointer_button_secondary:
sdl_button = SDL_BUTTON_RIGHT;
break;
- case mir_motion_button_tertiary:
+ case mir_pointer_button_tertiary:
sdl_button = SDL_BUTTON_MIDDLE;
break;
- case mir_motion_button_forward:
+ case mir_pointer_button_forward:
sdl_button = SDL_BUTTON_X1;
break;
- case mir_motion_button_back:
+ case mir_pointer_button_back:
sdl_button = SDL_BUTTON_X2;
break;
default:
- sdl_button = last_sdl_button;
break;
}
- last_sdl_button = sdl_button;
+ old_button_states = new_button_states;
+
SDL_SendMouseButton(sdl_window, 0, state, sdl_button);
}
static void
HandleMouseMotion(SDL_Window* sdl_window, int x, int y)
{
- SDL_SendMouseMotion(sdl_window, 0, 0, x, y);
+ SDL_Mouse* mouse = SDL_GetMouse();
+ SDL_SendMouseMotion(sdl_window, 0, mouse->relative_mode, x, y);
}
static void
@@ -148,71 +154,102 @@ AddTouchDevice(int device_id)
}
static void
-HandleTouchEvent(MirMotionEvent const motion, int cord_index, SDL_Window* sdl_window)
+HandleTouchEvent(MirTouchEvent const* touch, int device_id, SDL_Window* sdl_window)
{
- int device_id = motion.device_id;
- int id = motion.pointer_coordinates[cord_index].id;
+ int i, point_count;
+ point_count = MIR_mir_touch_event_point_count(touch);
- int width = sdl_window->w;
- int height = sdl_window->h;
- float x = motion.pointer_coordinates[cord_index].x;
- float y = motion.pointer_coordinates[cord_index].y;
+ AddTouchDevice(device_id);
- float n_x = x / width;
- float n_y = y / height;
- float pressure = motion.pointer_coordinates[cord_index].pressure;
+ for (i = 0; i < point_count; i++) {
+ int id = MIR_mir_touch_event_id(touch, i);
- AddTouchDevice(motion.device_id);
+ int width = sdl_window->w;
+ int height = sdl_window->h;
- switch (motion.action) {
- case mir_motion_action_down:
- case mir_motion_action_pointer_down:
- HandleTouchPress(device_id, id, SDL_TRUE, n_x, n_y, pressure);
- break;
- case mir_motion_action_up:
- case mir_motion_action_pointer_up:
- HandleTouchPress(device_id, id, SDL_FALSE, n_x, n_y, pressure);
- break;
- case mir_motion_action_hover_move:
- case mir_motion_action_move:
- HandleTouchMotion(device_id, id, n_x, n_y, pressure);
- break;
- default:
- break;
+ float x = MIR_mir_touch_event_axis_value(touch, i, mir_touch_axis_x);
+ float y = MIR_mir_touch_event_axis_value(touch, i, mir_touch_axis_y);
+
+ float n_x = x / width;
+ float n_y = y / height;
+
+ float pressure = MIR_mir_touch_event_axis_value(touch, i, mir_touch_axis_pressure);
+
+ switch (MIR_mir_touch_event_action(touch, i)) {
+ case mir_touch_action_up:
+ HandleTouchPress(device_id, id, SDL_FALSE, n_x, n_y, pressure);
+ break;
+ case mir_touch_action_down:
+ HandleTouchPress(device_id, id, SDL_TRUE, n_x, n_y, pressure);
+ break;
+ case mir_touch_action_change:
+ HandleTouchMotion(device_id, id, n_x, n_y, pressure);
+ break;
+ case mir_touch_actions:
+ break;
+ }
}
}
static void
-HandleMouseEvent(MirMotionEvent const motion, int cord_index, SDL_Window* sdl_window)
+HandleMouseEvent(MirPointerEvent const* pointer, SDL_Window* sdl_window)
{
SDL_SetMouseFocus(sdl_window);
- switch (motion.action) {
- case mir_motion_action_down:
- case mir_motion_action_pointer_down:
- HandleMouseButton(sdl_window, SDL_PRESSED, motion.button_state);
+ switch (MIR_mir_pointer_event_action(pointer)) {
+ case mir_pointer_action_button_down:
+ HandleMouseButton(sdl_window, SDL_PRESSED, pointer);
break;
- case mir_motion_action_up:
- case mir_motion_action_pointer_up:
- HandleMouseButton(sdl_window, SDL_RELEASED, motion.button_state);
+ case mir_pointer_action_button_up:
+ HandleMouseButton(sdl_window, SDL_RELEASED, pointer);
break;
- case mir_motion_action_hover_move:
- case mir_motion_action_move:
- HandleMouseMotion(sdl_window,
- motion.pointer_coordinates[cord_index].x,
- motion.pointer_coordinates[cord_index].y);
+ case mir_pointer_action_motion: {
+ int x, y;
+ int hscroll, vscroll;
+ SDL_Mouse* mouse = SDL_GetMouse();
+ x = MIR_mir_pointer_event_axis_value(pointer, mir_pointer_axis_x);
+ y = MIR_mir_pointer_event_axis_value(pointer, mir_pointer_axis_y);
+
+ if (mouse) {
+ if (mouse->relative_mode) {
+ int relative_x = MIR_mir_pointer_event_axis_value(pointer, mir_pointer_axis_relative_x);
+ int relative_y = MIR_mir_pointer_event_axis_value(pointer, mir_pointer_axis_relative_y);
+ HandleMouseMotion(sdl_window, relative_x, relative_y);
+ }
+ else if (mouse->x != x || mouse->y != y) {
+ HandleMouseMotion(sdl_window, x, y);
+ }
+ }
+
+ hscroll = MIR_mir_pointer_event_axis_value(pointer, mir_pointer_axis_hscroll);
+ vscroll = MIR_mir_pointer_event_axis_value(pointer, mir_pointer_axis_vscroll);
+ if (vscroll != 0 || hscroll != 0)
+ HandleMouseScroll(sdl_window, hscroll, vscroll);
+ }
break;
- case mir_motion_action_outside:
+ case mir_pointer_action_leave:
SDL_SetMouseFocus(NULL);
break;
- case mir_motion_action_scroll:
- HandleMouseScroll(sdl_window,
- motion.pointer_coordinates[cord_index].hscroll,
- motion.pointer_coordinates[cord_index].vscroll);
+ case mir_pointer_action_enter:
+ default:
break;
- case mir_motion_action_cancel:
- case mir_motion_action_hover_enter:
- case mir_motion_action_hover_exit:
+ }
+}
+
+static void
+MIR_HandleInput(MirInputEvent const* input_event, SDL_Window* window)
+{
+ switch (MIR_mir_input_event_get_type(input_event)) {
+ case (mir_input_event_type_key):
+ HandleKeyEvent(MIR_mir_input_event_get_keyboard_event(input_event), window);
+ break;
+ case (mir_input_event_type_pointer):
+ HandleMouseEvent(MIR_mir_input_event_get_pointer_event(input_event), window);
+ break;
+ case (mir_input_event_type_touch):
+ HandleTouchEvent(MIR_mir_input_event_get_touch_event(input_event),
+ MIR_mir_input_event_get_device_id(input_event),
+ window);
break;
default:
break;
@@ -220,32 +257,54 @@ HandleMouseEvent(MirMotionEvent const motion, int cord_index, SDL_Window* sdl_wi
}
static void
-HandleMotionEvent(MirMotionEvent const motion, SDL_Window* sdl_window)
+MIR_HandleResize(MirResizeEvent const* resize_event, SDL_Window* window)
{
- int cord_index;
- for (cord_index = 0; cord_index < motion.pointer_count; cord_index++) {
- if (motion.pointer_coordinates[cord_index].tool_type == mir_motion_tool_type_finger) {
- HandleTouchEvent(motion, cord_index, sdl_window);
+ int new_w = MIR_mir_resize_event_get_width (resize_event);
+ int new_h = MIR_mir_resize_event_get_height(resize_event);
+
+ int old_w = window->w;
+ int old_h = window->h;
+
+ if (new_w != old_w || new_h != old_h)
+ SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, new_w, new_h);
+}
+
+static void
+MIR_HandleSurface(MirSurfaceEvent const* surface_event, SDL_Window* window)
+{
+ MirSurfaceAttrib attrib = MIR_mir_surface_event_get_attribute(surface_event);
+ int value = MIR_mir_surface_event_get_attribute_value(surface_event);
+
+ if (attrib == mir_surface_attrib_focus) {
+ if (value == mir_surface_focused) {
+ SDL_SetKeyboardFocus(window);
}
- else {
- HandleMouseEvent(motion, cord_index, sdl_window);
+ else if (value == mir_surface_unfocused) {
+ SDL_SetKeyboardFocus(NULL);
}
}
}
void
-MIR_HandleInput(MirSurface* surface, MirEvent const* ev, void* context)
+MIR_HandleEvent(MirSurface* surface, MirEvent const* ev, void* context)
{
- SDL_Window* window = (SDL_Window*)context;
- switch (ev->type) {
- case (mir_event_type_key):
- HandleKeyEvent(ev->key, window);
- break;
- case (mir_event_type_motion):
- HandleMotionEvent(ev->motion, window);
- break;
- default:
- break;
+ MirEventType event_type = MIR_mir_event_get_type(ev);
+ SDL_Window* window = (SDL_Window*)context;
+
+ if (window) {
+ switch (event_type) {
+ case (mir_event_type_input):
+ MIR_HandleInput(MIR_mir_event_get_input_event(ev), window);
+ break;
+ case (mir_event_type_resize):
+ MIR_HandleResize(MIR_mir_event_get_resize_event(ev), window);
+ break;
+ case (mir_event_type_surface):
+ MIR_HandleSurface(MIR_mir_event_get_surface_event(ev), window);
+ break;
+ default:
+ break;
+ }
}
}
diff --git a/Engine/lib/sdl/src/video/mir/SDL_mirevents.h b/Engine/lib/sdl/src/video/mir/SDL_mirevents.h
index 3e0d96625..121c4b365 100644
--- a/Engine/lib/sdl/src/video/mir/SDL_mirevents.h
+++ b/Engine/lib/sdl/src/video/mir/SDL_mirevents.h
@@ -29,7 +29,7 @@
#include
extern void
-MIR_HandleInput(MirSurface* surface, MirEvent const* ev, void* context);
+MIR_HandleEvent(MirSurface* surface, MirEvent const* ev, void* context);
#endif /* _SDL_mirevents_h */
diff --git a/Engine/lib/sdl/src/video/mir/SDL_mirframebuffer.c b/Engine/lib/sdl/src/video/mir/SDL_mirframebuffer.c
index 53e6056ff..775bc0797 100644
--- a/Engine/lib/sdl/src/video/mir/SDL_mirframebuffer.c
+++ b/Engine/lib/sdl/src/video/mir/SDL_mirframebuffer.c
@@ -33,39 +33,18 @@
#include "SDL_mirdyn.h"
-static const Uint32 mir_pixel_format_to_sdl_format[] = {
- SDL_PIXELFORMAT_UNKNOWN, /* mir_pixel_format_invalid */
- SDL_PIXELFORMAT_ABGR8888, /* mir_pixel_format_abgr_8888 */
- SDL_PIXELFORMAT_BGR888, /* mir_pixel_format_xbgr_8888 */
- SDL_PIXELFORMAT_ARGB8888, /* mir_pixel_format_argb_8888 */
- SDL_PIXELFORMAT_RGB888, /* mir_pixel_format_xrgb_8888 */
- SDL_PIXELFORMAT_BGR24 /* mir_pixel_format_bgr_888 */
-};
-
-Uint32
-MIR_GetSDLPixelFormat(MirPixelFormat format)
-{
- return mir_pixel_format_to_sdl_format[format];
-}
-
int
MIR_CreateWindowFramebuffer(_THIS, SDL_Window* window, Uint32* format,
void** pixels, int* pitch)
{
MIR_Data* mir_data = _this->driverdata;
- MIR_Window* mir_window;
- MirSurfaceParameters surfaceparm;
mir_data->software = SDL_TRUE;
if (MIR_CreateWindow(_this, window) < 0)
return SDL_SetError("Failed to created a mir window.");
- mir_window = window->driverdata;
-
- MIR_mir_surface_get_parameters(mir_window->surface, &surfaceparm);
-
- *format = MIR_GetSDLPixelFormat(surfaceparm.pixel_format);
+ *format = MIR_GetSDLPixelFormat(mir_data->pixel_format);
if (*format == SDL_PIXELFORMAT_UNKNOWN)
return SDL_SetError("Unknown pixel format");
@@ -75,12 +54,6 @@ MIR_CreateWindowFramebuffer(_THIS, SDL_Window* window, Uint32* format,
if (*pixels == NULL)
return SDL_OutOfMemory();
- mir_window->surface = MIR_mir_connection_create_surface_sync(mir_data->connection, &surfaceparm);
- if (!MIR_mir_surface_is_valid(mir_window->surface)) {
- const char* error = MIR_mir_surface_get_error_message(mir_window->surface);
- return SDL_SetError("Failed to created a mir surface: %s", error);
- }
-
return 0;
}
@@ -91,12 +64,14 @@ MIR_UpdateWindowFramebuffer(_THIS, SDL_Window* window,
MIR_Window* mir_window = window->driverdata;
MirGraphicsRegion region;
+ MirBufferStream* bs;
int i, j, x, y, w, h, start;
int bytes_per_pixel, bytes_per_row, s_stride, d_stride;
char* s_dest;
char* pixels;
- MIR_mir_surface_get_graphics_region(mir_window->surface, ®ion);
+ bs = MIR_mir_surface_get_buffer_stream(mir_window->surface);
+ MIR_mir_buffer_stream_get_graphics_region(bs, ®ion);
s_dest = region.vaddr;
pixels = (char*)window->surface->pixels;
@@ -138,13 +113,13 @@ MIR_UpdateWindowFramebuffer(_THIS, SDL_Window* window,
bytes_per_row = bytes_per_pixel * w;
for (j = 0; j < h; j++) {
- memcpy(s_dest, pixels, bytes_per_row);
+ SDL_memcpy(s_dest, pixels, bytes_per_row);
pixels += s_stride;
s_dest += d_stride;
}
}
- MIR_mir_surface_swap_buffers_sync(mir_window->surface);
+ MIR_mir_buffer_stream_swap_buffers_sync(bs);
return 0;
}
diff --git a/Engine/lib/sdl/src/video/mir/SDL_mirmouse.c b/Engine/lib/sdl/src/video/mir/SDL_mirmouse.c
index bb8dc6c4e..1a22b28e8 100644
--- a/Engine/lib/sdl/src/video/mir/SDL_mirmouse.c
+++ b/Engine/lib/sdl/src/video/mir/SDL_mirmouse.c
@@ -27,13 +27,22 @@
#if SDL_VIDEO_DRIVER_MIR
-#include "SDL_mirmouse.h"
-
#include "../../events/SDL_mouse_c.h"
+#include "../SDL_sysvideo.h"
#include "SDL_assert.h"
#include "SDL_mirdyn.h"
+#include "SDL_mirvideo.h"
+#include "SDL_mirmouse.h"
+#include "SDL_mirwindow.h"
+
+typedef struct
+{
+ MirCursorConfiguration* conf;
+ MirBufferStream* stream;
+} MIR_Cursor;
+
static SDL_Cursor*
MIR_CreateDefaultCursor()
{
@@ -41,6 +50,18 @@ MIR_CreateDefaultCursor()
cursor = SDL_calloc(1, sizeof(SDL_Cursor));
if (cursor) {
+
+ MIR_Cursor* mir_cursor = SDL_calloc(1, sizeof(MIR_Cursor));
+ if (mir_cursor) {
+ mir_cursor->conf = NULL;
+ mir_cursor->stream = NULL;
+ cursor->driverdata = mir_cursor;
+ }
+ else {
+ SDL_OutOfMemory();
+ SDL_free(cursor);
+ cursor = NULL;
+ }
}
else {
SDL_OutOfMemory();
@@ -49,58 +70,168 @@ MIR_CreateDefaultCursor()
return cursor;
}
-static SDL_Cursor*
-MIR_CreateCursor(SDL_Surface* sruface, int hot_x, int hot_y)
+static void
+CopySurfacePixelsToMirStream(SDL_Surface* surface, MirBufferStream* stream)
{
- return MIR_CreateDefaultCursor();
+ char* dest, *pixels;
+ int i, s_w, s_h, r_stride, p_stride, bytes_per_pixel, bytes_per_row;
+
+ MirGraphicsRegion region;
+ MIR_mir_buffer_stream_get_graphics_region(stream, ®ion);
+
+ s_w = surface->w;
+ s_h = surface->h;
+
+ bytes_per_pixel = surface->format->BytesPerPixel;
+ bytes_per_row = bytes_per_pixel * s_w;
+
+ dest = region.vaddr;
+ pixels = (char*)surface->pixels;
+
+ r_stride = region.stride;
+ p_stride = surface->pitch;
+
+ for (i = 0; i < s_h; i++)
+ {
+ SDL_memcpy(dest, pixels, bytes_per_row);
+ dest += r_stride;
+ pixels += p_stride;
+ }
+}
+
+static SDL_Cursor*
+MIR_CreateCursor(SDL_Surface* surface, int hot_x, int hot_y)
+{
+ MirCursorConfiguration* conf;
+ MirBufferStream* stream;
+
+ int s_w = surface->w;
+ int s_h = surface->h;
+
+ MIR_Data* mir_data = (MIR_Data*)SDL_GetVideoDevice()->driverdata;
+ SDL_Cursor* cursor = MIR_CreateDefaultCursor();
+ MIR_Cursor* mir_cursor;
+
+ if (!cursor) {
+ return NULL;
+ }
+
+ mir_cursor = (MIR_Cursor*)cursor->driverdata;
+
+ stream = MIR_mir_connection_create_buffer_stream_sync(mir_data->connection,
+ s_w, s_h, mir_data->pixel_format,
+ mir_buffer_usage_software);
+
+ conf = MIR_mir_cursor_configuration_from_buffer_stream(stream, hot_x, hot_y);
+
+ CopySurfacePixelsToMirStream(surface, stream);
+ MIR_mir_buffer_stream_swap_buffers_sync(stream);
+
+ mir_cursor->conf = conf;
+ mir_cursor->stream = stream;
+
+ return cursor;
}
static SDL_Cursor*
MIR_CreateSystemCursor(SDL_SystemCursor id)
{
+ char const* cursor_name = NULL;
+ SDL_Cursor* cursor = MIR_CreateDefaultCursor();
+ MIR_Cursor* mir_cursor = (MIR_Cursor*)cursor->driverdata;
+
+ if (!cursor) {
+ return NULL;
+ }
+
switch(id) {
case SDL_SYSTEM_CURSOR_ARROW:
+ cursor_name = MIR_mir_arrow_cursor_name;
break;
case SDL_SYSTEM_CURSOR_IBEAM:
+ cursor_name = MIR_mir_caret_cursor_name;
break;
case SDL_SYSTEM_CURSOR_WAIT:
+ cursor_name = MIR_mir_busy_cursor_name;
break;
case SDL_SYSTEM_CURSOR_CROSSHAIR:
+ /* Unsupported */
+ cursor_name = MIR_mir_arrow_cursor_name;
break;
case SDL_SYSTEM_CURSOR_WAITARROW:
+ cursor_name = MIR_mir_busy_cursor_name;
break;
case SDL_SYSTEM_CURSOR_SIZENWSE:
+ cursor_name = MIR_mir_omnidirectional_resize_cursor_name;
break;
case SDL_SYSTEM_CURSOR_SIZENESW:
+ cursor_name = MIR_mir_omnidirectional_resize_cursor_name;
break;
case SDL_SYSTEM_CURSOR_SIZEWE:
+ cursor_name = MIR_mir_horizontal_resize_cursor_name;
break;
case SDL_SYSTEM_CURSOR_SIZENS:
+ cursor_name = MIR_mir_vertical_resize_cursor_name;
break;
case SDL_SYSTEM_CURSOR_SIZEALL:
+ cursor_name = MIR_mir_omnidirectional_resize_cursor_name;
break;
case SDL_SYSTEM_CURSOR_NO:
+ /* Unsupported */
+ cursor_name = MIR_mir_closed_hand_cursor_name;
break;
case SDL_SYSTEM_CURSOR_HAND:
+ cursor_name = MIR_mir_open_hand_cursor_name;
break;
default:
SDL_assert(0);
return NULL;
}
- return MIR_CreateDefaultCursor();
+ mir_cursor->conf = MIR_mir_cursor_configuration_from_name(cursor_name);
+
+ return cursor;
}
static void
MIR_FreeCursor(SDL_Cursor* cursor)
{
- if (cursor)
- SDL_free(cursor);
+ if (cursor) {
+
+ if (cursor->driverdata) {
+ MIR_Cursor* mir_cursor = (MIR_Cursor*)cursor->driverdata;
+
+ if (mir_cursor->conf)
+ MIR_mir_cursor_configuration_destroy(mir_cursor->conf);
+ if (mir_cursor->stream)
+ MIR_mir_buffer_stream_release_sync(mir_cursor->stream);
+
+ SDL_free(mir_cursor);
+ }
+
+ SDL_free(cursor);
+ }
}
static int
MIR_ShowCursor(SDL_Cursor* cursor)
{
+ MIR_Data* mir_data = (MIR_Data*)SDL_GetVideoDevice()->driverdata;
+ MIR_Window* mir_window = mir_data->current_window;
+
+ if (cursor && cursor->driverdata) {
+ if (mir_window && MIR_mir_surface_is_valid(mir_window->surface)) {
+ MIR_Cursor* mir_cursor = (MIR_Cursor*)cursor->driverdata;
+
+ if (mir_cursor->conf) {
+ MIR_mir_surface_configure_cursor(mir_window->surface, mir_cursor->conf);
+ }
+ }
+ }
+ else if(mir_window && MIR_mir_surface_is_valid(mir_window->surface)) {
+ MIR_mir_surface_configure_cursor(mir_window->surface, NULL);
+ }
+
return 0;
}
@@ -119,7 +250,7 @@ MIR_WarpMouseGlobal(int x, int y)
static int
MIR_SetRelativeMouseMode(SDL_bool enabled)
{
- return SDL_Unsupported();
+ return 0;
}
/* TODO Actually implement the cursor, need to wait for mir support */
diff --git a/Engine/lib/sdl/src/video/mir/SDL_mirsym.h b/Engine/lib/sdl/src/video/mir/SDL_mirsym.h
index d0aaf70a3..4f97ed96c 100644
--- a/Engine/lib/sdl/src/video/mir/SDL_mirsym.h
+++ b/Engine/lib/sdl/src/video/mir/SDL_mirsym.h
@@ -21,29 +21,122 @@
/* *INDENT-OFF* */
+#ifndef SDL_MIR_MODULE
+#define SDL_MIR_MODULE(modname)
+#endif
+
+#ifndef SDL_MIR_SYM
+#define SDL_MIR_SYM(rc,fn,params)
+#endif
+
+#ifndef SDL_MIR_SYM_CONST
+#define SDL_MIR_SYM_CONST(type, name)
+#endif
+
SDL_MIR_MODULE(MIR_CLIENT)
-SDL_MIR_SYM(MirDisplayConfiguration*,mir_connection_create_display_config,(MirConnection *connection))
-SDL_MIR_SYM(MirSurface *,mir_connection_create_surface_sync,(MirConnection *connection, MirSurfaceParameters const *params))
+SDL_MIR_SYM(MirSurface *,mir_surface_create_sync,(MirSurfaceSpec* spec))
+SDL_MIR_SYM(MirEGLNativeWindowType,mir_buffer_stream_get_egl_native_window,(MirBufferStream *surface))
+SDL_MIR_SYM(void,mir_buffer_stream_get_graphics_region,(MirBufferStream *stream, MirGraphicsRegion *graphics_region))
+SDL_MIR_SYM(void,mir_buffer_stream_swap_buffers_sync,(MirBufferStream *stream))
+SDL_MIR_SYM(void,mir_surface_set_event_handler,(MirSurface *surface, mir_surface_event_callback callback, void* context))
+SDL_MIR_SYM(MirSurfaceSpec*,mir_connection_create_spec_for_normal_surface,(MirConnection *connection, int width, int height, MirPixelFormat format))
+SDL_MIR_SYM(MirSurfaceSpec*,mir_connection_create_spec_for_changes,(MirConnection *connection))
+SDL_MIR_SYM(void,mir_surface_spec_set_buffer_usage,(MirSurfaceSpec *spec, MirBufferUsage usage))
+SDL_MIR_SYM(void,mir_surface_spec_set_name,(MirSurfaceSpec *spec, char const *name))
+SDL_MIR_SYM(void,mir_surface_spec_release,(MirSurfaceSpec *spec))
+SDL_MIR_SYM(void,mir_surface_spec_set_width,(MirSurfaceSpec *spec, unsigned width))
+SDL_MIR_SYM(void,mir_surface_spec_set_height,(MirSurfaceSpec *spec, unsigned height))
+SDL_MIR_SYM(void,mir_surface_spec_set_min_width,(MirSurfaceSpec *spec, unsigned min_width))
+SDL_MIR_SYM(void,mir_surface_spec_set_min_height,(MirSurfaceSpec *spec, unsigned min_height))
+SDL_MIR_SYM(void,mir_surface_spec_set_max_width,(MirSurfaceSpec *spec, unsigned max_width))
+SDL_MIR_SYM(void,mir_surface_spec_set_max_height,(MirSurfaceSpec *spec, unsigned max_height))
+SDL_MIR_SYM(void,mir_surface_spec_set_type,(MirSurfaceSpec *spec, MirSurfaceType type))
+SDL_MIR_SYM(void,mir_surface_spec_set_state,(MirSurfaceSpec *spec, MirSurfaceState state))
+SDL_MIR_SYM(void,mir_surface_spec_set_pointer_confinement,(MirSurfaceSpec *spec, MirPointerConfinementState state))
+SDL_MIR_SYM(void,mir_surface_apply_spec,(MirSurface *surface, MirSurfaceSpec *spec))
+SDL_MIR_SYM(void,mir_surface_get_parameters,(MirSurface *surface, MirSurfaceParameters *params))
+SDL_MIR_SYM(MirBufferStream*,mir_surface_get_buffer_stream,(MirSurface *surface))
+SDL_MIR_SYM(MirCursorConfiguration*,mir_cursor_configuration_from_buffer_stream,(MirBufferStream const* stream, int hot_x, int hot_y))
+SDL_MIR_SYM(MirBufferStream*,mir_connection_create_buffer_stream_sync,(MirConnection *connection, int w, int h, MirPixelFormat format, MirBufferUsage usage))
+SDL_MIR_SYM(MirKeyboardAction,mir_keyboard_event_action,(MirKeyboardEvent const *event))
+SDL_MIR_SYM(xkb_keysym_t,mir_keyboard_event_key_code,(MirKeyboardEvent const *event))
+SDL_MIR_SYM(int,mir_keyboard_event_scan_code,(MirKeyboardEvent const *event))
+SDL_MIR_SYM(bool,mir_pointer_event_button_state,(MirPointerEvent const *event, MirPointerButton button))
+SDL_MIR_SYM(MirPointerButtons,mir_pointer_event_buttons,(MirPointerEvent const *event))
+SDL_MIR_SYM(MirInputDeviceId,mir_input_event_get_device_id,(MirInputEvent const* ev))
+SDL_MIR_SYM(MirTouchId,mir_touch_event_id,(MirTouchEvent const *event, size_t touch_index))
+SDL_MIR_SYM(float,mir_touch_event_axis_value,(MirTouchEvent const *event, size_t touch_index, MirTouchAxis axis))
+SDL_MIR_SYM(MirTouchAction,mir_touch_event_action,(MirTouchEvent const *event, size_t touch_index))
+SDL_MIR_SYM(MirPointerAction,mir_pointer_event_action,(MirPointerEvent const *event))
+SDL_MIR_SYM(float,mir_pointer_event_axis_value,(MirPointerEvent const *event, MirPointerAxis))
+SDL_MIR_SYM(MirEventType,mir_event_get_type,(MirEvent const *event))
+SDL_MIR_SYM(MirInputEventType,mir_input_event_get_type,(MirInputEvent const *event))
+SDL_MIR_SYM(MirInputEvent const*,mir_event_get_input_event,(MirEvent const *event))
+SDL_MIR_SYM(MirResizeEvent const*,mir_event_get_resize_event,(MirEvent const *event))
+SDL_MIR_SYM(MirKeyboardEvent const*,mir_input_event_get_keyboard_event,(MirInputEvent const *event))
+SDL_MIR_SYM(MirPointerEvent const*,mir_input_event_get_pointer_event,(MirInputEvent const *event))
+SDL_MIR_SYM(MirTouchEvent const*,mir_input_event_get_touch_event,(MirInputEvent const *event))
+SDL_MIR_SYM(MirSurfaceEvent const*,mir_event_get_surface_event,(MirEvent const *event))
+SDL_MIR_SYM(unsigned int,mir_touch_event_point_count,(MirTouchEvent const *event))
SDL_MIR_SYM(void,mir_connection_get_available_surface_formats,(MirConnection* connection, MirPixelFormat* formats, unsigned const int format_size, unsigned int *num_valid_formats))
SDL_MIR_SYM(MirEGLNativeDisplayType,mir_connection_get_egl_native_display,(MirConnection *connection))
-SDL_MIR_SYM(MirBool,mir_connection_is_valid,(MirConnection *connection))
+SDL_MIR_SYM(bool,mir_connection_is_valid,(MirConnection *connection))
SDL_MIR_SYM(void,mir_connection_release,(MirConnection *connection))
+SDL_MIR_SYM(MirPixelFormat,mir_connection_get_egl_pixel_format,(MirConnection* connection, void* egldisplay, void* eglconfig))
SDL_MIR_SYM(MirConnection *,mir_connect_sync,(char const *server, char const *app_name))
-SDL_MIR_SYM(void,mir_display_config_destroy,(MirDisplayConfiguration* display_configuration))
-SDL_MIR_SYM(MirEGLNativeWindowType,mir_surface_get_egl_native_window,(MirSurface *surface))
SDL_MIR_SYM(char const *,mir_surface_get_error_message,(MirSurface *surface))
-SDL_MIR_SYM(void,mir_surface_get_graphics_region,(MirSurface *surface, MirGraphicsRegion *graphics_region))
-SDL_MIR_SYM(void,mir_surface_get_parameters,(MirSurface *surface, MirSurfaceParameters *parameters))
-SDL_MIR_SYM(MirBool,mir_surface_is_valid,(MirSurface *surface))
+SDL_MIR_SYM(bool,mir_surface_is_valid,(MirSurface *surface))
SDL_MIR_SYM(void,mir_surface_release_sync,(MirSurface *surface))
-SDL_MIR_SYM(void,mir_surface_set_event_handler,(MirSurface *surface, MirEventDelegate const *event_handler))
-SDL_MIR_SYM(MirWaitHandle*,mir_surface_set_type,(MirSurface *surface, MirSurfaceType type))
-SDL_MIR_SYM(MirWaitHandle*,mir_surface_set_state,(MirSurface *surface, MirSurfaceState state))
-SDL_MIR_SYM(void,mir_surface_swap_buffers_sync,(MirSurface *surface))
+SDL_MIR_SYM(void,mir_buffer_stream_release_sync,(MirBufferStream *stream))
+SDL_MIR_SYM(MirCursorConfiguration*,mir_cursor_configuration_from_name,(char const* cursor_name))
+SDL_MIR_SYM(MirWaitHandle*,mir_surface_configure_cursor,(MirSurface* surface, MirCursorConfiguration const* conf))
+SDL_MIR_SYM(void,mir_cursor_configuration_destroy,(MirCursorConfiguration* conf))
+SDL_MIR_SYM(int,mir_resize_event_get_width,(MirResizeEvent const* resize_event))
+SDL_MIR_SYM(int,mir_resize_event_get_height,(MirResizeEvent const* resize_event))
+SDL_MIR_SYM(char const*,mir_connection_get_error_message,(MirConnection* connection))
+SDL_MIR_SYM(MirSurfaceAttrib,mir_surface_event_get_attribute,(MirSurfaceEvent const* surface_event))
+SDL_MIR_SYM(int,mir_surface_event_get_attribute_value,(MirSurfaceEvent const* surface_event))
+SDL_MIR_SYM(void,mir_wait_for,(MirWaitHandle* handle))
+SDL_MIR_SYM(MirDisplayConfig*,mir_connection_create_display_configuration,(MirConnection* connection))
+SDL_MIR_SYM(void,mir_display_config_release,(MirDisplayConfig* config))
+SDL_MIR_SYM(int,mir_display_config_get_num_outputs,(MirDisplayConfig const* config))
+SDL_MIR_SYM(MirOutput*,mir_display_config_get_mutable_output,(MirDisplayConfig* config, size_t index))
+SDL_MIR_SYM(int,mir_output_get_num_modes,(MirOutput const* output))
+SDL_MIR_SYM(MirPixelFormat,mir_output_get_current_pixel_format,(MirOutput const* output))
+SDL_MIR_SYM(int,mir_output_get_position_x,(MirOutput const* output))
+SDL_MIR_SYM(int,mir_output_get_position_y,(MirOutput const* output))
+SDL_MIR_SYM(bool,mir_output_is_enabled,(MirOutput const* output))
+SDL_MIR_SYM(MirOutputConnectionState,mir_output_get_connection_state,(MirOutput const* output))
+SDL_MIR_SYM(size_t,mir_output_get_preferred_mode_index,(MirOutput const* output))
+SDL_MIR_SYM(MirOutputType,mir_output_get_type,(MirOutput const* output))
+SDL_MIR_SYM(char const*,mir_output_type_name,(MirOutputType type))
+SDL_MIR_SYM(void,mir_output_set_current_mode,(MirOutput* output, MirOutputMode const* mode))
+SDL_MIR_SYM(MirOutputMode const*,mir_output_get_mode,(MirOutput const* output, size_t index))
+SDL_MIR_SYM(int,mir_output_mode_get_width,(MirOutputMode const* mode))
+SDL_MIR_SYM(int,mir_output_mode_get_height,(MirOutputMode const* mode))
+SDL_MIR_SYM(double,mir_output_mode_get_refresh_rate,(MirOutputMode const* mode))
+SDL_MIR_SYM(MirOutputGammaSupported,mir_output_is_gamma_supported,(MirOutput const* output))
+SDL_MIR_SYM(uint32_t,mir_output_get_gamma_size,(MirOutput const* output))
+SDL_MIR_SYM(void,mir_output_get_gamma,(MirOutput const* output, uint16_t* red, uint16_t* green, uint16_t* blue, uint32_t size))
+SDL_MIR_SYM(void,mir_output_set_gamma,(MirOutput* output, uint16_t const* red, uint16_t const* green, uint16_t const* blue, uint32_t size))
+
+SDL_MIR_SYM_CONST(char const*,mir_omnidirectional_resize_cursor_name)
+SDL_MIR_SYM_CONST(char const*,mir_busy_cursor_name)
+SDL_MIR_SYM_CONST(char const*,mir_arrow_cursor_name)
+SDL_MIR_SYM_CONST(char const*,mir_caret_cursor_name)
+SDL_MIR_SYM_CONST(char const*,mir_vertical_resize_cursor_name)
+SDL_MIR_SYM_CONST(char const*,mir_horizontal_resize_cursor_name)
+SDL_MIR_SYM_CONST(char const*,mir_open_hand_cursor_name)
+SDL_MIR_SYM_CONST(char const*,mir_closed_hand_cursor_name)
+SDL_MIR_SYM_CONST(char const*,mir_disabled_cursor_name)
SDL_MIR_MODULE(XKBCOMMON)
SDL_MIR_SYM(int,xkb_keysym_to_utf8,(xkb_keysym_t keysym, char *buffer, size_t size))
+#undef SDL_MIR_MODULE
+#undef SDL_MIR_SYM
+#undef SDL_MIR_SYM_CONST
+
/* *INDENT-ON* */
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/video/mir/SDL_mirvideo.c b/Engine/lib/sdl/src/video/mir/SDL_mirvideo.c
index b6160fd92..6a8f9e482 100644
--- a/Engine/lib/sdl/src/video/mir/SDL_mirvideo.c
+++ b/Engine/lib/sdl/src/video/mir/SDL_mirvideo.c
@@ -27,18 +27,37 @@
#if SDL_VIDEO_DRIVER_MIR
+#include "SDL_mirwindow.h"
#include "SDL_video.h"
#include "SDL_mirframebuffer.h"
#include "SDL_mirmouse.h"
#include "SDL_miropengl.h"
#include "SDL_mirvideo.h"
-#include "SDL_mirwindow.h"
#include "SDL_mirdyn.h"
#define MIR_DRIVER_NAME "mir"
+static const Uint32 mir_pixel_format_to_sdl_format[] = {
+ SDL_PIXELFORMAT_UNKNOWN, /* mir_pixel_format_invalid */
+ SDL_PIXELFORMAT_ABGR8888, /* mir_pixel_format_abgr_8888 */
+ SDL_PIXELFORMAT_BGR888, /* mir_pixel_format_xbgr_8888 */
+ SDL_PIXELFORMAT_ARGB8888, /* mir_pixel_format_argb_8888 */
+ SDL_PIXELFORMAT_RGB888, /* mir_pixel_format_xrgb_8888 */
+ SDL_PIXELFORMAT_BGR24, /* mir_pixel_format_bgr_888 */
+ SDL_PIXELFORMAT_RGB24, /* mir_pixel_format_rgb_888 */
+ SDL_PIXELFORMAT_RGB565, /* mir_pixel_format_rgb_565 */
+ SDL_PIXELFORMAT_RGBA5551, /* mir_pixel_format_rgba_5551 */
+ SDL_PIXELFORMAT_RGBA4444 /* mir_pixel_format_rgba_4444 */
+};
+
+Uint32
+MIR_GetSDLPixelFormat(MirPixelFormat format)
+{
+ return mir_pixel_format_to_sdl_format[format];
+}
+
static int
MIR_VideoInit(_THIS);
@@ -94,7 +113,7 @@ MIR_DeleteDevice(SDL_VideoDevice* device)
SDL_MIR_UnloadSymbols();
}
-void
+static void
MIR_PumpEvents(_THIS)
{
}
@@ -146,29 +165,30 @@ MIR_CreateDevice(int device_index)
device->GL_GetProcAddress = MIR_GL_GetProcAddress;
/* mirwindow */
- device->CreateWindow = MIR_CreateWindow;
- device->DestroyWindow = MIR_DestroyWindow;
- device->GetWindowWMInfo = MIR_GetWindowWMInfo;
- device->SetWindowFullscreen = MIR_SetWindowFullscreen;
- device->MaximizeWindow = MIR_MaximizeWindow;
- device->MinimizeWindow = MIR_MinimizeWindow;
- device->RestoreWindow = MIR_RestoreWindow;
+ device->CreateWindow = MIR_CreateWindow;
+ device->DestroyWindow = MIR_DestroyWindow;
+ device->GetWindowWMInfo = MIR_GetWindowWMInfo;
+ device->SetWindowFullscreen = MIR_SetWindowFullscreen;
+ device->MaximizeWindow = MIR_MaximizeWindow;
+ device->MinimizeWindow = MIR_MinimizeWindow;
+ device->RestoreWindow = MIR_RestoreWindow;
+ device->ShowWindow = MIR_RestoreWindow;
+ device->HideWindow = MIR_HideWindow;
+ device->SetWindowSize = MIR_SetWindowSize;
+ device->SetWindowMinimumSize = MIR_SetWindowMinimumSize;
+ device->SetWindowMaximumSize = MIR_SetWindowMaximumSize;
+ device->SetWindowTitle = MIR_SetWindowTitle;
+ device->SetWindowGrab = MIR_SetWindowGrab;
+ device->SetWindowGammaRamp = MIR_SetWindowGammaRamp;
+ device->GetWindowGammaRamp = MIR_GetWindowGammaRamp;
device->CreateWindowFrom = NULL;
- device->SetWindowTitle = NULL;
device->SetWindowIcon = NULL;
- device->SetWindowPosition = NULL;
- device->SetWindowSize = NULL;
- device->SetWindowMinimumSize = NULL;
- device->SetWindowMaximumSize = NULL;
- device->ShowWindow = NULL;
- device->HideWindow = NULL;
device->RaiseWindow = NULL;
device->SetWindowBordered = NULL;
- device->SetWindowGammaRamp = NULL;
- device->GetWindowGammaRamp = NULL;
- device->SetWindowGrab = NULL;
+ device->SetWindowResizable = NULL;
device->OnWindowEnter = NULL;
+ device->SetWindowPosition = NULL;
/* mirframebuffer */
device->CreateWindowFramebuffer = MIR_CreateWindowFramebuffer;
@@ -206,77 +226,88 @@ VideoBootStrap MIR_bootstrap = {
MIR_Available, MIR_CreateDevice
};
-static void
-MIR_SetCurrentDisplayMode(MirDisplayOutput const* out, SDL_VideoDisplay* display)
+static SDL_DisplayMode
+MIR_ConvertModeToSDLMode(MirOutputMode const* mode, MirPixelFormat format)
{
- SDL_DisplayMode mode = {
- .format = SDL_PIXELFORMAT_RGB888,
- .w = out->modes[out->current_mode].horizontal_resolution,
- .h = out->modes[out->current_mode].vertical_resolution,
- .refresh_rate = out->modes[out->current_mode].refresh_rate,
- .driverdata = NULL
+ SDL_DisplayMode sdl_mode = {
+ .format = MIR_GetSDLPixelFormat(format),
+ .w = MIR_mir_output_mode_get_width(mode),
+ .h = MIR_mir_output_mode_get_height(mode),
+ .refresh_rate = MIR_mir_output_mode_get_refresh_rate(mode),
+ .driverdata = NULL
};
- display->desktop_mode = mode;
- display->current_mode = mode;
+ return sdl_mode;
}
static void
-MIR_AddAllModesFromDisplay(MirDisplayOutput const* out, SDL_VideoDisplay* display)
+MIR_AddModeToDisplay(SDL_VideoDisplay* display, MirOutputMode const* mode, MirPixelFormat format)
{
- int n_mode;
- for (n_mode = 0; n_mode < out->num_modes; ++n_mode) {
- SDL_DisplayMode mode = {
- .format = SDL_PIXELFORMAT_RGB888,
- .w = out->modes[n_mode].horizontal_resolution,
- .h = out->modes[n_mode].vertical_resolution,
- .refresh_rate = out->modes[n_mode].refresh_rate,
- .driverdata = NULL
- };
+ SDL_DisplayMode sdl_mode = MIR_ConvertModeToSDLMode(mode, format);
+ SDL_AddDisplayMode(display, &sdl_mode);
+}
- SDL_AddDisplayMode(display, &mode);
+static void
+MIR_InitDisplayFromOutput(_THIS, MirOutput* output)
+{
+ SDL_VideoDisplay display;
+ int m;
+
+ MirPixelFormat format = MIR_mir_output_get_current_pixel_format(output);
+ int num_modes = MIR_mir_output_get_num_modes(output);
+ SDL_DisplayMode current_mode = MIR_ConvertModeToSDLMode(mir_output_get_current_mode(output), format);
+
+ SDL_zero(display);
+
+ // Unfortunate cast, but SDL_AddVideoDisplay will strdup this pointer so its read-only in this case.
+ display.name = (char*)MIR_mir_output_type_name(MIR_mir_output_get_type(output));
+
+ for (m = 0; m < num_modes; m++) {
+ MirOutputMode const* mode = MIR_mir_output_get_mode(output, m);
+ MIR_AddModeToDisplay(&display, mode, format);
}
+
+ display.desktop_mode = current_mode;
+ display.current_mode = current_mode;
+
+ display.driverdata = output;
+ SDL_AddVideoDisplay(&display);
}
static void
MIR_InitDisplays(_THIS)
{
MIR_Data* mir_data = _this->driverdata;
+ int num_outputs = MIR_mir_display_config_get_num_outputs(mir_data->display_config);
int d;
- MirDisplayConfiguration* display_config = MIR_mir_connection_create_display_config(mir_data->connection);
+ for (d = 0; d < num_outputs; d++) {
+ MirOutput* output = MIR_mir_display_config_get_mutable_output(mir_data->display_config, d);
+ SDL_bool enabled = MIR_mir_output_is_enabled(output);
+ MirOutputConnectionState state = MIR_mir_output_get_connection_state(output);
- for (d = 0; d < display_config->num_outputs; d++) {
- MirDisplayOutput const* out = display_config->outputs + d;
-
- SDL_VideoDisplay display;
- SDL_zero(display);
-
- if (out->used &&
- out->connected &&
- out->num_modes &&
- out->current_mode < out->num_modes) {
-
- MIR_SetCurrentDisplayMode(out, &display);
- MIR_AddAllModesFromDisplay(out, &display);
-
- SDL_AddVideoDisplay(&display);
+ if (enabled && state == mir_output_connection_state_connected) {
+ MIR_InitDisplayFromOutput(_this, output);
}
}
-
- MIR_mir_display_config_destroy(display_config);
}
-int
+static int
MIR_VideoInit(_THIS)
{
MIR_Data* mir_data = _this->driverdata;
- mir_data->connection = MIR_mir_connect_sync(NULL, __PRETTY_FUNCTION__);
- mir_data->software = SDL_FALSE;
+ mir_data->connection = MIR_mir_connect_sync(NULL, __PRETTY_FUNCTION__);
+ mir_data->current_window = NULL;
+ mir_data->software = SDL_FALSE;
+ mir_data->pixel_format = mir_pixel_format_invalid;
- if (!MIR_mir_connection_is_valid(mir_data->connection))
- return SDL_SetError("Failed to connect to the Mir Server");
+ if (!MIR_mir_connection_is_valid(mir_data->connection)) {
+ return SDL_SetError("Failed to connect to the mir server: %s",
+ MIR_mir_connection_get_error_message(mir_data->connection));
+ }
+
+ mir_data->display_config = MIR_mir_connection_create_display_configuration(mir_data->connection);
MIR_InitDisplays(_this);
MIR_InitMouse();
@@ -284,11 +315,27 @@ MIR_VideoInit(_THIS)
return 0;
}
-void
+static void
+MIR_CleanUpDisplayConfig(_THIS)
+{
+ MIR_Data* mir_data = _this->driverdata;
+ int i;
+
+ // SDL_VideoQuit frees the display driverdata, we own it not them
+ for (i = 0; i < _this->num_displays; ++i) {
+ _this->displays[i].driverdata = NULL;
+ }
+
+ MIR_mir_display_config_release(mir_data->display_config);
+}
+
+static void
MIR_VideoQuit(_THIS)
{
MIR_Data* mir_data = _this->driverdata;
+ MIR_CleanUpDisplayConfig(_this);
+
MIR_FiniMouse();
MIR_GL_DeleteContext(_this, NULL);
@@ -303,40 +350,48 @@ MIR_VideoQuit(_THIS)
static int
MIR_GetDisplayBounds(_THIS, SDL_VideoDisplay* display, SDL_Rect* rect)
{
- MIR_Data* mir_data = _this->driverdata;
- int d;
+ MirOutput const* output = display->driverdata;
- MirDisplayConfiguration* display_config = MIR_mir_connection_create_display_config(mir_data->connection);
-
- for (d = 0; d < display_config->num_outputs; d++) {
- MirDisplayOutput const* out = display_config->outputs + d;
-
- if (out->used &&
- out->connected &&
- out->num_modes &&
- out->current_mode < out->num_modes) {
-
- rect->x = out->position_x;
- rect->y = out->position_y;
- rect->w = out->modes->horizontal_resolution;
- rect->h = out->modes->vertical_resolution;
- }
- }
-
- MIR_mir_display_config_destroy(display_config);
+ rect->x = MIR_mir_output_get_position_x(output);
+ rect->y = MIR_mir_output_get_position_y(output);
+ rect->w = display->current_mode.w;
+ rect->h = display->current_mode.h;
return 0;
}
static void
-MIR_GetDisplayModes(_THIS, SDL_VideoDisplay* sdl_display)
+MIR_GetDisplayModes(_THIS, SDL_VideoDisplay* display)
{
}
static int
-MIR_SetDisplayMode(_THIS, SDL_VideoDisplay* sdl_display, SDL_DisplayMode* mode)
+MIR_SetDisplayMode(_THIS, SDL_VideoDisplay* display, SDL_DisplayMode* mode)
{
- return 0;
+ int m;
+ MirOutput* output = display->driverdata;
+ int num_modes = MIR_mir_output_get_num_modes(output);
+ Uint32 sdl_format = MIR_GetSDLPixelFormat(
+ MIR_mir_output_get_current_pixel_format(output));
+
+ for (m = 0; m < num_modes; m++) {
+ MirOutputMode const* mir_mode = MIR_mir_output_get_mode(output, m);
+ int width = MIR_mir_output_mode_get_width(mir_mode);
+ int height = MIR_mir_output_mode_get_height(mir_mode);
+ double refresh_rate = MIR_mir_output_mode_get_refresh_rate(mir_mode);
+
+ if (mode->format == sdl_format &&
+ mode->w == width &&
+ mode->h == height &&
+ mode->refresh_rate == refresh_rate) {
+
+ // FIXME Currently wont actually *set* anything. Need to wait for applying display changes
+ MIR_mir_output_set_current_mode(output, mir_mode);
+ return 0;
+ }
+ }
+
+ return -1;
}
#endif /* SDL_VIDEO_DRIVER_MIR */
diff --git a/Engine/lib/sdl/src/video/mir/SDL_mirvideo.h b/Engine/lib/sdl/src/video/mir/SDL_mirvideo.h
index c5ef4758d..71ef4ecc1 100644
--- a/Engine/lib/sdl/src/video/mir/SDL_mirvideo.h
+++ b/Engine/lib/sdl/src/video/mir/SDL_mirvideo.h
@@ -29,13 +29,20 @@
#include
#include
+typedef struct MIR_Window MIR_Window;
+
typedef struct
{
- MirConnection* connection;
- SDL_bool software;
-
+ MirConnection* connection;
+ MirDisplayConfig* display_config;
+ MIR_Window* current_window;
+ SDL_bool software;
+ MirPixelFormat pixel_format;
} MIR_Data;
+extern Uint32
+MIR_GetSDLPixelFormat(MirPixelFormat format);
+
#endif /* _SDL_mirvideo_h_ */
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/video/mir/SDL_mirwindow.c b/Engine/lib/sdl/src/video/mir/SDL_mirwindow.c
index 0eb54be01..1bf9016a0 100644
--- a/Engine/lib/sdl/src/video/mir/SDL_mirwindow.c
+++ b/Engine/lib/sdl/src/video/mir/SDL_mirwindow.c
@@ -29,6 +29,7 @@
#include "../SDL_egl_c.h"
#include "../SDL_sysvideo.h"
+#include "../../events/SDL_keyboard_c.h"
#include "SDL_mirevents.h"
#include "SDL_mirwindow.h"
@@ -55,7 +56,7 @@ FindValidPixelFormat(MIR_Data* mir_data)
MirPixelFormat formats[pf_size];
MIR_mir_connection_get_available_surface_formats(mir_data->connection, formats,
- pf_size, &valid_formats);
+ pf_size, &valid_formats);
for (f = 0; f < valid_formats; f++) {
MirPixelFormat cur_pf = formats[f];
@@ -77,21 +78,10 @@ MIR_CreateWindow(_THIS, SDL_Window* window)
{
MIR_Window* mir_window;
MIR_Data* mir_data;
+ MirPixelFormat pixel_format;
+ MirBufferUsage buffer_usage;
- MirSurfaceParameters surfaceparm =
- {
- .name = "MirSurface",
- .width = window->w,
- .height = window->h,
- .pixel_format = mir_pixel_format_invalid,
- .buffer_usage = mir_buffer_usage_hardware,
- .output_id = mir_display_output_id_invalid
- };
-
- MirEventDelegate delegate = {
- MIR_HandleInput,
- window
- };
+ MirSurfaceSpec* spec;
mir_window = SDL_calloc(1, sizeof(MIR_Window));
if (!mir_window)
@@ -100,9 +90,6 @@ MIR_CreateWindow(_THIS, SDL_Window* window)
mir_data = _this->driverdata;
window->driverdata = mir_window;
- if (mir_data->software)
- surfaceparm.buffer_usage = mir_buffer_usage_software;
-
if (window->x == SDL_WINDOWPOS_UNDEFINED)
window->x = 0;
@@ -112,20 +99,49 @@ MIR_CreateWindow(_THIS, SDL_Window* window)
mir_window->mir_data = mir_data;
mir_window->sdl_window = window;
- surfaceparm.pixel_format = FindValidPixelFormat(mir_data);
- if (surfaceparm.pixel_format == mir_pixel_format_invalid) {
+ if (window->flags & SDL_WINDOW_OPENGL) {
+ pixel_format = MIR_mir_connection_get_egl_pixel_format(mir_data->connection,
+ _this->egl_data->egl_display,
+ _this->egl_data->egl_config);
+ }
+ else {
+ pixel_format = FindValidPixelFormat(mir_data);
+ }
+
+ mir_data->pixel_format = pixel_format;
+ if (pixel_format == mir_pixel_format_invalid) {
return SDL_SetError("Failed to find a valid pixel format.");
}
- mir_window->surface = MIR_mir_connection_create_surface_sync(mir_data->connection, &surfaceparm);
+ buffer_usage = mir_buffer_usage_hardware;
+ if (mir_data->software)
+ buffer_usage = mir_buffer_usage_software;
+
+ spec = MIR_mir_connection_create_spec_for_normal_surface(mir_data->connection,
+ window->w,
+ window->h,
+ pixel_format);
+
+ MIR_mir_surface_spec_set_buffer_usage(spec, buffer_usage);
+ MIR_mir_surface_spec_set_name(spec, "Mir surface");
+
+ if (window->flags & SDL_WINDOW_INPUT_FOCUS)
+ SDL_SetKeyboardFocus(window);
+
+ mir_window->surface = MIR_mir_surface_create_sync(spec);
+ MIR_mir_surface_set_event_handler(mir_window->surface, MIR_HandleEvent, window);
+
+ MIR_mir_surface_spec_release(spec);
+
if (!MIR_mir_surface_is_valid(mir_window->surface)) {
- const char* error = MIR_mir_surface_get_error_message(mir_window->surface);
- return SDL_SetError("Failed to created a mir surface: %s", error);
+ return SDL_SetError("Failed to created a mir surface: %s",
+ MIR_mir_surface_get_error_message(mir_window->surface));
}
if (window->flags & SDL_WINDOW_OPENGL) {
EGLNativeWindowType egl_native_window =
- (EGLNativeWindowType)MIR_mir_surface_get_egl_native_window(mir_window->surface);
+ (EGLNativeWindowType)MIR_mir_buffer_stream_get_egl_native_window(
+ MIR_mir_surface_get_buffer_stream(mir_window->surface));
mir_window->egl_surface = SDL_EGL_CreateSurface(_this, egl_native_window);
@@ -138,7 +154,7 @@ MIR_CreateWindow(_THIS, SDL_Window* window)
mir_window->egl_surface = EGL_NO_SURFACE;
}
- MIR_mir_surface_set_event_handler(mir_window->surface, &delegate);
+ mir_data->current_window = mir_window;
return 0;
}
@@ -146,13 +162,15 @@ MIR_CreateWindow(_THIS, SDL_Window* window)
void
MIR_DestroyWindow(_THIS, SDL_Window* window)
{
- MIR_Data* mir_data = _this->driverdata;
+ MIR_Data* mir_data = _this->driverdata;
MIR_Window* mir_window = window->driverdata;
if (mir_data) {
SDL_EGL_DestroySurface(_this, mir_window->egl_surface);
MIR_mir_surface_release_sync(mir_window->surface);
+ mir_data->current_window = NULL;
+
SDL_free(mir_window);
}
window->driverdata = NULL;
@@ -180,49 +198,223 @@ MIR_SetWindowFullscreen(_THIS, SDL_Window* window,
SDL_VideoDisplay* display,
SDL_bool fullscreen)
{
+ MIR_Data* mir_data = _this->driverdata;
MIR_Window* mir_window = window->driverdata;
+ MirSurfaceSpec* spec;
+ MirSurfaceState state;
if (IsSurfaceValid(mir_window) < 0)
return;
if (fullscreen) {
- MIR_mir_surface_set_state(mir_window->surface, mir_surface_state_fullscreen);
+ state = mir_surface_state_fullscreen;
} else {
- MIR_mir_surface_set_state(mir_window->surface, mir_surface_state_restored);
+ state = mir_surface_state_restored;
}
+
+ spec = MIR_mir_connection_create_spec_for_changes(mir_data->connection);
+ MIR_mir_surface_spec_set_state(spec, state);
+
+ MIR_mir_surface_apply_spec(mir_window->surface, spec);
+ MIR_mir_surface_spec_release(spec);
}
void
MIR_MaximizeWindow(_THIS, SDL_Window* window)
{
+ MIR_Data* mir_data = _this->driverdata;
MIR_Window* mir_window = window->driverdata;
+ MirSurfaceSpec* spec;
if (IsSurfaceValid(mir_window) < 0)
return;
- MIR_mir_surface_set_state(mir_window->surface, mir_surface_state_maximized);
+ spec = MIR_mir_connection_create_spec_for_changes(mir_data->connection);
+ MIR_mir_surface_spec_set_state(spec, mir_surface_state_maximized);
+
+ MIR_mir_surface_apply_spec(mir_window->surface, spec);
+ MIR_mir_surface_spec_release(spec);
}
void
MIR_MinimizeWindow(_THIS, SDL_Window* window)
{
+ MIR_Data* mir_data = _this->driverdata;
MIR_Window* mir_window = window->driverdata;
+ MirSurfaceSpec* spec;
if (IsSurfaceValid(mir_window) < 0)
return;
- MIR_mir_surface_set_state(mir_window->surface, mir_surface_state_minimized);
+ spec = MIR_mir_connection_create_spec_for_changes(mir_data->connection);
+ MIR_mir_surface_spec_set_state(spec, mir_surface_state_minimized);
+
+ MIR_mir_surface_apply_spec(mir_window->surface, spec);
+ MIR_mir_surface_spec_release(spec);
}
void
MIR_RestoreWindow(_THIS, SDL_Window * window)
{
+ MIR_Data* mir_data = _this->driverdata;
MIR_Window* mir_window = window->driverdata;
+ MirSurfaceSpec* spec;
if (IsSurfaceValid(mir_window) < 0)
return;
- MIR_mir_surface_set_state(mir_window->surface, mir_surface_state_restored);
+ spec = MIR_mir_connection_create_spec_for_changes(mir_data->connection);
+ MIR_mir_surface_spec_set_state(spec, mir_surface_state_restored);
+
+ MIR_mir_surface_apply_spec(mir_window->surface, spec);
+ MIR_mir_surface_spec_release(spec);
+}
+
+void
+MIR_HideWindow(_THIS, SDL_Window* window)
+{
+ MIR_Data* mir_data = _this->driverdata;
+ MIR_Window* mir_window = window->driverdata;
+ MirSurfaceSpec* spec;
+
+ if (IsSurfaceValid(mir_window) < 0)
+ return;
+
+ spec = MIR_mir_connection_create_spec_for_changes(mir_data->connection);
+ MIR_mir_surface_spec_set_state(spec, mir_surface_state_hidden);
+
+ MIR_mir_surface_apply_spec(mir_window->surface, spec);
+ MIR_mir_surface_spec_release(spec);
+}
+
+void
+MIR_SetWindowSize(_THIS, SDL_Window* window)
+{
+ MIR_Data* mir_data = _this->driverdata;
+ MIR_Window* mir_window = window->driverdata;
+ MirSurfaceSpec* spec;
+
+ if (IsSurfaceValid(mir_window) < 0)
+ return;
+
+ /* You cannot set the x/y of a mir window! So only update w/h */
+ spec = MIR_mir_connection_create_spec_for_changes(mir_data->connection);
+ MIR_mir_surface_spec_set_width (spec, window->w);
+ MIR_mir_surface_spec_set_height(spec, window->h);
+
+ MIR_mir_surface_apply_spec(mir_window->surface, spec);
+ MIR_mir_surface_spec_release(spec);
+}
+
+void
+MIR_SetWindowMinimumSize(_THIS, SDL_Window* window)
+{
+ MIR_Data* mir_data = _this->driverdata;
+ MIR_Window* mir_window = window->driverdata;
+ MirSurfaceSpec* spec;
+
+ if (IsSurfaceValid(mir_window) < 0)
+ return;
+
+ spec = MIR_mir_connection_create_spec_for_changes(mir_data->connection);
+ MIR_mir_surface_spec_set_min_width (spec, window->min_w);
+ MIR_mir_surface_spec_set_min_height(spec, window->min_h);
+
+ MIR_mir_surface_apply_spec(mir_window->surface, spec);
+ MIR_mir_surface_spec_release(spec);
+}
+
+void
+MIR_SetWindowMaximumSize(_THIS, SDL_Window* window)
+{
+ MIR_Data* mir_data = _this->driverdata;
+ MIR_Window* mir_window = window->driverdata;
+ MirSurfaceSpec* spec;
+
+ if (IsSurfaceValid(mir_window) < 0)
+ return;
+
+ spec = MIR_mir_connection_create_spec_for_changes(mir_data->connection);
+ MIR_mir_surface_spec_set_max_width (spec, window->max_w);
+ MIR_mir_surface_spec_set_max_height(spec, window->max_h);
+
+ MIR_mir_surface_apply_spec(mir_window->surface, spec);
+ MIR_mir_surface_spec_release(spec);
+}
+
+void
+MIR_SetWindowTitle(_THIS, SDL_Window* window)
+{
+ MIR_Data* mir_data = _this->driverdata;
+ MIR_Window* mir_window = window->driverdata;
+ char const* title = window->title ? window->title : "";
+ MirSurfaceSpec* spec;
+
+ if (IsSurfaceValid(mir_window) < 0)
+ return;
+
+ spec = MIR_mir_connection_create_spec_for_changes(mir_data->connection);
+ MIR_mir_surface_spec_set_name(spec, title);
+
+ MIR_mir_surface_apply_spec(mir_window->surface, spec);
+ MIR_mir_surface_spec_release(spec);
+}
+
+void
+MIR_SetWindowGrab(_THIS, SDL_Window* window, SDL_bool grabbed)
+{
+ MIR_Data* mir_data = _this->driverdata;
+ MIR_Window* mir_window = window->driverdata;
+ MirPointerConfinementState confined = mir_pointer_unconfined;
+ MirSurfaceSpec* spec;
+
+ if (grabbed)
+ confined = mir_pointer_confined_to_surface;
+
+ spec = MIR_mir_connection_create_spec_for_changes(mir_data->connection);
+ MIR_mir_surface_spec_set_pointer_confinement(spec, confined);
+
+ MIR_mir_surface_apply_spec(mir_window->surface, spec);
+ MIR_mir_surface_spec_release(spec);
+}
+
+int
+MIR_SetWindowGammaRamp(_THIS, SDL_Window* window, Uint16 const* ramp)
+{
+ MirOutput* output = SDL_GetDisplayForWindow(window)->driverdata;
+ Uint32 ramp_size = 256;
+
+ // FIXME Need to apply the changes to the output, once that public API function is around
+ if (MIR_mir_output_is_gamma_supported(output) == mir_output_gamma_supported) {
+ MIR_mir_output_set_gamma(output,
+ ramp + ramp_size * 0,
+ ramp + ramp_size * 1,
+ ramp + ramp_size * 2,
+ ramp_size);
+ return 0;
+ }
+
+ return -1;
+}
+
+int
+MIR_GetWindowGammaRamp(_THIS, SDL_Window* window, Uint16* ramp)
+{
+ MirOutput* output = SDL_GetDisplayForWindow(window)->driverdata;
+ Uint32 ramp_size = 256;
+
+ if (MIR_mir_output_is_gamma_supported(output) == mir_output_gamma_supported) {
+ if (MIR_mir_output_get_gamma_size(output) == ramp_size) {
+ MIR_mir_output_get_gamma(output,
+ ramp + ramp_size * 0,
+ ramp + ramp_size * 1,
+ ramp + ramp_size * 2,
+ ramp_size);
+ return 0;
+ }
+ }
+
+ return -1;
}
#endif /* SDL_VIDEO_DRIVER_MIR */
diff --git a/Engine/lib/sdl/src/video/mir/SDL_mirwindow.h b/Engine/lib/sdl/src/video/mir/SDL_mirwindow.h
index c21fc9292..c4084aa4e 100644
--- a/Engine/lib/sdl/src/video/mir/SDL_mirwindow.h
+++ b/Engine/lib/sdl/src/video/mir/SDL_mirwindow.h
@@ -31,13 +31,13 @@
#include "SDL_mirvideo.h"
-typedef struct {
+struct MIR_Window {
SDL_Window* sdl_window;
- MIR_Data* mir_data;
+ MIR_Data* mir_data;
MirSurface* surface;
- EGLSurface egl_surface;
-} MIR_Window;
+ EGLSurface egl_surface;
+};
extern int
@@ -60,9 +60,33 @@ MIR_MinimizeWindow(_THIS, SDL_Window* window);
extern void
MIR_RestoreWindow(_THIS, SDL_Window* window);
+extern void
+MIR_HideWindow(_THIS, SDL_Window* window);
+
extern SDL_bool
MIR_GetWindowWMInfo(_THIS, SDL_Window* window, SDL_SysWMinfo* info);
+extern void
+MIR_SetWindowSize(_THIS, SDL_Window* window);
+
+extern void
+MIR_SetWindowMinimumSize(_THIS, SDL_Window* window);
+
+extern void
+MIR_SetWindowMaximumSize(_THIS, SDL_Window* window);
+
+extern void
+MIR_SetWindowTitle(_THIS, SDL_Window* window);
+
+extern void
+MIR_SetWindowGrab(_THIS, SDL_Window* window, SDL_bool grabbed);
+
+extern int
+MIR_SetWindowGammaRamp(_THIS, SDL_Window* window, Uint16 const* ramp);
+
+extern int
+MIR_GetWindowGammaRamp(_THIS, SDL_Window* window, Uint16* ramp);
+
#endif /* _SDL_mirwindow_h */
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/video/pandora/SDL_pandora.c b/Engine/lib/sdl/src/video/pandora/SDL_pandora.c
index d1c35a705..7afa54306 100644
--- a/Engine/lib/sdl/src/video/pandora/SDL_pandora.c
+++ b/Engine/lib/sdl/src/video/pandora/SDL_pandora.c
@@ -41,8 +41,6 @@
static NativeWindowType hNativeWnd = 0; /* A handle to the window we will create. */
#endif
-static SDL_bool PND_initialized = SDL_FALSE;
-
static int
PND_available(void)
{
@@ -52,11 +50,11 @@ PND_available(void)
static void
PND_destroy(SDL_VideoDevice * device)
{
- SDL_VideoData *phdata = (SDL_VideoData *) device->driverdata;
-
if (device->driverdata != NULL) {
+ SDL_free(device->driverdata);
device->driverdata = NULL;
}
+ SDL_free(device);
}
static SDL_VideoDevice *
@@ -93,9 +91,8 @@ PND_create()
phdata->egl_initialized = SDL_TRUE;
- /* Setup amount of available displays and current display */
+ /* Setup amount of available displays */
device->num_displays = 0;
- device->current_display = 0;
/* Set device free function */
device->free = PND_destroy;
@@ -204,10 +201,6 @@ PND_createwindow(_THIS, SDL_Window * window)
SDL_WindowData *wdata;
- uint32_t winargc = 0;
- int32_t status;
-
-
/* Allocate window internal data */
wdata = (SDL_WindowData *) SDL_calloc(1, sizeof(SDL_WindowData));
if (wdata == NULL) {
@@ -292,7 +285,7 @@ PND_restorewindow(_THIS, SDL_Window * window)
{
}
void
-PND_setwindowgrab(_THIS, SDL_Window * window)
+PND_setwindowgrab(_THIS, SDL_Window * window, SDL_bool grabbed)
{
}
void
@@ -326,8 +319,6 @@ PND_getwindowwminfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo *info)
int
PND_gl_loadlibrary(_THIS, const char *path)
{
- SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
-
/* Check if OpenGL ES library is specified for GF driver */
if (path == NULL) {
path = SDL_getenv("SDL_OPENGL_LIBRARY");
@@ -365,7 +356,6 @@ PND_gl_loadlibrary(_THIS, const char *path)
void *
PND_gl_getprocaddres(_THIS, const char *proc)
{
- SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
void *function_address;
/* Try to get function address through the egl interface */
@@ -409,10 +399,7 @@ PND_gl_createcontext(_THIS, SDL_Window * window)
{
SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
SDL_WindowData *wdata = (SDL_WindowData *) window->driverdata;
- SDL_DisplayData *didata =
- (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
EGLBoolean status;
- int32_t gfstatus;
EGLint configs;
uint32_t attr_pos;
EGLint attr_value;
@@ -629,12 +616,12 @@ PND_gl_createcontext(_THIS, SDL_Window * window)
hNativeWnd = (NativeWindowType)malloc(16*1024);
if(!hNativeWnd)
- printf( "Error : Wiz framebuffer allocatation failed\n" );
+ printf( "Error: Wiz framebuffer allocatation failed\n" );
else
- printf( "SDL13: Wiz framebuffer allocated: %X\n", hNativeWnd );
+ printf( "SDL: Wiz framebuffer allocated: %X\n", hNativeWnd );
}
else {
- printf( "SDL13: Wiz framebuffer already allocated: %X\n", hNativeWnd );
+ printf( "SDL: Wiz framebuffer already allocated: %X\n", hNativeWnd );
}
wdata->gles_surface =
@@ -792,9 +779,6 @@ PND_gl_swapwindow(_THIS, SDL_Window * window)
{
SDL_VideoData *phdata = (SDL_VideoData *) _this->driverdata;
SDL_WindowData *wdata = (SDL_WindowData *) window->driverdata;
- SDL_DisplayData *didata =
- (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata;
-
if (phdata->egl_initialized != SDL_TRUE) {
SDL_SetError("PND: GLES initialization failed, no OpenGL ES support");
@@ -838,7 +822,7 @@ PND_gl_deletecontext(_THIS, SDL_GLContext context)
{
free(hNativeWnd);
hNativeWnd = 0;
- printf( "SDL13: Wiz framebuffer released\n" );
+ printf( "SDL: Wiz framebuffer released\n" );
}
#endif
diff --git a/Engine/lib/sdl/src/video/pandora/SDL_pandora.h b/Engine/lib/sdl/src/video/pandora/SDL_pandora.h
index b95cd10b1..859b7ee5d 100644
--- a/Engine/lib/sdl/src/video/pandora/SDL_pandora.h
+++ b/Engine/lib/sdl/src/video/pandora/SDL_pandora.h
@@ -77,7 +77,7 @@ void PND_raisewindow(_THIS, SDL_Window * window);
void PND_maximizewindow(_THIS, SDL_Window * window);
void PND_minimizewindow(_THIS, SDL_Window * window);
void PND_restorewindow(_THIS, SDL_Window * window);
-void PND_setwindowgrab(_THIS, SDL_Window * window);
+void PND_setwindowgrab(_THIS, SDL_Window * window, SDL_bool grabbed);
void PND_destroywindow(_THIS, SDL_Window * window);
/* Window manager function */
diff --git a/Engine/lib/sdl/src/video/psp/SDL_pspevents.c b/Engine/lib/sdl/src/video/psp/SDL_pspevents.c
index c1a095dbb..71267272d 100644
--- a/Engine/lib/sdl/src/video/psp/SDL_pspevents.c
+++ b/Engine/lib/sdl/src/video/psp/SDL_pspevents.c
@@ -31,8 +31,8 @@
#include "../../events/SDL_keyboard_c.h"
#include "SDL_pspvideo.h"
#include "SDL_pspevents_c.h"
-#include "SDL_thread.h"
#include "SDL_keyboard.h"
+#include "../../thread/SDL_systhread.h"
#include
#ifdef PSPIRKEYB
@@ -264,7 +264,7 @@ void PSP_EventInit(_THIS)
return;
}
running = 1;
- if((thread = SDL_CreateThread(EventUpdate, "PSPInputThread",NULL)) == NULL) {
+ if((thread = SDL_CreateThreadInternal(EventUpdate, "PSPInputThread", 4096, NULL)) == NULL) {
SDL_SetError("Can't create input thread\n");
return;
}
diff --git a/Engine/lib/sdl/src/video/psp/SDL_pspvideo.c b/Engine/lib/sdl/src/video/psp/SDL_pspvideo.c
index 955666877..381e4899e 100644
--- a/Engine/lib/sdl/src/video/psp/SDL_pspvideo.c
+++ b/Engine/lib/sdl/src/video/psp/SDL_pspvideo.c
@@ -92,6 +92,7 @@ PSP_Create()
if (gldata == NULL) {
SDL_OutOfMemory();
SDL_free(device);
+ SDL_free(phdata);
return NULL;
}
device->gl_data = gldata;
@@ -101,7 +102,7 @@ PSP_Create()
phdata->egl_initialized = SDL_TRUE;
- /* Setup amount of available displays and current display */
+ /* Setup amount of available displays */
device->num_displays = 0;
/* Set device free function */
@@ -234,7 +235,7 @@ PSP_CreateWindow(_THIS, SDL_Window * window)
int
PSP_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
{
- return -1;
+ return SDL_Unsupported();
}
void
diff --git a/Engine/lib/sdl/src/video/raspberry/SDL_rpimouse.c b/Engine/lib/sdl/src/video/raspberry/SDL_rpimouse.c
index 0d1482c04..ae9bdfd5c 100644
--- a/Engine/lib/sdl/src/video/raspberry/SDL_rpimouse.c
+++ b/Engine/lib/sdl/src/video/raspberry/SDL_rpimouse.c
@@ -24,6 +24,7 @@
#include "SDL_assert.h"
#include "SDL_surface.h"
+#include "SDL_hints.h"
#include "SDL_rpivideo.h"
#include "SDL_rpimouse.h"
@@ -70,7 +71,16 @@ RPI_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
SDL_assert(surface->pitch == surface->w * 4);
cursor = (SDL_Cursor *) SDL_calloc(1, sizeof(*cursor));
+ if (cursor == NULL) {
+ SDL_OutOfMemory();
+ return NULL;
+ }
curdata = (RPI_CursorData *) SDL_calloc(1, sizeof(*curdata));
+ if (curdata == NULL) {
+ SDL_OutOfMemory();
+ SDL_free(cursor);
+ return NULL;
+ }
curdata->hot_x = hot_x;
curdata->hot_y = hot_y;
@@ -78,17 +88,17 @@ RPI_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
curdata->h = surface->h;
/* This usage is inspired by Wayland/Weston RPI code, how they figured this out is anyone's guess */
- curdata->resource = vc_dispmanx_resource_create( VC_IMAGE_ARGB8888, surface->w | (surface->pitch << 16), surface->h | (surface->h << 16), &dummy );
+ curdata->resource = vc_dispmanx_resource_create(VC_IMAGE_ARGB8888, surface->w | (surface->pitch << 16), surface->h | (surface->h << 16), &dummy);
SDL_assert(curdata->resource);
- vc_dispmanx_rect_set( &dst_rect, 0, 0, curdata->w, curdata->h);
+ vc_dispmanx_rect_set(&dst_rect, 0, 0, curdata->w, curdata->h);
/* A note from Weston:
* vc_dispmanx_resource_write_data() ignores ifmt,
* rect.x, rect.width, and uses stride only for computing
* the size of the transfer as rect.height * stride.
* Therefore we can only write rows starting at x=0.
*/
- ret = vc_dispmanx_resource_write_data( curdata->resource, VC_IMAGE_ARGB8888, surface->pitch, surface->pixels, &dst_rect );
- SDL_assert ( ret == DISPMANX_SUCCESS );
+ ret = vc_dispmanx_resource_write_data(curdata->resource, VC_IMAGE_ARGB8888, surface->pitch, surface->pixels, &dst_rect);
+ SDL_assert (ret == DISPMANX_SUCCESS);
cursor->driverdata = curdata;
@@ -108,7 +118,9 @@ RPI_ShowCursor(SDL_Cursor * cursor)
SDL_VideoDisplay *display;
SDL_DisplayData *data;
VC_DISPMANX_ALPHA_T alpha = { DISPMANX_FLAGS_ALPHA_FROM_SOURCE /* flags */ , 255 /*opacity 0->255*/, 0 /* mask */ };
-
+ uint32_t layer = SDL_RPI_MOUSELAYER;
+ const char *env;
+
mouse = SDL_GetMouse();
if (mouse == NULL) {
return -1;
@@ -117,15 +129,15 @@ RPI_ShowCursor(SDL_Cursor * cursor)
if (cursor == NULL) {
/* FIXME: We hide the current mouse's cursor, what we actually need is *_HideCursor */
- if ( mouse->cur_cursor != NULL && mouse->cur_cursor->driverdata != NULL) {
+ if (mouse->cur_cursor != NULL && mouse->cur_cursor->driverdata != NULL) {
curdata = (RPI_CursorData *) mouse->cur_cursor->driverdata;
if (curdata->element > DISPMANX_NO_HANDLE) {
- update = vc_dispmanx_update_start( 10 );
- SDL_assert( update );
- ret = vc_dispmanx_element_remove( update, curdata->element );
- SDL_assert( ret == DISPMANX_SUCCESS );
- ret = vc_dispmanx_update_submit_sync( update );
- SDL_assert( ret == DISPMANX_SUCCESS );
+ update = vc_dispmanx_update_start(10);
+ SDL_assert(update);
+ ret = vc_dispmanx_element_remove(update, curdata->element);
+ SDL_assert(ret == DISPMANX_SUCCESS);
+ ret = vc_dispmanx_update_submit_sync(update);
+ SDL_assert(ret == DISPMANX_SUCCESS);
curdata->element = DISPMANX_NO_HANDLE;
}
}
@@ -152,25 +164,30 @@ RPI_ShowCursor(SDL_Cursor * cursor)
}
if (curdata->element == DISPMANX_NO_HANDLE) {
- vc_dispmanx_rect_set( &src_rect, 0, 0, curdata->w << 16, curdata->h << 16 );
- vc_dispmanx_rect_set( &dst_rect, 0, 0, curdata->w, curdata->h);
+ vc_dispmanx_rect_set(&src_rect, 0, 0, curdata->w << 16, curdata->h << 16);
+ vc_dispmanx_rect_set(&dst_rect, 0, 0, curdata->w, curdata->h);
- update = vc_dispmanx_update_start( 10 );
- SDL_assert( update );
+ update = vc_dispmanx_update_start(10);
+ SDL_assert(update);
- curdata->element = vc_dispmanx_element_add( update,
+ env = SDL_GetHint(SDL_HINT_RPI_VIDEO_LAYER);
+ if (env) {
+ layer = SDL_atoi(env) + 1;
+ }
+
+ curdata->element = vc_dispmanx_element_add(update,
data->dispman_display,
- SDL_RPI_MOUSELAYER, // layer
+ layer,
&dst_rect,
curdata->resource,
&src_rect,
DISPMANX_PROTECTION_NONE,
&alpha,
DISPMANX_NO_HANDLE, // clamp
- VC_IMAGE_ROT0 );
- SDL_assert( curdata->element > DISPMANX_NO_HANDLE);
- ret = vc_dispmanx_update_submit_sync( update );
- SDL_assert( ret == DISPMANX_SUCCESS );
+ VC_IMAGE_ROT0);
+ SDL_assert(curdata->element > DISPMANX_NO_HANDLE);
+ ret = vc_dispmanx_update_submit_sync(update);
+ SDL_assert(ret == DISPMANX_SUCCESS);
}
return 0;
@@ -189,17 +206,17 @@ RPI_FreeCursor(SDL_Cursor * cursor)
if (curdata != NULL) {
if (curdata->element != DISPMANX_NO_HANDLE) {
- update = vc_dispmanx_update_start( 10 );
- SDL_assert( update );
- ret = vc_dispmanx_element_remove( update, curdata->element );
- SDL_assert( ret == DISPMANX_SUCCESS );
- ret = vc_dispmanx_update_submit_sync( update );
- SDL_assert( ret == DISPMANX_SUCCESS );
+ update = vc_dispmanx_update_start(10);
+ SDL_assert(update);
+ ret = vc_dispmanx_element_remove(update, curdata->element);
+ SDL_assert(ret == DISPMANX_SUCCESS);
+ ret = vc_dispmanx_update_submit_sync(update);
+ SDL_assert(ret == DISPMANX_SUCCESS);
}
if (curdata->resource != DISPMANX_NO_HANDLE) {
- ret = vc_dispmanx_resource_delete( curdata->resource );
- SDL_assert( ret == DISPMANX_SUCCESS );
+ ret = vc_dispmanx_resource_delete(curdata->resource);
+ SDL_assert(ret == DISPMANX_SUCCESS);
}
SDL_free(cursor->driverdata);
@@ -221,35 +238,54 @@ RPI_WarpMouseGlobal(int x, int y)
{
RPI_CursorData *curdata;
DISPMANX_UPDATE_HANDLE_T update;
+ int ret;
VC_RECT_T dst_rect;
+ VC_RECT_T src_rect;
SDL_Mouse *mouse = SDL_GetMouse();
- if (mouse != NULL && mouse->cur_cursor != NULL && mouse->cur_cursor->driverdata != NULL) {
- curdata = (RPI_CursorData *) mouse->cur_cursor->driverdata;
- if (curdata->element != DISPMANX_NO_HANDLE) {
- int ret;
- update = vc_dispmanx_update_start( 10 );
- SDL_assert( update );
- vc_dispmanx_rect_set( &dst_rect, x, y, curdata->w, curdata->h);
- ret = vc_dispmanx_element_change_attributes(
- update,
- curdata->element,
- ELEMENT_CHANGE_DEST_RECT,
- 0,
- 0,
- &dst_rect,
- NULL,
- DISPMANX_NO_HANDLE,
- DISPMANX_NO_ROTATE);
- SDL_assert( ret == DISPMANX_SUCCESS );
- /* Submit asynchronously, otherwise the peformance suffers a lot */
- ret = vc_dispmanx_update_submit( update, 0, NULL );
- SDL_assert( ret == DISPMANX_SUCCESS );
- return (ret == DISPMANX_SUCCESS) ? 0 : -1;
- }
- }
+ if (mouse == NULL || mouse->cur_cursor == NULL || mouse->cur_cursor->driverdata == NULL) {
+ return 0;
+ }
- return -1; /* !!! FIXME: this should SDL_SetError() somewhere. */
+ curdata = (RPI_CursorData *) mouse->cur_cursor->driverdata;
+ if (curdata->element == DISPMANX_NO_HANDLE) {
+ return 0;
+ }
+
+ update = vc_dispmanx_update_start(10);
+ if (!update) {
+ return 0;
+ }
+
+ src_rect.x = 0;
+ src_rect.y = 0;
+ src_rect.width = curdata->w << 16;
+ src_rect.height = curdata->h << 16;
+ dst_rect.x = x;
+ dst_rect.y = y;
+ dst_rect.width = curdata->w;
+ dst_rect.height = curdata->h;
+
+ ret = vc_dispmanx_element_change_attributes(
+ update,
+ curdata->element,
+ 0,
+ 0,
+ 0,
+ &dst_rect,
+ &src_rect,
+ DISPMANX_NO_HANDLE,
+ DISPMANX_NO_ROTATE);
+ if (ret != DISPMANX_SUCCESS) {
+ return SDL_SetError("vc_dispmanx_element_change_attributes() failed");
+ }
+
+ /* Submit asynchronously, otherwise the peformance suffers a lot */
+ ret = vc_dispmanx_update_submit(update, 0, NULL);
+ if (ret != DISPMANX_SUCCESS) {
+ return SDL_SetError("vc_dispmanx_update_submit() failed");
+ }
+ return 0;
}
void
diff --git a/Engine/lib/sdl/src/video/raspberry/SDL_rpivideo.c b/Engine/lib/sdl/src/video/raspberry/SDL_rpivideo.c
index 539c88c9b..67dc77b1c 100644
--- a/Engine/lib/sdl/src/video/raspberry/SDL_rpivideo.c
+++ b/Engine/lib/sdl/src/video/raspberry/SDL_rpivideo.c
@@ -38,6 +38,7 @@
#include "SDL_events.h"
#include "../../events/SDL_mouse_c.h"
#include "../../events/SDL_keyboard_c.h"
+#include "SDL_hints.h"
#ifdef SDL_INPUT_LINUXEV
#include "../../core/linux/SDL_evdev.h"
@@ -88,7 +89,7 @@ RPI_Create()
device->driverdata = phdata;
- /* Setup amount of available displays and current display */
+ /* Setup amount of available displays */
device->num_displays = 0;
/* Set device free function */
@@ -221,6 +222,8 @@ RPI_CreateWindow(_THIS, SDL_Window * window)
VC_RECT_T src_rect;
VC_DISPMANX_ALPHA_T dispman_alpha;
DISPMANX_UPDATE_HANDLE_T dispman_update;
+ uint32_t layer = SDL_RPI_VIDEOLAYER;
+ const char *env;
/* Disable alpha, otherwise the app looks composed with whatever dispman is showing (X11, console,etc) */
dispman_alpha.flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS;
@@ -253,11 +256,25 @@ RPI_CreateWindow(_THIS, SDL_Window * window)
src_rect.width = window->w << 16;
src_rect.height = window->h << 16;
+ env = SDL_GetHint(SDL_HINT_RPI_VIDEO_LAYER);
+ if (env) {
+ layer = SDL_atoi(env);
+ }
+
dispman_update = vc_dispmanx_update_start( 0 );
- wdata->dispman_window.element = vc_dispmanx_element_add ( dispman_update, displaydata->dispman_display, SDL_RPI_VIDEOLAYER /* layer */, &dst_rect, 0/*src*/, &src_rect, DISPMANX_PROTECTION_NONE, &dispman_alpha /*alpha*/, 0/*clamp*/, 0/*transform*/);
+ wdata->dispman_window.element = vc_dispmanx_element_add (dispman_update,
+ displaydata->dispman_display,
+ layer /* layer */,
+ &dst_rect,
+ 0 /*src*/,
+ &src_rect,
+ DISPMANX_PROTECTION_NONE,
+ &dispman_alpha /*alpha*/,
+ 0 /*clamp*/,
+ 0 /*transform*/);
wdata->dispman_window.width = window->w;
wdata->dispman_window.height = window->h;
- vc_dispmanx_update_submit_sync( dispman_update );
+ vc_dispmanx_update_submit_sync(dispman_update);
if (!_this->egl_data) {
if (SDL_GL_LoadLibrary(NULL) < 0) {
diff --git a/Engine/lib/sdl/src/video/sdlgenblit.pl b/Engine/lib/sdl/src/video/sdlgenblit.pl
old mode 100644
new mode 100755
diff --git a/Engine/lib/sdl/src/video/uikit/SDL_uikitappdelegate.h b/Engine/lib/sdl/src/video/uikit/SDL_uikitappdelegate.h
index 1879f0b3a..edf09f50f 100644
--- a/Engine/lib/sdl/src/video/uikit/SDL_uikitappdelegate.h
+++ b/Engine/lib/sdl/src/video/uikit/SDL_uikitappdelegate.h
@@ -24,8 +24,8 @@
@interface SDLLaunchScreenController : UIViewController
- (instancetype)init;
+- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil;
- (void)loadView;
-- (NSUInteger)supportedInterfaceOrientations;
@end
diff --git a/Engine/lib/sdl/src/video/uikit/SDL_uikitappdelegate.m b/Engine/lib/sdl/src/video/uikit/SDL_uikitappdelegate.m
index 971b438b0..c94c78a41 100644
--- a/Engine/lib/sdl/src/video/uikit/SDL_uikitappdelegate.m
+++ b/Engine/lib/sdl/src/video/uikit/SDL_uikitappdelegate.m
@@ -76,6 +76,7 @@ SDL_IdleTimerDisabledChanged(void *userdata, const char *name, const char *oldVa
[UIApplication sharedApplication].idleTimerDisabled = disable;
}
+#if !TARGET_OS_TV
/* Load a launch image using the old UILaunchImageFile-era naming rules. */
static UIImage *
SDL_LoadLaunchImageNamed(NSString *name, int screenh)
@@ -114,17 +115,31 @@ SDL_LoadLaunchImageNamed(NSString *name, int screenh)
return image;
}
+#endif /* !TARGET_OS_TV */
+
+@interface SDLLaunchScreenController ()
+
+#if !TARGET_OS_TV
+- (NSUInteger)supportedInterfaceOrientations;
+#endif
+
+@end
@implementation SDLLaunchScreenController
- (instancetype)init
+{
+ return [self initWithNibName:nil bundle:[NSBundle mainBundle]];
+}
+
+- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
if (!(self = [super initWithNibName:nil bundle:nil])) {
return nil;
}
- NSBundle *bundle = [NSBundle mainBundle];
- NSString *screenname = [bundle objectForInfoDictionaryKey:@"UILaunchStoryboardName"];
+ NSString *screenname = nibNameOrNil;
+ NSBundle *bundle = nibBundleOrNil;
BOOL atleastiOS8 = UIKit_IsSystemVersionAtLeast(8.0);
/* Launch screens were added in iOS 8. Otherwise we use launch images. */
@@ -141,27 +156,28 @@ SDL_LoadLaunchImageNamed(NSString *name, int screenh)
if (!self.view) {
NSArray *launchimages = [bundle objectForInfoDictionaryKey:@"UILaunchImages"];
- UIInterfaceOrientation curorient = [UIApplication sharedApplication].statusBarOrientation;
NSString *imagename = nil;
UIImage *image = nil;
int screenw = (int)([UIScreen mainScreen].bounds.size.width + 0.5);
int screenh = (int)([UIScreen mainScreen].bounds.size.height + 0.5);
+#if !TARGET_OS_TV
+ UIInterfaceOrientation curorient = [UIApplication sharedApplication].statusBarOrientation;
+
/* We always want portrait-oriented size, to match UILaunchImageSize. */
if (screenw > screenh) {
int width = screenw;
screenw = screenh;
screenh = width;
}
+#endif
/* Xcode 5 introduced a dictionary of launch images in Info.plist. */
if (launchimages) {
for (NSDictionary *dict in launchimages) {
- UIInterfaceOrientationMask orientmask = UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
- NSString *minversion = dict[@"UILaunchImageMinimumOSVersion"];
- NSString *sizestring = dict[@"UILaunchImageSize"];
- NSString *orientstring = dict[@"UILaunchImageOrientation"];
+ NSString *minversion = dict[@"UILaunchImageMinimumOSVersion"];
+ NSString *sizestring = dict[@"UILaunchImageSize"];
/* Ignore this image if the current version is too low. */
if (minversion && !UIKit_IsSystemVersionAtLeast(minversion.doubleValue)) {
@@ -176,6 +192,10 @@ SDL_LoadLaunchImageNamed(NSString *name, int screenh)
}
}
+#if !TARGET_OS_TV
+ UIInterfaceOrientationMask orientmask = UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
+ NSString *orientstring = dict[@"UILaunchImageOrientation"];
+
if (orientstring) {
if ([orientstring isEqualToString:@"PortraitUpsideDown"]) {
orientmask = UIInterfaceOrientationMaskPortraitUpsideDown;
@@ -192,6 +212,7 @@ SDL_LoadLaunchImageNamed(NSString *name, int screenh)
if ((orientmask & (1 << curorient)) == 0) {
continue;
}
+#endif
imagename = dict[@"UILaunchImageName"];
}
@@ -199,7 +220,9 @@ SDL_LoadLaunchImageNamed(NSString *name, int screenh)
if (imagename) {
image = [UIImage imageNamed:imagename];
}
- } else {
+ }
+#if !TARGET_OS_TV
+ else {
imagename = [bundle objectForInfoDictionaryKey:@"UILaunchImageFile"];
if (imagename) {
@@ -210,11 +233,13 @@ SDL_LoadLaunchImageNamed(NSString *name, int screenh)
image = SDL_LoadLaunchImageNamed(@"Default", screenh);
}
}
+#endif
if (image) {
UIImageView *view = [[UIImageView alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIImageOrientation imageorient = UIImageOrientationUp;
+#if !TARGET_OS_TV
/* Bugs observed / workaround tested in iOS 8.3, 7.1, and 6.1. */
if (UIInterfaceOrientationIsLandscape(curorient)) {
if (atleastiOS8 && image.size.width < image.size.height) {
@@ -238,6 +263,7 @@ SDL_LoadLaunchImageNamed(NSString *name, int screenh)
}
}
}
+#endif
/* Create the properly oriented image. */
view.image = [[UIImage alloc] initWithCGImage:image.CGImage scale:image.scale orientation:imageorient];
@@ -254,6 +280,7 @@ SDL_LoadLaunchImageNamed(NSString *name, int screenh)
/* Do nothing. */
}
+#if !TARGET_OS_TV
- (BOOL)shouldAutorotate
{
/* If YES, the launch image will be incorrectly rotated in some cases. */
@@ -267,6 +294,7 @@ SDL_LoadLaunchImageNamed(NSString *name, int screenh)
* the ones set here (it will cause an exception in that case.) */
return UIInterfaceOrientationMaskAll;
}
+#endif /* !TARGET_OS_TV */
@end
@@ -333,7 +361,6 @@ SDL_LoadLaunchImageNamed(NSString *name, int screenh)
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSBundle *bundle = [NSBundle mainBundle];
- NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
#if SDL_IPHONE_LAUNCHSCREEN
/* The normal launch screen is displayed until didFinishLaunching returns,
@@ -342,9 +369,32 @@ SDL_LoadLaunchImageNamed(NSString *name, int screenh)
* displayed (e.g. if resources are loaded before SDL_GL_SwapWindow is
* called), so we show the launch screen programmatically until the first
* time events are pumped. */
- UIViewController *viewcontroller = [[SDLLaunchScreenController alloc] init];
+ UIViewController *vc = nil;
+ NSString *screenname = nil;
- if (viewcontroller.view) {
+ /* tvOS only uses a plain launch image. */
+#if !TARGET_OS_TV
+ screenname = [bundle objectForInfoDictionaryKey:@"UILaunchStoryboardName"];
+
+ if (screenname && UIKit_IsSystemVersionAtLeast(8.0)) {
+ @try {
+ /* The launch storyboard is actually a nib in some older versions of
+ * Xcode. We'll try to load it as a storyboard first, as it's more
+ * modern. */
+ UIStoryboard *storyboard = [UIStoryboard storyboardWithName:screenname bundle:bundle];
+ vc = [storyboard instantiateInitialViewController];
+ }
+ @catch (NSException *exception) {
+ /* Do nothing (there's more code to execute below). */
+ }
+ }
+#endif
+
+ if (vc == nil) {
+ vc = [[SDLLaunchScreenController alloc] initWithNibName:screenname bundle:bundle];
+ }
+
+ if (vc.view) {
launchWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
/* We don't want the launch window immediately hidden when a real SDL
@@ -355,7 +405,7 @@ SDL_LoadLaunchImageNamed(NSString *name, int screenh)
* other windows when possible. */
launchWindow.hidden = NO;
- launchWindow.rootViewController = viewcontroller;
+ launchWindow.rootViewController = vc;
}
#endif
@@ -382,6 +432,7 @@ SDL_LoadLaunchImageNamed(NSString *name, int screenh)
SDL_SendAppEvent(SDL_APP_LOWMEMORY);
}
+#if !TARGET_OS_TV
- (void)application:(UIApplication *)application didChangeStatusBarOrientation:(UIInterfaceOrientation)oldStatusBarOrientation
{
BOOL isLandscape = UIInterfaceOrientationIsLandscape(application.statusBarOrientation);
@@ -409,6 +460,7 @@ SDL_LoadLaunchImageNamed(NSString *name, int screenh)
}
}
}
+#endif
- (void)applicationWillResignActive:(UIApplication*)application
{
@@ -447,16 +499,34 @@ SDL_LoadLaunchImageNamed(NSString *name, int screenh)
}
}
-- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
+- (void)sendDropFileForURL:(NSURL *)url
{
NSURL *fileURL = url.filePathURL;
if (fileURL != nil) {
- SDL_SendDropFile([fileURL.path UTF8String]);
+ SDL_SendDropFile(NULL, fileURL.path.UTF8String);
} else {
- SDL_SendDropFile([url.absoluteString UTF8String]);
+ SDL_SendDropFile(NULL, url.absoluteString.UTF8String);
}
+ SDL_SendDropComplete(NULL);
+}
+
+#if TARGET_OS_TV
+/* TODO: Use this on iOS 9+ as well? */
+- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options
+{
+ /* TODO: Handle options */
+ [self sendDropFileForURL:url];
return YES;
}
+#endif /* TARGET_OS_TV */
+
+#if !TARGET_OS_TV
+- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
+{
+ [self sendDropFileForURL:url];
+ return YES;
+}
+#endif /* !TARGET_OS_TV */
@end
diff --git a/Engine/lib/sdl/src/video/uikit/SDL_uikitclipboard.h b/Engine/lib/sdl/src/video/uikit/SDL_uikitclipboard.h
new file mode 100644
index 000000000..7d1c35f99
--- /dev/null
+++ b/Engine/lib/sdl/src/video/uikit/SDL_uikitclipboard.h
@@ -0,0 +1,35 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2016 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#ifndef _SDL_uikitclipboard_h
+#define _SDL_uikitclipboard_h
+
+#include "../SDL_sysvideo.h"
+
+extern int UIKit_SetClipboardText(_THIS, const char *text);
+extern char *UIKit_GetClipboardText(_THIS);
+extern SDL_bool UIKit_HasClipboardText(_THIS);
+
+extern void UIKit_InitClipboard(_THIS);
+extern void UIKit_QuitClipboard(_THIS);
+
+#endif /* _SDL_uikitclipboard_h */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/video/uikit/SDL_uikitclipboard.m b/Engine/lib/sdl/src/video/uikit/SDL_uikitclipboard.m
new file mode 100644
index 000000000..050d5885f
--- /dev/null
+++ b/Engine/lib/sdl/src/video/uikit/SDL_uikitclipboard.m
@@ -0,0 +1,111 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2016 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_UIKIT
+
+#include "SDL_uikitvideo.h"
+#include "../../events/SDL_clipboardevents_c.h"
+
+#import
+
+int
+UIKit_SetClipboardText(_THIS, const char *text)
+{
+#if TARGET_OS_TV
+ return SDL_SetError("The clipboard is not available on tvOS");
+#else
+ @autoreleasepool {
+ [UIPasteboard generalPasteboard].string = @(text);
+ return 0;
+ }
+#endif
+}
+
+char *
+UIKit_GetClipboardText(_THIS)
+{
+#if TARGET_OS_TV
+ return SDL_strdup(""); // Unsupported.
+#else
+ @autoreleasepool {
+ UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
+ NSString *string = pasteboard.string;
+
+ if (string != nil) {
+ return SDL_strdup(string.UTF8String);
+ } else {
+ return SDL_strdup("");
+ }
+ }
+#endif
+}
+
+SDL_bool
+UIKit_HasClipboardText(_THIS)
+{
+ @autoreleasepool {
+#if !TARGET_OS_TV
+ if ([UIPasteboard generalPasteboard].string != nil) {
+ return SDL_TRUE;
+ }
+#endif
+ return SDL_FALSE;
+ }
+}
+
+void
+UIKit_InitClipboard(_THIS)
+{
+#if !TARGET_OS_TV
+ @autoreleasepool {
+ SDL_VideoData *data = (__bridge SDL_VideoData *) _this->driverdata;
+ NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
+
+ id observer = [center addObserverForName:UIPasteboardChangedNotification
+ object:nil
+ queue:nil
+ usingBlock:^(NSNotification *note) {
+ SDL_SendClipboardUpdate();
+ }];
+
+ data.pasteboardObserver = observer;
+ }
+#endif
+}
+
+void
+UIKit_QuitClipboard(_THIS)
+{
+ @autoreleasepool {
+ SDL_VideoData *data = (__bridge SDL_VideoData *) _this->driverdata;
+
+ if (data.pasteboardObserver != nil) {
+ [[NSNotificationCenter defaultCenter] removeObserver:data.pasteboardObserver];
+ }
+
+ data.pasteboardObserver = nil;
+ }
+}
+
+#endif /* SDL_VIDEO_DRIVER_UIKIT */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/video/uikit/SDL_uikitevents.m b/Engine/lib/sdl/src/video/uikit/SDL_uikitevents.m
index 1d7044d88..7083e204b 100644
--- a/Engine/lib/sdl/src/video/uikit/SDL_uikitevents.m
+++ b/Engine/lib/sdl/src/video/uikit/SDL_uikitevents.m
@@ -26,6 +26,7 @@
#include "SDL_uikitvideo.h"
#include "SDL_uikitevents.h"
+#include "SDL_uikitopengles.h"
#import
@@ -62,6 +63,9 @@ UIKit_PumpEvents(_THIS)
do {
result = CFRunLoopRunInMode((CFStringRef)UITrackingRunLoopMode, seconds, TRUE);
} while(result == kCFRunLoopRunHandledSource);
+
+ /* See the comment in the function definition. */
+ UIKit_GL_RestoreCurrentContext();
}
#endif /* SDL_VIDEO_DRIVER_UIKIT */
diff --git a/Engine/lib/sdl/src/video/uikit/SDL_uikitmodes.h b/Engine/lib/sdl/src/video/uikit/SDL_uikitmodes.h
index 027cf7aa0..b936df616 100644
--- a/Engine/lib/sdl/src/video/uikit/SDL_uikitmodes.h
+++ b/Engine/lib/sdl/src/video/uikit/SDL_uikitmodes.h
@@ -43,6 +43,7 @@ extern int UIKit_InitModes(_THIS);
extern void UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay * display);
extern int UIKit_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);
extern void UIKit_QuitModes(_THIS);
+extern int UIKit_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect);
#endif /* _SDL_uikitmodes_h */
diff --git a/Engine/lib/sdl/src/video/uikit/SDL_uikitmodes.m b/Engine/lib/sdl/src/video/uikit/SDL_uikitmodes.m
index 98d031484..cd3b8d08e 100644
--- a/Engine/lib/sdl/src/video/uikit/SDL_uikitmodes.m
+++ b/Engine/lib/sdl/src/video/uikit/SDL_uikitmodes.m
@@ -156,9 +156,12 @@ UIKit_AddDisplay(UIScreen *uiscreen)
SDL_bool
UIKit_IsDisplayLandscape(UIScreen *uiscreen)
{
+#if !TARGET_OS_TV
if (uiscreen == [UIScreen mainScreen]) {
return UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation);
- } else {
+ } else
+#endif /* !TARGET_OS_TV */
+ {
CGSize size = uiscreen.bounds.size;
return (size.width > size.height);
}
@@ -187,6 +190,14 @@ UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
SDL_bool isLandscape = UIKit_IsDisplayLandscape(data.uiscreen);
SDL_bool addRotation = (data.uiscreen == [UIScreen mainScreen]);
CGFloat scale = data.uiscreen.scale;
+ NSArray *availableModes = nil;
+
+#if TARGET_OS_TV
+ addRotation = SDL_FALSE;
+ availableModes = @[data.uiscreen.currentMode];
+#else
+ availableModes = data.uiscreen.availableModes;
+#endif
#ifdef __IPHONE_8_0
/* The UIScreenMode of an iPhone 6 Plus should be 1080x1920 rather than
@@ -196,7 +207,7 @@ UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
}
#endif
- for (UIScreenMode *uimode in data.uiscreen.availableModes) {
+ for (UIScreenMode *uimode in availableModes) {
/* The size of a UIScreenMode is in pixels, but we deal exclusively
* in points (except in SDL_GL_GetDrawableSize.) */
int w = (int)(uimode.size.width / scale);
@@ -219,9 +230,11 @@ UIKit_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
{
@autoreleasepool {
SDL_DisplayData *data = (__bridge SDL_DisplayData *) display->driverdata;
- SDL_DisplayModeData *modedata = (__bridge SDL_DisplayModeData *)mode->driverdata;
+#if !TARGET_OS_TV
+ SDL_DisplayModeData *modedata = (__bridge SDL_DisplayModeData *)mode->driverdata;
[data.uiscreen setCurrentMode:modedata.uiscreenmode];
+#endif
if (data.uiscreen == [UIScreen mainScreen]) {
/* [UIApplication setStatusBarOrientation:] no longer works reliably
@@ -242,6 +255,36 @@ UIKit_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
return 0;
}
+int
+UIKit_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect)
+{
+ @autoreleasepool {
+ int displayIndex = (int) (display - _this->displays);
+ SDL_DisplayData *data = (__bridge SDL_DisplayData *) display->driverdata;
+
+ /* the default function iterates displays to make a fake offset,
+ as if all the displays were side-by-side, which is fine for iOS. */
+ if (SDL_GetDisplayBounds(displayIndex, rect) < 0) {
+ return -1;
+ }
+
+ CGRect frame = data.uiscreen.bounds;
+
+#if !TARGET_OS_TV
+ if (!UIKit_IsSystemVersionAtLeast(7.0)) {
+ frame = [data.uiscreen applicationFrame];
+ }
+#endif
+
+ rect->x += frame.origin.x;
+ rect->y += frame.origin.y;
+ rect->w = frame.size.width;
+ rect->h = frame.size.height;
+ }
+
+ return 0;
+}
+
void
UIKit_QuitModes(_THIS)
{
diff --git a/Engine/lib/sdl/src/video/uikit/SDL_uikitopengles.h b/Engine/lib/sdl/src/video/uikit/SDL_uikitopengles.h
index 10697610d..b52e42913 100644
--- a/Engine/lib/sdl/src/video/uikit/SDL_uikitopengles.h
+++ b/Engine/lib/sdl/src/video/uikit/SDL_uikitopengles.h
@@ -33,6 +33,8 @@ extern void UIKit_GL_DeleteContext(_THIS, SDL_GLContext context);
extern void *UIKit_GL_GetProcAddress(_THIS, const char *proc);
extern int UIKit_GL_LoadLibrary(_THIS, const char *path);
+extern void UIKit_GL_RestoreCurrentContext();
+
#endif
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/video/uikit/SDL_uikitopengles.m b/Engine/lib/sdl/src/video/uikit/SDL_uikitopengles.m
index a2ea4ab67..461ff9b80 100644
--- a/Engine/lib/sdl/src/video/uikit/SDL_uikitopengles.m
+++ b/Engine/lib/sdl/src/video/uikit/SDL_uikitopengles.m
@@ -140,10 +140,19 @@ UIKit_GL_CreateContext(_THIS, SDL_Window * window)
EAGLSharegroup *sharegroup = nil;
CGFloat scale = 1.0;
int samples = 0;
+ int major = _this->gl_config.major_version;
+ int minor = _this->gl_config.minor_version;
/* The EAGLRenderingAPI enum values currently map 1:1 to major GLES
* versions. */
- EAGLRenderingAPI api = _this->gl_config.major_version;
+ EAGLRenderingAPI api = major;
+
+ /* iOS currently doesn't support GLES >3.0. iOS 6 also only supports up
+ * to GLES 2.0. */
+ if (major > 3 || (major == 3 && (minor > 0 || !UIKit_IsSystemVersionAtLeast(7.0)))) {
+ SDL_SetError("OpenGL ES %d.%d context could not be created", major, minor);
+ return NULL;
+ }
if (_this->gl_config.multisamplebuffers > 0) {
samples = _this->gl_config.multisamplesamples;
@@ -217,6 +226,24 @@ UIKit_GL_DeleteContext(_THIS, SDL_GLContext context)
}
}
+void
+UIKit_GL_RestoreCurrentContext()
+{
+ @autoreleasepool {
+ /* Some iOS system functionality (such as Dictation on the on-screen
+ keyboard) uses its own OpenGL ES context but doesn't restore the
+ previous one when it's done. This is a workaround to make sure the
+ expected SDL-created OpenGL ES context is active after the OS is
+ finished running its own code for the frame. If this isn't done, the
+ app may crash or have other nasty symptoms when Dictation is used.
+ */
+ EAGLContext *context = (__bridge EAGLContext *) SDL_GL_GetCurrentContext();
+ if (context != NULL && [EAGLContext currentContext] != context) {
+ [EAGLContext setCurrentContext:context];
+ }
+ }
+}
+
#endif /* SDL_VIDEO_DRIVER_UIKIT */
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/video/uikit/SDL_uikitopenglview.m b/Engine/lib/sdl/src/video/uikit/SDL_uikitopenglview.m
index 60c247e6a..aae7ee8f2 100644
--- a/Engine/lib/sdl/src/video/uikit/SDL_uikitopenglview.m
+++ b/Engine/lib/sdl/src/video/uikit/SDL_uikitopenglview.m
@@ -239,7 +239,7 @@
if (msaaRenderbuffer != 0) {
glBindRenderbuffer(GL_RENDERBUFFER, msaaRenderbuffer);
- glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, GL_RGBA8, backingWidth, backingHeight);
+ glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, colorBufferFormat, backingWidth, backingHeight);
}
if (depthRenderbuffer != 0) {
diff --git a/Engine/lib/sdl/src/video/uikit/SDL_uikitvideo.h b/Engine/lib/sdl/src/video/uikit/SDL_uikitvideo.h
index 3fbaf92f1..aafb714d7 100644
--- a/Engine/lib/sdl/src/video/uikit/SDL_uikitvideo.h
+++ b/Engine/lib/sdl/src/video/uikit/SDL_uikitvideo.h
@@ -21,14 +21,25 @@
#ifndef _SDL_uikitvideo_h
#define _SDL_uikitvideo_h
+#include "../SDL_sysvideo.h"
+
+#ifdef __OBJC__
+
#include
-#include "../SDL_sysvideo.h"
+@interface SDL_VideoData : NSObject
+
+@property (nonatomic) id pasteboardObserver;
+
+@end
+
+CGRect UIKit_ComputeViewFrame(SDL_Window *window, UIScreen *screen);
+
+#endif /* __OBJC__ */
void UIKit_SuspendScreenSaver(_THIS);
-BOOL UIKit_IsSystemVersionAtLeast(double version);
-CGRect UIKit_ComputeViewFrame(SDL_Window *window, UIScreen *screen);
+SDL_bool UIKit_IsSystemVersionAtLeast(double version);
#endif /* _SDL_uikitvideo_h */
diff --git a/Engine/lib/sdl/src/video/uikit/SDL_uikitvideo.m b/Engine/lib/sdl/src/video/uikit/SDL_uikitvideo.m
index 4f3c7dc43..88d461751 100644
--- a/Engine/lib/sdl/src/video/uikit/SDL_uikitvideo.m
+++ b/Engine/lib/sdl/src/video/uikit/SDL_uikitvideo.m
@@ -36,9 +36,14 @@
#include "SDL_uikitmodes.h"
#include "SDL_uikitwindow.h"
#include "SDL_uikitopengles.h"
+#include "SDL_uikitclipboard.h"
#define UIKITVID_DRIVER_NAME "uikit"
+@implementation SDL_VideoData
+
+@end
+
/* Initialization/Query functions */
static int UIKit_VideoInit(_THIS);
static void UIKit_VideoQuit(_THIS);
@@ -53,60 +58,75 @@ UIKit_Available(void)
static void UIKit_DeleteDevice(SDL_VideoDevice * device)
{
- SDL_free(device);
+ @autoreleasepool {
+ CFRelease(device->driverdata);
+ SDL_free(device);
+ }
}
static SDL_VideoDevice *
UIKit_CreateDevice(int devindex)
{
- SDL_VideoDevice *device;
+ @autoreleasepool {
+ SDL_VideoDevice *device;
+ SDL_VideoData *data;
- /* Initialize all variables that we clean on shutdown */
- device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
- if (!device) {
- SDL_free(device);
- SDL_OutOfMemory();
- return (0);
+ /* Initialize all variables that we clean on shutdown */
+ device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
+ if (device) {
+ data = [SDL_VideoData new];
+ } else {
+ SDL_free(device);
+ SDL_OutOfMemory();
+ return (0);
+ }
+
+ device->driverdata = (void *) CFBridgingRetain(data);
+
+ /* Set the function pointers */
+ device->VideoInit = UIKit_VideoInit;
+ device->VideoQuit = UIKit_VideoQuit;
+ device->GetDisplayModes = UIKit_GetDisplayModes;
+ device->SetDisplayMode = UIKit_SetDisplayMode;
+ device->PumpEvents = UIKit_PumpEvents;
+ device->SuspendScreenSaver = UIKit_SuspendScreenSaver;
+ device->CreateWindow = UIKit_CreateWindow;
+ device->SetWindowTitle = UIKit_SetWindowTitle;
+ device->ShowWindow = UIKit_ShowWindow;
+ device->HideWindow = UIKit_HideWindow;
+ device->RaiseWindow = UIKit_RaiseWindow;
+ device->SetWindowBordered = UIKit_SetWindowBordered;
+ device->SetWindowFullscreen = UIKit_SetWindowFullscreen;
+ device->DestroyWindow = UIKit_DestroyWindow;
+ device->GetWindowWMInfo = UIKit_GetWindowWMInfo;
+ device->GetDisplayUsableBounds = UIKit_GetDisplayUsableBounds;
+
+ #if SDL_IPHONE_KEYBOARD
+ device->HasScreenKeyboardSupport = UIKit_HasScreenKeyboardSupport;
+ device->ShowScreenKeyboard = UIKit_ShowScreenKeyboard;
+ device->HideScreenKeyboard = UIKit_HideScreenKeyboard;
+ device->IsScreenKeyboardShown = UIKit_IsScreenKeyboardShown;
+ device->SetTextInputRect = UIKit_SetTextInputRect;
+ #endif
+
+ device->SetClipboardText = UIKit_SetClipboardText;
+ device->GetClipboardText = UIKit_GetClipboardText;
+ device->HasClipboardText = UIKit_HasClipboardText;
+
+ /* OpenGL (ES) functions */
+ device->GL_MakeCurrent = UIKit_GL_MakeCurrent;
+ device->GL_GetDrawableSize = UIKit_GL_GetDrawableSize;
+ device->GL_SwapWindow = UIKit_GL_SwapWindow;
+ device->GL_CreateContext = UIKit_GL_CreateContext;
+ device->GL_DeleteContext = UIKit_GL_DeleteContext;
+ device->GL_GetProcAddress = UIKit_GL_GetProcAddress;
+ device->GL_LoadLibrary = UIKit_GL_LoadLibrary;
+ device->free = UIKit_DeleteDevice;
+
+ device->gl_config.accelerated = 1;
+
+ return device;
}
-
- /* Set the function pointers */
- device->VideoInit = UIKit_VideoInit;
- device->VideoQuit = UIKit_VideoQuit;
- device->GetDisplayModes = UIKit_GetDisplayModes;
- device->SetDisplayMode = UIKit_SetDisplayMode;
- device->PumpEvents = UIKit_PumpEvents;
- device->SuspendScreenSaver = UIKit_SuspendScreenSaver;
- device->CreateWindow = UIKit_CreateWindow;
- device->SetWindowTitle = UIKit_SetWindowTitle;
- device->ShowWindow = UIKit_ShowWindow;
- device->HideWindow = UIKit_HideWindow;
- device->RaiseWindow = UIKit_RaiseWindow;
- device->SetWindowBordered = UIKit_SetWindowBordered;
- device->SetWindowFullscreen = UIKit_SetWindowFullscreen;
- device->DestroyWindow = UIKit_DestroyWindow;
- device->GetWindowWMInfo = UIKit_GetWindowWMInfo;
-
-#if SDL_IPHONE_KEYBOARD
- device->HasScreenKeyboardSupport = UIKit_HasScreenKeyboardSupport;
- device->ShowScreenKeyboard = UIKit_ShowScreenKeyboard;
- device->HideScreenKeyboard = UIKit_HideScreenKeyboard;
- device->IsScreenKeyboardShown = UIKit_IsScreenKeyboardShown;
- device->SetTextInputRect = UIKit_SetTextInputRect;
-#endif
-
- /* OpenGL (ES) functions */
- device->GL_MakeCurrent = UIKit_GL_MakeCurrent;
- device->GL_GetDrawableSize = UIKit_GL_GetDrawableSize;
- device->GL_SwapWindow = UIKit_GL_SwapWindow;
- device->GL_CreateContext = UIKit_GL_CreateContext;
- device->GL_DeleteContext = UIKit_GL_DeleteContext;
- device->GL_GetProcAddress = UIKit_GL_GetProcAddress;
- device->GL_LoadLibrary = UIKit_GL_LoadLibrary;
- device->free = UIKit_DeleteDevice;
-
- device->gl_config.accelerated = 1;
-
- return device;
}
VideoBootStrap UIKIT_bootstrap = {
@@ -138,7 +158,7 @@ UIKit_SuspendScreenSaver(_THIS)
@autoreleasepool {
/* Ignore ScreenSaver API calls if the idle timer hint has been set. */
/* FIXME: The idle timer hint should be deprecated for SDL 2.1. */
- if (SDL_GetHint(SDL_HINT_IDLE_TIMER_DISABLED) == NULL) {
+ if (!SDL_GetHintBoolean(SDL_HINT_IDLE_TIMER_DISABLED, SDL_FALSE)) {
UIApplication *app = [UIApplication sharedApplication];
/* Prevent the display from dimming and going to sleep. */
@@ -147,7 +167,7 @@ UIKit_SuspendScreenSaver(_THIS)
}
}
-BOOL
+SDL_bool
UIKit_IsSystemVersionAtLeast(double version)
{
return [[UIDevice currentDevice].systemVersion doubleValue] >= version;
@@ -156,6 +176,7 @@ UIKit_IsSystemVersionAtLeast(double version)
CGRect
UIKit_ComputeViewFrame(SDL_Window *window, UIScreen *screen)
{
+#if !TARGET_OS_TV && (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_7_0)
BOOL hasiOS7 = UIKit_IsSystemVersionAtLeast(7.0);
if (hasiOS7 || (window->flags & (SDL_WINDOW_BORDERLESS|SDL_WINDOW_FULLSCREEN))) {
@@ -164,6 +185,9 @@ UIKit_ComputeViewFrame(SDL_Window *window, UIScreen *screen)
} else {
return screen.applicationFrame;
}
+#else
+ return screen.bounds;
+#endif
}
/*
diff --git a/Engine/lib/sdl/src/video/uikit/SDL_uikitview.m b/Engine/lib/sdl/src/video/uikit/SDL_uikitview.m
index 1ccda98ff..c7d9f51d9 100644
--- a/Engine/lib/sdl/src/video/uikit/SDL_uikitview.m
+++ b/Engine/lib/sdl/src/video/uikit/SDL_uikitview.m
@@ -45,7 +45,9 @@
self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.autoresizesSubviews = YES;
+#if !TARGET_OS_TV
self.multipleTouchEnabled = YES;
+#endif
touchId = 1;
SDL_AddTouch(touchId, "");
@@ -141,12 +143,13 @@
if (!firstFingerDown) {
CGPoint locationInView = [self touchLocation:touch shouldNormalize:NO];
+ int clicks = (int) touch.tapCount;
/* send mouse moved event */
SDL_SendMouseMotion(sdlwindow, SDL_TOUCH_MOUSEID, 0, locationInView.x, locationInView.y);
/* send mouse down event */
- SDL_SendMouseButton(sdlwindow, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT);
+ SDL_SendMouseButtonClicks(sdlwindow, SDL_TOUCH_MOUSEID, SDL_PRESSED, SDL_BUTTON_LEFT, clicks);
firstFingerDown = touch;
}
@@ -164,7 +167,8 @@
if (touch == firstFingerDown) {
/* send mouse up */
- SDL_SendMouseButton(sdlwindow, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT);
+ int clicks = (int) touch.tapCount;
+ SDL_SendMouseButtonClicks(sdlwindow, SDL_TOUCH_MOUSEID, SDL_RELEASED, SDL_BUTTON_LEFT, clicks);
firstFingerDown = nil;
}
@@ -197,6 +201,69 @@
}
}
+#if TARGET_OS_TV || defined(__IPHONE_9_1)
+- (SDL_Scancode)scancodeFromPressType:(UIPressType)presstype
+{
+ switch (presstype) {
+ case UIPressTypeUpArrow:
+ return SDL_SCANCODE_UP;
+ case UIPressTypeDownArrow:
+ return SDL_SCANCODE_DOWN;
+ case UIPressTypeLeftArrow:
+ return SDL_SCANCODE_LEFT;
+ case UIPressTypeRightArrow:
+ return SDL_SCANCODE_RIGHT;
+ case UIPressTypeSelect:
+ /* HIG says: "primary button behavior" */
+ return SDL_SCANCODE_SELECT;
+ case UIPressTypeMenu:
+ /* HIG says: "returns to previous screen" */
+ return SDL_SCANCODE_MENU;
+ case UIPressTypePlayPause:
+ /* HIG says: "secondary button behavior" */
+ return SDL_SCANCODE_PAUSE;
+ default:
+ return SDL_SCANCODE_UNKNOWN;
+ }
+}
+
+- (void)pressesBegan:(NSSet *)presses withEvent:(UIPressesEvent *)event
+{
+ for (UIPress *press in presses) {
+ SDL_Scancode scancode = [self scancodeFromPressType:press.type];
+ SDL_SendKeyboardKey(SDL_PRESSED, scancode);
+ }
+
+ [super pressesBegan:presses withEvent:event];
+}
+
+- (void)pressesEnded:(NSSet *)presses withEvent:(UIPressesEvent *)event
+{
+ for (UIPress *press in presses) {
+ SDL_Scancode scancode = [self scancodeFromPressType:press.type];
+ SDL_SendKeyboardKey(SDL_RELEASED, scancode);
+ }
+
+ [super pressesEnded:presses withEvent:event];
+}
+
+- (void)pressesCancelled:(NSSet *)presses withEvent:(UIPressesEvent *)event
+{
+ for (UIPress *press in presses) {
+ SDL_Scancode scancode = [self scancodeFromPressType:press.type];
+ SDL_SendKeyboardKey(SDL_RELEASED, scancode);
+ }
+
+ [super pressesCancelled:presses withEvent:event];
+}
+
+- (void)pressesChanged:(NSSet *)presses withEvent:(UIPressesEvent *)event
+{
+ /* This is only called when the force of a press changes. */
+ [super pressesChanged:presses withEvent:event];
+}
+#endif /* TARGET_OS_TV || defined(__IPHONE_9_1) */
+
@end
#endif /* SDL_VIDEO_DRIVER_UIKIT */
diff --git a/Engine/lib/sdl/src/video/uikit/SDL_uikitviewcontroller.h b/Engine/lib/sdl/src/video/uikit/SDL_uikitviewcontroller.h
index c78396802..860852441 100644
--- a/Engine/lib/sdl/src/video/uikit/SDL_uikitviewcontroller.h
+++ b/Engine/lib/sdl/src/video/uikit/SDL_uikitviewcontroller.h
@@ -1,23 +1,24 @@
/*
- Simple DirectMedia Layer
- Copyright (C) 1997-2016 Sam Lantinga
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2016 Sam Lantinga
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
#import
@@ -25,10 +26,17 @@
#include "SDL_touch.h"
-#if SDL_IPHONE_KEYBOARD
-@interface SDL_uikitviewcontroller : UIViewController
+#if TARGET_OS_TV
+#import
+#define SDLRootViewController GCEventViewController
#else
-@interface SDL_uikitviewcontroller : UIViewController
+#define SDLRootViewController UIViewController
+#endif
+
+#if SDL_IPHONE_KEYBOARD
+@interface SDL_uikitviewcontroller : SDLRootViewController
+#else
+@interface SDL_uikitviewcontroller : SDLRootViewController
#endif
@property (nonatomic, assign) SDL_Window *window;
@@ -46,8 +54,11 @@
- (void)loadView;
- (void)viewDidLayoutSubviews;
+
+#if !TARGET_OS_TV
- (NSUInteger)supportedInterfaceOrientations;
- (BOOL)prefersStatusBarHidden;
+#endif
#if SDL_IPHONE_KEYBOARD
- (void)showKeyboard;
diff --git a/Engine/lib/sdl/src/video/uikit/SDL_uikitviewcontroller.m b/Engine/lib/sdl/src/video/uikit/SDL_uikitviewcontroller.m
index 58cdf1ac5..e6e903ee4 100644
--- a/Engine/lib/sdl/src/video/uikit/SDL_uikitviewcontroller.m
+++ b/Engine/lib/sdl/src/video/uikit/SDL_uikitviewcontroller.m
@@ -33,11 +33,23 @@
#include "SDL_uikitvideo.h"
#include "SDL_uikitmodes.h"
#include "SDL_uikitwindow.h"
+#include "SDL_uikitopengles.h"
#if SDL_IPHONE_KEYBOARD
#include "keyinfotable.h"
#endif
+#if TARGET_OS_TV
+static void
+SDL_AppleTVControllerUIHintChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
+{
+ @autoreleasepool {
+ SDL_uikitviewcontroller *viewcontroller = (__bridge SDL_uikitviewcontroller *) userdata;
+ viewcontroller.controllerUserInteractionEnabled = hint && (*hint != '0');
+ }
+}
+#endif
+
@implementation SDL_uikitviewcontroller {
CADisplayLink *displayLink;
int animationInterval;
@@ -59,6 +71,12 @@
#if SDL_IPHONE_KEYBOARD
[self initKeyboard];
#endif
+
+#if TARGET_OS_TV
+ SDL_AddHintCallback(SDL_HINT_APPLE_TV_CONTROLLER_UI_EVENTS,
+ SDL_AppleTVControllerUIHintChanged,
+ (__bridge void *) self);
+#endif
}
return self;
}
@@ -68,6 +86,12 @@
#if SDL_IPHONE_KEYBOARD
[self deinitKeyboard];
#endif
+
+#if TARGET_OS_TV
+ SDL_DelHintCallback(SDL_HINT_APPLE_TV_CONTROLLER_UI_EVENTS,
+ SDL_AppleTVControllerUIHintChanged,
+ (__bridge void *) self);
+#endif
}
- (void)setAnimationCallback:(int)interval
@@ -102,6 +126,9 @@
{
/* Don't run the game loop while a messagebox is up */
if (!UIKit_ShowingMessageBox()) {
+ /* See the comment in the function definition. */
+ UIKit_GL_RestoreCurrentContext();
+
animationCallback(animationCallbackParam);
}
}
@@ -120,6 +147,7 @@
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, w, h);
}
+#if !TARGET_OS_TV
- (NSUInteger)supportedInterfaceOrientations
{
return UIKit_GetSupportedOrientations(window);
@@ -134,6 +162,7 @@
{
return (window->flags & (SDL_WINDOW_FULLSCREEN|SDL_WINDOW_BORDERLESS)) != 0;
}
+#endif
/*
---- Keyboard related functionality below this line ----
@@ -164,9 +193,11 @@
textField.hidden = YES;
keyboardVisible = NO;
+#if !TARGET_OS_TV
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[center addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
+#endif
}
- (void)setView:(UIView *)view
@@ -182,9 +213,11 @@
- (void)deinitKeyboard
{
+#if !TARGET_OS_TV
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center removeObserver:self name:UIKeyboardWillShowNotification object:nil];
[center removeObserver:self name:UIKeyboardWillHideNotification object:nil];
+#endif
}
/* reveal onscreen virtual keyboard */
@@ -205,6 +238,7 @@
- (void)keyboardWillShow:(NSNotification *)notification
{
+#if !TARGET_OS_TV
CGRect kbrect = [[notification userInfo][UIKeyboardFrameBeginUserInfoKey] CGRectValue];
/* The keyboard rect is in the coordinate space of the screen/window, but we
@@ -212,10 +246,12 @@
kbrect = [self.view convertRect:kbrect fromView:nil];
[self setKeyboardHeight:(int)kbrect.size.height];
+#endif
}
- (void)keyboardWillHide:(NSNotification *)notification
{
+ SDL_StopTextInput();
[self setKeyboardHeight:0];
}
diff --git a/Engine/lib/sdl/src/video/uikit/SDL_uikitwindow.m b/Engine/lib/sdl/src/video/uikit/SDL_uikitwindow.m
index c5f385b8c..35c549b43 100644
--- a/Engine/lib/sdl/src/video/uikit/SDL_uikitwindow.m
+++ b/Engine/lib/sdl/src/video/uikit/SDL_uikitwindow.m
@@ -99,14 +99,13 @@ static int SetupWindowData(_THIS, SDL_Window *window, UIWindow *uiwindow, SDL_bo
/* only one window on iOS, always shown */
window->flags &= ~SDL_WINDOW_HIDDEN;
- if (displaydata.uiscreen == [UIScreen mainScreen]) {
- window->flags |= SDL_WINDOW_INPUT_FOCUS; /* always has input focus */
- } else {
+ if (displaydata.uiscreen != [UIScreen mainScreen]) {
window->flags &= ~SDL_WINDOW_RESIZABLE; /* window is NEVER resizable */
window->flags &= ~SDL_WINDOW_INPUT_FOCUS; /* never has input focus */
window->flags |= SDL_WINDOW_BORDERLESS; /* never has a status bar. */
}
+#if !TARGET_OS_TV
if (displaydata.uiscreen == [UIScreen mainScreen]) {
NSUInteger orients = UIKit_GetSupportedOrientations(window);
BOOL supportsLandscape = (orients & UIInterfaceOrientationMaskLandscape) != 0;
@@ -119,6 +118,7 @@ static int SetupWindowData(_THIS, SDL_Window *window, UIWindow *uiwindow, SDL_bo
height = temp;
}
}
+#endif /* !TARGET_OS_TV */
window->x = 0;
window->y = 0;
@@ -152,7 +152,6 @@ UIKit_CreateWindow(_THIS, SDL_Window *window)
@autoreleasepool {
SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window);
SDL_DisplayData *data = (__bridge SDL_DisplayData *) display->driverdata;
- const CGSize origsize = data.uiscreen.currentMode.size;
/* SDL currently puts this window at the start of display's linked list. We rely on this. */
SDL_assert(_this->windows == window);
@@ -165,6 +164,8 @@ UIKit_CreateWindow(_THIS, SDL_Window *window)
/* If monitor has a resolution of 0x0 (hasn't been explicitly set by the
* user, so it's in standby), try to force the display to a resolution
* that most closely matches the desired window size. */
+#if !TARGET_OS_TV
+ const CGSize origsize = data.uiscreen.currentMode.size;
if ((origsize.width == 0.0f) && (origsize.height == 0.0f)) {
if (display->num_display_modes == 0) {
_this->GetDisplayModes(_this, display);
@@ -197,6 +198,7 @@ UIKit_CreateWindow(_THIS, SDL_Window *window)
[UIApplication sharedApplication].statusBarHidden = NO;
}
}
+#endif /* !TARGET_OS_TV */
/* ignore the size user requested, and make a fullscreen window */
/* !!! FIXME: can we have a smaller view? */
@@ -258,6 +260,7 @@ UIKit_UpdateWindowBorder(_THIS, SDL_Window * window)
SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
SDL_uikitviewcontroller *viewcontroller = data.viewcontroller;
+#if !TARGET_OS_TV
if (data.uiwindow.screen == [UIScreen mainScreen]) {
if (window->flags & (SDL_WINDOW_FULLSCREEN | SDL_WINDOW_BORDERLESS)) {
[UIApplication sharedApplication].statusBarHidden = YES;
@@ -273,6 +276,7 @@ UIKit_UpdateWindowBorder(_THIS, SDL_Window * window)
/* Update the view's frame to account for the status bar change. */
viewcontroller.view.frame = UIKit_ComputeViewFrame(window, data.uiwindow.screen);
+#endif /* !TARGET_OS_TV */
#ifdef SDL_IPHONE_KEYBOARD
/* Make sure the view is offset correctly when the keyboard is visible. */
@@ -363,6 +367,7 @@ UIKit_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
}
}
+#if !TARGET_OS_TV
NSUInteger
UIKit_GetSupportedOrientations(SDL_Window * window)
{
@@ -428,6 +433,7 @@ UIKit_GetSupportedOrientations(SDL_Window * window)
return orientationMask;
}
+#endif /* !TARGET_OS_TV */
int
SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam)
diff --git a/Engine/lib/sdl/src/video/vivante/SDL_vivantevideo.c b/Engine/lib/sdl/src/video/vivante/SDL_vivantevideo.c
index fe4ea089d..0372de5c3 100644
--- a/Engine/lib/sdl/src/video/vivante/SDL_vivantevideo.c
+++ b/Engine/lib/sdl/src/video/vivante/SDL_vivantevideo.c
@@ -77,7 +77,7 @@ VIVANTE_Create()
device->driverdata = data;
- /* Setup amount of available displays and current display */
+ /* Setup amount of available displays */
device->num_displays = 0;
/* Set device free function */
@@ -366,12 +366,13 @@ VIVANTE_HideWindow(_THIS, SDL_Window * window)
SDL_bool
VIVANTE_GetWindowWMInfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo *info)
{
-/*
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ SDL_DisplayData *displaydata = SDL_GetDisplayDriverData(0);
if (info->version.major == SDL_MAJOR_VERSION &&
info->version.minor == SDL_MINOR_VERSION) {
info->subsystem = SDL_SYSWM_VIVANTE;
+ info->info.vivante.display = displaydata->native_display;
info->info.vivante.window = data->native_window;
return SDL_TRUE;
} else {
@@ -379,9 +380,6 @@ VIVANTE_GetWindowWMInfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo *info)
SDL_MAJOR_VERSION, SDL_MINOR_VERSION);
return SDL_FALSE;
}
-*/
- SDL_Unsupported();
- return SDL_FALSE;
}
/*****************************************************************************/
diff --git a/Engine/lib/sdl/src/video/wayland/SDL_waylanddyn.c b/Engine/lib/sdl/src/video/wayland/SDL_waylanddyn.c
index bc1d06e46..14674fbe2 100644
--- a/Engine/lib/sdl/src/video/wayland/SDL_waylanddyn.c
+++ b/Engine/lib/sdl/src/video/wayland/SDL_waylanddyn.c
@@ -94,9 +94,6 @@ WAYLAND_GetSym(const char *fnname, int *pHasModule)
#define SDL_WAYLAND_SYM(rc,fn,params) SDL_DYNWAYLANDFN_##fn WAYLAND_##fn = NULL;
#define SDL_WAYLAND_INTERFACE(iface) const struct wl_interface *WAYLAND_##iface = NULL;
#include "SDL_waylandsym.h"
-#undef SDL_WAYLAND_MODULE
-#undef SDL_WAYLAND_SYM
-#undef SDL_WAYLAND_INTERFACE
static int wayland_load_refcount = 0;
@@ -115,9 +112,6 @@ SDL_WAYLAND_UnloadSymbols(void)
#define SDL_WAYLAND_SYM(rc,fn,params) WAYLAND_##fn = NULL;
#define SDL_WAYLAND_INTERFACE(iface) WAYLAND_##iface = NULL;
#include "SDL_waylandsym.h"
-#undef SDL_WAYLAND_MODULE
-#undef SDL_WAYLAND_SYM
-#undef SDL_WAYLAND_INTERFACE
#ifdef SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC
@@ -150,20 +144,12 @@ SDL_WAYLAND_LoadSymbols(void)
}
#define SDL_WAYLAND_MODULE(modname) SDL_WAYLAND_HAVE_##modname = 1; /* default yes */
-#define SDL_WAYLAND_SYM(rc,fn,params)
-#define SDL_WAYLAND_INTERFACE(iface)
#include "SDL_waylandsym.h"
-#undef SDL_WAYLAND_MODULE
-#undef SDL_WAYLAND_SYM
-#undef SDL_WAYLAND_INTERFACE
#define SDL_WAYLAND_MODULE(modname) thismod = &SDL_WAYLAND_HAVE_##modname;
#define SDL_WAYLAND_SYM(rc,fn,params) WAYLAND_##fn = (SDL_DYNWAYLANDFN_##fn) WAYLAND_GetSym(#fn,thismod);
#define SDL_WAYLAND_INTERFACE(iface) WAYLAND_##iface = (struct wl_interface *) WAYLAND_GetSym(#iface,thismod);
#include "SDL_waylandsym.h"
-#undef SDL_WAYLAND_MODULE
-#undef SDL_WAYLAND_SYM
-#undef SDL_WAYLAND_INTERFACE
if (SDL_WAYLAND_HAVE_WAYLAND_CLIENT) {
/* all required symbols loaded. */
@@ -180,9 +166,6 @@ SDL_WAYLAND_LoadSymbols(void)
#define SDL_WAYLAND_SYM(rc,fn,params) WAYLAND_##fn = fn;
#define SDL_WAYLAND_INTERFACE(iface) WAYLAND_##iface = &iface;
#include "SDL_waylandsym.h"
-#undef SDL_WAYLAND_MODULE
-#undef SDL_WAYLAND_SYM
-#undef SDL_WAYLAND_INTERFACE
#endif
}
diff --git a/Engine/lib/sdl/src/video/wayland/SDL_waylanddyn.h b/Engine/lib/sdl/src/video/wayland/SDL_waylanddyn.h
index b3ff9d8e9..f1f652566 100644
--- a/Engine/lib/sdl/src/video/wayland/SDL_waylanddyn.h
+++ b/Engine/lib/sdl/src/video/wayland/SDL_waylanddyn.h
@@ -53,10 +53,7 @@ void SDL_WAYLAND_UnloadSymbols(void);
extern SDL_DYNWAYLANDFN_##fn WAYLAND_##fn;
#define SDL_WAYLAND_INTERFACE(iface) extern const struct wl_interface *WAYLAND_##iface;
#include "SDL_waylandsym.h"
-#undef SDL_WAYLAND_MODULE
-#undef SDL_WAYLAND_SYM
-#undef SDL_WAYLAND_INTERFACE
-
+
#ifdef __cplusplus
}
@@ -79,6 +76,7 @@ void SDL_WAYLAND_UnloadSymbols(void);
#define wl_proxy_get_user_data (*WAYLAND_wl_proxy_get_user_data)
#define wl_proxy_add_listener (*WAYLAND_wl_proxy_add_listener)
#define wl_proxy_marshal_constructor (*WAYLAND_wl_proxy_marshal_constructor)
+#define wl_proxy_marshal_constructor_versioned (*WAYLAND_wl_proxy_marshal_constructor_versioned)
#define wl_seat_interface (*WAYLAND_wl_seat_interface)
#define wl_surface_interface (*WAYLAND_wl_surface_interface)
@@ -96,7 +94,8 @@ void SDL_WAYLAND_UnloadSymbols(void);
#endif /* SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC */
-#include "wayland-client.h"
+#include "wayland-client-core.h"
+#include "wayland-client-protocol.h"
#include "wayland-egl.h"
#endif /* !defined _SDL_waylanddyn_h */
diff --git a/Engine/lib/sdl/src/video/wayland/SDL_waylandevents.c b/Engine/lib/sdl/src/video/wayland/SDL_waylandevents.c
index 53b0ac907..2443aef7a 100644
--- a/Engine/lib/sdl/src/video/wayland/SDL_waylandevents.c
+++ b/Engine/lib/sdl/src/video/wayland/SDL_waylandevents.c
@@ -25,6 +25,7 @@
#include "SDL_stdinc.h"
#include "SDL_assert.h"
+#include "SDL_log.h"
#include "../../events/SDL_sysevents.h"
#include "../../events/SDL_events_c.h"
@@ -36,11 +37,13 @@
#include "SDL_waylanddyn.h"
+#include "pointer-constraints-unstable-v1-client-protocol.h"
+#include "relative-pointer-unstable-v1-client-protocol.h"
+
#include
#include
#include
#include
-#include
#include
#include
@@ -49,13 +52,17 @@ struct SDL_WaylandInput {
struct wl_seat *seat;
struct wl_pointer *pointer;
struct wl_keyboard *keyboard;
+ struct zwp_relative_pointer_v1 *relative_pointer;
SDL_WindowData *pointer_focus;
SDL_WindowData *keyboard_focus;
/* Last motion location */
wl_fixed_t sx_w;
wl_fixed_t sy_w;
-
+
+ double dx_frac;
+ double dy_frac;
+
struct {
struct xkb_keymap *keymap;
struct xkb_state *state;
@@ -171,10 +178,9 @@ ProcessHitTest(struct SDL_WaylandInput *input, uint32_t serial)
}
static void
-pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial,
- uint32_t time, uint32_t button, uint32_t state_w)
+pointer_handle_button_common(struct SDL_WaylandInput *input, uint32_t serial,
+ uint32_t time, uint32_t button, uint32_t state_w)
{
- struct SDL_WaylandInput *input = data;
SDL_WindowData *window = input->pointer_focus;
enum wl_pointer_button_state state = state_w;
uint32_t sdl_button;
@@ -183,7 +189,7 @@ pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial,
switch (button) {
case BTN_LEFT:
sdl_button = SDL_BUTTON_LEFT;
- if (ProcessHitTest(data, serial)) {
+ if (ProcessHitTest(input, serial)) {
return; /* don't pass this event on to app. */
}
break;
@@ -209,10 +215,18 @@ pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial,
}
static void
-pointer_handle_axis(void *data, struct wl_pointer *pointer,
- uint32_t time, uint32_t axis, wl_fixed_t value)
+pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial,
+ uint32_t time, uint32_t button, uint32_t state_w)
{
struct SDL_WaylandInput *input = data;
+
+ pointer_handle_button_common(input, serial, time, button, state_w);
+}
+
+static void
+pointer_handle_axis_common(struct SDL_WaylandInput *input,
+ uint32_t time, uint32_t axis, wl_fixed_t value)
+{
SDL_WindowData *window = input->pointer_focus;
enum wl_pointer_axis a = axis;
int x, y;
@@ -235,6 +249,15 @@ pointer_handle_axis(void *data, struct wl_pointer *pointer,
}
}
+static void
+pointer_handle_axis(void *data, struct wl_pointer *pointer,
+ uint32_t time, uint32_t axis, wl_fixed_t value)
+{
+ struct SDL_WaylandInput *input = data;
+
+ pointer_handle_axis_common(input, time, axis, value);
+}
+
static const struct wl_pointer_listener pointer_listener = {
pointer_handle_enter,
pointer_handle_leave,
@@ -302,9 +325,9 @@ keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
window = wl_surface_get_user_data(surface);
- input->keyboard_focus = window;
- window->keyboard_device = input;
if (window) {
+ input->keyboard_focus = window;
+ window->keyboard_device = input;
SDL_SetKeyboardFocus(window->sdlwindow);
}
}
@@ -454,6 +477,164 @@ void Wayland_display_destroy_input(SDL_VideoData *d)
d->input = NULL;
}
+void Wayland_display_add_relative_pointer_manager(SDL_VideoData *d, uint32_t id)
+{
+ d->relative_pointer_manager =
+ wl_registry_bind(d->registry, id,
+ &zwp_relative_pointer_manager_v1_interface, 1);
+}
+
+void Wayland_display_destroy_relative_pointer_manager(SDL_VideoData *d)
+{
+ if (d->relative_pointer_manager)
+ zwp_relative_pointer_manager_v1_destroy(d->relative_pointer_manager);
+}
+
+void Wayland_display_add_pointer_constraints(SDL_VideoData *d, uint32_t id)
+{
+ d->pointer_constraints =
+ wl_registry_bind(d->registry, id,
+ &zwp_pointer_constraints_v1_interface, 1);
+}
+
+void Wayland_display_destroy_pointer_constraints(SDL_VideoData *d)
+{
+ if (d->pointer_constraints)
+ zwp_pointer_constraints_v1_destroy(d->pointer_constraints);
+}
+
+static void
+relative_pointer_handle_relative_motion(void *data,
+ struct zwp_relative_pointer_v1 *pointer,
+ uint32_t time_hi,
+ uint32_t time_lo,
+ wl_fixed_t dx_w,
+ wl_fixed_t dy_w,
+ wl_fixed_t dx_unaccel_w,
+ wl_fixed_t dy_unaccel_w)
+{
+ struct SDL_WaylandInput *input = data;
+ SDL_VideoData *d = input->display;
+ SDL_WindowData *window = input->pointer_focus;
+ double dx_unaccel;
+ double dy_unaccel;
+ double dx;
+ double dy;
+
+ dx_unaccel = wl_fixed_to_double(dx_unaccel_w);
+ dy_unaccel = wl_fixed_to_double(dy_unaccel_w);
+
+ /* Add left over fraction from last event. */
+ dx_unaccel += input->dx_frac;
+ dy_unaccel += input->dy_frac;
+
+ input->dx_frac = modf(dx_unaccel, &dx);
+ input->dy_frac = modf(dy_unaccel, &dy);
+
+ if (input->pointer_focus && d->relative_mouse_mode) {
+ SDL_SendMouseMotion(window->sdlwindow, 0, 1, (int)dx, (int)dy);
+ }
+}
+
+static const struct zwp_relative_pointer_v1_listener relative_pointer_listener = {
+ relative_pointer_handle_relative_motion,
+};
+
+static void
+locked_pointer_locked(void *data,
+ struct zwp_locked_pointer_v1 *locked_pointer)
+{
+}
+
+static void
+locked_pointer_unlocked(void *data,
+ struct zwp_locked_pointer_v1 *locked_pointer)
+{
+}
+
+static const struct zwp_locked_pointer_v1_listener locked_pointer_listener = {
+ locked_pointer_locked,
+ locked_pointer_unlocked,
+};
+
+static void
+lock_pointer_to_window(SDL_Window *window,
+ struct SDL_WaylandInput *input)
+{
+ SDL_WindowData *w = window->driverdata;
+ SDL_VideoData *d = input->display;
+ struct zwp_locked_pointer_v1 *locked_pointer;
+
+ if (w->locked_pointer)
+ return;
+
+ locked_pointer =
+ zwp_pointer_constraints_v1_lock_pointer(d->pointer_constraints,
+ w->surface,
+ input->pointer,
+ NULL,
+ ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
+ zwp_locked_pointer_v1_add_listener(locked_pointer,
+ &locked_pointer_listener,
+ window);
+
+ w->locked_pointer = locked_pointer;
+}
+
+int Wayland_input_lock_pointer(struct SDL_WaylandInput *input)
+{
+ SDL_VideoDevice *vd = SDL_GetVideoDevice();
+ SDL_VideoData *d = input->display;
+ SDL_Window *window;
+ struct zwp_relative_pointer_v1 *relative_pointer;
+
+ if (!d->relative_pointer_manager)
+ return -1;
+
+ if (!d->pointer_constraints)
+ return -1;
+
+ if (!input->relative_pointer) {
+ relative_pointer =
+ zwp_relative_pointer_manager_v1_get_relative_pointer(
+ d->relative_pointer_manager,
+ input->pointer);
+ zwp_relative_pointer_v1_add_listener(relative_pointer,
+ &relative_pointer_listener,
+ input);
+ input->relative_pointer = relative_pointer;
+ }
+
+ for (window = vd->windows; window; window = window->next)
+ lock_pointer_to_window(window, input);
+
+ d->relative_mouse_mode = 1;
+
+ return 0;
+}
+
+int Wayland_input_unlock_pointer(struct SDL_WaylandInput *input)
+{
+ SDL_VideoDevice *vd = SDL_GetVideoDevice();
+ SDL_VideoData *d = input->display;
+ SDL_Window *window;
+ SDL_WindowData *w;
+
+ for (window = vd->windows; window; window = window->next) {
+ w = window->driverdata;
+ if (w->locked_pointer)
+ zwp_locked_pointer_v1_destroy(w->locked_pointer);
+ w->locked_pointer = NULL;
+ }
+
+ zwp_relative_pointer_v1_destroy(input->relative_pointer);
+ input->relative_pointer = NULL;
+
+ d->relative_mouse_mode = 0;
+
+ return 0;
+}
+
#endif /* SDL_VIDEO_DRIVER_WAYLAND */
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/video/wayland/SDL_waylandevents_c.h b/Engine/lib/sdl/src/video/wayland/SDL_waylandevents_c.h
index 62b163bf6..56d12ec27 100644
--- a/Engine/lib/sdl/src/video/wayland/SDL_waylandevents_c.h
+++ b/Engine/lib/sdl/src/video/wayland/SDL_waylandevents_c.h
@@ -32,6 +32,15 @@ extern void Wayland_PumpEvents(_THIS);
extern void Wayland_display_add_input(SDL_VideoData *d, uint32_t id);
extern void Wayland_display_destroy_input(SDL_VideoData *d);
+extern void Wayland_display_add_pointer_constraints(SDL_VideoData *d, uint32_t id);
+extern void Wayland_display_destroy_pointer_constraints(SDL_VideoData *d);
+
+extern int Wayland_input_lock_pointer(struct SDL_WaylandInput *input);
+extern int Wayland_input_unlock_pointer(struct SDL_WaylandInput *input);
+
+extern void Wayland_display_add_relative_pointer_manager(SDL_VideoData *d, uint32_t id);
+extern void Wayland_display_destroy_relative_pointer_manager(SDL_VideoData *d);
+
#endif /* _SDL_waylandevents_h */
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/video/wayland/SDL_waylandmouse.c b/Engine/lib/sdl/src/video/wayland/SDL_waylandmouse.c
index b810f7784..8dfc9eea3 100644
--- a/Engine/lib/sdl/src/video/wayland/SDL_waylandmouse.c
+++ b/Engine/lib/sdl/src/video/wayland/SDL_waylandmouse.c
@@ -27,7 +27,6 @@
#define _GNU_SOURCE
#endif
-#include
#include
#include
#include
@@ -70,7 +69,6 @@ wayland_create_tmp_file(off_t size)
xdg_path = SDL_getenv("XDG_RUNTIME_DIR");
if (!xdg_path) {
- errno = ENOENT;
return -1;
}
@@ -116,8 +114,7 @@ create_buffer_from_shm(Wayland_CursorData *d,
shm_fd = wayland_create_tmp_file(size);
if (shm_fd < 0)
{
- fprintf(stderr, "creating mouse cursor buffer failed!\n");
- return -1;
+ return SDL_SetError("Creating mouse cursor buffer failed.");
}
d->shm_data = mmap(NULL,
@@ -128,8 +125,8 @@ create_buffer_from_shm(Wayland_CursorData *d,
0);
if (d->shm_data == MAP_FAILED) {
d->shm_data = NULL;
- fprintf (stderr, "mmap () failed\n");
close (shm_fd);
+ return SDL_SetError("mmap() failed.");
}
shm_pool = wl_shm_create_pool(data->shm, shm_fd, size);
@@ -159,6 +156,11 @@ Wayland_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y)
SDL_VideoDevice *vd = SDL_GetVideoDevice ();
SDL_VideoData *wd = (SDL_VideoData *) vd->driverdata;
Wayland_CursorData *data = calloc (1, sizeof (Wayland_CursorData));
+ if (!data) {
+ SDL_OutOfMemory();
+ free(cursor);
+ return NULL;
+ }
cursor->driverdata = (void *) data;
/* Assume ARGB8888 */
@@ -169,7 +171,7 @@ Wayland_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y)
if (create_buffer_from_shm (data,
surface->w,
surface->h,
- WL_SHM_FORMAT_XRGB8888) < 0)
+ WL_SHM_FORMAT_ARGB8888) < 0)
{
free (cursor->driverdata);
free (cursor);
@@ -187,6 +189,8 @@ Wayland_CreateCursor(SDL_Surface *surface, int hot_x, int hot_y)
data->hot_y = hot_y;
data->w = surface->w;
data->h = surface->h;
+ } else {
+ SDL_OutOfMemory();
}
return cursor;
@@ -200,6 +204,11 @@ CreateCursorFromWlCursor(SDL_VideoData *d, struct wl_cursor *wlcursor)
cursor = calloc(1, sizeof (*cursor));
if (cursor) {
Wayland_CursorData *data = calloc (1, sizeof (Wayland_CursorData));
+ if (!data) {
+ SDL_OutOfMemory();
+ free(cursor);
+ return NULL;
+ }
cursor->driverdata = (void *) data;
data->buffer = WAYLAND_wl_cursor_image_get_buffer(wlcursor->images[0]);
@@ -322,13 +331,13 @@ Wayland_ShowCursor(SDL_Cursor *cursor)
{
Wayland_CursorData *data = cursor->driverdata;
- wl_surface_attach(data->surface, data->buffer, 0, 0);
- wl_surface_damage(data->surface, 0, 0, data->w, data->h);
- wl_surface_commit(data->surface);
wl_pointer_set_cursor (pointer, 0,
data->surface,
data->hot_x,
data->hot_y);
+ wl_surface_attach(data->surface, data->buffer, 0, 0);
+ wl_surface_damage(data->surface, 0, 0, data->w, data->h);
+ wl_surface_commit(data->surface);
}
else
{
@@ -356,7 +365,13 @@ Wayland_WarpMouseGlobal(int x, int y)
static int
Wayland_SetRelativeMouseMode(SDL_bool enabled)
{
- return SDL_Unsupported();
+ SDL_VideoDevice *vd = SDL_GetVideoDevice();
+ SDL_VideoData *data = (SDL_VideoData *) vd->driverdata;
+
+ if (enabled)
+ return Wayland_input_lock_pointer(data->input);
+ else
+ return Wayland_input_unlock_pointer(data->input);
}
void
diff --git a/Engine/lib/sdl/src/video/wayland/SDL_waylandsym.h b/Engine/lib/sdl/src/video/wayland/SDL_waylandsym.h
index b093d9db1..aea3cb129 100644
--- a/Engine/lib/sdl/src/video/wayland/SDL_waylandsym.h
+++ b/Engine/lib/sdl/src/video/wayland/SDL_waylandsym.h
@@ -21,6 +21,18 @@
/* *INDENT-OFF* */
+#ifndef SDL_WAYLAND_MODULE
+#define SDL_WAYLAND_MODULE(modname)
+#endif
+
+#ifndef SDL_WAYLAND_SYM
+#define SDL_WAYLAND_SYM(rc,fn,params)
+#endif
+
+#ifndef SDL_WAYLAND_INTERFACE
+#define SDL_WAYLAND_INTERFACE(iface)
+#endif
+
SDL_WAYLAND_MODULE(WAYLAND_CLIENT)
SDL_WAYLAND_SYM(void, wl_proxy_marshal, (struct wl_proxy *, uint32_t, ...))
SDL_WAYLAND_SYM(struct wl_proxy *, wl_proxy_create, (struct wl_proxy *, const struct wl_interface *))
@@ -55,6 +67,9 @@ SDL_WAYLAND_SYM(void, wl_list_insert_list, (struct wl_list *, struct wl_list *))
SDL_WAYLAND_MODULE(WAYLAND_CLIENT_1_4)
SDL_WAYLAND_SYM(struct wl_proxy *, wl_proxy_marshal_constructor, (struct wl_proxy *, uint32_t opcode, const struct wl_interface *interface, ...))
+SDL_WAYLAND_MODULE(WAYLAND_CLIENT_1_10)
+SDL_WAYLAND_SYM(struct wl_proxy *, wl_proxy_marshal_constructor_versioned, (struct wl_proxy *proxy, uint32_t opcode, const struct wl_interface *interface, uint32_t version, ...))
+
SDL_WAYLAND_INTERFACE(wl_seat_interface)
SDL_WAYLAND_INTERFACE(wl_surface_interface)
SDL_WAYLAND_INTERFACE(wl_shm_pool_interface)
@@ -99,8 +114,10 @@ SDL_WAYLAND_SYM(enum xkb_state_component, xkb_state_update_mask, (struct xkb_sta
xkb_layout_index_t latched_layout,\
xkb_layout_index_t locked_layout) )
+#undef SDL_WAYLAND_MODULE
+#undef SDL_WAYLAND_SYM
+#undef SDL_WAYLAND_INTERFACE
/* *INDENT-ON* */
/* vi: set ts=4 sw=4 expandtab: */
-//SDL_WAYLAND_SYM(ret, fn, params)
diff --git a/Engine/lib/sdl/src/video/wayland/SDL_waylandvideo.c b/Engine/lib/sdl/src/video/wayland/SDL_waylandvideo.c
index b47ec29be..554b0ecad 100644
--- a/Engine/lib/sdl/src/video/wayland/SDL_waylandvideo.c
+++ b/Engine/lib/sdl/src/video/wayland/SDL_waylandvideo.c
@@ -35,6 +35,8 @@
#include "SDL_waylandmouse.h"
#include "SDL_waylandtouch.h"
+#include
+#include
#include
#include
@@ -55,6 +57,56 @@ Wayland_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode);
static void
Wayland_VideoQuit(_THIS);
+/* Find out what class name we should use
+ * Based on src/video/x11/SDL_x11video.c */
+static char *
+get_classname()
+{
+ char *spot;
+#if defined(__LINUX__) || defined(__FREEBSD__)
+ char procfile[1024];
+ char linkfile[1024];
+ int linksize;
+#endif
+
+ /* First allow environment variable override */
+ spot = SDL_getenv("SDL_VIDEO_WAYLAND_WMCLASS");
+ if (spot) {
+ return SDL_strdup(spot);
+ } else {
+ /* Fallback to the "old" envvar */
+ spot = SDL_getenv("SDL_VIDEO_X11_WMCLASS");
+ if (spot) {
+ return SDL_strdup(spot);
+ }
+ }
+
+ /* Next look at the application's executable name */
+#if defined(__LINUX__) || defined(__FREEBSD__)
+#if defined(__LINUX__)
+ SDL_snprintf(procfile, SDL_arraysize(procfile), "/proc/%d/exe", getpid());
+#elif defined(__FREEBSD__)
+ SDL_snprintf(procfile, SDL_arraysize(procfile), "/proc/%d/file",
+ getpid());
+#else
+#error Where can we find the executable name?
+#endif
+ linksize = readlink(procfile, linkfile, sizeof(linkfile) - 1);
+ if (linksize > 0) {
+ linkfile[linksize] = '\0';
+ spot = SDL_strrchr(linkfile, '/');
+ if (spot) {
+ return SDL_strdup(spot + 1);
+ } else {
+ return SDL_strdup(linkfile);
+ }
+ }
+#endif /* __LINUX__ || __FREEBSD__ */
+
+ /* Finally use the default we've used forever */
+ return SDL_strdup("SDL_App");
+}
+
/* Wayland driver bootstrap functions */
static int
Wayland_Available(void)
@@ -117,7 +169,10 @@ Wayland_CreateDevice(int devindex)
device->CreateWindow = Wayland_CreateWindow;
device->ShowWindow = Wayland_ShowWindow;
device->SetWindowFullscreen = Wayland_SetWindowFullscreen;
+ device->MaximizeWindow = Wayland_MaximizeWindow;
+ device->RestoreWindow = Wayland_RestoreWindow;
device->SetWindowSize = Wayland_SetWindowSize;
+ device->SetWindowTitle = Wayland_SetWindowTitle;
device->DestroyWindow = Wayland_DestroyWindow;
device->SetWindowHitTest = Wayland_SetWindowHitTest;
@@ -145,7 +200,7 @@ display_handle_geometry(void *data,
{
SDL_VideoDisplay *display = data;
- display->name = strdup(model);
+ display->name = SDL_strdup(model);
display->driverdata = output;
}
@@ -253,8 +308,10 @@ display_handle_global(void *data, struct wl_registry *registry, uint32_t id,
} else if (strcmp(interface, "wl_shm") == 0) {
d->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
d->cursor_theme = WAYLAND_wl_cursor_theme_load(NULL, 32, d->shm);
- d->default_cursor = WAYLAND_wl_cursor_theme_get_cursor(d->cursor_theme, "left_ptr");
-
+ } else if (strcmp(interface, "zwp_relative_pointer_manager_v1") == 0) {
+ Wayland_display_add_relative_pointer_manager(d, id);
+ } else if (strcmp(interface, "zwp_pointer_constraints_v1") == 0) {
+ Wayland_display_add_pointer_constraints(d, id);
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
} else if (strcmp(interface, "qt_touch_extension") == 0) {
Wayland_touch_create(d, id);
@@ -283,6 +340,11 @@ Wayland_VideoInit(_THIS)
_this->driverdata = data;
+ data->xkb_context = WAYLAND_xkb_context_new(0);
+ if (!data->xkb_context) {
+ return SDL_SetError("Failed to create XKB context");
+ }
+
data->display = WAYLAND_wl_display_connect(NULL);
if (data->display == NULL) {
return SDL_SetError("Failed to connect to a Wayland display");
@@ -301,13 +363,11 @@ Wayland_VideoInit(_THIS)
// Second roundtrip to receive all output events.
WAYLAND_wl_display_roundtrip(data->display);
- data->xkb_context = WAYLAND_xkb_context_new(0);
- if (!data->xkb_context) {
- return SDL_SetError("Failed to create XKB context");
- }
-
Wayland_InitMouse();
+ /* Get the surface class name, usually the name of the application */
+ data->classname = get_classname();
+
WAYLAND_wl_display_flush(data->display);
return 0;
@@ -341,6 +401,8 @@ Wayland_VideoQuit(_THIS)
}
Wayland_display_destroy_input(data);
+ Wayland_display_destroy_pointer_constraints(data);
+ Wayland_display_destroy_relative_pointer_manager(data);
if (data->xkb_context) {
WAYLAND_xkb_context_unref(data->xkb_context);
@@ -376,6 +438,7 @@ Wayland_VideoQuit(_THIS)
WAYLAND_wl_display_disconnect(data->display);
}
+ SDL_free(data->classname);
free(data);
_this->driverdata = NULL;
}
diff --git a/Engine/lib/sdl/src/video/wayland/SDL_waylandvideo.h b/Engine/lib/sdl/src/video/wayland/SDL_waylandvideo.h
index 8111bf153..ccd7ecf92 100644
--- a/Engine/lib/sdl/src/video/wayland/SDL_waylandvideo.h
+++ b/Engine/lib/sdl/src/video/wayland/SDL_waylandvideo.h
@@ -42,9 +42,10 @@ typedef struct {
struct wl_compositor *compositor;
struct wl_shm *shm;
struct wl_cursor_theme *cursor_theme;
- struct wl_cursor *default_cursor;
struct wl_pointer *pointer;
struct wl_shell *shell;
+ struct zwp_relative_pointer_manager_v1 *relative_pointer_manager;
+ struct zwp_pointer_constraints_v1 *pointer_constraints;
EGLDisplay edpy;
EGLContext context;
@@ -58,6 +59,10 @@ typedef struct {
struct qt_surface_extension *surface_extension;
struct qt_windowmanager *windowmanager;
#endif /* SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH */
+
+ char *classname;
+
+ int relative_mouse_mode;
} SDL_VideoData;
#endif /* _SDL_waylandvideo_h */
diff --git a/Engine/lib/sdl/src/video/wayland/SDL_waylandwindow.c b/Engine/lib/sdl/src/video/wayland/SDL_waylandwindow.c
index b59759a7c..85fca8de6 100644
--- a/Engine/lib/sdl/src/video/wayland/SDL_waylandwindow.c
+++ b/Engine/lib/sdl/src/video/wayland/SDL_waylandwindow.c
@@ -26,6 +26,7 @@
#include "../SDL_sysvideo.h"
#include "../../events/SDL_windowevents_c.h"
#include "../SDL_egl_c.h"
+#include "SDL_waylandevents_c.h"
#include "SDL_waylandwindow.h"
#include "SDL_waylandvideo.h"
#include "SDL_waylandtouch.h"
@@ -46,6 +47,33 @@ handle_configure(void *data, struct wl_shell_surface *shell_surface,
SDL_Window *window = wind->sdlwindow;
struct wl_region *region;
+ /* wl_shell_surface spec states that this is a suggestion.
+ Ignore if less than or greater than max/min size. */
+
+ if (width == 0 || height == 0) {
+ return;
+ }
+
+ if (!(window->flags & SDL_WINDOW_FULLSCREEN)) {
+ if ((window->flags & SDL_WINDOW_RESIZABLE)) {
+ if (window->max_w > 0) {
+ width = SDL_min(width, window->max_w);
+ }
+ width = SDL_max(width, window->min_w);
+
+ if (window->max_h > 0) {
+ height = SDL_min(height, window->max_h);
+ }
+ height = SDL_max(height, window->min_h);
+ } else {
+ return;
+ }
+ }
+
+ if (width == window->w && height == window->h) {
+ return;
+ }
+
window->w = width;
window->h = height;
WAYLAND_wl_egl_window_resize(wind->egl_window, window->w, window->h, 0, 0);
@@ -145,6 +173,26 @@ Wayland_SetWindowFullscreen(_THIS, SDL_Window * window,
WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
}
+void
+Wayland_RestoreWindow(_THIS, SDL_Window * window)
+{
+ SDL_WindowData *wind = window->driverdata;
+
+ wl_shell_surface_set_toplevel(wind->shell_surface);
+
+ WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
+}
+
+void
+Wayland_MaximizeWindow(_THIS, SDL_Window * window)
+{
+ SDL_WindowData *wind = window->driverdata;
+
+ wl_shell_surface_set_maximized(wind->shell_surface, NULL);
+
+ WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
+}
+
int Wayland_CreateWindow(_THIS, SDL_Window *window)
{
SDL_WindowData *data;
@@ -178,6 +226,7 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window)
wl_surface_set_user_data(data->surface, data);
data->shell_surface = wl_shell_get_shell_surface(c->shell,
data->surface);
+ wl_shell_surface_set_class (data->shell_surface, c->classname);
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
if (c->surface_extension) {
data->extended_surface = qt_surface_extension_get_extended_surface(
@@ -214,6 +263,10 @@ int Wayland_CreateWindow(_THIS, SDL_Window *window)
wl_surface_set_opaque_region(data->surface, region);
wl_region_destroy(region);
+ if (c->relative_mouse_mode) {
+ Wayland_input_lock_pointer(c->input);
+ }
+
WAYLAND_wl_display_flush(c->display);
return 0;
@@ -233,6 +286,17 @@ void Wayland_SetWindowSize(_THIS, SDL_Window * window)
wl_region_destroy(region);
}
+void Wayland_SetWindowTitle(_THIS, SDL_Window * window)
+{
+ SDL_WindowData *wind = window->driverdata;
+
+ if (window->title != NULL) {
+ wl_shell_surface_set_title(wind->shell_surface, window->title);
+ }
+
+ WAYLAND_wl_display_flush( ((SDL_VideoData*)_this->driverdata)->display );
+}
+
void Wayland_DestroyWindow(_THIS, SDL_Window *window)
{
SDL_VideoData *data = _this->driverdata;
diff --git a/Engine/lib/sdl/src/video/wayland/SDL_waylandwindow.h b/Engine/lib/sdl/src/video/wayland/SDL_waylandwindow.h
index 053b1281f..319a573dc 100644
--- a/Engine/lib/sdl/src/video/wayland/SDL_waylandwindow.h
+++ b/Engine/lib/sdl/src/video/wayland/SDL_waylandwindow.h
@@ -39,6 +39,7 @@ typedef struct {
struct wl_egl_window *egl_window;
struct SDL_WaylandInput *keyboard_device;
EGLSurface egl_surface;
+ struct zwp_locked_pointer_v1 *locked_pointer;
#ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
struct qt_extended_surface *extended_surface;
@@ -49,8 +50,11 @@ extern void Wayland_ShowWindow(_THIS, SDL_Window *window);
extern void Wayland_SetWindowFullscreen(_THIS, SDL_Window * window,
SDL_VideoDisplay * _display,
SDL_bool fullscreen);
+extern void Wayland_MaximizeWindow(_THIS, SDL_Window * window);
+extern void Wayland_RestoreWindow(_THIS, SDL_Window * window);
extern int Wayland_CreateWindow(_THIS, SDL_Window *window);
extern void Wayland_SetWindowSize(_THIS, SDL_Window * window);
+extern void Wayland_SetWindowTitle(_THIS, SDL_Window * window);
extern void Wayland_DestroyWindow(_THIS, SDL_Window *window);
extern SDL_bool
diff --git a/Engine/lib/sdl/src/video/windows/SDL_windowsevents.c b/Engine/lib/sdl/src/video/windows/SDL_windowsevents.c
index 61420894f..02768fb68 100644
--- a/Engine/lib/sdl/src/video/windows/SDL_windowsevents.c
+++ b/Engine/lib/sdl/src/video/windows/SDL_windowsevents.c
@@ -198,13 +198,26 @@ WindowsScanCodeToSDLScanCode(LPARAM lParam, WPARAM wParam)
return code;
}
+static SDL_bool
+WIN_ShouldIgnoreFocusClick()
+{
+ return !SDL_GetHintBoolean(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, SDL_FALSE);
+}
void
WIN_CheckWParamMouseButton(SDL_bool bwParamMousePressed, SDL_bool bSDLMousePressed, SDL_WindowData *data, Uint8 button, SDL_MouseID mouseID)
{
- if (data->focus_click_pending && button == SDL_BUTTON_LEFT && !bwParamMousePressed) {
- data->focus_click_pending = SDL_FALSE;
- WIN_UpdateClipCursor(data->window);
+ if (data->focus_click_pending & SDL_BUTTON(button)) {
+ /* Ignore the button click for activation */
+ if (!bwParamMousePressed) {
+ data->focus_click_pending &= ~SDL_BUTTON(button);
+ if (!data->focus_click_pending) {
+ WIN_UpdateClipCursor(data->window);
+ }
+ }
+ if (WIN_ShouldIgnoreFocusClick()) {
+ return;
+ }
}
if (bwParamMousePressed && !bSDLMousePressed) {
@@ -326,17 +339,7 @@ WIN_ConvertUTF32toUTF8(UINT32 codepoint, char * text)
static SDL_bool
ShouldGenerateWindowCloseOnAltF4(void)
{
- const char *hint;
-
- hint = SDL_GetHint(SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4);
- if (hint) {
- if (*hint == '0') {
- return SDL_TRUE;
- } else {
- return SDL_FALSE;
- }
- }
- return SDL_TRUE;
+ return !SDL_GetHintBoolean(SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4, SDL_FALSE);
}
LRESULT CALLBACK
@@ -398,8 +401,24 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
minimized = HIWORD(wParam);
if (!minimized && (LOWORD(wParam) != WA_INACTIVE)) {
- data->focus_click_pending = (GetAsyncKeyState(VK_LBUTTON) != 0);
-
+ if (LOWORD(wParam) == WA_CLICKACTIVE) {
+ if (GetAsyncKeyState(VK_LBUTTON)) {
+ data->focus_click_pending |= SDL_BUTTON_LMASK;
+ }
+ if (GetAsyncKeyState(VK_RBUTTON)) {
+ data->focus_click_pending |= SDL_BUTTON_RMASK;
+ }
+ if (GetAsyncKeyState(VK_MBUTTON)) {
+ data->focus_click_pending |= SDL_BUTTON_MMASK;
+ }
+ if (GetAsyncKeyState(VK_XBUTTON1)) {
+ data->focus_click_pending |= SDL_BUTTON_X1MASK;
+ }
+ if (GetAsyncKeyState(VK_XBUTTON2)) {
+ data->focus_click_pending |= SDL_BUTTON_X2MASK;
+ }
+ }
+
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_SHOWN, 0, 0);
if (SDL_GetKeyboardFocus() != data->window) {
SDL_SetKeyboardFocus(data->window);
@@ -423,6 +442,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
if (SDL_GetKeyboardFocus() == data->window) {
SDL_SetKeyboardFocus(NULL);
+ WIN_ResetDeadKeys();
}
ClipCursor(NULL);
@@ -737,6 +757,13 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
break;
#endif /* WM_GETMINMAXINFO */
+ case WM_WINDOWPOSCHANGING:
+
+ if (data->expected_resize) {
+ returnCode = 0;
+ }
+ break;
+
case WM_WINDOWPOSCHANGED:
{
RECT rect;
@@ -763,6 +790,9 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
h = rect.bottom - rect.top;
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESIZED, w,
h);
+
+ /* Forces a WM_PAINT event */
+ InvalidateRect(hwnd, NULL, FALSE);
}
break;
@@ -907,12 +937,13 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
if (buffer) {
if (DragQueryFile(drop, i, buffer, size)) {
char *file = WIN_StringToUTF8(buffer);
- SDL_SendDropFile(file);
+ SDL_SendDropFile(data->window, file);
SDL_free(file);
}
SDL_stack_free(buffer);
}
}
+ SDL_SendDropComplete(data->window);
DragFinish(drop);
return 0;
}
@@ -927,15 +958,17 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
const SDL_Point point = { (int) winpoint.x, (int) winpoint.y };
const SDL_HitTestResult rc = window->hit_test(window, &point, window->hit_test_data);
switch (rc) {
- case SDL_HITTEST_DRAGGABLE: return HTCAPTION;
- case SDL_HITTEST_RESIZE_TOPLEFT: return HTTOPLEFT;
- case SDL_HITTEST_RESIZE_TOP: return HTTOP;
- case SDL_HITTEST_RESIZE_TOPRIGHT: return HTTOPRIGHT;
- case SDL_HITTEST_RESIZE_RIGHT: return HTRIGHT;
- case SDL_HITTEST_RESIZE_BOTTOMRIGHT: return HTBOTTOMRIGHT;
- case SDL_HITTEST_RESIZE_BOTTOM: return HTBOTTOM;
- case SDL_HITTEST_RESIZE_BOTTOMLEFT: return HTBOTTOMLEFT;
- case SDL_HITTEST_RESIZE_LEFT: return HTLEFT;
+ #define POST_HIT_TEST(ret) { SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_HIT_TEST, 0, 0); return ret; }
+ case SDL_HITTEST_DRAGGABLE: POST_HIT_TEST(HTCAPTION);
+ case SDL_HITTEST_RESIZE_TOPLEFT: POST_HIT_TEST(HTTOPLEFT);
+ case SDL_HITTEST_RESIZE_TOP: POST_HIT_TEST(HTTOP);
+ case SDL_HITTEST_RESIZE_TOPRIGHT: POST_HIT_TEST(HTTOPRIGHT);
+ case SDL_HITTEST_RESIZE_RIGHT: POST_HIT_TEST(HTRIGHT);
+ case SDL_HITTEST_RESIZE_BOTTOMRIGHT: POST_HIT_TEST(HTBOTTOMRIGHT);
+ case SDL_HITTEST_RESIZE_BOTTOM: POST_HIT_TEST(HTBOTTOM);
+ case SDL_HITTEST_RESIZE_BOTTOMLEFT: POST_HIT_TEST(HTBOTTOMLEFT);
+ case SDL_HITTEST_RESIZE_LEFT: POST_HIT_TEST(HTLEFT);
+ #undef POST_HIT_TEST
case SDL_HITTEST_NORMAL: return HTCLIENT;
}
}
@@ -1012,7 +1045,8 @@ HINSTANCE SDL_Instance = NULL;
int
SDL_RegisterApp(char *name, Uint32 style, void *hInst)
{
- WNDCLASS class;
+ WNDCLASSEX wcex;
+ TCHAR path[MAX_PATH];
/* Only do this once... */
if (app_registered) {
@@ -1034,19 +1068,24 @@ SDL_RegisterApp(char *name, Uint32 style, void *hInst)
}
/* Register the application class */
- class.hCursor = NULL;
- class.hIcon =
- LoadImage(SDL_Instance, SDL_Appname, IMAGE_ICON, 0, 0,
- LR_DEFAULTCOLOR);
- class.lpszMenuName = NULL;
- class.lpszClassName = SDL_Appname;
- class.hbrBackground = NULL;
- class.hInstance = SDL_Instance;
- class.style = SDL_Appstyle;
- class.lpfnWndProc = WIN_WindowProc;
- class.cbWndExtra = 0;
- class.cbClsExtra = 0;
- if (!RegisterClass(&class)) {
+ wcex.cbSize = sizeof(WNDCLASSEX);
+ wcex.hCursor = NULL;
+ wcex.hIcon = NULL;
+ wcex.hIconSm = NULL;
+ wcex.lpszMenuName = NULL;
+ wcex.lpszClassName = SDL_Appname;
+ wcex.style = SDL_Appstyle;
+ wcex.hbrBackground = NULL;
+ wcex.lpfnWndProc = WIN_WindowProc;
+ wcex.hInstance = SDL_Instance;
+ wcex.cbClsExtra = 0;
+ wcex.cbWndExtra = 0;
+
+ /* Use the first icon as a default icon, like in the Explorer */
+ GetModuleFileName(SDL_Instance, path, MAX_PATH);
+ ExtractIconEx(path, 0, &wcex.hIcon, &wcex.hIconSm, 1);
+
+ if (!RegisterClassEx(&wcex)) {
return SDL_SetError("Couldn't register application class");
}
@@ -1058,7 +1097,7 @@ SDL_RegisterApp(char *name, Uint32 style, void *hInst)
void
SDL_UnregisterApp()
{
- WNDCLASS class;
+ WNDCLASSEX wcex;
/* SDL_RegisterApp might not have been called before */
if (!app_registered) {
@@ -1067,8 +1106,10 @@ SDL_UnregisterApp()
--app_registered;
if (app_registered == 0) {
/* Check for any registered window classes. */
- if (GetClassInfo(SDL_Instance, SDL_Appname, &class)) {
+ if (GetClassInfoEx(SDL_Instance, SDL_Appname, &wcex)) {
UnregisterClass(SDL_Appname, SDL_Instance);
+ if (wcex.hIcon) DestroyIcon(wcex.hIcon);
+ if (wcex.hIconSm) DestroyIcon(wcex.hIconSm);
}
SDL_free(SDL_Appname);
SDL_Appname = NULL;
diff --git a/Engine/lib/sdl/src/video/windows/SDL_windowskeyboard.c b/Engine/lib/sdl/src/video/windows/SDL_windowskeyboard.c
index d3e16c8bf..8271b0421 100644
--- a/Engine/lib/sdl/src/video/windows/SDL_windowskeyboard.c
+++ b/Engine/lib/sdl/src/video/windows/SDL_windowskeyboard.c
@@ -157,11 +157,47 @@ WIN_QuitKeyboard(_THIS)
#endif
}
+void
+WIN_ResetDeadKeys()
+{
+ /*
+ if a deadkey has been typed, but not the next character (which the deadkey might modify),
+ this tries to undo the effect pressing the deadkey.
+ see: http://archives.miloush.net/michkap/archive/2006/09/10/748775.html
+ */
+ BYTE keyboardState[256];
+ WCHAR buffer[16];
+ int keycode, scancode, result, i;
+
+ GetKeyboardState(keyboardState);
+
+ keycode = VK_SPACE;
+ scancode = MapVirtualKey(keycode, MAPVK_VK_TO_VSC);
+ if (scancode == 0) {
+ /* the keyboard doesn't have this key */
+ return;
+ }
+
+ for (i = 0; i < 5; i++) {
+ result = ToUnicode(keycode, scancode, keyboardState, (LPWSTR)buffer, 16, 0);
+ if (result > 0) {
+ /* success */
+ return;
+ }
+ }
+}
+
void
WIN_StartTextInput(_THIS)
{
#ifndef SDL_DISABLE_WINDOWS_IME
- SDL_Window *window = SDL_GetKeyboardFocus();
+ SDL_Window *window;
+#endif
+
+ WIN_ResetDeadKeys();
+
+#ifndef SDL_DISABLE_WINDOWS_IME
+ window = SDL_GetKeyboardFocus();
if (window) {
HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
@@ -176,7 +212,13 @@ void
WIN_StopTextInput(_THIS)
{
#ifndef SDL_DISABLE_WINDOWS_IME
- SDL_Window *window = SDL_GetKeyboardFocus();
+ SDL_Window *window;
+#endif
+
+ WIN_ResetDeadKeys();
+
+#ifndef SDL_DISABLE_WINDOWS_IME
+ window = SDL_GetKeyboardFocus();
if (window) {
HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
SDL_VideoData *videodata = (SDL_VideoData *)_this->driverdata;
diff --git a/Engine/lib/sdl/src/video/windows/SDL_windowskeyboard.h b/Engine/lib/sdl/src/video/windows/SDL_windowskeyboard.h
index d330d3871..84654d7b8 100644
--- a/Engine/lib/sdl/src/video/windows/SDL_windowskeyboard.h
+++ b/Engine/lib/sdl/src/video/windows/SDL_windowskeyboard.h
@@ -27,6 +27,8 @@ extern void WIN_InitKeyboard(_THIS);
extern void WIN_UpdateKeymap(void);
extern void WIN_QuitKeyboard(_THIS);
+extern void WIN_ResetDeadKeys(void);
+
extern void WIN_StartTextInput(_THIS);
extern void WIN_StopTextInput(_THIS);
extern void WIN_SetTextInputRect(_THIS, SDL_Rect *rect);
diff --git a/Engine/lib/sdl/src/video/windows/SDL_windowsmessagebox.c b/Engine/lib/sdl/src/video/windows/SDL_windowsmessagebox.c
index b39df32fc..689e5bbc3 100644
--- a/Engine/lib/sdl/src/video/windows/SDL_windowsmessagebox.c
+++ b/Engine/lib/sdl/src/video/windows/SDL_windowsmessagebox.c
@@ -452,9 +452,9 @@ WIN_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
}
/* Align the buttons to the right/bottom. */
- x = Size.cx - ButtonWidth - ButtonMargin;
+ x = Size.cx - (ButtonWidth + ButtonMargin) * messageboxdata->numbuttons;
y = Size.cy - ButtonHeight - ButtonMargin;
- for (i = 0; i < messageboxdata->numbuttons; ++i) {
+ for (i = messageboxdata->numbuttons - 1; i >= 0; --i) {
SDL_bool isDefault;
if (buttons[i].flags & SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT) {
@@ -466,7 +466,7 @@ WIN_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid)
FreeDialogData(dialog);
return -1;
}
- x -= ButtonWidth + ButtonMargin;
+ x += ButtonWidth + ButtonMargin;
}
/* FIXME: If we have a parent window, get the Instance and HWND for them */
diff --git a/Engine/lib/sdl/src/video/windows/SDL_windowsmodes.c b/Engine/lib/sdl/src/video/windows/SDL_windowsmodes.c
index 91ed67f87..f172f9a3d 100644
--- a/Engine/lib/sdl/src/video/windows/SDL_windowsmodes.c
+++ b/Engine/lib/sdl/src/video/windows/SDL_windowsmodes.c
@@ -23,6 +23,7 @@
#if SDL_VIDEO_DRIVER_WINDOWS
#include "SDL_windowsvideo.h"
+#include "../../../include/SDL_assert.h"
/* Windows CE compatibility */
#ifndef CDS_FULLSCREEN
@@ -69,40 +70,16 @@ WIN_GetMonitorDPI(HMONITOR hMonitor,
return TRUE;
}
-static SDL_bool
-WIN_GetDisplayMode(_THIS, LPCTSTR deviceName, DWORD index, SDL_DisplayMode * mode)
+static void
+WIN_UpdateDisplayMode(_THIS, LPCTSTR deviceName, DWORD index, SDL_DisplayMode * mode)
{
SDL_VideoData *vid_data = (SDL_VideoData *) _this->driverdata;
- SDL_DisplayModeData *data;
- DEVMODE devmode;
+ SDL_DisplayModeData *data = (SDL_DisplayModeData *) mode->driverdata;
HDC hdc;
- devmode.dmSize = sizeof(devmode);
- devmode.dmDriverExtra = 0;
- if (!EnumDisplaySettings(deviceName, index, &devmode)) {
- return SDL_FALSE;
- }
-
- data = (SDL_DisplayModeData *) SDL_malloc(sizeof(*data));
- if (!data) {
- return SDL_FALSE;
- }
- data->DeviceMode = devmode;
data->DeviceMode.dmFields =
(DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY |
DM_DISPLAYFLAGS);
- data->ScaleX = 1.0f;
- data->ScaleY = 1.0f;
- data->DiagDPI = 0.0f;
- data->HorzDPI = 0.0f;
- data->VertDPI = 0.0f;
-
- /* Fill in the mode information */
- mode->format = SDL_PIXELFORMAT_UNKNOWN;
- mode->w = devmode.dmPelsWidth;
- mode->h = devmode.dmPelsHeight;
- mode->refresh_rate = devmode.dmDisplayFrequency;
- mode->driverdata = data;
if (index == ENUM_CURRENT_SETTINGS
&& (hdc = CreateDC(deviceName, NULL, NULL, NULL)) != NULL) {
@@ -112,8 +89,8 @@ WIN_GetDisplayMode(_THIS, LPCTSTR deviceName, DWORD index, SDL_DisplayMode * mod
int logical_width = GetDeviceCaps( hdc, HORZRES );
int logical_height = GetDeviceCaps( hdc, VERTRES );
- data->ScaleX = (float)logical_width / devmode.dmPelsWidth;
- data->ScaleY = (float)logical_height / devmode.dmPelsHeight;
+ data->ScaleX = (float)logical_width / data->DeviceMode.dmPelsWidth;
+ data->ScaleY = (float)logical_height / data->DeviceMode.dmPelsHeight;
mode->w = logical_width;
mode->h = logical_height;
@@ -126,8 +103,8 @@ WIN_GetDisplayMode(_THIS, LPCTSTR deviceName, DWORD index, SDL_DisplayMode * mod
dpi_data.vid_data = vid_data;
dpi_data.mode = mode;
dpi_data.mode_data = data;
- monitor_rect.left = devmode.dmPosition.x;
- monitor_rect.top = devmode.dmPosition.y;
+ monitor_rect.left = data->DeviceMode.dmPosition.x;
+ monitor_rect.top = data->DeviceMode.dmPosition.y;
monitor_rect.right = monitor_rect.left + 1;
monitor_rect.bottom = monitor_rect.top + 1;
EnumDisplayMonitors(NULL, &monitor_rect, WIN_GetMonitorDPI, (LPARAM)&dpi_data);
@@ -175,10 +152,10 @@ WIN_GetDisplayMode(_THIS, LPCTSTR deviceName, DWORD index, SDL_DisplayMode * mod
} else if (bmi->bmiHeader.biBitCount == 4) {
mode->format = SDL_PIXELFORMAT_INDEX4LSB;
}
- } else {
+ } else if (mode->format == SDL_PIXELFORMAT_UNKNOWN) {
/* FIXME: Can we tell what this will be? */
- if ((devmode.dmFields & DM_BITSPERPEL) == DM_BITSPERPEL) {
- switch (devmode.dmBitsPerPel) {
+ if ((data->DeviceMode.dmFields & DM_BITSPERPEL) == DM_BITSPERPEL) {
+ switch (data->DeviceMode.dmBitsPerPel) {
case 32:
mode->format = SDL_PIXELFORMAT_RGB888;
break;
@@ -200,6 +177,42 @@ WIN_GetDisplayMode(_THIS, LPCTSTR deviceName, DWORD index, SDL_DisplayMode * mod
}
}
}
+}
+
+static SDL_bool
+WIN_GetDisplayMode(_THIS, LPCTSTR deviceName, DWORD index, SDL_DisplayMode * mode)
+{
+ SDL_DisplayModeData *data;
+ DEVMODE devmode;
+
+ devmode.dmSize = sizeof(devmode);
+ devmode.dmDriverExtra = 0;
+ if (!EnumDisplaySettings(deviceName, index, &devmode)) {
+ return SDL_FALSE;
+ }
+
+ data = (SDL_DisplayModeData *) SDL_malloc(sizeof(*data));
+ if (!data) {
+ return SDL_FALSE;
+ }
+
+ mode->driverdata = data;
+ data->DeviceMode = devmode;
+
+ /* Default basic information */
+ data->ScaleX = 1.0f;
+ data->ScaleY = 1.0f;
+ data->DiagDPI = 0.0f;
+ data->HorzDPI = 0.0f;
+ data->VertDPI = 0.0f;
+
+ mode->format = SDL_PIXELFORMAT_UNKNOWN;
+ mode->w = data->DeviceMode.dmPelsWidth;
+ mode->h = data->DeviceMode.dmPelsHeight;
+ mode->refresh_rate = data->DeviceMode.dmDisplayFrequency;
+
+ /* Fill in the mode information */
+ WIN_UpdateDisplayMode(_this, deviceName, index, mode);
return SDL_TRUE;
}
@@ -329,7 +342,44 @@ WIN_GetDisplayDPI(_THIS, SDL_VideoDisplay * display, float * ddpi, float * hdpi,
*vdpi = data->VertDPI;
}
- return data->DiagDPI != 0.0f ? 0 : -1;
+ return data->DiagDPI != 0.0f ? 0 : SDL_SetError("Couldn't get DPI");
+}
+
+int
+WIN_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect)
+{
+ const SDL_DisplayModeData *data = (const SDL_DisplayModeData *) display->current_mode.driverdata;
+ const DEVMODE *pDevMode = &data->DeviceMode;
+ POINT pt = {
+ /* !!! FIXME: no scale, right? */
+ (LONG) (pDevMode->dmPosition.x + (pDevMode->dmPelsWidth / 2)),
+ (LONG) (pDevMode->dmPosition.y + (pDevMode->dmPelsHeight / 2))
+ };
+ HMONITOR hmon = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL);
+ MONITORINFO minfo;
+ const RECT *work;
+ BOOL rc = FALSE;
+
+ SDL_assert(hmon != NULL);
+
+ if (hmon != NULL) {
+ SDL_zero(minfo);
+ minfo.cbSize = sizeof (MONITORINFO);
+ rc = GetMonitorInfo(hmon, &minfo);
+ SDL_assert(rc);
+ }
+
+ if (!rc) {
+ return SDL_SetError("Couldn't find monitor data");
+ }
+
+ work = &minfo.rcWork;
+ rect->x = (int)SDL_ceil(work->left * data->ScaleX);
+ rect->y = (int)SDL_ceil(work->top * data->ScaleY);
+ rect->w = (int)SDL_ceil((work->right - work->left) * data->ScaleX);
+ rect->h = (int)SDL_ceil((work->bottom - work->top) * data->ScaleY);
+
+ return 0;
}
void
@@ -366,7 +416,7 @@ WIN_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
LONG status;
if (mode->driverdata == display->desktop_mode.driverdata) {
- status = ChangeDisplaySettingsEx(displaydata->DeviceName, NULL, NULL, 0, NULL);
+ status = ChangeDisplaySettingsEx(displaydata->DeviceName, NULL, NULL, CDS_FULLSCREEN, NULL);
} else {
status = ChangeDisplaySettingsEx(displaydata->DeviceName, &data->DeviceMode, NULL, CDS_FULLSCREEN, NULL);
}
@@ -389,6 +439,7 @@ WIN_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
return SDL_SetError("ChangeDisplaySettingsEx() failed: %s", reason);
}
EnumDisplaySettings(displaydata->DeviceName, ENUM_CURRENT_SETTINGS, &data->DeviceMode);
+ WIN_UpdateDisplayMode(_this, displaydata->DeviceName, ENUM_CURRENT_SETTINGS, mode);
return 0;
}
diff --git a/Engine/lib/sdl/src/video/windows/SDL_windowsmodes.h b/Engine/lib/sdl/src/video/windows/SDL_windowsmodes.h
index e725848b2..6aa293d21 100644
--- a/Engine/lib/sdl/src/video/windows/SDL_windowsmodes.h
+++ b/Engine/lib/sdl/src/video/windows/SDL_windowsmodes.h
@@ -40,6 +40,7 @@ typedef struct
extern int WIN_InitModes(_THIS);
extern int WIN_GetDisplayBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect);
+extern int WIN_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect);
extern int WIN_GetDisplayDPI(_THIS, SDL_VideoDisplay * display, float * ddpi, float * hdpi, float * vdpi);
extern void WIN_GetDisplayModes(_THIS, SDL_VideoDisplay * display);
extern int WIN_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);
diff --git a/Engine/lib/sdl/src/video/windows/SDL_windowsvideo.c b/Engine/lib/sdl/src/video/windows/SDL_windowsvideo.c
index 37199805b..21f63a018 100644
--- a/Engine/lib/sdl/src/video/windows/SDL_windowsvideo.c
+++ b/Engine/lib/sdl/src/video/windows/SDL_windowsvideo.c
@@ -124,6 +124,7 @@ WIN_CreateDevice(int devindex)
device->VideoInit = WIN_VideoInit;
device->VideoQuit = WIN_VideoQuit;
device->GetDisplayBounds = WIN_GetDisplayBounds;
+ device->GetDisplayUsableBounds = WIN_GetDisplayUsableBounds;
device->GetDisplayDPI = WIN_GetDisplayDPI;
device->GetDisplayModes = WIN_GetDisplayModes;
device->SetDisplayMode = WIN_SetDisplayMode;
@@ -136,6 +137,7 @@ WIN_CreateDevice(int devindex)
device->SetWindowIcon = WIN_SetWindowIcon;
device->SetWindowPosition = WIN_SetWindowPosition;
device->SetWindowSize = WIN_SetWindowSize;
+ device->SetWindowOpacity = WIN_SetWindowOpacity;
device->ShowWindow = WIN_ShowWindow;
device->HideWindow = WIN_HideWindow;
device->RaiseWindow = WIN_RaiseWindow;
@@ -143,6 +145,7 @@ WIN_CreateDevice(int devindex)
device->MinimizeWindow = WIN_MinimizeWindow;
device->RestoreWindow = WIN_RestoreWindow;
device->SetWindowBordered = WIN_SetWindowBordered;
+ device->SetWindowResizable = WIN_SetWindowResizable;
device->SetWindowFullscreen = WIN_SetWindowFullscreen;
device->SetWindowGammaRamp = WIN_SetWindowGammaRamp;
device->GetWindowGammaRamp = WIN_GetWindowGammaRamp;
diff --git a/Engine/lib/sdl/src/video/windows/SDL_windowswindow.c b/Engine/lib/sdl/src/video/windows/SDL_windowswindow.c
index 26683a0ed..5ce40e6ba 100644
--- a/Engine/lib/sdl/src/video/windows/SDL_windowswindow.c
+++ b/Engine/lib/sdl/src/video/windows/SDL_windowswindow.c
@@ -478,7 +478,8 @@ WIN_HideWindow(_THIS, SDL_Window * window)
void
WIN_RaiseWindow(_THIS, SDL_Window * window)
{
- WIN_SetWindowPositionInternal(_this, window, SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOSIZE);
+ HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd;
+ SetForegroundWindow(hwnd);
}
void
@@ -519,6 +520,22 @@ WIN_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
data->in_border_change = SDL_FALSE;
}
+void
+WIN_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable)
+{
+ SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
+ HWND hwnd = data->hwnd;
+ DWORD style = GetWindowLong(hwnd, GWL_STYLE);
+
+ if (resizable) {
+ style |= STYLE_RESIZABLE;
+ } else {
+ style &= ~STYLE_RESIZABLE;
+ }
+
+ SetWindowLong(hwnd, GWL_STYLE, style);
+}
+
void
WIN_RestoreWindow(_THIS, SDL_Window * window)
{
@@ -826,6 +843,39 @@ WIN_SetWindowHitTest(SDL_Window *window, SDL_bool enabled)
return 0; /* just succeed, the real work is done elsewhere. */
}
+int
+WIN_SetWindowOpacity(_THIS, SDL_Window * window, float opacity)
+{
+ const SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ const HWND hwnd = data->hwnd;
+ const LONG style = GetWindowLong(hwnd, GWL_EXSTYLE);
+
+ SDL_assert(style != 0);
+
+ if (opacity == 1.0f) {
+ /* want it fully opaque, just mark it unlayered if necessary. */
+ if (style & WS_EX_LAYERED) {
+ if (SetWindowLong(hwnd, GWL_EXSTYLE, style & ~WS_EX_LAYERED) == 0) {
+ return WIN_SetError("SetWindowLong()");
+ }
+ }
+ } else {
+ const BYTE alpha = (BYTE) ((int) (opacity * 255.0f));
+ /* want it transparent, mark it layered if necessary. */
+ if ((style & WS_EX_LAYERED) == 0) {
+ if (SetWindowLong(hwnd, GWL_EXSTYLE, style | WS_EX_LAYERED) == 0) {
+ return WIN_SetError("SetWindowLong()");
+ }
+ }
+
+ if (SetLayeredWindowAttributes(hwnd, 0, alpha, LWA_ALPHA) == 0) {
+ return WIN_SetError("SetLayeredWindowAttributes()");
+ }
+ }
+
+ return 0;
+}
+
#endif /* SDL_VIDEO_DRIVER_WINDOWS */
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/video/windows/SDL_windowswindow.h b/Engine/lib/sdl/src/video/windows/SDL_windowswindow.h
index f91aa0ed2..7d50ba66e 100644
--- a/Engine/lib/sdl/src/video/windows/SDL_windowswindow.h
+++ b/Engine/lib/sdl/src/video/windows/SDL_windowswindow.h
@@ -41,7 +41,7 @@ typedef struct
SDL_bool expected_resize;
SDL_bool in_border_change;
SDL_bool in_title_click;
- SDL_bool focus_click_pending;
+ Uint8 focus_click_pending;
SDL_bool windowed_mode_was_maximized;
SDL_bool in_window_deactivation;
struct SDL_VideoData *videodata;
@@ -56,6 +56,7 @@ extern void WIN_SetWindowTitle(_THIS, SDL_Window * window);
extern void WIN_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon);
extern void WIN_SetWindowPosition(_THIS, SDL_Window * window);
extern void WIN_SetWindowSize(_THIS, SDL_Window * window);
+extern int WIN_SetWindowOpacity(_THIS, SDL_Window * window, float opacity);
extern void WIN_ShowWindow(_THIS, SDL_Window * window);
extern void WIN_HideWindow(_THIS, SDL_Window * window);
extern void WIN_RaiseWindow(_THIS, SDL_Window * window);
@@ -63,6 +64,7 @@ extern void WIN_MaximizeWindow(_THIS, SDL_Window * window);
extern void WIN_MinimizeWindow(_THIS, SDL_Window * window);
extern void WIN_RestoreWindow(_THIS, SDL_Window * window);
extern void WIN_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered);
+extern void WIN_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable);
extern void WIN_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
extern int WIN_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp);
extern int WIN_GetWindowGammaRamp(_THIS, SDL_Window * window, Uint16 * ramp);
diff --git a/Engine/lib/sdl/src/video/winrt/SDL_winrtevents.cpp b/Engine/lib/sdl/src/video/winrt/SDL_winrtevents.cpp
index e9df726d4..30cf01633 100644
--- a/Engine/lib/sdl/src/video/winrt/SDL_winrtevents.cpp
+++ b/Engine/lib/sdl/src/video/winrt/SDL_winrtevents.cpp
@@ -40,6 +40,7 @@ using Windows::UI::Core::CoreCursor;
#include "SDL_system.h"
extern "C" {
+#include "../../thread/SDL_systhread.h"
#include "../SDL_sysvideo.h"
#include "../../events/SDL_events_c.h"
}
@@ -113,7 +114,7 @@ WINRT_CycleXAMLThread()
_mutex = SDL_CreateMutex();
_threadState = ThreadState_Running;
- _XAMLThread = SDL_CreateThread(WINRT_XAMLThreadMain, "SDL/XAML App Thread", nullptr);
+ _XAMLThread = SDL_CreateThreadInternal(WINRT_XAMLThreadMain, "SDL/XAML App Thread", 0, nullptr);
SDL_LockMutex(_mutex);
while (_threadState != ThreadState_Yielding) {
diff --git a/Engine/lib/sdl/src/video/winrt/SDL_winrtevents_c.h b/Engine/lib/sdl/src/video/winrt/SDL_winrtevents_c.h
index dc94526bb..05a90a3bf 100644
--- a/Engine/lib/sdl/src/video/winrt/SDL_winrtevents_c.h
+++ b/Engine/lib/sdl/src/video/winrt/SDL_winrtevents_c.h
@@ -67,6 +67,13 @@ extern void WINRT_ProcessKeyDownEvent(Windows::UI::Core::KeyEventArgs ^args);
extern void WINRT_ProcessKeyUpEvent(Windows::UI::Core::KeyEventArgs ^args);
extern void WINRT_ProcessCharacterReceivedEvent(Windows::UI::Core::CharacterReceivedEventArgs ^args);
+#if NTDDI_VERSION >= NTDDI_WIN10
+extern SDL_bool WINRT_HasScreenKeyboardSupport(_THIS);
+extern void WINRT_ShowScreenKeyboard(_THIS, SDL_Window *window);
+extern void WINRT_HideScreenKeyboard(_THIS, SDL_Window *window);
+extern SDL_bool WINRT_IsScreenKeyboardShown(_THIS, SDL_Window *window);
+#endif // NTDDI_VERSION >= ...
+
/* XAML Thread Management */
extern void WINRT_CycleXAMLThread();
diff --git a/Engine/lib/sdl/src/video/winrt/SDL_winrtgamebar.cpp b/Engine/lib/sdl/src/video/winrt/SDL_winrtgamebar.cpp
new file mode 100644
index 000000000..215dfcc83
--- /dev/null
+++ b/Engine/lib/sdl/src/video/winrt/SDL_winrtgamebar.cpp
@@ -0,0 +1,196 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2016 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_DRIVER_WINRT
+
+/* Windows includes */
+#include
+#include
+#include
+
+
+/* SDL includes */
+extern "C" {
+#include "SDL_mouse.h"
+#include "../SDL_sysvideo.h"
+}
+#include "SDL_winrtvideo_cpp.h"
+
+
+/* Game Bar events can come in off the main thread. Use the following
+ WinRT CoreDispatcher to deal with them on SDL's thread.
+*/
+static Platform::WeakReference WINRT_MainThreadDispatcher;
+
+
+/* Win10's initial SDK (the 10.0.10240.0 release) does not include references
+ to Game Bar APIs, as the Game Bar was released via Win10 10.0.10586.0.
+
+ Declare its WinRT/COM interface here, to allow compilation with earlier
+ Windows SDKs.
+*/
+MIDL_INTERFACE("1DB9A292-CC78-4173-BE45-B61E67283EA7")
+IGameBarStatics_ : public IInspectable
+{
+public:
+ virtual HRESULT STDMETHODCALLTYPE add_VisibilityChanged(
+ __FIEventHandler_1_IInspectable *handler,
+ Windows::Foundation::EventRegistrationToken *token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE remove_VisibilityChanged(
+ Windows::Foundation::EventRegistrationToken token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE add_IsInputRedirectedChanged(
+ __FIEventHandler_1_IInspectable *handler,
+ Windows::Foundation::EventRegistrationToken *token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE remove_IsInputRedirectedChanged(
+ Windows::Foundation::EventRegistrationToken token) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE get_Visible(
+ boolean *value) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE get_IsInputRedirected(
+ boolean *value) = 0;
+};
+
+/* Declare the game bar's COM GUID */
+static GUID IID_IGameBarStatics_ = { MAKELONG(0xA292, 0x1DB9), 0xCC78, 0x4173, { 0xBE, 0x45, 0xB6, 0x1E, 0x67, 0x28, 0x3E, 0xA7 } };
+
+/* Retrieves a pointer to the game bar, or NULL if it is not available.
+ If a pointer is returned, it's ->Release() method must be called
+ after the caller has finished using it.
+*/
+static IGameBarStatics_ *
+WINRT_GetGameBar()
+{
+ wchar_t *wClassName = L"Windows.Gaming.UI.GameBar";
+ HSTRING hClassName;
+ IActivationFactory *pActivationFactory = NULL;
+ IGameBarStatics_ *pGameBar = NULL;
+ HRESULT hr;
+
+ hr = ::WindowsCreateString(wClassName, (UINT32)wcslen(wClassName), &hClassName);
+ if (FAILED(hr)) {
+ goto done;
+ }
+
+ hr = Windows::Foundation::GetActivationFactory(hClassName, &pActivationFactory);
+ if (FAILED(hr)) {
+ goto done;
+ }
+
+ pActivationFactory->QueryInterface(IID_IGameBarStatics_, (void **) &pGameBar);
+
+done:
+ if (pActivationFactory) {
+ pActivationFactory->Release();
+ }
+ if (hClassName) {
+ ::WindowsDeleteString(hClassName);
+ }
+ return pGameBar;
+}
+
+static void
+WINRT_HandleGameBarIsInputRedirected_MainThread()
+{
+ IGameBarStatics_ *gameBar;
+ boolean isInputRedirected = 0;
+ if (!WINRT_MainThreadDispatcher) {
+ /* The game bar event handler has been deregistered! */
+ return;
+ }
+ gameBar = WINRT_GetGameBar();
+ if (!gameBar) {
+ /* Shouldn't happen, but just in case... */
+ return;
+ }
+ if (SUCCEEDED(gameBar->get_IsInputRedirected(&isInputRedirected))) {
+ if ( ! isInputRedirected) {
+ /* Input-control is now back to the SDL app. Restore the cursor,
+ in case Windows does not (it does not in either Win10
+ 10.0.10240.0 or 10.0.10586.0, maybe later version(s) too.
+ */
+ SDL_Cursor *cursor = SDL_GetCursor();
+ SDL_SetCursor(cursor);
+ }
+ }
+ gameBar->Release();
+}
+
+static void
+WINRT_HandleGameBarIsInputRedirected_NonMainThread(Platform::Object ^ o1, Platform::Object ^o2)
+{
+ Windows::UI::Core::CoreDispatcher ^dispatcher = WINRT_MainThreadDispatcher.Resolve();
+ if (dispatcher) {
+ dispatcher->RunAsync(
+ Windows::UI::Core::CoreDispatcherPriority::Normal,
+ ref new Windows::UI::Core::DispatchedHandler(&WINRT_HandleGameBarIsInputRedirected_MainThread));
+ }
+}
+
+void
+WINRT_InitGameBar(_THIS)
+{
+ SDL_VideoData *driverdata = (SDL_VideoData *)_this->driverdata;
+ IGameBarStatics_ *gameBar = WINRT_GetGameBar();
+ if (gameBar) {
+ /* GameBar.IsInputRedirected events can come in via something other than
+ the main/SDL thread.
+
+ Get a WinRT 'CoreDispatcher' that can be used to call back into the
+ SDL thread.
+ */
+ WINRT_MainThreadDispatcher = Windows::UI::Core::CoreWindow::GetForCurrentThread()->Dispatcher;
+ Windows::Foundation::EventHandler ^handler = \
+ ref new Windows::Foundation::EventHandler(&WINRT_HandleGameBarIsInputRedirected_NonMainThread);
+ __FIEventHandler_1_IInspectable * pHandler = reinterpret_cast<__FIEventHandler_1_IInspectable *>(handler);
+ gameBar->add_IsInputRedirectedChanged(pHandler, &driverdata->gameBarIsInputRedirectedToken);
+ gameBar->Release();
+ }
+}
+
+void
+WINRT_QuitGameBar(_THIS)
+{
+ SDL_VideoData *driverdata;
+ IGameBarStatics_ *gameBar;
+ if (!_this || !_this->driverdata) {
+ return;
+ }
+ gameBar = WINRT_GetGameBar();
+ if (!gameBar) {
+ return;
+ }
+ driverdata = (SDL_VideoData *)_this->driverdata;
+ if (driverdata->gameBarIsInputRedirectedToken.Value) {
+ gameBar->remove_IsInputRedirectedChanged(driverdata->gameBarIsInputRedirectedToken);
+ driverdata->gameBarIsInputRedirectedToken.Value = 0;
+ }
+ WINRT_MainThreadDispatcher = nullptr;
+ gameBar->Release();
+}
+
+#endif /* SDL_VIDEO_DRIVER_WINRT */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/audio/SDL_audiomem.h b/Engine/lib/sdl/src/video/winrt/SDL_winrtgamebar_cpp.h
similarity index 74%
rename from Engine/lib/sdl/src/audio/SDL_audiomem.h
rename to Engine/lib/sdl/src/video/winrt/SDL_winrtgamebar_cpp.h
index 091d15c29..afcef37b2 100644
--- a/Engine/lib/sdl/src/audio/SDL_audiomem.h
+++ b/Engine/lib/sdl/src/video/winrt/SDL_winrtgamebar_cpp.h
@@ -18,8 +18,18 @@
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
-#include "../SDL_internal.h"
+#include "SDL_config.h"
+
+#ifndef _SDL_winrtgamebar_h
+#define _SDL_winrtgamebar_h
+
+#ifdef __cplusplus
+/* These are exported as C++ functions, rather than C, to fix a compilation
+ bug with MSVC 2013, for Windows 8.x builds. */
+extern void WINRT_InitGameBar(_THIS);
+extern void WINRT_QuitGameBar(_THIS);
+#endif
+
+#endif /* _SDL_winrtmouse_h */
-#define SDL_AllocAudioMem SDL_malloc
-#define SDL_FreeAudioMem SDL_free
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/video/winrt/SDL_winrtkeyboard.cpp b/Engine/lib/sdl/src/video/winrt/SDL_winrtkeyboard.cpp
index 7477cdeeb..affcae62b 100644
--- a/Engine/lib/sdl/src/video/winrt/SDL_winrtkeyboard.cpp
+++ b/Engine/lib/sdl/src/video/winrt/SDL_winrtkeyboard.cpp
@@ -383,4 +383,48 @@ WINRT_ProcessCharacterReceivedEvent(Windows::UI::Core::CharacterReceivedEventArg
}
}
+
+#if NTDDI_VERSION >= NTDDI_WIN10
+
+SDL_bool WINRT_HasScreenKeyboardSupport(_THIS)
+{
+ return SDL_TRUE;
+}
+
+void WINRT_ShowScreenKeyboard(_THIS, SDL_Window *window)
+{
+ using namespace Windows::UI::ViewManagement;
+ InputPane ^ inputPane = InputPane::GetForCurrentView();
+ if (inputPane) {
+ inputPane->TryShow();
+ }
+}
+
+void WINRT_HideScreenKeyboard(_THIS, SDL_Window *window)
+{
+ using namespace Windows::UI::ViewManagement;
+ InputPane ^ inputPane = InputPane::GetForCurrentView();
+ if (inputPane) {
+ inputPane->TryHide();
+ }
+}
+
+SDL_bool WINRT_IsScreenKeyboardShown(_THIS, SDL_Window *window)
+{
+ using namespace Windows::UI::ViewManagement;
+ InputPane ^ inputPane = InputPane::GetForCurrentView();
+ if (inputPane) {
+ // dludwig@pobox.com: checking inputPane->Visible doesn't seem to detect visibility,
+ // at least not on the Windows Phone 10.0.10240.0 emulator. Checking
+ // the size of inputPane->OccludedRect, however, does seem to work.
+ Windows::Foundation::Rect rect = inputPane->OccludedRect;
+ if (rect.Width > 0 && rect.Height > 0) {
+ return SDL_TRUE;
+ }
+ }
+ return SDL_FALSE;
+}
+
+#endif // NTDDI_VERSION >= ...
+
#endif // SDL_VIDEO_DRIVER_WINRT
diff --git a/Engine/lib/sdl/src/video/winrt/SDL_winrtmouse.cpp b/Engine/lib/sdl/src/video/winrt/SDL_winrtmouse.cpp
index d3140a4a4..9997d6ea4 100644
--- a/Engine/lib/sdl/src/video/winrt/SDL_winrtmouse.cpp
+++ b/Engine/lib/sdl/src/video/winrt/SDL_winrtmouse.cpp
@@ -26,6 +26,7 @@
* Windows includes:
*/
#include
+#include
using namespace Windows::UI::Core;
using Windows::UI::Core::CoreCursor;
@@ -116,11 +117,69 @@ WINRT_ShowCursor(SDL_Cursor * cursor)
return 0;
}
+ CoreWindow ^ coreWindow = CoreWindow::GetForCurrentThread();
if (cursor) {
CoreCursor ^* theCursor = (CoreCursor ^*) cursor->driverdata;
- CoreWindow::GetForCurrentThread()->PointerCursor = *theCursor;
+ coreWindow->PointerCursor = *theCursor;
} else {
- CoreWindow::GetForCurrentThread()->PointerCursor = nullptr;
+ // HACK ALERT: TL;DR - Hiding the cursor in WinRT/UWP apps is weird, and
+ // a Win32-style cursor resource file must be directly included in apps,
+ // otherwise hiding the cursor will cause mouse-motion data to never be
+ // received.
+ //
+ // Here's the lengthy explanation:
+ //
+ // There are two ways to hide a cursor in WinRT/UWP apps.
+ // Both involve setting the WinRT CoreWindow's (which is somewhat analogous
+ // to a Win32 HWND) 'PointerCursor' property.
+ //
+ // The first way to hide a cursor sets PointerCursor to nullptr. This
+ // is, arguably, the easiest to implement for an app. It does have an
+ // unfortunate side-effect: it'll prevent mouse-motion events from being
+ // sent to the app (via CoreWindow).
+ //
+ // The second way to hide a cursor sets PointerCursor to a transparent
+ // cursor. This allows mouse-motion events to be sent to the app, but is
+ // more difficult to set up, as:
+ // 1. WinRT/UWP, while providing a few stock cursors, does not provide
+ // a completely transparent cursor.
+ // 2. WinRT/UWP allows apps to provide custom-built cursors, but *ONLY*
+ // if they are linked directly inside the app, via Win32-style
+ // cursor resource files. APIs to create cursors at runtime are
+ // not provided to apps, and attempting to link-to or use Win32
+ // cursor-creation APIs could cause an app to fail Windows Store
+ // certification.
+ //
+ // SDL can use either means of hiding the cursor. It provides a Win32-style
+ // set of cursor resource files in its source distribution, inside
+ // src/main/winrt/. If those files are linked to an SDL-for-WinRT/UWP app
+ // (by including them in a MSVC project, for example), SDL will attempt to
+ // use those, if and when the cursor is hidden via SDL APIs. If those
+ // files are not linked in, SDL will attempt to hide the cursor via the
+ // 'set PointerCursor to nullptr' means (which, if you recall, causes
+ // mouse-motion data to NOT be sent to the app!).
+ //
+ // Tech notes:
+ // - SDL's blank cursor resource uses a resource ID of 5000.
+ // - SDL's cursor resources consist of the following two files:
+ // - src/main/winrt/SDL2-WinRTResource_BlankCursor.cur -- cursor pixel data
+ // - src/main/winrt/SDL2-WinRTResources.rc -- declares the cursor resource, and its ID (of 5000)
+ //
+
+ const unsigned int win32CursorResourceID = 5000;
+ CoreCursor ^ blankCursor = ref new CoreCursor(CoreCursorType::Custom, win32CursorResourceID);
+
+ // Set 'PointerCursor' to 'blankCursor' in a way that shouldn't throw
+ // an exception if the app hasn't loaded that resource.
+ ABI::Windows::UI::Core::ICoreCursor * iblankCursor = reinterpret_cast(blankCursor);
+ ABI::Windows::UI::Core::ICoreWindow * icoreWindow = reinterpret_cast(coreWindow);
+ HRESULT hr = icoreWindow->put_PointerCursor(iblankCursor);
+ if (FAILED(hr)) {
+ // The app doesn't contain the cursor resource, or some other error
+ // occurred. Just use the other, but mouse-motion-preventing, means of
+ // hiding the cursor.
+ coreWindow->PointerCursor = nullptr;
+ }
}
return 0;
}
diff --git a/Engine/lib/sdl/src/video/winrt/SDL_winrtvideo.cpp b/Engine/lib/sdl/src/video/winrt/SDL_winrtvideo.cpp
index 9d7c1ccee..9a26705ad 100644
--- a/Engine/lib/sdl/src/video/winrt/SDL_winrtvideo.cpp
+++ b/Engine/lib/sdl/src/video/winrt/SDL_winrtvideo.cpp
@@ -31,6 +31,7 @@
/* Windows includes */
#include
#include
+#include
#include
#include
using namespace Windows::ApplicationModel::Core;
@@ -41,7 +42,8 @@ using namespace Windows::UI::ViewManagement;
/* [re]declare Windows GUIDs locally, to limit the amount of external lib(s) SDL has to link to */
-static const GUID IID_IDXGIFactory2 = { 0x50c83a1c, 0xe072, 0x4c48,{ 0x87, 0xb0, 0x36, 0x30, 0xfa, 0x36, 0xa6, 0xd0 } };
+static const GUID IID_IDisplayRequest = { 0xe5732044, 0xf49f, 0x4b60, { 0x8d, 0xd4, 0x5e, 0x7e, 0x3a, 0x63, 0x2a, 0xc0 } };
+static const GUID IID_IDXGIFactory2 = { 0x50c83a1c, 0xe072, 0x4c48, { 0x87, 0xb0, 0x36, 0x30, 0xfa, 0x36, 0xa6, 0xd0 } };
/* SDL includes */
@@ -61,6 +63,7 @@ extern "C" {
#include "../../core/winrt/SDL_winrtapp_xaml.h"
#include "SDL_winrtvideo_cpp.h"
#include "SDL_winrtevents_c.h"
+#include "SDL_winrtgamebar_cpp.h"
#include "SDL_winrtmouse_c.h"
#include "SDL_main.h"
#include "SDL_system.h"
@@ -82,6 +85,11 @@ static void WINRT_DestroyWindow(_THIS, SDL_Window * window);
static SDL_bool WINRT_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info);
+/* Misc functions */
+static ABI::Windows::System::Display::IDisplayRequest * WINRT_CreateDisplayRequest(_THIS);
+extern void WINRT_SuspendScreenSaver(_THIS);
+
+
/* SDL-internal globals: */
SDL_Window * WINRT_GlobalSDLWindow = NULL;
@@ -118,18 +126,15 @@ WINRT_CreateDevice(int devindex)
device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
if (!device) {
SDL_OutOfMemory();
- if (device) {
- SDL_free(device);
- }
return (0);
}
data = (SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
if (!data) {
SDL_OutOfMemory();
+ SDL_free(device);
return (0);
}
- SDL_zerop(data);
device->driverdata = data;
/* Set the function pointers */
@@ -142,6 +147,15 @@ WINRT_CreateDevice(int devindex)
device->SetDisplayMode = WINRT_SetDisplayMode;
device->PumpEvents = WINRT_PumpEvents;
device->GetWindowWMInfo = WINRT_GetWindowWMInfo;
+ device->SuspendScreenSaver = WINRT_SuspendScreenSaver;
+
+#if NTDDI_VERSION >= NTDDI_WIN10
+ device->HasScreenKeyboardSupport = WINRT_HasScreenKeyboardSupport;
+ device->ShowScreenKeyboard = WINRT_ShowScreenKeyboard;
+ device->HideScreenKeyboard = WINRT_HideScreenKeyboard;
+ device->IsScreenKeyboardShown = WINRT_IsScreenKeyboardShown;
+#endif
+
#ifdef SDL_VIDEO_OPENGL_EGL
device->GL_LoadLibrary = WINRT_GLES_LoadLibrary;
device->GL_GetProcAddress = WINRT_GLES_GetProcAddress;
@@ -167,12 +181,17 @@ VideoBootStrap WINRT_bootstrap = {
int
WINRT_VideoInit(_THIS)
{
+ SDL_VideoData * driverdata = (SDL_VideoData *) _this->driverdata;
if (WINRT_InitModes(_this) < 0) {
return -1;
}
WINRT_InitMouse(_this);
WINRT_InitTouch(_this);
-
+ WINRT_InitGameBar(_this);
+ if (driverdata) {
+ /* Initialize screensaver-disabling support */
+ driverdata->displayRequest = WINRT_CreateDisplayRequest(_this);
+ }
return 0;
}
@@ -414,6 +433,12 @@ WINRT_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
void
WINRT_VideoQuit(_THIS)
{
+ SDL_VideoData * driverdata = (SDL_VideoData *) _this->driverdata;
+ if (driverdata && driverdata->displayRequest) {
+ driverdata->displayRequest->Release();
+ driverdata->displayRequest = NULL;
+ }
+ WINRT_QuitGameBar(_this);
WINRT_QuitMouse(_this);
}
@@ -483,7 +508,7 @@ WINRT_DetectWindowFlags(SDL_Window * window)
// data->coreWindow->PointerPosition is not supported on WinPhone 8.0
latestFlags |= SDL_WINDOW_MOUSE_FOCUS;
#else
- if (data->coreWindow->Bounds.Contains(data->coreWindow->PointerPosition)) {
+ if (data->coreWindow->Visible && data->coreWindow->Bounds.Contains(data->coreWindow->PointerPosition)) {
latestFlags |= SDL_WINDOW_MOUSE_FOCUS;
}
#endif
@@ -753,6 +778,65 @@ WINRT_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info)
return SDL_FALSE;
}
+static ABI::Windows::System::Display::IDisplayRequest *
+WINRT_CreateDisplayRequest(_THIS)
+{
+ /* Setup a WinRT DisplayRequest object, usable for enabling/disabling screensaver requests */
+ wchar_t *wClassName = L"Windows.System.Display.DisplayRequest";
+ HSTRING hClassName;
+ IActivationFactory *pActivationFactory = NULL;
+ IInspectable * pDisplayRequestRaw = nullptr;
+ ABI::Windows::System::Display::IDisplayRequest * pDisplayRequest = nullptr;
+ HRESULT hr;
+
+ hr = ::WindowsCreateString(wClassName, (UINT32)wcslen(wClassName), &hClassName);
+ if (FAILED(hr)) {
+ goto done;
+ }
+
+ hr = Windows::Foundation::GetActivationFactory(hClassName, &pActivationFactory);
+ if (FAILED(hr)) {
+ goto done;
+ }
+
+ hr = pActivationFactory->ActivateInstance(&pDisplayRequestRaw);
+ if (FAILED(hr)) {
+ goto done;
+ }
+
+ hr = pDisplayRequestRaw->QueryInterface(IID_IDisplayRequest, (void **) &pDisplayRequest);
+ if (FAILED(hr)) {
+ goto done;
+ }
+
+done:
+ if (pDisplayRequestRaw) {
+ pDisplayRequestRaw->Release();
+ }
+ if (pActivationFactory) {
+ pActivationFactory->Release();
+ }
+ if (hClassName) {
+ ::WindowsDeleteString(hClassName);
+ }
+
+ return pDisplayRequest;
+}
+
+void
+WINRT_SuspendScreenSaver(_THIS)
+{
+ SDL_VideoData *driverdata = (SDL_VideoData *)_this->driverdata;
+ if (driverdata && driverdata->displayRequest) {
+ ABI::Windows::System::Display::IDisplayRequest * displayRequest = (ABI::Windows::System::Display::IDisplayRequest *) driverdata->displayRequest;
+ if (_this->suspend_screensaver) {
+ displayRequest->RequestActive();
+ } else {
+ displayRequest->RequestRelease();
+ }
+ }
+}
+
#endif /* SDL_VIDEO_DRIVER_WINRT */
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/video/winrt/SDL_winrtvideo_cpp.h b/Engine/lib/sdl/src/video/winrt/SDL_winrtvideo_cpp.h
index 26eb008d4..7d5ce13e0 100644
--- a/Engine/lib/sdl/src/video/winrt/SDL_winrtvideo_cpp.h
+++ b/Engine/lib/sdl/src/video/winrt/SDL_winrtvideo_cpp.h
@@ -46,6 +46,17 @@ typedef struct SDL_VideoData {
* passed to eglGetDisplay and eglCreateWindowSurface:
*/
IUnknown *winrtEglWindow;
+
+ /* Event token(s), for unregistering WinRT event handler(s).
+ These are just a struct with a 64-bit integer inside them
+ */
+ Windows::Foundation::EventRegistrationToken gameBarIsInputRedirectedToken;
+
+ /* A WinRT DisplayRequest, used for implementing SDL_*ScreenSaver() functions.
+ * This is really a pointer to a 'ABI::Windows::System::Display::IDisplayRequest *',
+ * It's casted to 'IUnknown *', to help with building SDL.
+ */
+ IUnknown *displayRequest;
} SDL_VideoData;
/* The global, WinRT, SDL Window.
diff --git a/Engine/lib/sdl/src/video/x11/SDL_x11dyn.c b/Engine/lib/sdl/src/video/x11/SDL_x11dyn.c
index 7cbfa3e97..d07fda740 100644
--- a/Engine/lib/sdl/src/video/x11/SDL_x11dyn.c
+++ b/Engine/lib/sdl/src/video/x11/SDL_x11dyn.c
@@ -106,11 +106,8 @@ X11_GetSym(const char *fnname, int *pHasModule)
#endif /* SDL_VIDEO_DRIVER_X11_DYNAMIC */
/* Define all the function pointers and wrappers... */
-#define SDL_X11_MODULE(modname)
#define SDL_X11_SYM(rc,fn,params,args,ret) SDL_DYNX11FN_##fn X11_##fn = NULL;
#include "SDL_x11sym.h"
-#undef SDL_X11_MODULE
-#undef SDL_X11_SYM
/* Annoying varargs entry point... */
#ifdef X_HAVE_UTF8_STRING
@@ -120,10 +117,7 @@ SDL_DYNX11FN_XGetICValues X11_XGetICValues = NULL;
/* These SDL_X11_HAVE_* flags are here whether you have dynamic X11 or not. */
#define SDL_X11_MODULE(modname) int SDL_X11_HAVE_##modname = 0;
-#define SDL_X11_SYM(rc,fn,params,args,ret)
#include "SDL_x11sym.h"
-#undef SDL_X11_MODULE
-#undef SDL_X11_SYM
static int x11_load_refcount = 0;
@@ -139,8 +133,6 @@ SDL_X11_UnloadSymbols(void)
#define SDL_X11_MODULE(modname) SDL_X11_HAVE_##modname = 0;
#define SDL_X11_SYM(rc,fn,params,args,ret) X11_##fn = NULL;
#include "SDL_x11sym.h"
-#undef SDL_X11_MODULE
-#undef SDL_X11_SYM
#ifdef X_HAVE_UTF8_STRING
X11_XCreateIC = NULL;
@@ -177,16 +169,11 @@ SDL_X11_LoadSymbols(void)
}
#define SDL_X11_MODULE(modname) SDL_X11_HAVE_##modname = 1; /* default yes */
-#define SDL_X11_SYM(a,fn,x,y,z)
#include "SDL_x11sym.h"
-#undef SDL_X11_MODULE
-#undef SDL_X11_SYM
#define SDL_X11_MODULE(modname) thismod = &SDL_X11_HAVE_##modname;
#define SDL_X11_SYM(a,fn,x,y,z) X11_##fn = (SDL_DYNX11FN_##fn) X11_GetSym(#fn,thismod);
#include "SDL_x11sym.h"
-#undef SDL_X11_MODULE
-#undef SDL_X11_SYM
#ifdef X_HAVE_UTF8_STRING
X11_XCreateIC = (SDL_DYNX11FN_XCreateIC)
@@ -209,8 +196,6 @@ SDL_X11_LoadSymbols(void)
#define SDL_X11_MODULE(modname) SDL_X11_HAVE_##modname = 1; /* default yes */
#define SDL_X11_SYM(a,fn,x,y,z) X11_##fn = (SDL_DYNX11FN_##fn) fn;
#include "SDL_x11sym.h"
-#undef SDL_X11_MODULE
-#undef SDL_X11_SYM
#ifdef X_HAVE_UTF8_STRING
X11_XCreateIC = XCreateIC;
diff --git a/Engine/lib/sdl/src/video/x11/SDL_x11dyn.h b/Engine/lib/sdl/src/video/x11/SDL_x11dyn.h
index 136609b85..be1ddaa1c 100644
--- a/Engine/lib/sdl/src/video/x11/SDL_x11dyn.h
+++ b/Engine/lib/sdl/src/video/x11/SDL_x11dyn.h
@@ -86,13 +86,10 @@ int SDL_X11_LoadSymbols(void);
void SDL_X11_UnloadSymbols(void);
/* Declare all the function pointers and wrappers... */
-#define SDL_X11_MODULE(modname)
#define SDL_X11_SYM(rc,fn,params,args,ret) \
typedef rc (*SDL_DYNX11FN_##fn) params; \
extern SDL_DYNX11FN_##fn X11_##fn;
#include "SDL_x11sym.h"
-#undef SDL_X11_MODULE
-#undef SDL_X11_SYM
/* Annoying varargs entry point... */
#ifdef X_HAVE_UTF8_STRING
@@ -104,10 +101,7 @@ extern SDL_DYNX11FN_XGetICValues X11_XGetICValues;
/* These SDL_X11_HAVE_* flags are here whether you have dynamic X11 or not. */
#define SDL_X11_MODULE(modname) extern int SDL_X11_HAVE_##modname;
-#define SDL_X11_SYM(rc,fn,params,args,ret)
#include "SDL_x11sym.h"
-#undef SDL_X11_MODULE
-#undef SDL_X11_SYM
#ifdef __cplusplus
}
diff --git a/Engine/lib/sdl/src/video/x11/SDL_x11events.c b/Engine/lib/sdl/src/video/x11/SDL_x11events.c
index 208009607..56d2368a0 100644
--- a/Engine/lib/sdl/src/video/x11/SDL_x11events.c
+++ b/Engine/lib/sdl/src/video/x11/SDL_x11events.c
@@ -35,6 +35,7 @@
#include "../../events/SDL_mouse_c.h"
#include "../../events/SDL_touch_c.h"
+#include "SDL_hints.h"
#include "SDL_timer.h"
#include "SDL_syswm.h"
@@ -117,7 +118,9 @@ static Atom X11_PickTarget(Display *disp, Atom list[], int list_count)
int i;
for (i=0; i < list_count && request == None; i++) {
name = X11_XGetAtomName(disp, list[i]);
- if (strcmp("text/uri-list", name)==0) request = list[i];
+ if ((SDL_strcmp("text/uri-list", name) == 0) || (SDL_strcmp("text/plain", name) == 0)) {
+ request = list[i];
+ }
X11_XFree(name);
}
return request;
@@ -377,8 +380,8 @@ X11_DispatchFocusIn(_THIS, SDL_WindowData *data)
X11_XSetICFocus(data->ic);
}
#endif
-#ifdef SDL_USE_IBUS
- SDL_IBus_SetFocus(SDL_TRUE);
+#ifdef SDL_USE_IME
+ SDL_IME_SetFocus(SDL_TRUE);
#endif
}
@@ -400,8 +403,8 @@ X11_DispatchFocusOut(_THIS, SDL_WindowData *data)
X11_XUnsetICFocus(data->ic);
}
#endif
-#ifdef SDL_USE_IBUS
- SDL_IBus_SetFocus(SDL_FALSE);
+#ifdef SDL_USE_IME
+ SDL_IME_SetFocus(SDL_FALSE);
#endif
}
@@ -512,11 +515,28 @@ ProcessHitTest(_THIS, const SDL_WindowData *data, const XEvent *xev)
return SDL_FALSE;
}
+static void
+X11_UpdateUserTime(SDL_WindowData *data, const unsigned long latest)
+{
+ if (latest && (latest != data->user_time)) {
+ SDL_VideoData *videodata = data->videodata;
+ Display *display = videodata->display;
+ X11_XChangeProperty(display, data->xwindow, videodata->_NET_WM_USER_TIME,
+ XA_CARDINAL, 32, PropModeReplace,
+ (const unsigned char *) &latest, 1);
+#ifdef DEBUG_XEVENTS
+ printf("window %p: updating _NET_WM_USER_TIME to %lu\n", data, latest);
+#endif
+ data->user_time = latest;
+ }
+}
+
+
static void
X11_DispatchEvent(_THIS)
{
SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
- Display *display = videodata->display;
+ Display *display;
SDL_WindowData *data;
XEvent xevent;
int orig_event_type;
@@ -524,6 +544,11 @@ X11_DispatchEvent(_THIS)
XClientMessageEvent m;
int i;
+ if (!videodata) {
+ return;
+ }
+ display = videodata->display;
+
SDL_zero(xevent); /* valgrind fix. --ryan. */
X11_XNextEvent(display, &xevent);
@@ -545,15 +570,12 @@ X11_DispatchEvent(_THIS)
#endif
if (orig_keycode) {
/* Make sure dead key press/release events are sent */
- /* Actually, don't do this because it causes double-delivery
- of some keys on Ubuntu 14.04 (bug 2526)
SDL_Scancode scancode = videodata->key_layout[orig_keycode];
if (orig_event_type == KeyPress) {
SDL_SendKeyboardKey(SDL_PRESSED, scancode);
} else {
SDL_SendKeyboardKey(SDL_RELEASED, scancode);
}
- */
}
return;
}
@@ -617,6 +639,7 @@ X11_DispatchEvent(_THIS)
/* Gaining mouse coverage? */
case EnterNotify:{
+ SDL_Mouse *mouse = SDL_GetMouse();
#ifdef DEBUG_XEVENTS
printf("window %p: EnterNotify! (%d,%d,%d)\n", data,
xevent.xcrossing.x,
@@ -629,7 +652,10 @@ X11_DispatchEvent(_THIS)
#endif
SDL_SetMouseFocus(data->window);
- if (!SDL_GetMouse()->relative_mode) {
+ mouse->last_x = xevent.xcrossing.x;
+ mouse->last_y = xevent.xcrossing.y;
+
+ if (!mouse->relative_mode) {
SDL_SendMouseMotion(data->window, 0, 0, xevent.xcrossing.x, xevent.xcrossing.y);
}
}
@@ -688,6 +714,7 @@ X11_DispatchEvent(_THIS)
data->pending_focus = PENDING_FOCUS_IN;
data->pending_focus_time = SDL_GetTicks() + PENDING_FOCUS_TIME;
}
+ data->last_focus_event_time = SDL_GetTicks();
}
break;
@@ -739,11 +766,7 @@ X11_DispatchEvent(_THIS)
if (videodata->key_layout[keycode] == SDL_SCANCODE_UNKNOWN && keycode) {
int min_keycode, max_keycode;
X11_XDisplayKeycodes(display, &min_keycode, &max_keycode);
-#if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
- keysym = X11_XkbKeycodeToKeysym(display, keycode, 0, 0);
-#else
- keysym = X11_XKeycodeToKeysym(display, keycode, 0);
-#endif
+ keysym = X11_KeyCodeToSym(_this, keycode, xevent.xkey.state >> 13);
fprintf(stderr,
"The key you just pressed is not recognized by SDL. To help get this fixed, please report this to the SDL mailing list X11 KeyCode %d (%d), X11 KeySym 0x%lX (%s).\n",
keycode, keycode - min_keycode, keysym,
@@ -756,14 +779,16 @@ X11_DispatchEvent(_THIS)
if (data->ic) {
X11_Xutf8LookupString(data->ic, &xevent.xkey, text, sizeof(text),
&keysym, &status);
+ } else {
+ X11_XLookupString(&xevent.xkey, text, sizeof(text), &keysym, NULL);
}
#else
X11_XLookupString(&xevent.xkey, text, sizeof(text), &keysym, NULL);
#endif
-#ifdef SDL_USE_IBUS
+#ifdef SDL_USE_IME
if(SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE){
- handled_by_ime = SDL_IBus_ProcessKeyEvent(keysym, keycode);
+ handled_by_ime = SDL_IME_ProcessKeyEvent(keysym, keycode);
}
#endif
if (!handled_by_ime) {
@@ -773,6 +798,7 @@ X11_DispatchEvent(_THIS)
}
}
+ X11_UpdateUserTime(data, xevent.xkey.time);
}
break;
@@ -816,36 +842,28 @@ X11_DispatchEvent(_THIS)
xevent.xconfigure.x, xevent.xconfigure.y,
xevent.xconfigure.width, xevent.xconfigure.height);
#endif
- long border_left = 0;
- long border_top = 0;
- if (data->xwindow) {
- Atom _net_frame_extents = X11_XInternAtom(display, "_NET_FRAME_EXTENTS", 0);
- Atom type;
- int format;
- unsigned long nitems, bytes_after;
- unsigned char *property;
- if (X11_XGetWindowProperty(display, data->xwindow,
- _net_frame_extents, 0, 16, 0,
- XA_CARDINAL, &type, &format,
- &nitems, &bytes_after, &property) == Success) {
- if (type != None && nitems == 4)
- {
- border_left = ((long*)property)[0];
- border_top = ((long*)property)[2];
- }
- X11_XFree(property);
- }
+ /* Real configure notify events are relative to the parent, synthetic events are absolute. */
+ if (!xevent.xconfigure.send_event) {
+ unsigned int NumChildren;
+ Window ChildReturn, Root, Parent;
+ Window * Children;
+ /* Translate these coodinates back to relative to root */
+ X11_XQueryTree(data->videodata->display, xevent.xconfigure.window, &Root, &Parent, &Children, &NumChildren);
+ X11_XTranslateCoordinates(xevent.xconfigure.display,
+ Parent, DefaultRootWindow(xevent.xconfigure.display),
+ xevent.xconfigure.x, xevent.xconfigure.y,
+ &xevent.xconfigure.x, &xevent.xconfigure.y,
+ &ChildReturn);
}
-
+
if (xevent.xconfigure.x != data->last_xconfigure.x ||
xevent.xconfigure.y != data->last_xconfigure.y) {
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_MOVED,
- xevent.xconfigure.x - border_left,
- xevent.xconfigure.y - border_top);
-#ifdef SDL_USE_IBUS
+ xevent.xconfigure.x, xevent.xconfigure.y);
+#ifdef SDL_USE_IME
if(SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE){
- /* Update IBus candidate list position */
- SDL_IBus_UpdateTextRect(NULL);
+ /* Update IME candidate list position */
+ SDL_IME_UpdateTextRect(NULL);
}
#endif
}
@@ -959,6 +977,16 @@ X11_DispatchEvent(_THIS)
SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_CLOSE, 0, 0);
break;
}
+ else if ((xevent.xclient.message_type == videodata->WM_PROTOCOLS) &&
+ (xevent.xclient.format == 32) &&
+ (xevent.xclient.data.l[0] == videodata->WM_TAKE_FOCUS)) {
+
+#ifdef DEBUG_XEVENTS
+ printf("window %p: WM_TAKE_FOCUS\n", data);
+#endif
+ SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_TAKE_FOCUS, 0, 0);
+ break;
+ }
}
break;
@@ -975,7 +1003,7 @@ X11_DispatchEvent(_THIS)
SDL_Mouse *mouse = SDL_GetMouse();
if(!mouse->relative_mode || mouse->relative_mode_warp) {
#ifdef DEBUG_MOTION
- printf("window %p: X11 motion: %d,%d\n", xevent.xmotion.x, xevent.xmotion.y);
+ printf("window %p: X11 motion: %d,%d\n", data, xevent.xmotion.x, xevent.xmotion.y);
#endif
SDL_SendMouseMotion(data->window, 0, 0, xevent.xmotion.x, xevent.xmotion.y);
@@ -985,12 +1013,17 @@ X11_DispatchEvent(_THIS)
case ButtonPress:{
int xticks = 0, yticks = 0;
+#ifdef DEBUG_XEVENTS
+ printf("window %p: ButtonPress (X11 button = %d)\n", data, xevent.xbutton.button);
+#endif
if (X11_IsWheelEvent(display,&xevent,&xticks, &yticks)) {
SDL_SendMouseWheel(data->window, 0, xticks, yticks, SDL_MOUSEWHEEL_NORMAL);
} else {
+ SDL_bool ignore_click = SDL_FALSE;
int button = xevent.xbutton.button;
if(button == Button1) {
if (ProcessHitTest(_this, data, &xevent)) {
+ SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_HIT_TEST, 0, 0);
break; /* don't pass this event on to app. */
}
}
@@ -999,8 +1032,18 @@ X11_DispatchEvent(_THIS)
=> subtract (8-SDL_BUTTON_X1) to get value SDL expects */
button -= (8-SDL_BUTTON_X1);
}
- SDL_SendMouseButton(data->window, 0, SDL_PRESSED, button);
+ if (data->last_focus_event_time) {
+ const int X11_FOCUS_CLICK_TIMEOUT = 10;
+ if (!SDL_TICKS_PASSED(SDL_GetTicks(), data->last_focus_event_time + X11_FOCUS_CLICK_TIMEOUT)) {
+ ignore_click = !SDL_GetHintBoolean(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, SDL_FALSE);
+ }
+ data->last_focus_event_time = 0;
+ }
+ if (!ignore_click) {
+ SDL_SendMouseButton(data->window, 0, SDL_PRESSED, button);
+ }
}
+ X11_UpdateUserTime(data, xevent.xbutton.time);
}
break;
@@ -1008,7 +1051,10 @@ X11_DispatchEvent(_THIS)
int button = xevent.xbutton.button;
/* The X server sends a Release event for each Press for wheels. Ignore them. */
int xticks = 0, yticks = 0;
- if (!X11_IsWheelEvent(display,&xevent,&xticks, &yticks)) {
+#ifdef DEBUG_XEVENTS
+ printf("window %p: ButtonRelease (X11 button = %d)\n", data, xevent.xbutton.button);
+#endif
+ if (!X11_IsWheelEvent(display, &xevent, &xticks, &yticks)) {
if (button > 7) {
/* see explanation at case ButtonPress */
button -= (8-SDL_BUTTON_X1);
@@ -1027,7 +1073,7 @@ X11_DispatchEvent(_THIS)
char *name = X11_XGetAtomName(display, xevent.xproperty.atom);
if (name) {
- printf("window %p: PropertyNotify: %s %s\n", data, name, (xevent.xproperty.state == PropertyDelete) ? "deleted" : "changed");
+ printf("window %p: PropertyNotify: %s %s time=%lu\n", data, name, (xevent.xproperty.state == PropertyDelete) ? "deleted" : "changed", xevent.xproperty.time);
X11_XFree(name);
}
@@ -1095,6 +1141,17 @@ X11_DispatchEvent(_THIS)
}
#endif /* DEBUG_XEVENTS */
+ /* Take advantage of this moment to make sure user_time has a
+ valid timestamp from the X server, so if we later try to
+ raise/restore this window, _NET_ACTIVE_WINDOW can have a
+ non-zero timestamp, even if there's never been a mouse or
+ key press to this window so far. Note that we don't try to
+ set _NET_WM_USER_TIME here, though. That's only for legit
+ user interaction with the window. */
+ if (!data->user_time) {
+ data->user_time = xevent.xproperty.time;
+ }
+
if (xevent.xproperty.atom == data->videodata->_NET_WM_STATE) {
/* Get the new state from the window manager.
Compositing window managers can alter visibility of windows
@@ -1128,6 +1185,24 @@ X11_DispatchEvent(_THIS)
right approach, but it seems to work. */
X11_UpdateKeymap(_this);
SDL_SendKeymapChangedEvent();
+ } else if (xevent.xproperty.atom == videodata->_NET_FRAME_EXTENTS) {
+ Atom type;
+ int format;
+ unsigned long nitems, bytes_after;
+ unsigned char *property;
+ if (X11_XGetWindowProperty(display, data->xwindow, videodata->_NET_FRAME_EXTENTS, 0, 16, 0, XA_CARDINAL, &type, &format, &nitems, &bytes_after, &property) == Success) {
+ if (type != None && nitems == 4) {
+ data->border_left = (int) ((long*)property)[0];
+ data->border_right = (int) ((long*)property)[1];
+ data->border_top = (int) ((long*)property)[2];
+ data->border_bottom = (int) ((long*)property)[3];
+ }
+ X11_XFree(property);
+
+ #ifdef DEBUG_XEVENTS
+ printf("New _NET_FRAME_EXTENTS: left=%d right=%d, top=%d, bottom=%d\n", data->border_left, data->border_right, data->border_top, data->border_bottom);
+ #endif
+ }
}
}
break;
@@ -1182,51 +1257,33 @@ X11_DispatchEvent(_THIS)
break;
case SelectionNotify: {
+ Atom target = xevent.xselection.target;
#ifdef DEBUG_XEVENTS
printf("window %p: SelectionNotify (requestor = %ld, target = %ld)\n", data,
xevent.xselection.requestor, xevent.xselection.target);
#endif
- Atom target = xevent.xselection.target;
if (target == data->xdnd_req) {
/* read data */
SDL_x11Prop p;
X11_ReadProperty(&p, display, data->xwindow, videodata->PRIMARY);
if (p.format == 8) {
- SDL_bool expect_lf = SDL_FALSE;
- char *start = NULL;
- char *scan = (char*)p.data;
- char *fn;
- char *uri;
- int length = 0;
- while (p.count--) {
- if (!expect_lf) {
- if (*scan == 0x0D) {
- expect_lf = SDL_TRUE;
+ /* !!! FIXME: don't use strtok here. It's not reentrant and not in SDL_stdinc. */
+ char* name = X11_XGetAtomName(display, target);
+ char *token = strtok((char *) p.data, "\r\n");
+ while (token != NULL) {
+ if (SDL_strcmp("text/plain", name)==0) {
+ SDL_SendDropText(data->window, token);
+ } else if (SDL_strcmp("text/uri-list", name)==0) {
+ char *fn = X11_URIToLocal(token);
+ if (fn) {
+ SDL_SendDropFile(data->window, fn);
}
- if (start == NULL) {
- start = scan;
- length = 0;
- }
- length++;
- } else {
- if (*scan == 0x0A && length > 0) {
- uri = SDL_malloc(length--);
- SDL_memcpy(uri, start, length);
- uri[length] = '\0';
- fn = X11_URIToLocal(uri);
- if (fn) {
- SDL_SendDropFile(fn);
- }
- SDL_free(uri);
- }
- expect_lf = SDL_FALSE;
- start = NULL;
}
- scan++;
+ token = strtok(NULL, "\r\n");
}
+ SDL_SendDropComplete(data->window);
}
-
X11_XFree(p.data);
/* send reply */
@@ -1350,9 +1407,9 @@ X11_PumpEvents(_THIS)
X11_DispatchEvent(_this);
}
-#ifdef SDL_USE_IBUS
+#ifdef SDL_USE_IME
if(SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE){
- SDL_IBus_PumpEvents();
+ SDL_IME_PumpEvents();
}
#endif
diff --git a/Engine/lib/sdl/src/video/x11/SDL_x11keyboard.c b/Engine/lib/sdl/src/video/x11/SDL_x11keyboard.c
index 2c3acdadd..b888bff35 100644
--- a/Engine/lib/sdl/src/video/x11/SDL_x11keyboard.c
+++ b/Engine/lib/sdl/src/video/x11/SDL_x11keyboard.c
@@ -129,9 +129,21 @@ static const struct {
{ XK_Control_R, SDL_SCANCODE_RCTRL },
{ XK_Shift_R, SDL_SCANCODE_RSHIFT },
{ XK_Alt_R, SDL_SCANCODE_RALT },
+ { XK_ISO_Level3_Shift, SDL_SCANCODE_RALT },
{ XK_Meta_R, SDL_SCANCODE_RGUI },
{ XK_Super_R, SDL_SCANCODE_RGUI },
{ XK_Mode_switch, SDL_SCANCODE_MODE },
+ { XK_period, SDL_SCANCODE_PERIOD },
+ { XK_comma, SDL_SCANCODE_COMMA },
+ { XK_slash, SDL_SCANCODE_SLASH },
+ { XK_backslash, SDL_SCANCODE_BACKSLASH },
+ { XK_minus, SDL_SCANCODE_MINUS },
+ { XK_equal, SDL_SCANCODE_EQUALS },
+ { XK_space, SDL_SCANCODE_SPACE },
+ { XK_grave, SDL_SCANCODE_GRAVE },
+ { XK_apostrophe, SDL_SCANCODE_APOSTROPHE },
+ { XK_bracketleft, SDL_SCANCODE_LEFTBRACKET },
+ { XK_bracketright, SDL_SCANCODE_RIGHTBRACKET },
};
static const struct
@@ -142,31 +154,34 @@ static const struct
{ darwin_scancode_table, SDL_arraysize(darwin_scancode_table) },
{ xfree86_scancode_table, SDL_arraysize(xfree86_scancode_table) },
{ xfree86_scancode_table2, SDL_arraysize(xfree86_scancode_table2) },
+ { xvnc_scancode_table, SDL_arraysize(xvnc_scancode_table) },
};
/* *INDENT-OFF* */
/* This function only works for keyboards in US QWERTY layout */
static SDL_Scancode
-X11_KeyCodeToSDLScancode(Display *display, KeyCode keycode)
+X11_KeyCodeToSDLScancode(_THIS, KeyCode keycode)
{
KeySym keysym;
int i;
-#if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
- keysym = X11_XkbKeycodeToKeysym(display, keycode, 0, 0);
-#else
- keysym = X11_XKeycodeToKeysym(display, keycode, 0);
-#endif
+ keysym = X11_KeyCodeToSym(_this, keycode, 0);
if (keysym == NoSymbol) {
return SDL_SCANCODE_UNKNOWN;
}
+ if (keysym >= XK_a && keysym <= XK_z) {
+ return SDL_SCANCODE_A + (keysym - XK_a);
+ }
if (keysym >= XK_A && keysym <= XK_Z) {
return SDL_SCANCODE_A + (keysym - XK_A);
}
- if (keysym >= XK_0 && keysym <= XK_9) {
- return SDL_SCANCODE_0 + (keysym - XK_0);
+ if (keysym == XK_0) {
+ return SDL_SCANCODE_0;
+ }
+ if (keysym >= XK_1 && keysym <= XK_9) {
+ return SDL_SCANCODE_1 + (keysym - XK_1);
}
for (i = 0; i < SDL_arraysize(KeySymToSDLScancode); ++i) {
@@ -178,15 +193,10 @@ X11_KeyCodeToSDLScancode(Display *display, KeyCode keycode)
}
static Uint32
-X11_KeyCodeToUcs4(Display *display, KeyCode keycode, unsigned char group)
+X11_KeyCodeToUcs4(_THIS, KeyCode keycode, unsigned char group)
{
- KeySym keysym;
+ KeySym keysym = X11_KeyCodeToSym(_this, keycode, group);
-#if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
- keysym = X11_XkbKeycodeToKeysym(display, keycode, group, 0);
-#else
- keysym = X11_XKeycodeToKeysym(display, keycode, 0);
-#endif
if (keysym == NoSymbol) {
return 0;
}
@@ -194,6 +204,42 @@ X11_KeyCodeToUcs4(Display *display, KeyCode keycode, unsigned char group)
return X11_KeySymToUcs4(keysym);
}
+KeySym
+X11_KeyCodeToSym(_THIS, KeyCode keycode, unsigned char group)
+{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+ KeySym keysym;
+
+#if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
+ if (data->xkb) {
+ int num_groups = XkbKeyNumGroups(data->xkb, keycode);
+ unsigned char info = XkbKeyGroupInfo(data->xkb, keycode);
+
+ if (num_groups && group >= num_groups) {
+
+ int action = XkbOutOfRangeGroupAction(info);
+
+ if (action == XkbRedirectIntoRange) {
+ if ((group = XkbOutOfRangeGroupNumber(info)) >= num_groups) {
+ group = 0;
+ }
+ } else if (action == XkbClampIntoRange) {
+ group = num_groups - 1;
+ } else {
+ group %= num_groups;
+ }
+ }
+ keysym = X11_XkbKeycodeToKeysym(data->display, keycode, group, 0);
+ } else {
+ keysym = X11_XKeycodeToKeysym(data->display, keycode, 0);
+ }
+#else
+ keysym = X11_XKeycodeToKeysym(data->display, keycode, 0);
+#endif
+
+ return keysym;
+}
+
int
X11_InitKeyboard(_THIS)
{
@@ -219,6 +265,16 @@ X11_InitKeyboard(_THIS)
X11_XAutoRepeatOn(data->display);
+#if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
+ {
+ int xkb_major = XkbMajorVersion;
+ int xkb_minor = XkbMinorVersion;
+ if (X11_XkbQueryExtension(data->display, NULL, NULL, NULL, &xkb_major, &xkb_minor)) {
+ data->xkb = X11_XkbGetMap(data->display, XkbAllClientInfoMask, XkbUseCoreKbd);
+ }
+ }
+#endif
+
/* Try to determine which scancodes are being used based on fingerprint */
best_distance = SDL_arraysize(fingerprint) + 1;
best_index = -1;
@@ -263,16 +319,12 @@ X11_InitKeyboard(_THIS)
SDL_GetDefaultKeymap(keymap);
for (i = min_keycode; i <= max_keycode; ++i) {
KeySym sym;
-#if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
- sym = X11_XkbKeycodeToKeysym(data->display, i, 0, 0);
-#else
- sym = X11_XKeycodeToKeysym(data->display, i, 0);
-#endif
+ sym = X11_KeyCodeToSym(_this, (KeyCode) i, 0);
if (sym != NoSymbol) {
SDL_Scancode scancode;
printf("code = %d, sym = 0x%X (%s) ", i - min_keycode,
(unsigned int) sym, X11_XKeysymToString(sym));
- scancode = X11_KeyCodeToSDLScancode(data->display, i);
+ scancode = X11_KeyCodeToSDLScancode(_this, i);
data->key_layout[i] = scancode;
if (scancode == SDL_SCANCODE_UNKNOWN) {
printf("scancode not found\n");
@@ -287,8 +339,8 @@ X11_InitKeyboard(_THIS)
SDL_SetScancodeName(SDL_SCANCODE_APPLICATION, "Menu");
-#ifdef SDL_USE_IBUS
- SDL_IBus_Init();
+#ifdef SDL_USE_IME
+ SDL_IME_Init();
#endif
return 0;
@@ -304,10 +356,12 @@ X11_UpdateKeymap(_THIS)
unsigned char group = 0;
SDL_GetDefaultKeymap(keymap);
-
+
#if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
- {
+ if (data->xkb) {
XkbStateRec state;
+ X11_XkbGetUpdatedMap(data->display, XkbAllClientInfoMask, data->xkb);
+
if (X11_XkbGetState(data->display, XkbUseCoreKbd, &state) == Success) {
group = state.group;
}
@@ -325,11 +379,11 @@ X11_UpdateKeymap(_THIS)
}
/* See if there is a UCS keycode for this scancode */
- key = X11_KeyCodeToUcs4(data->display, (KeyCode)i, group);
+ key = X11_KeyCodeToUcs4(_this, (KeyCode)i, group);
if (key) {
keymap[scancode] = key;
} else {
- SDL_Scancode keyScancode = X11_KeyCodeToSDLScancode(data->display, (KeyCode)i);
+ SDL_Scancode keyScancode = X11_KeyCodeToSDLScancode(_this, (KeyCode)i);
switch (keyScancode) {
case SDL_SCANCODE_RETURN:
@@ -359,22 +413,54 @@ X11_UpdateKeymap(_THIS)
void
X11_QuitKeyboard(_THIS)
{
-#ifdef SDL_USE_IBUS
- SDL_IBus_Quit();
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+
+#if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
+ if (data->xkb) {
+ X11_XkbFreeClientMap(data->xkb, 0, True);
+ data->xkb = NULL;
+ }
+#endif
+
+#ifdef SDL_USE_IME
+ SDL_IME_Quit();
+#endif
+}
+
+static void
+X11_ResetXIM(_THIS)
+{
+#ifdef X_HAVE_UTF8_STRING
+ SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
+ int i;
+
+ if (videodata && videodata->windowlist) {
+ for (i = 0; i < videodata->numwindows; ++i) {
+ SDL_WindowData *data = videodata->windowlist[i];
+ if (data && data->ic) {
+ /* Clear any partially entered dead keys */
+ char *contents = X11_Xutf8ResetIC(data->ic);
+ if (contents) {
+ X11_XFree(contents);
+ }
+ }
+ }
+ }
#endif
}
void
X11_StartTextInput(_THIS)
{
-
+ X11_ResetXIM(_this);
}
void
X11_StopTextInput(_THIS)
{
-#ifdef SDL_USE_IBUS
- SDL_IBus_Reset();
+ X11_ResetXIM(_this);
+#ifdef SDL_USE_IME
+ SDL_IME_Reset();
#endif
}
@@ -386,8 +472,8 @@ X11_SetTextInputRect(_THIS, SDL_Rect *rect)
return;
}
-#ifdef SDL_USE_IBUS
- SDL_IBus_UpdateTextRect(rect);
+#ifdef SDL_USE_IME
+ SDL_IME_UpdateTextRect(rect);
#endif
}
diff --git a/Engine/lib/sdl/src/video/x11/SDL_x11keyboard.h b/Engine/lib/sdl/src/video/x11/SDL_x11keyboard.h
index a1102ed75..6ce3c9cce 100644
--- a/Engine/lib/sdl/src/video/x11/SDL_x11keyboard.h
+++ b/Engine/lib/sdl/src/video/x11/SDL_x11keyboard.h
@@ -29,6 +29,7 @@ extern void X11_QuitKeyboard(_THIS);
extern void X11_StartTextInput(_THIS);
extern void X11_StopTextInput(_THIS);
extern void X11_SetTextInputRect(_THIS, SDL_Rect *rect);
+extern KeySym X11_KeyCodeToSym(_THIS, KeyCode, unsigned char group);
#endif /* _SDL_x11keyboard_h */
diff --git a/Engine/lib/sdl/src/video/x11/SDL_x11modes.c b/Engine/lib/sdl/src/video/x11/SDL_x11modes.c
index 446da2b64..29307b3a6 100644
--- a/Engine/lib/sdl/src/video/x11/SDL_x11modes.c
+++ b/Engine/lib/sdl/src/video/x11/SDL_x11modes.c
@@ -157,14 +157,12 @@ CheckXinerama(Display * display, int *major, int *minor)
{
int event_base = 0;
int error_base = 0;
- const char *env;
/* Default the extension not available */
*major = *minor = 0;
/* Allow environment override */
- env = SDL_GetHint(SDL_HINT_VIDEO_X11_XINERAMA);
- if (env && !SDL_atoi(env)) {
+ if (!SDL_GetHintBoolean(SDL_HINT_VIDEO_X11_XINERAMA, SDL_TRUE)) {
#ifdef X11MODES_DEBUG
printf("Xinerama disabled due to hint\n");
#endif
@@ -213,22 +211,19 @@ X11_XineramaFailed(Display * d, XErrorEvent * e)
static SDL_bool
CheckXRandR(Display * display, int *major, int *minor)
{
- const char *env;
-
/* Default the extension not available */
*major = *minor = 0;
/* Allow environment override */
- env = SDL_GetHint(SDL_HINT_VIDEO_X11_XRANDR);
#ifdef XRANDR_DISABLED_BY_DEFAULT
- if (!env || !SDL_atoi(env)) {
+ if (!SDL_GetHintBoolean(SDL_HINT_VIDEO_X11_XRANDR, SDL_FALSE)) {
#ifdef X11MODES_DEBUG
printf("XRandR disabled by default due to window manager issues\n");
#endif
return SDL_FALSE;
}
#else
- if (env && !SDL_atoi(env)) {
+ if (!SDL_GetHintBoolean(SDL_HINT_VIDEO_X11_XRANDR, SDL_TRUE)) {
#ifdef X11MODES_DEBUG
printf("XRandR disabled due to hint\n");
#endif
@@ -264,8 +259,8 @@ CheckXRandR(Display * display, int *major, int *minor)
static int
CalculateXRandRRefreshRate(const XRRModeInfo *info)
{
- return (info->hTotal
- && info->vTotal) ? (info->dotClock / (info->hTotal * info->vTotal)) : 0;
+ return (info->hTotal && info->vTotal) ?
+ round(((double)info->dotClock / (double)(info->hTotal * info->vTotal))) : 0;
}
static SDL_bool
@@ -342,7 +337,7 @@ SetXRandRDisplayName(Display *dpy, Atom EDID, char *name, const size_t namelen,
X11_XFree(props);
}
- inches = (int)((SDL_sqrt(widthmm * widthmm + heightmm * heightmm) / 25.4f) + 0.5f);
+ inches = (int)((SDL_sqrtf(widthmm * widthmm + heightmm * heightmm) / 25.4f) + 0.5f);
if (*name && inches) {
const size_t len = SDL_strlen(name);
SDL_snprintf(&name[len], namelen-len, " %d\"", inches);
@@ -507,14 +502,11 @@ X11_InitModes_XRandR(_THIS)
static SDL_bool
CheckVidMode(Display * display, int *major, int *minor)
{
- const char *env;
-
/* Default the extension not available */
*major = *minor = 0;
/* Allow environment override */
- env = SDL_GetHint(SDL_HINT_VIDEO_X11_XVIDMODE);
- if (env && !SDL_atoi(env)) {
+ if (!SDL_GetHintBoolean(SDL_HINT_VIDEO_X11_XVIDMODE, SDL_TRUE)) {
#ifdef X11MODES_DEBUG
printf("XVidMode disabled due to hint\n");
#endif
@@ -618,6 +610,19 @@ X11_InitModes(_THIS)
/* !!! FIXME: eventually remove support for Xinerama and XVidMode (everything below here). */
+ /* This is a workaround for some apps (UnrealEngine4, for example) until
+ we sort out the ramifications of removing XVidMode support outright.
+ This block should be removed with the XVidMode support. */
+ {
+ if (SDL_GetHintBoolean("SDL_VIDEO_X11_REQUIRE_XRANDR", SDL_FALSE)) {
+ #if SDL_VIDEO_DRIVER_X11_XRANDR
+ return SDL_SetError("XRandR support is required but not available");
+ #else
+ return SDL_SetError("XRandR support is required but not built into SDL!");
+ #endif
+ }
+ }
+
#if SDL_VIDEO_DRIVER_X11_XINERAMA
/* Query Xinerama extention
* NOTE: This works with Nvidia Twinview correctly, but you need version 302.17 (released on June 2012)
@@ -1056,7 +1061,44 @@ X11_GetDisplayDPI(_THIS, SDL_VideoDisplay * sdl_display, float * ddpi, float * h
*vdpi = data->vdpi;
}
- return data->ddpi != 0.0f ? 0 : -1;
+ return data->ddpi != 0.0f ? 0 : SDL_SetError("Couldn't get DPI");
+}
+
+int
+X11_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * sdl_display, SDL_Rect * rect)
+{
+ SDL_VideoData *data = (SDL_VideoData *) _this->driverdata;
+ Display *display = data->display;
+ Atom _NET_WORKAREA;
+ int status, real_format;
+ int retval = -1;
+ Atom real_type;
+ unsigned long items_read = 0, items_left = 0;
+ unsigned char *propdata = NULL;
+
+ if (X11_GetDisplayBounds(_this, sdl_display, rect) < 0) {
+ return -1;
+ }
+
+ _NET_WORKAREA = X11_XInternAtom(display, "_NET_WORKAREA", False);
+ status = X11_XGetWindowProperty(display, DefaultRootWindow(display),
+ _NET_WORKAREA, 0L, 4L, False, XA_CARDINAL,
+ &real_type, &real_format, &items_read,
+ &items_left, &propdata);
+ if ((status == Success) && (items_read >= 4)) {
+ const long *p = (long*) propdata;
+ const SDL_Rect usable = { (int)p[0], (int)p[1], (int)p[2], (int)p[3] };
+ retval = 0;
+ if (!SDL_IntersectRect(rect, &usable, rect)) {
+ SDL_zerop(rect);
+ }
+ }
+
+ if (propdata) {
+ X11_XFree(propdata);
+ }
+
+ return retval;
}
#endif /* SDL_VIDEO_DRIVER_X11 */
diff --git a/Engine/lib/sdl/src/video/x11/SDL_x11modes.h b/Engine/lib/sdl/src/video/x11/SDL_x11modes.h
index a68286ab1..4f47f3b5c 100644
--- a/Engine/lib/sdl/src/video/x11/SDL_x11modes.h
+++ b/Engine/lib/sdl/src/video/x11/SDL_x11modes.h
@@ -77,6 +77,7 @@ extern int X11_GetVisualInfoFromVisual(Display * display, Visual * visual,
extern Uint32 X11_GetPixelFormatFromVisualInfo(Display * display,
XVisualInfo * vinfo);
extern int X11_GetDisplayBounds(_THIS, SDL_VideoDisplay * sdl_display, SDL_Rect * rect);
+extern int X11_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * sdl_display, SDL_Rect * rect);
extern int X11_GetDisplayDPI(_THIS, SDL_VideoDisplay * sdl_display, float * ddpi, float * hdpi, float * vdpi);
#endif /* _SDL_x11modes_h */
diff --git a/Engine/lib/sdl/src/video/x11/SDL_x11mouse.c b/Engine/lib/sdl/src/video/x11/SDL_x11mouse.c
index 245b116ea..e1a16c225 100644
--- a/Engine/lib/sdl/src/video/x11/SDL_x11mouse.c
+++ b/Engine/lib/sdl/src/video/x11/SDL_x11mouse.c
@@ -366,39 +366,52 @@ X11_CaptureMouse(SDL_Window *window)
static Uint32
X11_GetGlobalMouseState(int *x, int *y)
{
+ SDL_VideoData *videodata = (SDL_VideoData *) SDL_GetVideoDevice()->driverdata;
Display *display = GetDisplay();
const int num_screens = SDL_GetNumVideoDisplays();
int i;
/* !!! FIXME: should we XSync() here first? */
- for (i = 0; i < num_screens; i++) {
- SDL_DisplayData *data = (SDL_DisplayData *) SDL_GetDisplayDriverData(i);
- if (data != NULL) {
- Window root, child;
- int rootx, rooty, winx, winy;
- unsigned int mask;
- if (X11_XQueryPointer(display, RootWindow(display, data->screen), &root, &child, &rootx, &rooty, &winx, &winy, &mask)) {
- XWindowAttributes root_attrs;
- Uint32 retval = 0;
- retval |= (mask & Button1Mask) ? SDL_BUTTON_LMASK : 0;
- retval |= (mask & Button2Mask) ? SDL_BUTTON_MMASK : 0;
- retval |= (mask & Button3Mask) ? SDL_BUTTON_RMASK : 0;
- /* SDL_DisplayData->x,y point to screen origin, and adding them to mouse coordinates relative to root window doesn't do the right thing
- * (observed on dual monitor setup with primary display being the rightmost one - mouse was offset to the right).
- *
- * Adding root position to root-relative coordinates seems to be a better way to get absolute position. */
- X11_XGetWindowAttributes(display, root, &root_attrs);
- *x = root_attrs.x + rootx;
- *y = root_attrs.y + rooty;
- return retval;
+#if !SDL_VIDEO_DRIVER_X11_XINPUT2
+ videodata->global_mouse_changed = SDL_TRUE;
+#endif
+
+ /* check if we have this cached since XInput last saw the mouse move. */
+ /* !!! FIXME: can we just calculate this from XInput's events? */
+ if (videodata->global_mouse_changed) {
+ for (i = 0; i < num_screens; i++) {
+ SDL_DisplayData *data = (SDL_DisplayData *) SDL_GetDisplayDriverData(i);
+ if (data != NULL) {
+ Window root, child;
+ int rootx, rooty, winx, winy;
+ unsigned int mask;
+ if (X11_XQueryPointer(display, RootWindow(display, data->screen), &root, &child, &rootx, &rooty, &winx, &winy, &mask)) {
+ XWindowAttributes root_attrs;
+ Uint32 buttons = 0;
+ buttons |= (mask & Button1Mask) ? SDL_BUTTON_LMASK : 0;
+ buttons |= (mask & Button2Mask) ? SDL_BUTTON_MMASK : 0;
+ buttons |= (mask & Button3Mask) ? SDL_BUTTON_RMASK : 0;
+ /* SDL_DisplayData->x,y point to screen origin, and adding them to mouse coordinates relative to root window doesn't do the right thing
+ * (observed on dual monitor setup with primary display being the rightmost one - mouse was offset to the right).
+ *
+ * Adding root position to root-relative coordinates seems to be a better way to get absolute position. */
+ X11_XGetWindowAttributes(display, root, &root_attrs);
+ videodata->global_mouse_position.x = root_attrs.x + rootx;
+ videodata->global_mouse_position.y = root_attrs.y + rooty;
+ videodata->global_mouse_buttons = buttons;
+ videodata->global_mouse_changed = SDL_FALSE;
+ break;
+ }
}
}
}
- SDL_assert(0 && "The pointer wasn't on any X11 screen?!");
+ SDL_assert(!videodata->global_mouse_changed); /* The pointer wasn't on any X11 screen?! */
- return 0;
+ *x = videodata->global_mouse_position.x;
+ *y = videodata->global_mouse_position.y;
+ return videodata->global_mouse_buttons;
}
diff --git a/Engine/lib/sdl/src/video/x11/SDL_x11opengl.c b/Engine/lib/sdl/src/video/x11/SDL_x11opengl.c
index 8b634be3d..abc699dd4 100644
--- a/Engine/lib/sdl/src/video/x11/SDL_x11opengl.c
+++ b/Engine/lib/sdl/src/video/x11/SDL_x11opengl.c
@@ -695,7 +695,7 @@ X11_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
if (errorCode != Success) { /* uhoh, an X error was thrown! */
return -1; /* the error handler called SDL_SetError() already. */
- } else if (!rc) { /* glxMakeCurrent() failed without throwing an X error */
+ } else if (!rc) { /* glXMakeCurrent() failed without throwing an X error */
return SDL_SetError("Unable to make GL context current");
}
@@ -703,14 +703,14 @@ X11_GL_MakeCurrent(_THIS, SDL_Window * window, SDL_GLContext context)
}
/*
- 0 is a valid argument to glxSwapInterval(MESA|EXT) and setting it to 0
+ 0 is a valid argument to glXSwapInterval(MESA|EXT) and setting it to 0
will undo the effect of a previous call with a value that is greater
than zero (or at least that is what the docs say). OTOH, 0 is an invalid
- argument to glxSwapIntervalSGI and it returns an error if you call it
+ argument to glXSwapIntervalSGI and it returns an error if you call it
with 0 as an argument.
*/
-static int swapinterval = -1;
+static int swapinterval = 0;
int
X11_GL_SetSwapInterval(_THIS, int interval)
{
@@ -742,14 +742,14 @@ X11_GL_SetSwapInterval(_THIS, int interval)
} else if (_this->gl_data->glXSwapIntervalMESA) {
status = _this->gl_data->glXSwapIntervalMESA(interval);
if (status != 0) {
- SDL_SetError("glxSwapIntervalMESA failed");
+ SDL_SetError("glXSwapIntervalMESA failed");
} else {
swapinterval = interval;
}
} else if (_this->gl_data->glXSwapIntervalSGI) {
status = _this->gl_data->glXSwapIntervalSGI(interval);
if (status != 0) {
- SDL_SetError("glxSwapIntervalSGI failed");
+ SDL_SetError("glXSwapIntervalSGI failed");
} else {
swapinterval = interval;
}
diff --git a/Engine/lib/sdl/src/video/x11/SDL_x11sym.h b/Engine/lib/sdl/src/video/x11/SDL_x11sym.h
index 3683ac0a5..7290412b7 100644
--- a/Engine/lib/sdl/src/video/x11/SDL_x11sym.h
+++ b/Engine/lib/sdl/src/video/x11/SDL_x11sym.h
@@ -21,6 +21,14 @@
/* *INDENT-OFF* */
+#ifndef SDL_X11_MODULE
+#define SDL_X11_MODULE(modname)
+#endif
+
+#ifndef SDL_X11_SYM
+#define SDL_X11_SYM(rc,fn,params,args,ret)
+#endif
+
SDL_X11_MODULE(BASEXLIB)
SDL_X11_SYM(XSizeHints*,XAllocSizeHints,(void),(),return)
SDL_X11_SYM(XWMHints*,XAllocWMHints,(void),(),return)
@@ -153,6 +161,7 @@ SDL_X11_SYM(SDL_X11_XSynchronizeRetType,XSynchronize,(Display* a,Bool b),(a,b),r
SDL_X11_SYM(SDL_X11_XESetWireToEventRetType,XESetWireToEvent,(Display* a,int b,SDL_X11_XESetWireToEventRetType c),(a,b,c),return)
SDL_X11_SYM(SDL_X11_XESetEventToWireRetType,XESetEventToWire,(Display* a,int b,SDL_X11_XESetEventToWireRetType c),(a,b,c),return)
SDL_X11_SYM(void,XRefreshKeyboardMapping,(XMappingEvent *a),(a),)
+SDL_X11_SYM(int,XQueryTree,(Display* a,Window b,Window* c,Window* d,Window** e,unsigned int* f),(a,b,c,d,e,f),return)
#if SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS
SDL_X11_SYM(Bool,XGetEventData,(Display* a,XGenericEventCookie* b),(a,b),return)
@@ -160,12 +169,16 @@ SDL_X11_SYM(void,XFreeEventData,(Display* a,XGenericEventCookie* b),(a,b),)
#endif
#if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
+SDL_X11_SYM(Bool,XkbQueryExtension,(Display* a,int * b,int * c,int * d,int * e, int *f),(a,b,c,d,e,f),return)
#if NeedWidePrototypes
SDL_X11_SYM(KeySym,XkbKeycodeToKeysym,(Display* a,unsigned int b,int c,int d),(a,b,c,d),return)
#else
SDL_X11_SYM(KeySym,XkbKeycodeToKeysym,(Display* a,KeyCode b,int c,int d),(a,b,c,d),return)
#endif
SDL_X11_SYM(Status,XkbGetState,(Display* a,unsigned int b,XkbStatePtr c),(a,b,c),return)
+SDL_X11_SYM(Status,XkbGetUpdatedMap,(Display* a,unsigned int b,XkbDescPtr c),(a,b,c),return)
+SDL_X11_SYM(XkbDescPtr,XkbGetMap,(Display* a,unsigned int b,unsigned int c),(a,b,c),return)
+SDL_X11_SYM(void,XkbFreeClientMap,(XkbDescPtr a,unsigned int b, Bool c),(a,b,c),)
#endif
#if NeedWidePrototypes
@@ -187,6 +200,8 @@ SDL_X11_SYM(XIM,XOpenIM,(Display* a,struct _XrmHashBucketRec* b,char* c,char* d)
SDL_X11_SYM(Status,XCloseIM,(XIM a),(a),return)
SDL_X11_SYM(void,Xutf8DrawString,(Display *a, Drawable b, XFontSet c, GC d, int e, int f, _Xconst char *g, int h),(a,b,c,d,e,f,g,h),)
SDL_X11_SYM(int,Xutf8TextExtents,(XFontSet a, _Xconst char* b, int c, XRectangle* d, XRectangle* e),(a,b,c,d,e),return)
+SDL_X11_SYM(char*,XSetLocaleModifiers,(const char *a),(a),return)
+SDL_X11_SYM(char*,Xutf8ResetIC,(XIC a),(a),return)
#endif
#ifndef NO_SHARED_MEMORY
@@ -311,6 +326,9 @@ SDL_X11_SYM(Bool,XF86VidModeSwitchToMode,(Display *a,int b,XF86VidModeModeInfo *
SDL_X11_SYM(Bool,XF86VidModeLockModeSwitch,(Display *a,int b,int c),(a,b,c),return)
#endif
+#undef SDL_X11_MODULE
+#undef SDL_X11_SYM
+
/* *INDENT-ON* */
/* vi: set ts=4 sw=4 expandtab: */
diff --git a/Engine/lib/sdl/src/video/x11/SDL_x11video.c b/Engine/lib/sdl/src/video/x11/SDL_x11video.c
index 01f8ae60f..38b34de34 100644
--- a/Engine/lib/sdl/src/video/x11/SDL_x11video.c
+++ b/Engine/lib/sdl/src/video/x11/SDL_x11video.c
@@ -39,6 +39,10 @@
#include "SDL_x11opengles.h"
#endif
+#ifdef X_HAVE_UTF8_STRING
+#include
+#endif
+
/* Initialization/Query functions */
static int X11_VideoInit(_THIS);
static void X11_VideoQuit(_THIS);
@@ -175,6 +179,8 @@ X11_CreateDevice(int devindex)
}
device->driverdata = data;
+ data->global_mouse_changed = SDL_TRUE;
+
/* FIXME: Do we need this?
if ( (SDL_strncmp(X11_XDisplayName(display), ":", 1) == 0) ||
(SDL_strncmp(X11_XDisplayName(display), "unix:", 5) == 0) ) {
@@ -216,6 +222,7 @@ X11_CreateDevice(int devindex)
device->VideoQuit = X11_VideoQuit;
device->GetDisplayModes = X11_GetDisplayModes;
device->GetDisplayBounds = X11_GetDisplayBounds;
+ device->GetDisplayUsableBounds = X11_GetDisplayUsableBounds;
device->GetDisplayDPI = X11_GetDisplayDPI;
device->SetDisplayMode = X11_SetDisplayMode;
device->SuspendScreenSaver = X11_SuspendScreenSaver;
@@ -229,6 +236,10 @@ X11_CreateDevice(int devindex)
device->SetWindowSize = X11_SetWindowSize;
device->SetWindowMinimumSize = X11_SetWindowMinimumSize;
device->SetWindowMaximumSize = X11_SetWindowMaximumSize;
+ device->GetWindowBordersSize = X11_GetWindowBordersSize;
+ device->SetWindowOpacity = X11_SetWindowOpacity;
+ device->SetWindowModalFor = X11_SetWindowModalFor;
+ device->SetWindowInputFocus = X11_SetWindowInputFocus;
device->ShowWindow = X11_ShowWindow;
device->HideWindow = X11_HideWindow;
device->RaiseWindow = X11_RaiseWindow;
@@ -236,6 +247,7 @@ X11_CreateDevice(int devindex)
device->MinimizeWindow = X11_MinimizeWindow;
device->RestoreWindow = X11_RestoreWindow;
device->SetWindowBordered = X11_SetWindowBordered;
+ device->SetWindowResizable = X11_SetWindowResizable;
device->SetWindowFullscreen = X11_SetWindowFullscreen;
device->SetWindowGammaRamp = X11_SetWindowGammaRamp;
device->SetWindowGrab = X11_SetWindowGrab;
@@ -278,7 +290,7 @@ X11_CreateDevice(int devindex)
device->StartTextInput = X11_StartTextInput;
device->StopTextInput = X11_StopTextInput;
device->SetTextInputRect = X11_SetTextInputRect;
-
+
device->free = X11_DeleteDevice;
return device;
@@ -373,11 +385,65 @@ X11_VideoInit(_THIS)
/* Get the process PID to be associated to the window */
data->pid = getpid();
+ /* I have no idea how random this actually is, or has to be. */
+ data->window_group = (XID) (((size_t) data->pid) ^ ((size_t) _this));
+
/* Open a connection to the X input manager */
#ifdef X_HAVE_UTF8_STRING
if (SDL_X11_HAVE_UTF8) {
- data->im =
- X11_XOpenIM(data->display, NULL, data->classname, data->classname);
+ /* Set the locale, and call XSetLocaleModifiers before XOpenIM so that
+ Compose keys will work correctly. */
+ char *prev_locale = setlocale(LC_ALL, NULL);
+ char *prev_xmods = X11_XSetLocaleModifiers(NULL);
+ const char *new_xmods = "";
+#if defined(HAVE_IBUS_IBUS_H) || defined(HAVE_FCITX_FRONTEND_H)
+ const char *env_xmods = SDL_getenv("XMODIFIERS");
+#endif
+ SDL_bool has_dbus_ime_support = SDL_FALSE;
+
+ if (prev_locale) {
+ prev_locale = SDL_strdup(prev_locale);
+ }
+
+ if (prev_xmods) {
+ prev_xmods = SDL_strdup(prev_xmods);
+ }
+
+ /* IBus resends some key events that were filtered by XFilterEvents
+ when it is used via XIM which causes issues. Prevent this by forcing
+ @im=none if XMODIFIERS contains @im=ibus. IBus can still be used via
+ the DBus implementation, which also has support for pre-editing. */
+#ifdef HAVE_IBUS_IBUS_H
+ if (env_xmods && SDL_strstr(env_xmods, "@im=ibus") != NULL) {
+ has_dbus_ime_support = SDL_TRUE;
+ }
+#endif
+#ifdef HAVE_FCITX_FRONTEND_H
+ if (env_xmods && SDL_strstr(env_xmods, "@im=fcitx") != NULL) {
+ has_dbus_ime_support = SDL_TRUE;
+ }
+#endif
+ if (has_dbus_ime_support) {
+ new_xmods = "@im=none";
+ }
+
+ setlocale(LC_ALL, "");
+ X11_XSetLocaleModifiers(new_xmods);
+
+ data->im = X11_XOpenIM(data->display, NULL, data->classname, data->classname);
+
+ /* Reset the locale + X locale modifiers back to how they were,
+ locale first because the X locale modifiers depend on it. */
+ setlocale(LC_ALL, prev_locale);
+ X11_XSetLocaleModifiers(prev_xmods);
+
+ if (prev_locale) {
+ SDL_free(prev_locale);
+ }
+
+ if (prev_xmods) {
+ SDL_free(prev_xmods);
+ }
}
#endif
@@ -385,19 +451,26 @@ X11_VideoInit(_THIS)
#define GET_ATOM(X) data->X = X11_XInternAtom(data->display, #X, False)
GET_ATOM(WM_PROTOCOLS);
GET_ATOM(WM_DELETE_WINDOW);
+ GET_ATOM(WM_TAKE_FOCUS);
GET_ATOM(_NET_WM_STATE);
GET_ATOM(_NET_WM_STATE_HIDDEN);
GET_ATOM(_NET_WM_STATE_FOCUSED);
GET_ATOM(_NET_WM_STATE_MAXIMIZED_VERT);
GET_ATOM(_NET_WM_STATE_MAXIMIZED_HORZ);
GET_ATOM(_NET_WM_STATE_FULLSCREEN);
+ GET_ATOM(_NET_WM_STATE_ABOVE);
+ GET_ATOM(_NET_WM_STATE_SKIP_TASKBAR);
+ GET_ATOM(_NET_WM_STATE_SKIP_PAGER);
GET_ATOM(_NET_WM_ALLOWED_ACTIONS);
GET_ATOM(_NET_WM_ACTION_FULLSCREEN);
GET_ATOM(_NET_WM_NAME);
GET_ATOM(_NET_WM_ICON_NAME);
GET_ATOM(_NET_WM_ICON);
GET_ATOM(_NET_WM_PING);
+ GET_ATOM(_NET_WM_WINDOW_OPACITY);
+ GET_ATOM(_NET_WM_USER_TIME);
GET_ATOM(_NET_ACTIVE_WINDOW);
+ GET_ATOM(_NET_FRAME_EXTENTS);
GET_ATOM(UTF8_STRING);
GET_ATOM(PRIMARY);
GET_ATOM(XdndEnter);
diff --git a/Engine/lib/sdl/src/video/x11/SDL_x11video.h b/Engine/lib/sdl/src/video/x11/SDL_x11video.h
index 2083defd2..a3324ff53 100644
--- a/Engine/lib/sdl/src/video/x11/SDL_x11video.h
+++ b/Engine/lib/sdl/src/video/x11/SDL_x11video.h
@@ -57,7 +57,7 @@
#endif
#include "../../core/linux/SDL_dbus.h"
-#include "../../core/linux/SDL_ibus.h"
+#include "../../core/linux/SDL_ime.h"
#include "SDL_x11dyn.h"
@@ -81,6 +81,7 @@ typedef struct SDL_VideoData
int numwindows;
SDL_WindowData **windowlist;
int windowlistlength;
+ XID window_group;
/* This is true for ICCCM2.0-compliant window managers */
SDL_bool net_wm;
@@ -88,19 +89,26 @@ typedef struct SDL_VideoData
/* Useful atoms */
Atom WM_PROTOCOLS;
Atom WM_DELETE_WINDOW;
+ Atom WM_TAKE_FOCUS;
Atom _NET_WM_STATE;
Atom _NET_WM_STATE_HIDDEN;
Atom _NET_WM_STATE_FOCUSED;
Atom _NET_WM_STATE_MAXIMIZED_VERT;
Atom _NET_WM_STATE_MAXIMIZED_HORZ;
Atom _NET_WM_STATE_FULLSCREEN;
+ Atom _NET_WM_STATE_ABOVE;
+ Atom _NET_WM_STATE_SKIP_TASKBAR;
+ Atom _NET_WM_STATE_SKIP_PAGER;
Atom _NET_WM_ALLOWED_ACTIONS;
Atom _NET_WM_ACTION_FULLSCREEN;
Atom _NET_WM_NAME;
Atom _NET_WM_ICON_NAME;
Atom _NET_WM_ICON;
Atom _NET_WM_PING;
+ Atom _NET_WM_WINDOW_OPACITY;
+ Atom _NET_WM_USER_TIME;
Atom _NET_ACTIVE_WINDOW;
+ Atom _NET_FRAME_EXTENTS;
Atom UTF8_STRING;
Atom PRIMARY;
Atom XdndEnter;
@@ -117,6 +125,14 @@ typedef struct SDL_VideoData
SDL_bool selection_waiting;
Uint32 last_mode_change_deadline;
+
+ SDL_bool global_mouse_changed;
+ SDL_Point global_mouse_position;
+ Uint32 global_mouse_buttons;
+
+#if SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM
+ XkbDescPtr xkb;
+#endif
} SDL_VideoData;
extern SDL_bool X11_UseDirectColorVisuals(void);
diff --git a/Engine/lib/sdl/src/video/x11/SDL_x11window.c b/Engine/lib/sdl/src/video/x11/SDL_x11window.c
index afc802198..668bce225 100644
--- a/Engine/lib/sdl/src/video/x11/SDL_x11window.c
+++ b/Engine/lib/sdl/src/video/x11/SDL_x11window.c
@@ -130,13 +130,17 @@ X11_SetNetWMState(_THIS, Window xwindow, Uint32 flags)
{
SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata;
Display *display = videodata->display;
+ /* !!! FIXME: just dereference videodata below instead of copying to locals. */
Atom _NET_WM_STATE = videodata->_NET_WM_STATE;
/* Atom _NET_WM_STATE_HIDDEN = videodata->_NET_WM_STATE_HIDDEN; */
Atom _NET_WM_STATE_FOCUSED = videodata->_NET_WM_STATE_FOCUSED;
Atom _NET_WM_STATE_MAXIMIZED_VERT = videodata->_NET_WM_STATE_MAXIMIZED_VERT;
Atom _NET_WM_STATE_MAXIMIZED_HORZ = videodata->_NET_WM_STATE_MAXIMIZED_HORZ;
Atom _NET_WM_STATE_FULLSCREEN = videodata->_NET_WM_STATE_FULLSCREEN;
- Atom atoms[5];
+ Atom _NET_WM_STATE_ABOVE = videodata->_NET_WM_STATE_ABOVE;
+ Atom _NET_WM_STATE_SKIP_TASKBAR = videodata->_NET_WM_STATE_SKIP_TASKBAR;
+ Atom _NET_WM_STATE_SKIP_PAGER = videodata->_NET_WM_STATE_SKIP_PAGER;
+ Atom atoms[16];
int count = 0;
/* The window manager sets this property, we shouldn't set it.
@@ -147,6 +151,14 @@ X11_SetNetWMState(_THIS, Window xwindow, Uint32 flags)
atoms[count++] = _NET_WM_STATE_HIDDEN;
}
*/
+
+ if (flags & SDL_WINDOW_ALWAYS_ON_TOP) {
+ atoms[count++] = _NET_WM_STATE_ABOVE;
+ }
+ if (flags & SDL_WINDOW_SKIP_TASKBAR) {
+ atoms[count++] = _NET_WM_STATE_SKIP_TASKBAR;
+ atoms[count++] = _NET_WM_STATE_SKIP_PAGER;
+ }
if (flags & SDL_WINDOW_INPUT_FOCUS) {
atoms[count++] = _NET_WM_STATE_FOCUSED;
}
@@ -157,6 +169,9 @@ X11_SetNetWMState(_THIS, Window xwindow, Uint32 flags)
if (flags & SDL_WINDOW_FULLSCREEN) {
atoms[count++] = _NET_WM_STATE_FULLSCREEN;
}
+
+ SDL_assert(count <= SDL_arraysize(atoms));
+
if (count > 0) {
X11_XChangeProperty(display, xwindow, _NET_WM_STATE, XA_ATOM, 32,
PropModeReplace, (unsigned char *)atoms, count);
@@ -206,7 +221,9 @@ X11_GetNetWMState(_THIS, Window xwindow)
}
if (maximized == 3) {
flags |= SDL_WINDOW_MAXIMIZED;
- } else if (fullscreen == 1) {
+ }
+
+ if (fullscreen == 1) {
flags |= SDL_WINDOW_FULLSCREEN;
}
X11_XFree(propertyValue);
@@ -355,10 +372,11 @@ X11_CreateWindow(_THIS, SDL_Window * window)
XSizeHints *sizehints;
XWMHints *wmhints;
XClassHint *classhints;
- const long _NET_WM_BYPASS_COMPOSITOR_HINT_ON = 1;
Atom _NET_WM_BYPASS_COMPOSITOR;
Atom _NET_WM_WINDOW_TYPE;
- Atom _NET_WM_WINDOW_TYPE_NORMAL;
+ Atom wintype;
+ const char *wintype_name = NULL;
+ int compositor = 1;
Atom _NET_WM_PID;
Atom XdndAware, xdnd_version = 5;
long fevent = 0;
@@ -396,7 +414,7 @@ X11_CreateWindow(_THIS, SDL_Window * window)
depth = displaydata->depth;
}
- xattr.override_redirect = False;
+ xattr.override_redirect = ((window->flags & SDL_WINDOW_TOOLTIP) || (window->flags & SDL_WINDOW_POPUP_MENU)) ? True : False;
xattr.background_pixmap = None;
xattr.border_pixel = 0;
@@ -506,7 +524,8 @@ X11_CreateWindow(_THIS, SDL_Window * window)
/* Setup the input hints so we get keyboard input */
wmhints = X11_XAllocWMHints();
wmhints->input = True;
- wmhints->flags = InputHint;
+ wmhints->window_group = data->window_group;
+ wmhints->flags = InputHint | WindowGroupHint;
/* Setup the class hints so we can get an icon (AfterStep) */
classhints = X11_XAllocClassHint();
@@ -521,39 +540,49 @@ X11_CreateWindow(_THIS, SDL_Window * window)
X11_XFree(classhints);
/* Set the PID related to the window for the given hostname, if possible */
if (data->pid > 0) {
+ long pid = (long) data->pid;
_NET_WM_PID = X11_XInternAtom(display, "_NET_WM_PID", False);
X11_XChangeProperty(display, w, _NET_WM_PID, XA_CARDINAL, 32, PropModeReplace,
- (unsigned char *)&data->pid, 1);
+ (unsigned char *) &pid, 1);
}
/* Set the window manager state */
X11_SetNetWMState(_this, w, window->flags);
- /* Let the window manager know we're a "normal" window */
+ compositor = 2; /* don't disable compositing except for "normal" windows */
+
+ if (window->flags & SDL_WINDOW_UTILITY) {
+ wintype_name = "_NET_WM_WINDOW_TYPE_UTILITY";
+ } else if (window->flags & SDL_WINDOW_TOOLTIP) {
+ wintype_name = "_NET_WM_WINDOW_TYPE_TOOLTIP";
+ } else if (window->flags & SDL_WINDOW_POPUP_MENU) {
+ wintype_name = "_NET_WM_WINDOW_TYPE_POPUP_MENU";
+ } else {
+ wintype_name = "_NET_WM_WINDOW_TYPE_NORMAL";
+ compositor = 1; /* disable compositing for "normal" windows */
+ }
+
+ /* Let the window manager know what type of window we are. */
_NET_WM_WINDOW_TYPE = X11_XInternAtom(display, "_NET_WM_WINDOW_TYPE", False);
- _NET_WM_WINDOW_TYPE_NORMAL = X11_XInternAtom(display, "_NET_WM_WINDOW_TYPE_NORMAL", False);
+ wintype = X11_XInternAtom(display, wintype_name, False);
X11_XChangeProperty(display, w, _NET_WM_WINDOW_TYPE, XA_ATOM, 32,
- PropModeReplace,
- (unsigned char *)&_NET_WM_WINDOW_TYPE_NORMAL, 1);
+ PropModeReplace, (unsigned char *)&wintype, 1);
_NET_WM_BYPASS_COMPOSITOR = X11_XInternAtom(display, "_NET_WM_BYPASS_COMPOSITOR", False);
X11_XChangeProperty(display, w, _NET_WM_BYPASS_COMPOSITOR, XA_CARDINAL, 32,
PropModeReplace,
- (unsigned char *)&_NET_WM_BYPASS_COMPOSITOR_HINT_ON, 1);
+ (unsigned char *)&compositor, 1);
{
- Atom protocols[2];
+ Atom protocols[3];
int proto_count = 0;
- const char *ping_hint;
- protocols[proto_count] = data->WM_DELETE_WINDOW; /* Allow window to be deleted by the WM */
- proto_count++;
-
- ping_hint = SDL_GetHint(SDL_HINT_VIDEO_X11_NET_WM_PING);
+ protocols[proto_count++] = data->WM_DELETE_WINDOW; /* Allow window to be deleted by the WM */
+ protocols[proto_count++] = data->WM_TAKE_FOCUS; /* Since we will want to set input focus explicitly */
+
/* Default to using ping if there is no hint */
- if (!ping_hint || SDL_atoi(ping_hint)) {
- protocols[proto_count] = data->_NET_WM_PING; /* Respond so WM knows we're alive */
- proto_count++;
+ if (SDL_GetHintBoolean(SDL_HINT_VIDEO_X11_NET_WM_PING, SDL_TRUE)) {
+ protocols[proto_count++] = data->_NET_WM_PING; /* Respond so WM knows we're alive */
}
SDL_assert(proto_count <= sizeof(protocols) / sizeof(protocols[0]));
@@ -750,7 +779,7 @@ X11_SetWindowPosition(_THIS, SDL_Window * window)
SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
Display *display = data->videodata->display;
- X11_XMoveWindow(display, data->xwindow, window->x, window->y);
+ X11_XMoveWindow(display, data->xwindow, window->x - data->border_left, window->y - data->border_top);
X11_XFlush(display);
}
@@ -776,7 +805,7 @@ X11_SetWindowMinimumSize(_THIS, SDL_Window * window)
/* See comment in X11_SetWindowSize. */
X11_XResizeWindow(display, data->xwindow, window->w, window->h);
- X11_XMoveWindow(display, data->xwindow, window->x, window->y);
+ X11_XMoveWindow(display, data->xwindow, window->x - data->border_left, window->y - data->border_top);
X11_XRaiseWindow(display, data->xwindow);
}
@@ -805,7 +834,7 @@ X11_SetWindowMaximumSize(_THIS, SDL_Window * window)
/* See comment in X11_SetWindowSize. */
X11_XResizeWindow(display, data->xwindow, window->w, window->h);
- X11_XMoveWindow(display, data->xwindow, window->x, window->y);
+ X11_XMoveWindow(display, data->xwindow, window->x - data->border_left, window->y - data->border_top);
X11_XRaiseWindow(display, data->xwindow);
}
@@ -854,7 +883,7 @@ X11_SetWindowSize(_THIS, SDL_Window * window)
and transitioning from windowed to fullscreen in Unity.
*/
X11_XResizeWindow(display, data->xwindow, window->w, window->h);
- X11_XMoveWindow(display, data->xwindow, window->x, window->y);
+ X11_XMoveWindow(display, data->xwindow, window->x - data->border_left, window->y - data->border_top);
X11_XRaiseWindow(display, data->xwindow);
} else {
X11_XResizeWindow(display, data->xwindow, window->w, window->h);
@@ -863,6 +892,61 @@ X11_SetWindowSize(_THIS, SDL_Window * window)
X11_XFlush(display);
}
+int
+X11_GetWindowBordersSize(_THIS, SDL_Window * window, int *top, int *left, int *bottom, int *right)
+{
+ SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
+
+ *left = data->border_left;
+ *right = data->border_right;
+ *top = data->border_top;
+ *bottom = data->border_bottom;
+
+ return 0;
+}
+
+int
+X11_SetWindowOpacity(_THIS, SDL_Window * window, float opacity)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ Display *display = data->videodata->display;
+ Atom _NET_WM_WINDOW_OPACITY = data->videodata->_NET_WM_WINDOW_OPACITY;
+
+ if (opacity == 1.0f) {
+ X11_XDeleteProperty(display, data->xwindow, _NET_WM_WINDOW_OPACITY);
+ } else {
+ const Uint32 FullyOpaque = 0xFFFFFFFF;
+ const long alpha = (long) ((double)opacity * (double)FullyOpaque);
+ X11_XChangeProperty(display, data->xwindow, _NET_WM_WINDOW_OPACITY, XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char *)&alpha, 1);
+ }
+
+ return 0;
+}
+
+int
+X11_SetWindowModalFor(_THIS, SDL_Window * modal_window, SDL_Window * parent_window) {
+ SDL_WindowData *data = (SDL_WindowData *) modal_window->driverdata;
+ SDL_WindowData *parent_data = (SDL_WindowData *) parent_window->driverdata;
+ Display *display = data->videodata->display;
+
+ X11_XSetTransientForHint(display, data->xwindow, parent_data->xwindow);
+ return 0;
+}
+
+int
+X11_SetWindowInputFocus(_THIS, SDL_Window * window)
+{
+ if (X11_IsWindowMapped(_this, window)) {
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ Display *display = data->videodata->display;
+ X11_XSetInputFocus(display, data->xwindow, RevertToNone, CurrentTime);
+ X11_XFlush(display);
+ return 0;
+ }
+ return -1;
+}
+
void
X11_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
{
@@ -895,6 +979,44 @@ X11_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered)
X11_XCheckIfEvent(display, &event, &isMapNotify, (XPointer)&data->xwindow);
}
+void
+X11_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable)
+{
+ SDL_WindowData *data = (SDL_WindowData *) window->driverdata;
+ Display *display = data->videodata->display;
+
+ XSizeHints *sizehints = X11_XAllocSizeHints();
+ long userhints;
+
+ X11_XGetWMNormalHints(display, data->xwindow, sizehints, &userhints);
+
+ if (resizable) {
+ /* FIXME: Is there a better way to get max window size from X? -flibit */
+ const int maxsize = 0x7FFFFFFF;
+ sizehints->min_width = window->min_w;
+ sizehints->min_height = window->min_h;
+ sizehints->max_width = (window->max_w == 0) ? maxsize : window->max_w;
+ sizehints->max_height = (window->max_h == 0) ? maxsize : window->max_h;
+ } else {
+ sizehints->min_width = window->w;
+ sizehints->min_height = window->h;
+ sizehints->max_width = window->w;
+ sizehints->max_height = window->h;
+ }
+ sizehints->flags |= PMinSize | PMaxSize;
+
+ X11_XSetWMNormalHints(display, data->xwindow, sizehints);
+
+ X11_XFree(sizehints);
+
+ /* See comment in X11_SetWindowSize. */
+ X11_XResizeWindow(display, data->xwindow, window->w, window->h);
+ X11_XMoveWindow(display, data->xwindow, window->x - data->border_left, window->y - data->border_top);
+ X11_XRaiseWindow(display, data->xwindow);
+
+ X11_XFlush(display);
+}
+
void
X11_ShowWindow(_THIS, SDL_Window * window)
{
@@ -946,13 +1068,15 @@ SetWindowActive(_THIS, SDL_Window * window)
if (X11_IsWindowMapped(_this, window)) {
XEvent e;
+ /*printf("SDL Window %p: sending _NET_ACTIVE_WINDOW with timestamp %lu\n", window, data->user_time);*/
+
SDL_zero(e);
e.xany.type = ClientMessage;
e.xclient.message_type = _NET_ACTIVE_WINDOW;
e.xclient.format = 32;
e.xclient.window = data->xwindow;
e.xclient.data.l[0] = 1; /* source indication. 1 = application */
- e.xclient.data.l[1] = CurrentTime;
+ e.xclient.data.l[1] = data->user_time;
e.xclient.data.l[2] = 0;
X11_XSendEvent(display, RootWindow(display, displaydata->screen), 0,
@@ -1038,7 +1162,7 @@ X11_RestoreWindow(_THIS, SDL_Window * window)
SetWindowActive(_this, window);
}
-/* This asks the Window Manager to handle fullscreen for us. Most don't do it right, though. */
+/* This asks the Window Manager to handle fullscreen for us. This is the modern way. */
static void
X11_SetWindowFullscreenViaWM(_THIS, SDL_Window * window, SDL_VideoDisplay * _display, SDL_bool fullscreen)
{
@@ -1083,6 +1207,22 @@ X11_SetWindowFullscreenViaWM(_THIS, SDL_Window * window, SDL_VideoDisplay * _dis
X11_XSendEvent(display, RootWindow(display, displaydata->screen), 0,
SubstructureNotifyMask | SubstructureRedirectMask, &e);
+
+ /* Fullscreen windows sometimes end up being marked maximized by
+ window managers. Force it back to how we expect it to be. */
+ if (!fullscreen && ((window->flags & SDL_WINDOW_MAXIMIZED) == 0)) {
+ SDL_zero(e);
+ e.xany.type = ClientMessage;
+ e.xclient.message_type = _NET_WM_STATE;
+ e.xclient.format = 32;
+ e.xclient.window = data->xwindow;
+ e.xclient.data.l[0] = _NET_WM_STATE_REMOVE;
+ e.xclient.data.l[1] = data->videodata->_NET_WM_STATE_MAXIMIZED_VERT;
+ e.xclient.data.l[2] = data->videodata->_NET_WM_STATE_MAXIMIZED_HORZ;
+ e.xclient.data.l[3] = 0l;
+ X11_XSendEvent(display, RootWindow(display, displaydata->screen), 0,
+ SubstructureNotifyMask | SubstructureRedirectMask, &e);
+ }
} else {
Uint32 flags;
@@ -1335,7 +1475,6 @@ X11_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
Display *display = data->videodata->display;
SDL_bool oldstyle_fullscreen;
SDL_bool grab_keyboard;
- const char *hint;
/* ICCCM2.0-compliant window managers can handle fullscreen windows
If we're using XVidMode to change resolution we need to confine
@@ -1359,8 +1498,7 @@ X11_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed)
X11_XRaiseWindow(display, data->xwindow);
/* Now grab the keyboard */
- hint = SDL_GetHint(SDL_HINT_GRAB_KEYBOARD);
- if (hint && SDL_atoi(hint)) {
+ if (SDL_GetHintBoolean(SDL_HINT_GRAB_KEYBOARD, SDL_FALSE)) {
grab_keyboard = SDL_TRUE;
} else {
/* We need to do this with the old style override_redirect
diff --git a/Engine/lib/sdl/src/video/x11/SDL_x11window.h b/Engine/lib/sdl/src/video/x11/SDL_x11window.h
index efe7ec0f0..50a739dad 100644
--- a/Engine/lib/sdl/src/video/x11/SDL_x11window.h
+++ b/Engine/lib/sdl/src/video/x11/SDL_x11window.h
@@ -56,10 +56,16 @@ typedef struct
GC gc;
XIC ic;
SDL_bool created;
+ int border_left;
+ int border_right;
+ int border_top;
+ int border_bottom;
+ Uint32 last_focus_event_time;
PendingFocusEnum pending_focus;
Uint32 pending_focus_time;
XConfigureEvent last_xconfigure;
struct SDL_VideoData *videodata;
+ unsigned long user_time;
Atom xdnd_req;
Window xdnd_source;
#if SDL_VIDEO_OPENGL_EGL
@@ -78,6 +84,10 @@ extern void X11_SetWindowIcon(_THIS, SDL_Window * window, SDL_Surface * icon);
extern void X11_SetWindowPosition(_THIS, SDL_Window * window);
extern void X11_SetWindowMinimumSize(_THIS, SDL_Window * window);
extern void X11_SetWindowMaximumSize(_THIS, SDL_Window * window);
+extern int X11_GetWindowBordersSize(_THIS, SDL_Window * window, int *top, int *left, int *bottom, int *right);
+extern int X11_SetWindowOpacity(_THIS, SDL_Window * window, float opacity);
+extern int X11_SetWindowModalFor(_THIS, SDL_Window * modal_window, SDL_Window * parent_window);
+extern int X11_SetWindowInputFocus(_THIS, SDL_Window * window);
extern void X11_SetWindowSize(_THIS, SDL_Window * window);
extern void X11_ShowWindow(_THIS, SDL_Window * window);
extern void X11_HideWindow(_THIS, SDL_Window * window);
@@ -86,6 +96,7 @@ extern void X11_MaximizeWindow(_THIS, SDL_Window * window);
extern void X11_MinimizeWindow(_THIS, SDL_Window * window);
extern void X11_RestoreWindow(_THIS, SDL_Window * window);
extern void X11_SetWindowBordered(_THIS, SDL_Window * window, SDL_bool bordered);
+extern void X11_SetWindowResizable(_THIS, SDL_Window * window, SDL_bool resizable);
extern void X11_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * display, SDL_bool fullscreen);
extern int X11_SetWindowGammaRamp(_THIS, SDL_Window * window, const Uint16 * ramp);
extern void X11_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed);
diff --git a/Engine/lib/sdl/src/video/x11/SDL_x11xinput2.c b/Engine/lib/sdl/src/video/x11/SDL_x11xinput2.c
index 57132fe9e..bed4234f0 100644
--- a/Engine/lib/sdl/src/video/x11/SDL_x11xinput2.c
+++ b/Engine/lib/sdl/src/video/x11/SDL_x11xinput2.c
@@ -118,6 +118,8 @@ X11_InitXinput2(_THIS)
eventmask.mask = mask;
XISetMask(mask, XI_RawMotion);
+ XISetMask(mask, XI_RawButtonPress);
+ XISetMask(mask, XI_RawButtonRelease);
if (X11_XISelectEvents(data->display,DefaultRootWindow(data->display),&eventmask,1) != Success) {
return;
@@ -140,6 +142,8 @@ X11_HandleXinput2Event(SDL_VideoData *videodata,XGenericEventCookie *cookie)
static Time prev_time = 0;
static double prev_rel_coords[2];
+ videodata->global_mouse_changed = SDL_TRUE;
+
if (!mouse->relative_mode || mouse->relative_mode_warp) {
return 0;
}
@@ -158,6 +162,12 @@ X11_HandleXinput2Event(SDL_VideoData *videodata,XGenericEventCookie *cookie)
return 1;
}
break;
+
+ case XI_RawButtonPress:
+ case XI_RawButtonRelease:
+ videodata->global_mouse_changed = SDL_TRUE;
+ break;
+
#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH
case XI_TouchBegin: {
const XIDeviceEvent *xev = (const XIDeviceEvent *) cookie->data;
diff --git a/Engine/lib/sdl/src/video/x11/edid-parse.c b/Engine/lib/sdl/src/video/x11/edid-parse.c
index 2c145e23c..57f225b85 100644
--- a/Engine/lib/sdl/src/video/x11/edid-parse.c
+++ b/Engine/lib/sdl/src/video/x11/edid-parse.c
@@ -21,6 +21,8 @@
*/
/* Author: Soren Sandmann */
+#include "../../SDL_internal.h"
+#include "SDL_stdinc.h"
#include "edid.h"
#include
@@ -247,7 +249,7 @@ decode_fraction (int high, int low)
high = (high << 2) | low;
for (i = 0; i < 10; ++i)
- result += get_bit (high, i) * pow (2, i - 10);
+ result += get_bit (high, i) * SDL_pow (2, i - 10);
return result;
}
diff --git a/Engine/lib/sdl/src/video/x11/imKStoUCS.c b/Engine/lib/sdl/src/video/x11/imKStoUCS.c
index e4f086464..40e224243 100644
--- a/Engine/lib/sdl/src/video/x11/imKStoUCS.c
+++ b/Engine/lib/sdl/src/video/x11/imKStoUCS.c
@@ -1,297 +1,296 @@
-/* Copyright (C) 1994-2003 The XFree86 Project, Inc. All Rights Reserved.
+/*
+Copyright (C) 2003-2006,2008 Jamey Sharp, Josh Triplett
+Copyright © 2009 Red Hat, Inc.
+Copyright 1990-1992,1999,2000,2004,2009,2010 Oracle and/or its affiliates.
+All rights reserved.
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is fur-
-nished to do so, subject to the following conditions:
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
-NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
-NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of the XFree86 Project shall not
-be used in advertising or otherwise to promote the sale, use or other deal-
-ings in this Software without prior written authorization from the XFree86
-Project.
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
*/
+
#include "../../SDL_internal.h"
#if SDL_VIDEO_DRIVER_X11
-
-/* $XFree86: xc/lib/X11/imKStoUCS.c,v 1.4 2003/04/29 11:29:18 pascal Exp $ */
-
#include
#include "imKStoUCS.h"
static unsigned short const keysym_to_unicode_1a1_1ff[] = {
- 0x0104, 0x02d8, 0x0141, 0x0000, 0x013d, 0x015a, 0x0000, /* 0x01a0-0x01a7 */
- 0x0000, 0x0160, 0x015e, 0x0164, 0x0179, 0x0000, 0x017d, 0x017b, /* 0x01a8-0x01af */
- 0x0000, 0x0105, 0x02db, 0x0142, 0x0000, 0x013e, 0x015b, 0x02c7, /* 0x01b0-0x01b7 */
- 0x0000, 0x0161, 0x015f, 0x0165, 0x017a, 0x02dd, 0x017e, 0x017c, /* 0x01b8-0x01bf */
- 0x0154, 0x0000, 0x0000, 0x0102, 0x0000, 0x0139, 0x0106, 0x0000, /* 0x01c0-0x01c7 */
- 0x010c, 0x0000, 0x0118, 0x0000, 0x011a, 0x0000, 0x0000, 0x010e, /* 0x01c8-0x01cf */
- 0x0110, 0x0143, 0x0147, 0x0000, 0x0000, 0x0150, 0x0000, 0x0000, /* 0x01d0-0x01d7 */
- 0x0158, 0x016e, 0x0000, 0x0170, 0x0000, 0x0000, 0x0162, 0x0000, /* 0x01d8-0x01df */
- 0x0155, 0x0000, 0x0000, 0x0103, 0x0000, 0x013a, 0x0107, 0x0000, /* 0x01e0-0x01e7 */
- 0x010d, 0x0000, 0x0119, 0x0000, 0x011b, 0x0000, 0x0000, 0x010f, /* 0x01e8-0x01ef */
- 0x0111, 0x0144, 0x0148, 0x0000, 0x0000, 0x0151, 0x0000, 0x0000, /* 0x01f0-0x01f7 */
- 0x0159, 0x016f, 0x0000, 0x0171, 0x0000, 0x0000, 0x0163, 0x02d9 /* 0x01f8-0x01ff */
+ 0x0104, 0x02d8, 0x0141, 0x0000, 0x013d, 0x015a, 0x0000, /* 0x01a0-0x01a7 */
+ 0x0000, 0x0160, 0x015e, 0x0164, 0x0179, 0x0000, 0x017d, 0x017b, /* 0x01a8-0x01af */
+ 0x0000, 0x0105, 0x02db, 0x0142, 0x0000, 0x013e, 0x015b, 0x02c7, /* 0x01b0-0x01b7 */
+ 0x0000, 0x0161, 0x015f, 0x0165, 0x017a, 0x02dd, 0x017e, 0x017c, /* 0x01b8-0x01bf */
+ 0x0154, 0x0000, 0x0000, 0x0102, 0x0000, 0x0139, 0x0106, 0x0000, /* 0x01c0-0x01c7 */
+ 0x010c, 0x0000, 0x0118, 0x0000, 0x011a, 0x0000, 0x0000, 0x010e, /* 0x01c8-0x01cf */
+ 0x0110, 0x0143, 0x0147, 0x0000, 0x0000, 0x0150, 0x0000, 0x0000, /* 0x01d0-0x01d7 */
+ 0x0158, 0x016e, 0x0000, 0x0170, 0x0000, 0x0000, 0x0162, 0x0000, /* 0x01d8-0x01df */
+ 0x0155, 0x0000, 0x0000, 0x0103, 0x0000, 0x013a, 0x0107, 0x0000, /* 0x01e0-0x01e7 */
+ 0x010d, 0x0000, 0x0119, 0x0000, 0x011b, 0x0000, 0x0000, 0x010f, /* 0x01e8-0x01ef */
+ 0x0111, 0x0144, 0x0148, 0x0000, 0x0000, 0x0151, 0x0000, 0x0000, /* 0x01f0-0x01f7 */
+ 0x0159, 0x016f, 0x0000, 0x0171, 0x0000, 0x0000, 0x0163, 0x02d9 /* 0x01f8-0x01ff */
};
static unsigned short const keysym_to_unicode_2a1_2fe[] = {
- 0x0126, 0x0000, 0x0000, 0x0000, 0x0000, 0x0124, 0x0000, /* 0x02a0-0x02a7 */
- 0x0000, 0x0130, 0x0000, 0x011e, 0x0134, 0x0000, 0x0000, 0x0000, /* 0x02a8-0x02af */
- 0x0000, 0x0127, 0x0000, 0x0000, 0x0000, 0x0000, 0x0125, 0x0000, /* 0x02b0-0x02b7 */
- 0x0000, 0x0131, 0x0000, 0x011f, 0x0135, 0x0000, 0x0000, 0x0000, /* 0x02b8-0x02bf */
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x010a, 0x0108, 0x0000, /* 0x02c0-0x02c7 */
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x02c8-0x02cf */
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0120, 0x0000, 0x0000, /* 0x02d0-0x02d7 */
- 0x011c, 0x0000, 0x0000, 0x0000, 0x0000, 0x016c, 0x015c, 0x0000, /* 0x02d8-0x02df */
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x010b, 0x0109, 0x0000, /* 0x02e0-0x02e7 */
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x02e8-0x02ef */
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0121, 0x0000, 0x0000, /* 0x02f0-0x02f7 */
- 0x011d, 0x0000, 0x0000, 0x0000, 0x0000, 0x016d, 0x015d /* 0x02f8-0x02ff */
+ 0x0126, 0x0000, 0x0000, 0x0000, 0x0000, 0x0124, 0x0000, /* 0x02a0-0x02a7 */
+ 0x0000, 0x0130, 0x0000, 0x011e, 0x0134, 0x0000, 0x0000, 0x0000, /* 0x02a8-0x02af */
+ 0x0000, 0x0127, 0x0000, 0x0000, 0x0000, 0x0000, 0x0125, 0x0000, /* 0x02b0-0x02b7 */
+ 0x0000, 0x0131, 0x0000, 0x011f, 0x0135, 0x0000, 0x0000, 0x0000, /* 0x02b8-0x02bf */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x010a, 0x0108, 0x0000, /* 0x02c0-0x02c7 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x02c8-0x02cf */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0120, 0x0000, 0x0000, /* 0x02d0-0x02d7 */
+ 0x011c, 0x0000, 0x0000, 0x0000, 0x0000, 0x016c, 0x015c, 0x0000, /* 0x02d8-0x02df */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x010b, 0x0109, 0x0000, /* 0x02e0-0x02e7 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x02e8-0x02ef */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0121, 0x0000, 0x0000, /* 0x02f0-0x02f7 */
+ 0x011d, 0x0000, 0x0000, 0x0000, 0x0000, 0x016d, 0x015d /* 0x02f8-0x02ff */
};
static unsigned short const keysym_to_unicode_3a2_3fe[] = {
- 0x0138, 0x0156, 0x0000, 0x0128, 0x013b, 0x0000, /* 0x03a0-0x03a7 */
- 0x0000, 0x0000, 0x0112, 0x0122, 0x0166, 0x0000, 0x0000, 0x0000, /* 0x03a8-0x03af */
- 0x0000, 0x0000, 0x0000, 0x0157, 0x0000, 0x0129, 0x013c, 0x0000, /* 0x03b0-0x03b7 */
- 0x0000, 0x0000, 0x0113, 0x0123, 0x0167, 0x014a, 0x0000, 0x014b, /* 0x03b8-0x03bf */
- 0x0100, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x012e, /* 0x03c0-0x03c7 */
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0116, 0x0000, 0x0000, 0x012a, /* 0x03c8-0x03cf */
- 0x0000, 0x0145, 0x014c, 0x0136, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x03d0-0x03d7 */
- 0x0000, 0x0172, 0x0000, 0x0000, 0x0000, 0x0168, 0x016a, 0x0000, /* 0x03d8-0x03df */
- 0x0101, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x012f, /* 0x03e0-0x03e7 */
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0117, 0x0000, 0x0000, 0x012b, /* 0x03e8-0x03ef */
- 0x0000, 0x0146, 0x014d, 0x0137, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x03f0-0x03f7 */
- 0x0000, 0x0173, 0x0000, 0x0000, 0x0000, 0x0169, 0x016b /* 0x03f8-0x03ff */
+ 0x0138, 0x0156, 0x0000, 0x0128, 0x013b, 0x0000, /* 0x03a0-0x03a7 */
+ 0x0000, 0x0000, 0x0112, 0x0122, 0x0166, 0x0000, 0x0000, 0x0000, /* 0x03a8-0x03af */
+ 0x0000, 0x0000, 0x0000, 0x0157, 0x0000, 0x0129, 0x013c, 0x0000, /* 0x03b0-0x03b7 */
+ 0x0000, 0x0000, 0x0113, 0x0123, 0x0167, 0x014a, 0x0000, 0x014b, /* 0x03b8-0x03bf */
+ 0x0100, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x012e, /* 0x03c0-0x03c7 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0116, 0x0000, 0x0000, 0x012a, /* 0x03c8-0x03cf */
+ 0x0000, 0x0145, 0x014c, 0x0136, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x03d0-0x03d7 */
+ 0x0000, 0x0172, 0x0000, 0x0000, 0x0000, 0x0168, 0x016a, 0x0000, /* 0x03d8-0x03df */
+ 0x0101, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x012f, /* 0x03e0-0x03e7 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0117, 0x0000, 0x0000, 0x012b, /* 0x03e8-0x03ef */
+ 0x0000, 0x0146, 0x014d, 0x0137, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x03f0-0x03f7 */
+ 0x0000, 0x0173, 0x0000, 0x0000, 0x0000, 0x0169, 0x016b /* 0x03f8-0x03ff */
};
static unsigned short const keysym_to_unicode_4a1_4df[] = {
- 0x3002, 0x3008, 0x3009, 0x3001, 0x30fb, 0x30f2, 0x30a1, /* 0x04a0-0x04a7 */
- 0x30a3, 0x30a5, 0x30a7, 0x30a9, 0x30e3, 0x30e5, 0x30e7, 0x30c3, /* 0x04a8-0x04af */
- 0x30fc, 0x30a2, 0x30a4, 0x30a6, 0x30a8, 0x30aa, 0x30ab, 0x30ad, /* 0x04b0-0x04b7 */
- 0x30af, 0x30b1, 0x30b3, 0x30b5, 0x30b7, 0x30b9, 0x30bb, 0x30bd, /* 0x04b8-0x04bf */
- 0x30bf, 0x30c1, 0x30c4, 0x30c6, 0x30c8, 0x30ca, 0x30cb, 0x30cc, /* 0x04c0-0x04c7 */
- 0x30cd, 0x30ce, 0x30cf, 0x30d2, 0x30d5, 0x30d8, 0x30db, 0x30de, /* 0x04c8-0x04cf */
- 0x30df, 0x30e0, 0x30e1, 0x30e2, 0x30e4, 0x30e6, 0x30e8, 0x30e9, /* 0x04d0-0x04d7 */
- 0x30ea, 0x30eb, 0x30ec, 0x30ed, 0x30ef, 0x30f3, 0x309b, 0x309c /* 0x04d8-0x04df */
+ 0x3002, 0x3008, 0x3009, 0x3001, 0x30fb, 0x30f2, 0x30a1, /* 0x04a0-0x04a7 */
+ 0x30a3, 0x30a5, 0x30a7, 0x30a9, 0x30e3, 0x30e5, 0x30e7, 0x30c3, /* 0x04a8-0x04af */
+ 0x30fc, 0x30a2, 0x30a4, 0x30a6, 0x30a8, 0x30aa, 0x30ab, 0x30ad, /* 0x04b0-0x04b7 */
+ 0x30af, 0x30b1, 0x30b3, 0x30b5, 0x30b7, 0x30b9, 0x30bb, 0x30bd, /* 0x04b8-0x04bf */
+ 0x30bf, 0x30c1, 0x30c4, 0x30c6, 0x30c8, 0x30ca, 0x30cb, 0x30cc, /* 0x04c0-0x04c7 */
+ 0x30cd, 0x30ce, 0x30cf, 0x30d2, 0x30d5, 0x30d8, 0x30db, 0x30de, /* 0x04c8-0x04cf */
+ 0x30df, 0x30e0, 0x30e1, 0x30e2, 0x30e4, 0x30e6, 0x30e8, 0x30e9, /* 0x04d0-0x04d7 */
+ 0x30ea, 0x30eb, 0x30ec, 0x30ed, 0x30ef, 0x30f3, 0x309b, 0x309c /* 0x04d8-0x04df */
};
static unsigned short const keysym_to_unicode_590_5fe[] = {
- 0x06f0, 0x06f1, 0x06f2, 0x06f3, 0x06f4, 0x06f5, 0x06f6, 0x06f7, /* 0x0590-0x0597 */
- 0x06f8, 0x06f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x0598-0x059f */
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x066a, 0x0670, 0x0679, /* 0x05a0-0x05a7 */
+ 0x06f0, 0x06f1, 0x06f2, 0x06f3, 0x06f4, 0x06f5, 0x06f6, 0x06f7, /* 0x0590-0x0597 */
+ 0x06f8, 0x06f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x0598-0x059f */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x066a, 0x0670, 0x0679, /* 0x05a0-0x05a7 */
- 0x067e, 0x0686, 0x0688, 0x0691, 0x060c, 0x0000, 0x06d4, 0x0000, /* 0x05ac-0x05af */
- 0x0660, 0x0661, 0x0662, 0x0663, 0x0664, 0x0665, 0x0666, 0x0667, /* 0x05b0-0x05b7 */
- 0x0668, 0x0669, 0x0000, 0x061b, 0x0000, 0x0000, 0x0000, 0x061f, /* 0x05b8-0x05bf */
- 0x0000, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, /* 0x05c0-0x05c7 */
- 0x0628, 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f, /* 0x05c8-0x05cf */
- 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637, /* 0x05d0-0x05d7 */
- 0x0638, 0x0639, 0x063a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x05d8-0x05df */
- 0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, /* 0x05e0-0x05e7 */
- 0x0648, 0x0649, 0x064a, 0x064b, 0x064c, 0x064d, 0x064e, 0x064f, /* 0x05e8-0x05ef */
- 0x0650, 0x0651, 0x0652, 0x0653, 0x0654, 0x0655, 0x0698, 0x06a4, /* 0x05f0-0x05f7 */
- 0x06a9, 0x06af, 0x06ba, 0x06be, 0x06cc, 0x06d2, 0x06c1 /* 0x05f8-0x05fe */
+ 0x067e, 0x0686, 0x0688, 0x0691, 0x060c, 0x0000, 0x06d4, 0x0000, /* 0x05ac-0x05af */
+ 0x0660, 0x0661, 0x0662, 0x0663, 0x0664, 0x0665, 0x0666, 0x0667, /* 0x05b0-0x05b7 */
+ 0x0668, 0x0669, 0x0000, 0x061b, 0x0000, 0x0000, 0x0000, 0x061f, /* 0x05b8-0x05bf */
+ 0x0000, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, /* 0x05c0-0x05c7 */
+ 0x0628, 0x0629, 0x062a, 0x062b, 0x062c, 0x062d, 0x062e, 0x062f, /* 0x05c8-0x05cf */
+ 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637, /* 0x05d0-0x05d7 */
+ 0x0638, 0x0639, 0x063a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x05d8-0x05df */
+ 0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, /* 0x05e0-0x05e7 */
+ 0x0648, 0x0649, 0x064a, 0x064b, 0x064c, 0x064d, 0x064e, 0x064f, /* 0x05e8-0x05ef */
+ 0x0650, 0x0651, 0x0652, 0x0653, 0x0654, 0x0655, 0x0698, 0x06a4, /* 0x05f0-0x05f7 */
+ 0x06a9, 0x06af, 0x06ba, 0x06be, 0x06cc, 0x06d2, 0x06c1 /* 0x05f8-0x05fe */
};
-static unsigned short const keysym_to_unicode_680_6ff[] = {
- 0x0492, 0x0496, 0x049a, 0x049c, 0x04a2, 0x04ae, 0x04b0, 0x04b2, /* 0x0680-0x0687 */
- 0x04b6, 0x04b8, 0x04ba, 0x0000, 0x04d8, 0x04e2, 0x04e8, 0x04ee, /* 0x0688-0x068f */
- 0x0493, 0x0497, 0x049b, 0x049d, 0x04a3, 0x04af, 0x04b1, 0x04b3, /* 0x0690-0x0697 */
- 0x04b7, 0x04b9, 0x04bb, 0x0000, 0x04d9, 0x04e3, 0x04e9, 0x04ef, /* 0x0698-0x069f */
- 0x0000, 0x0452, 0x0453, 0x0451, 0x0454, 0x0455, 0x0456, 0x0457, /* 0x06a0-0x06a7 */
- 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x0491, 0x045e, 0x045f, /* 0x06a8-0x06af */
- 0x2116, 0x0402, 0x0403, 0x0401, 0x0404, 0x0405, 0x0406, 0x0407, /* 0x06b0-0x06b7 */
- 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x0490, 0x040e, 0x040f, /* 0x06b8-0x06bf */
- 0x044e, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433, /* 0x06c0-0x06c7 */
- 0x0445, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, /* 0x06c8-0x06cf */
- 0x043f, 0x044f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432, /* 0x06d0-0x06d7 */
- 0x044c, 0x044b, 0x0437, 0x0448, 0x044d, 0x0449, 0x0447, 0x044a, /* 0x06d8-0x06df */
- 0x042e, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413, /* 0x06e0-0x06e7 */
- 0x0425, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, /* 0x06e8-0x06ef */
- 0x041f, 0x042f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412, /* 0x06f0-0x06f7 */
- 0x042c, 0x042b, 0x0417, 0x0428, 0x042d, 0x0429, 0x0427, 0x042a /* 0x06f8-0x06ff */
+static unsigned short keysym_to_unicode_680_6ff[] = {
+ 0x0492, 0x0496, 0x049a, 0x049c, 0x04a2, 0x04ae, 0x04b0, 0x04b2, /* 0x0680-0x0687 */
+ 0x04b6, 0x04b8, 0x04ba, 0x0000, 0x04d8, 0x04e2, 0x04e8, 0x04ee, /* 0x0688-0x068f */
+ 0x0493, 0x0497, 0x049b, 0x049d, 0x04a3, 0x04af, 0x04b1, 0x04b3, /* 0x0690-0x0697 */
+ 0x04b7, 0x04b9, 0x04bb, 0x0000, 0x04d9, 0x04e3, 0x04e9, 0x04ef, /* 0x0698-0x069f */
+ 0x0000, 0x0452, 0x0453, 0x0451, 0x0454, 0x0455, 0x0456, 0x0457, /* 0x06a0-0x06a7 */
+ 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x0491, 0x045e, 0x045f, /* 0x06a8-0x06af */
+ 0x2116, 0x0402, 0x0403, 0x0401, 0x0404, 0x0405, 0x0406, 0x0407, /* 0x06b0-0x06b7 */
+ 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x0490, 0x040e, 0x040f, /* 0x06b8-0x06bf */
+ 0x044e, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433, /* 0x06c0-0x06c7 */
+ 0x0445, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, /* 0x06c8-0x06cf */
+ 0x043f, 0x044f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432, /* 0x06d0-0x06d7 */
+ 0x044c, 0x044b, 0x0437, 0x0448, 0x044d, 0x0449, 0x0447, 0x044a, /* 0x06d8-0x06df */
+ 0x042e, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413, /* 0x06e0-0x06e7 */
+ 0x0425, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, /* 0x06e8-0x06ef */
+ 0x041f, 0x042f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412, /* 0x06f0-0x06f7 */
+ 0x042c, 0x042b, 0x0417, 0x0428, 0x042d, 0x0429, 0x0427, 0x042a /* 0x06f8-0x06ff */
};
static unsigned short const keysym_to_unicode_7a1_7f9[] = {
- 0x0386, 0x0388, 0x0389, 0x038a, 0x03aa, 0x0000, 0x038c, /* 0x07a0-0x07a7 */
- 0x038e, 0x03ab, 0x0000, 0x038f, 0x0000, 0x0000, 0x0385, 0x2015, /* 0x07a8-0x07af */
- 0x0000, 0x03ac, 0x03ad, 0x03ae, 0x03af, 0x03ca, 0x0390, 0x03cc, /* 0x07b0-0x07b7 */
- 0x03cd, 0x03cb, 0x03b0, 0x03ce, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x07b8-0x07bf */
- 0x0000, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, /* 0x07c0-0x07c7 */
- 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, /* 0x07c8-0x07cf */
- 0x03a0, 0x03a1, 0x03a3, 0x0000, 0x03a4, 0x03a5, 0x03a6, 0x03a7, /* 0x07d0-0x07d7 */
- 0x03a8, 0x03a9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x07d8-0x07df */
- 0x0000, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, /* 0x07e0-0x07e7 */
- 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, /* 0x07e8-0x07ef */
- 0x03c0, 0x03c1, 0x03c3, 0x03c2, 0x03c4, 0x03c5, 0x03c6, 0x03c7, /* 0x07f0-0x07f7 */
- 0x03c8, 0x03c9 /* 0x07f8-0x07ff */
+ 0x0386, 0x0388, 0x0389, 0x038a, 0x03aa, 0x0000, 0x038c, /* 0x07a0-0x07a7 */
+ 0x038e, 0x03ab, 0x0000, 0x038f, 0x0000, 0x0000, 0x0385, 0x2015, /* 0x07a8-0x07af */
+ 0x0000, 0x03ac, 0x03ad, 0x03ae, 0x03af, 0x03ca, 0x0390, 0x03cc, /* 0x07b0-0x07b7 */
+ 0x03cd, 0x03cb, 0x03b0, 0x03ce, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x07b8-0x07bf */
+ 0x0000, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, /* 0x07c0-0x07c7 */
+ 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, /* 0x07c8-0x07cf */
+ 0x03a0, 0x03a1, 0x03a3, 0x0000, 0x03a4, 0x03a5, 0x03a6, 0x03a7, /* 0x07d0-0x07d7 */
+ 0x03a8, 0x03a9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x07d8-0x07df */
+ 0x0000, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, /* 0x07e0-0x07e7 */
+ 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, /* 0x07e8-0x07ef */
+ 0x03c0, 0x03c1, 0x03c3, 0x03c2, 0x03c4, 0x03c5, 0x03c6, 0x03c7, /* 0x07f0-0x07f7 */
+ 0x03c8, 0x03c9 /* 0x07f8-0x07ff */
};
static unsigned short const keysym_to_unicode_8a4_8fe[] = {
- 0x2320, 0x2321, 0x0000, 0x231c, /* 0x08a0-0x08a7 */
- 0x231d, 0x231e, 0x231f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x08a8-0x08af */
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x08b0-0x08b7 */
- 0x0000, 0x0000, 0x0000, 0x0000, 0x2264, 0x2260, 0x2265, 0x222b, /* 0x08b8-0x08bf */
- 0x2234, 0x0000, 0x221e, 0x0000, 0x0000, 0x2207, 0x0000, 0x0000, /* 0x08c0-0x08c7 */
- 0x2245, 0x2246, 0x0000, 0x0000, 0x0000, 0x0000, 0x22a2, 0x0000, /* 0x08c8-0x08cf */
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x221a, 0x0000, /* 0x08d0-0x08d7 */
- 0x0000, 0x0000, 0x2282, 0x2283, 0x2229, 0x222a, 0x2227, 0x2228, /* 0x08d8-0x08df */
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x08e0-0x08e7 */
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x08e8-0x08ef */
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0192, 0x0000, /* 0x08f0-0x08f7 */
- 0x0000, 0x0000, 0x0000, 0x2190, 0x2191, 0x2192, 0x2193 /* 0x08f8-0x08ff */
+ 0x2320, 0x2321, 0x0000, 0x231c, /* 0x08a0-0x08a7 */
+ 0x231d, 0x231e, 0x231f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x08a8-0x08af */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x08b0-0x08b7 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x2264, 0x2260, 0x2265, 0x222b, /* 0x08b8-0x08bf */
+ 0x2234, 0x0000, 0x221e, 0x0000, 0x0000, 0x2207, 0x0000, 0x0000, /* 0x08c0-0x08c7 */
+ 0x2245, 0x2246, 0x0000, 0x0000, 0x0000, 0x0000, 0x21d2, 0x0000, /* 0x08c8-0x08cf */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x221a, 0x0000, /* 0x08d0-0x08d7 */
+ 0x0000, 0x0000, 0x2282, 0x2283, 0x2229, 0x222a, 0x2227, 0x2228, /* 0x08d8-0x08df */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x08e0-0x08e7 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2202, /* 0x08e8-0x08ef */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0192, 0x0000, /* 0x08f0-0x08f7 */
+ 0x0000, 0x0000, 0x0000, 0x2190, 0x2191, 0x2192, 0x2193 /* 0x08f8-0x08ff */
};
static unsigned short const keysym_to_unicode_9df_9f8[] = {
- 0x2422, /* 0x09d8-0x09df */
- 0x2666, 0x25a6, 0x2409, 0x240c, 0x240d, 0x240a, 0x0000, 0x0000, /* 0x09e0-0x09e7 */
- 0x240a, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 0x2500, /* 0x09e8-0x09ef */
- 0x0000, 0x0000, 0x0000, 0x0000, 0x251c, 0x2524, 0x2534, 0x252c, /* 0x09f0-0x09f7 */
- 0x2502 /* 0x09f8-0x09ff */
+ 0x2422, /* 0x09d8-0x09df */
+ 0x2666, 0x25a6, 0x2409, 0x240c, 0x240d, 0x240a, 0x0000, 0x0000, /* 0x09e0-0x09e7 */
+ 0x240a, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 0x2500, /* 0x09e8-0x09ef */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x251c, 0x2524, 0x2534, 0x252c, /* 0x09f0-0x09f7 */
+ 0x2502 /* 0x09f8-0x09ff */
};
static unsigned short const keysym_to_unicode_aa1_afe[] = {
- 0x2003, 0x2002, 0x2004, 0x2005, 0x2007, 0x2008, 0x2009, /* 0x0aa0-0x0aa7 */
- 0x200a, 0x2014, 0x2013, 0x0000, 0x0000, 0x0000, 0x2026, 0x2025, /* 0x0aa8-0x0aaf */
- 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159, 0x215a, /* 0x0ab0-0x0ab7 */
- 0x2105, 0x0000, 0x0000, 0x2012, 0x2039, 0x2024, 0x203a, 0x0000, /* 0x0ab8-0x0abf */
- 0x0000, 0x0000, 0x0000, 0x215b, 0x215c, 0x215d, 0x215e, 0x0000, /* 0x0ac0-0x0ac7 */
- 0x0000, 0x2122, 0x2120, 0x0000, 0x25c1, 0x25b7, 0x25cb, 0x25ad, /* 0x0ac8-0x0acf */
- 0x2018, 0x2019, 0x201c, 0x201d, 0x211e, 0x0000, 0x2032, 0x2033, /* 0x0ad0-0x0ad7 */
- 0x0000, 0x271d, 0x0000, 0x220e, 0x25c2, 0x2023, 0x25cf, 0x25ac, /* 0x0ad8-0x0adf */
- 0x25e6, 0x25ab, 0x25ae, 0x25b5, 0x25bf, 0x2606, 0x2022, 0x25aa, /* 0x0ae0-0x0ae7 */
- 0x25b4, 0x25be, 0x261a, 0x261b, 0x2663, 0x2666, 0x2665, 0x0000, /* 0x0ae8-0x0aef */
- 0x2720, 0x2020, 0x2021, 0x2713, 0x2612, 0x266f, 0x266d, 0x2642, /* 0x0af0-0x0af7 */
- 0x2640, 0x2121, 0x2315, 0x2117, 0x2038, 0x201a, 0x201e /* 0x0af8-0x0aff */
+ 0x2003, 0x2002, 0x2004, 0x2005, 0x2007, 0x2008, 0x2009, /* 0x0aa0-0x0aa7 */
+ 0x200a, 0x2014, 0x2013, 0x0000, 0x0000, 0x0000, 0x2026, 0x2025, /* 0x0aa8-0x0aaf */
+ 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159, 0x215a, /* 0x0ab0-0x0ab7 */
+ 0x2105, 0x0000, 0x0000, 0x2012, 0x2039, 0x2024, 0x203a, 0x0000, /* 0x0ab8-0x0abf */
+ 0x0000, 0x0000, 0x0000, 0x215b, 0x215c, 0x215d, 0x215e, 0x0000, /* 0x0ac0-0x0ac7 */
+ 0x0000, 0x2122, 0x2120, 0x0000, 0x25c1, 0x25b7, 0x25cb, 0x25ad, /* 0x0ac8-0x0acf */
+ 0x2018, 0x2019, 0x201c, 0x201d, 0x211e, 0x2030, 0x2032, 0x2033, /* 0x0ad0-0x0ad7 */
+ 0x0000, 0x271d, 0x0000, 0x220e, 0x25c2, 0x2023, 0x25cf, 0x25ac, /* 0x0ad8-0x0adf */
+ 0x25e6, 0x25ab, 0x25ae, 0x25b5, 0x25bf, 0x2606, 0x2022, 0x25aa, /* 0x0ae0-0x0ae7 */
+ 0x25b4, 0x25be, 0x261a, 0x261b, 0x2663, 0x2666, 0x2665, 0x0000, /* 0x0ae8-0x0aef */
+ 0x2720, 0x2020, 0x2021, 0x2713, 0x2612, 0x266f, 0x266d, 0x2642, /* 0x0af0-0x0af7 */
+ 0x2640, 0x2121, 0x2315, 0x2117, 0x2038, 0x201a, 0x201e /* 0x0af8-0x0aff */
};
/* none of the APL keysyms match the Unicode characters */
static unsigned short const keysym_to_unicode_cdf_cfa[] = {
- 0x2017, /* 0x0cd8-0x0cdf */
- 0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7, /* 0x0ce0-0x0ce7 */
- 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df, /* 0x0ce8-0x0cef */
- 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7, /* 0x0cf0-0x0cf7 */
- 0x05e8, 0x05e9, 0x05ea /* 0x0cf8-0x0cff */
+ 0x2017, /* 0x0cd8-0x0cdf */
+ 0x05d0, 0x05d1, 0x05d2, 0x05d3, 0x05d4, 0x05d5, 0x05d6, 0x05d7, /* 0x0ce0-0x0ce7 */
+ 0x05d8, 0x05d9, 0x05da, 0x05db, 0x05dc, 0x05dd, 0x05de, 0x05df, /* 0x0ce8-0x0cef */
+ 0x05e0, 0x05e1, 0x05e2, 0x05e3, 0x05e4, 0x05e5, 0x05e6, 0x05e7, /* 0x0cf0-0x0cf7 */
+ 0x05e8, 0x05e9, 0x05ea /* 0x0cf8-0x0cff */
};
static unsigned short const keysym_to_unicode_da1_df9[] = {
- 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07, /* 0x0da0-0x0da7 */
- 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f, /* 0x0da8-0x0daf */
- 0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17, /* 0x0db0-0x0db7 */
- 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f, /* 0x0db8-0x0dbf */
- 0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27, /* 0x0dc0-0x0dc7 */
- 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f, /* 0x0dc8-0x0dcf */
- 0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37, /* 0x0dd0-0x0dd7 */
- 0x0e38, 0x0e39, 0x0e3a, 0x0000, 0x0000, 0x0000, 0x0e3e, 0x0e3f, /* 0x0dd8-0x0ddf */
- 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47, /* 0x0de0-0x0de7 */
- 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0000, 0x0000, /* 0x0de8-0x0def */
- 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57, /* 0x0df0-0x0df7 */
- 0x0e58, 0x0e59 /* 0x0df8-0x0dff */
+ 0x0e01, 0x0e02, 0x0e03, 0x0e04, 0x0e05, 0x0e06, 0x0e07, /* 0x0da0-0x0da7 */
+ 0x0e08, 0x0e09, 0x0e0a, 0x0e0b, 0x0e0c, 0x0e0d, 0x0e0e, 0x0e0f, /* 0x0da8-0x0daf */
+ 0x0e10, 0x0e11, 0x0e12, 0x0e13, 0x0e14, 0x0e15, 0x0e16, 0x0e17, /* 0x0db0-0x0db7 */
+ 0x0e18, 0x0e19, 0x0e1a, 0x0e1b, 0x0e1c, 0x0e1d, 0x0e1e, 0x0e1f, /* 0x0db8-0x0dbf */
+ 0x0e20, 0x0e21, 0x0e22, 0x0e23, 0x0e24, 0x0e25, 0x0e26, 0x0e27, /* 0x0dc0-0x0dc7 */
+ 0x0e28, 0x0e29, 0x0e2a, 0x0e2b, 0x0e2c, 0x0e2d, 0x0e2e, 0x0e2f, /* 0x0dc8-0x0dcf */
+ 0x0e30, 0x0e31, 0x0e32, 0x0e33, 0x0e34, 0x0e35, 0x0e36, 0x0e37, /* 0x0dd0-0x0dd7 */
+ 0x0e38, 0x0e39, 0x0e3a, 0x0000, 0x0000, 0x0000, 0x0e3e, 0x0e3f, /* 0x0dd8-0x0ddf */
+ 0x0e40, 0x0e41, 0x0e42, 0x0e43, 0x0e44, 0x0e45, 0x0e46, 0x0e47, /* 0x0de0-0x0de7 */
+ 0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c, 0x0e4d, 0x0000, 0x0000, /* 0x0de8-0x0def */
+ 0x0e50, 0x0e51, 0x0e52, 0x0e53, 0x0e54, 0x0e55, 0x0e56, 0x0e57, /* 0x0df0-0x0df7 */
+ 0x0e58, 0x0e59 /* 0x0df8-0x0dff */
};
static unsigned short const keysym_to_unicode_ea0_eff[] = {
- 0x0000, 0x1101, 0x1101, 0x11aa, 0x1102, 0x11ac, 0x11ad, 0x1103, /* 0x0ea0-0x0ea7 */
- 0x1104, 0x1105, 0x11b0, 0x11b1, 0x11b2, 0x11b3, 0x11b4, 0x11b5, /* 0x0ea8-0x0eaf */
- 0x11b6, 0x1106, 0x1107, 0x1108, 0x11b9, 0x1109, 0x110a, 0x110b, /* 0x0eb0-0x0eb7 */
- 0x110c, 0x110d, 0x110e, 0x110f, 0x1110, 0x1111, 0x1112, 0x1161, /* 0x0eb8-0x0ebf */
- 0x1162, 0x1163, 0x1164, 0x1165, 0x1166, 0x1167, 0x1168, 0x1169, /* 0x0ec0-0x0ec7 */
- 0x116a, 0x116b, 0x116c, 0x116d, 0x116e, 0x116f, 0x1170, 0x1171, /* 0x0ec8-0x0ecf */
- 0x1172, 0x1173, 0x1174, 0x1175, 0x11a8, 0x11a9, 0x11aa, 0x11ab, /* 0x0ed0-0x0ed7 */
- 0x11ac, 0x11ad, 0x11ae, 0x11af, 0x11b0, 0x11b1, 0x11b2, 0x11b3, /* 0x0ed8-0x0edf */
- 0x11b4, 0x11b5, 0x11b6, 0x11b7, 0x11b8, 0x11b9, 0x11ba, 0x11bb, /* 0x0ee0-0x0ee7 */
- 0x11bc, 0x11bd, 0x11be, 0x11bf, 0x11c0, 0x11c1, 0x11c2, 0x0000, /* 0x0ee8-0x0eef */
- 0x0000, 0x0000, 0x1140, 0x0000, 0x0000, 0x1159, 0x119e, 0x0000, /* 0x0ef0-0x0ef7 */
- 0x11eb, 0x0000, 0x11f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x20a9, /* 0x0ef8-0x0eff */
+ 0x0000, 0x1101, 0x1101, 0x11aa, 0x1102, 0x11ac, 0x11ad, 0x1103, /* 0x0ea0-0x0ea7 */
+ 0x1104, 0x1105, 0x11b0, 0x11b1, 0x11b2, 0x11b3, 0x11b4, 0x11b5, /* 0x0ea8-0x0eaf */
+ 0x11b6, 0x1106, 0x1107, 0x1108, 0x11b9, 0x1109, 0x110a, 0x110b, /* 0x0eb0-0x0eb7 */
+ 0x110c, 0x110d, 0x110e, 0x110f, 0x1110, 0x1111, 0x1112, 0x1161, /* 0x0eb8-0x0ebf */
+ 0x1162, 0x1163, 0x1164, 0x1165, 0x1166, 0x1167, 0x1168, 0x1169, /* 0x0ec0-0x0ec7 */
+ 0x116a, 0x116b, 0x116c, 0x116d, 0x116e, 0x116f, 0x1170, 0x1171, /* 0x0ec8-0x0ecf */
+ 0x1172, 0x1173, 0x1174, 0x1175, 0x11a8, 0x11a9, 0x11aa, 0x11ab, /* 0x0ed0-0x0ed7 */
+ 0x11ac, 0x11ad, 0x11ae, 0x11af, 0x11b0, 0x11b1, 0x11b2, 0x11b3, /* 0x0ed8-0x0edf */
+ 0x11b4, 0x11b5, 0x11b6, 0x11b7, 0x11b8, 0x11b9, 0x11ba, 0x11bb, /* 0x0ee0-0x0ee7 */
+ 0x11bc, 0x11bd, 0x11be, 0x11bf, 0x11c0, 0x11c1, 0x11c2, 0x0000, /* 0x0ee8-0x0eef */
+ 0x0000, 0x0000, 0x1140, 0x0000, 0x0000, 0x1159, 0x119e, 0x0000, /* 0x0ef0-0x0ef7 */
+ 0x11eb, 0x0000, 0x11f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x20a9, /* 0x0ef8-0x0eff */
};
-static unsigned short const keysym_to_unicode_12a1_12fe[] = {
- 0x1e02, 0x1e03, 0x0000, 0x0000, 0x0000, 0x1e0a, 0x0000, /* 0x12a0-0x12a7 */
- 0x1e80, 0x0000, 0x1e82, 0x1e0b, 0x1ef2, 0x0000, 0x0000, 0x0000, /* 0x12a8-0x12af */
- 0x1e1e, 0x1e1f, 0x0000, 0x0000, 0x1e40, 0x1e41, 0x0000, 0x1e56, /* 0x12b0-0x12b7 */
- 0x1e81, 0x1e57, 0x1e83, 0x1e60, 0x1ef3, 0x1e84, 0x1e85, 0x1e61, /* 0x12b8-0x12bf */
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x12c0-0x12c7 */
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x12c8-0x12cf */
- 0x0174, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1e6a, /* 0x12d0-0x12d7 */
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0176, 0x0000, /* 0x12d8-0x12df */
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x12e0-0x12e7 */
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x12e8-0x12ef */
- 0x0175, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1e6b, /* 0x12f0-0x12f7 */
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0177 /* 0x12f0-0x12ff */
+static unsigned short keysym_to_unicode_12a1_12fe[] = {
+ 0x1e02, 0x1e03, 0x0000, 0x0000, 0x0000, 0x1e0a, 0x0000, /* 0x12a0-0x12a7 */
+ 0x1e80, 0x0000, 0x1e82, 0x1e0b, 0x1ef2, 0x0000, 0x0000, 0x0000, /* 0x12a8-0x12af */
+ 0x1e1e, 0x1e1f, 0x0000, 0x0000, 0x1e40, 0x1e41, 0x0000, 0x1e56, /* 0x12b0-0x12b7 */
+ 0x1e81, 0x1e57, 0x1e83, 0x1e60, 0x1ef3, 0x1e84, 0x1e85, 0x1e61, /* 0x12b8-0x12bf */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x12c0-0x12c7 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x12c8-0x12cf */
+ 0x0174, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1e6a, /* 0x12d0-0x12d7 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0176, 0x0000, /* 0x12d8-0x12df */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x12e0-0x12e7 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x12e8-0x12ef */
+ 0x0175, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x1e6b, /* 0x12f0-0x12f7 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0177 /* 0x12f0-0x12ff */
};
static unsigned short const keysym_to_unicode_13bc_13be[] = {
- 0x0152, 0x0153, 0x0178 /* 0x13b8-0x13bf */
+ 0x0152, 0x0153, 0x0178 /* 0x13b8-0x13bf */
};
-static unsigned short const keysym_to_unicode_14a1_14ff[] = {
- 0x2741, 0x00a7, 0x0589, 0x0029, 0x0028, 0x00bb, 0x00ab, /* 0x14a0-0x14a7 */
- 0x2014, 0x002e, 0x055d, 0x002c, 0x2013, 0x058a, 0x2026, 0x055c, /* 0x14a8-0x14af */
- 0x055b, 0x055e, 0x0531, 0x0561, 0x0532, 0x0562, 0x0533, 0x0563, /* 0x14b0-0x14b7 */
- 0x0534, 0x0564, 0x0535, 0x0565, 0x0536, 0x0566, 0x0537, 0x0567, /* 0x14b8-0x14bf */
- 0x0538, 0x0568, 0x0539, 0x0569, 0x053a, 0x056a, 0x053b, 0x056b, /* 0x14c0-0x14c7 */
- 0x053c, 0x056c, 0x053d, 0x056d, 0x053e, 0x056e, 0x053f, 0x056f, /* 0x14c8-0x14cf */
- 0x0540, 0x0570, 0x0541, 0x0571, 0x0542, 0x0572, 0x0543, 0x0573, /* 0x14d0-0x14d7 */
- 0x0544, 0x0574, 0x0545, 0x0575, 0x0546, 0x0576, 0x0547, 0x0577, /* 0x14d8-0x14df */
- 0x0548, 0x0578, 0x0549, 0x0579, 0x054a, 0x057a, 0x054b, 0x057b, /* 0x14e0-0x14e7 */
- 0x054c, 0x057c, 0x054d, 0x057d, 0x054e, 0x057e, 0x054f, 0x057f, /* 0x14e8-0x14ef */
- 0x0550, 0x0580, 0x0551, 0x0581, 0x0552, 0x0582, 0x0553, 0x0583, /* 0x14f0-0x14f7 */
- 0x0554, 0x0584, 0x0555, 0x0585, 0x0556, 0x0586, 0x2019, 0x0027, /* 0x14f8-0x14ff */
+static unsigned short keysym_to_unicode_14a1_14ff[] = {
+ 0x2741, 0x00a7, 0x0589, 0x0029, 0x0028, 0x00bb, 0x00ab, /* 0x14a0-0x14a7 */
+ 0x2014, 0x002e, 0x055d, 0x002c, 0x2013, 0x058a, 0x2026, 0x055c, /* 0x14a8-0x14af */
+ 0x055b, 0x055e, 0x0531, 0x0561, 0x0532, 0x0562, 0x0533, 0x0563, /* 0x14b0-0x14b7 */
+ 0x0534, 0x0564, 0x0535, 0x0565, 0x0536, 0x0566, 0x0537, 0x0567, /* 0x14b8-0x14bf */
+ 0x0538, 0x0568, 0x0539, 0x0569, 0x053a, 0x056a, 0x053b, 0x056b, /* 0x14c0-0x14c7 */
+ 0x053c, 0x056c, 0x053d, 0x056d, 0x053e, 0x056e, 0x053f, 0x056f, /* 0x14c8-0x14cf */
+ 0x0540, 0x0570, 0x0541, 0x0571, 0x0542, 0x0572, 0x0543, 0x0573, /* 0x14d0-0x14d7 */
+ 0x0544, 0x0574, 0x0545, 0x0575, 0x0546, 0x0576, 0x0547, 0x0577, /* 0x14d8-0x14df */
+ 0x0548, 0x0578, 0x0549, 0x0579, 0x054a, 0x057a, 0x054b, 0x057b, /* 0x14e0-0x14e7 */
+ 0x054c, 0x057c, 0x054d, 0x057d, 0x054e, 0x057e, 0x054f, 0x057f, /* 0x14e8-0x14ef */
+ 0x0550, 0x0580, 0x0551, 0x0581, 0x0552, 0x0582, 0x0553, 0x0583, /* 0x14f0-0x14f7 */
+ 0x0554, 0x0584, 0x0555, 0x0585, 0x0556, 0x0586, 0x2019, 0x0027, /* 0x14f8-0x14ff */
};
-static unsigned short const keysym_to_unicode_15d0_15f6[] = {
- 0x10d0, 0x10d1, 0x10d2, 0x10d3, 0x10d4, 0x10d5, 0x10d6, 0x10d7, /* 0x15d0-0x15d7 */
- 0x10d8, 0x10d9, 0x10da, 0x10db, 0x10dc, 0x10dd, 0x10de, 0x10df, /* 0x15d8-0x15df */
- 0x10e0, 0x10e1, 0x10e2, 0x10e3, 0x10e4, 0x10e5, 0x10e6, 0x10e7, /* 0x15e0-0x15e7 */
- 0x10e8, 0x10e9, 0x10ea, 0x10eb, 0x10ec, 0x10ed, 0x10ee, 0x10ef, /* 0x15e8-0x15ef */
- 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6 /* 0x15f0-0x15f7 */
+static unsigned short keysym_to_unicode_15d0_15f6[] = {
+ 0x10d0, 0x10d1, 0x10d2, 0x10d3, 0x10d4, 0x10d5, 0x10d6, 0x10d7, /* 0x15d0-0x15d7 */
+ 0x10d8, 0x10d9, 0x10da, 0x10db, 0x10dc, 0x10dd, 0x10de, 0x10df, /* 0x15d8-0x15df */
+ 0x10e0, 0x10e1, 0x10e2, 0x10e3, 0x10e4, 0x10e5, 0x10e6, 0x10e7, /* 0x15e0-0x15e7 */
+ 0x10e8, 0x10e9, 0x10ea, 0x10eb, 0x10ec, 0x10ed, 0x10ee, 0x10ef, /* 0x15e8-0x15ef */
+ 0x10f0, 0x10f1, 0x10f2, 0x10f3, 0x10f4, 0x10f5, 0x10f6 /* 0x15f0-0x15f7 */
};
-static unsigned short const keysym_to_unicode_16a0_16f6[] = {
- 0x0000, 0x0000, 0xf0a2, 0x1e8a, 0x0000, 0xf0a5, 0x012c, 0xf0a7, /* 0x16a0-0x16a7 */
- 0xf0a8, 0x01b5, 0x01e6, 0x0000, 0x0000, 0x0000, 0x0000, 0x019f, /* 0x16a8-0x16af */
- 0x0000, 0x0000, 0xf0b2, 0x1e8b, 0x01d1, 0xf0b5, 0x012d, 0xf0b7, /* 0x16b0-0x16b7 */
- 0xf0b8, 0x01b6, 0x01e7, 0x0000, 0x0000, 0x01d2, 0x0000, 0x0275, /* 0x16b8-0x16bf */
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x018f, 0x0000, /* 0x16c0-0x16c7 */
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16c8-0x16cf */
- 0x0000, 0x1e36, 0xf0d2, 0xf0d3, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16d0-0x16d7 */
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16d8-0x16df */
- 0x0000, 0x1e37, 0xf0e2, 0xf0e3, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16e0-0x16e7 */
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16e8-0x16ef */
- 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0259 /* 0x16f0-0x16f6 */
+static unsigned short keysym_to_unicode_16a0_16f6[] = {
+ 0x0000, 0x0000, 0xf0a2, 0x1e8a, 0x0000, 0xf0a5, 0x012c, 0xf0a7, /* 0x16a0-0x16a7 */
+ 0xf0a8, 0x01b5, 0x01e6, 0x0000, 0x0000, 0x0000, 0x0000, 0x019f, /* 0x16a8-0x16af */
+ 0x0000, 0x0000, 0xf0b2, 0x1e8b, 0x01d1, 0xf0b5, 0x012d, 0xf0b7, /* 0x16b0-0x16b7 */
+ 0xf0b8, 0x01b6, 0x01e7, 0x0000, 0x0000, 0x01d2, 0x0000, 0x0275, /* 0x16b8-0x16bf */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x018f, 0x0000, /* 0x16c0-0x16c7 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16c8-0x16cf */
+ 0x0000, 0x1e36, 0xf0d2, 0xf0d3, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16d0-0x16d7 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16d8-0x16df */
+ 0x0000, 0x1e37, 0xf0e2, 0xf0e3, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16e0-0x16e7 */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 0x16e8-0x16ef */
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0259 /* 0x16f0-0x16f6 */
};
static unsigned short const keysym_to_unicode_1e9f_1eff[] = {
- 0x0303,
- 0x1ea0, 0x1ea1, 0x1ea2, 0x1ea3, 0x1ea4, 0x1ea5, 0x1ea6, 0x1ea7, /* 0x1ea0-0x1ea7 */
- 0x1ea8, 0x1ea9, 0x1eaa, 0x1eab, 0x1eac, 0x1ead, 0x1eae, 0x1eaf, /* 0x1ea8-0x1eaf */
- 0x1eb0, 0x1eb1, 0x1eb2, 0x1eb3, 0x1eb4, 0x1eb5, 0x1eb6, 0x1eb7, /* 0x1eb0-0x1eb7 */
- 0x1eb8, 0x1eb9, 0x1eba, 0x1ebb, 0x1ebc, 0x1ebd, 0x1ebe, 0x1ebf, /* 0x1eb8-0x1ebf */
- 0x1ec0, 0x1ec1, 0x1ec2, 0x1ec3, 0x1ec4, 0x1ec5, 0x1ec6, 0x1ec7, /* 0x1ec0-0x1ec7 */
- 0x1ec8, 0x1ec9, 0x1eca, 0x1ecb, 0x1ecc, 0x1ecd, 0x1ece, 0x1ecf, /* 0x1ec8-0x1ecf */
- 0x1ed0, 0x1ed1, 0x1ed2, 0x1ed3, 0x1ed4, 0x1ed5, 0x1ed6, 0x1ed7, /* 0x1ed0-0x1ed7 */
- 0x1ed8, 0x1ed9, 0x1eda, 0x1edb, 0x1edc, 0x1edd, 0x1ede, 0x1edf, /* 0x1ed8-0x1edf */
- 0x1ee0, 0x1ee1, 0x1ee2, 0x1ee3, 0x1ee4, 0x1ee5, 0x1ee6, 0x1ee7, /* 0x1ee0-0x1ee7 */
- 0x1ee8, 0x1ee9, 0x1eea, 0x1eeb, 0x1eec, 0x1eed, 0x1eee, 0x1eef, /* 0x1ee8-0x1eef */
- 0x1ef0, 0x1ef1, 0x0300, 0x0301, 0x1ef4, 0x1ef5, 0x1ef6, 0x1ef7, /* 0x1ef0-0x1ef7 */
- 0x1ef8, 0x1ef9, 0x01a0, 0x01a1, 0x01af, 0x01b0, 0x0309, 0x0323 /* 0x1ef8-0x1eff */
+ 0x0303,
+ 0x1ea0, 0x1ea1, 0x1ea2, 0x1ea3, 0x1ea4, 0x1ea5, 0x1ea6, 0x1ea7, /* 0x1ea0-0x1ea7 */
+ 0x1ea8, 0x1ea9, 0x1eaa, 0x1eab, 0x1eac, 0x1ead, 0x1eae, 0x1eaf, /* 0x1ea8-0x1eaf */
+ 0x1eb0, 0x1eb1, 0x1eb2, 0x1eb3, 0x1eb4, 0x1eb5, 0x1eb6, 0x1eb7, /* 0x1eb0-0x1eb7 */
+ 0x1eb8, 0x1eb9, 0x1eba, 0x1ebb, 0x1ebc, 0x1ebd, 0x1ebe, 0x1ebf, /* 0x1eb8-0x1ebf */
+ 0x1ec0, 0x1ec1, 0x1ec2, 0x1ec3, 0x1ec4, 0x1ec5, 0x1ec6, 0x1ec7, /* 0x1ec0-0x1ec7 */
+ 0x1ec8, 0x1ec9, 0x1eca, 0x1ecb, 0x1ecc, 0x1ecd, 0x1ece, 0x1ecf, /* 0x1ec8-0x1ecf */
+ 0x1ed0, 0x1ed1, 0x1ed2, 0x1ed3, 0x1ed4, 0x1ed5, 0x1ed6, 0x1ed7, /* 0x1ed0-0x1ed7 */
+ 0x1ed8, 0x1ed9, 0x1eda, 0x1edb, 0x1edc, 0x1edd, 0x1ede, 0x1edf, /* 0x1ed8-0x1edf */
+ 0x1ee0, 0x1ee1, 0x1ee2, 0x1ee3, 0x1ee4, 0x1ee5, 0x1ee6, 0x1ee7, /* 0x1ee0-0x1ee7 */
+ 0x1ee8, 0x1ee9, 0x1eea, 0x1eeb, 0x1eec, 0x1eed, 0x1eee, 0x1eef, /* 0x1ee8-0x1eef */
+ 0x1ef0, 0x1ef1, 0x0300, 0x0301, 0x1ef4, 0x1ef5, 0x1ef6, 0x1ef7, /* 0x1ef0-0x1ef7 */
+ 0x1ef8, 0x1ef9, 0x01a0, 0x01a1, 0x01af, 0x01b0, 0x0309, 0x0323 /* 0x1ef8-0x1eff */
};
static unsigned short const keysym_to_unicode_20a0_20ac[] = {
- 0x20a0, 0x20a1, 0x20a2, 0x20a3, 0x20a4, 0x20a5, 0x20a6, 0x20a7, /* 0x20a0-0x20a7 */
- 0x20a8, 0x20a9, 0x20aa, 0x20ab, 0x20ac /* 0x20a8-0x20af */
+ 0x20a0, 0x20a1, 0x20a2, 0x20a3, 0x20a4, 0x20a5, 0x20a6, 0x20a7, /* 0x20a0-0x20a7 */
+ 0x20a8, 0x20a9, 0x20aa, 0x20ab, 0x20ac /* 0x20a8-0x20af */
};
unsigned int
@@ -302,49 +301,50 @@ X11_KeySymToUcs4(KeySym keysym)
return (keysym & 0x00ffffff);
if (keysym > 0 && keysym < 0x100)
- return keysym;
+ return keysym;
else if (keysym > 0x1a0 && keysym < 0x200)
- return keysym_to_unicode_1a1_1ff[keysym - 0x1a1];
+ return keysym_to_unicode_1a1_1ff[keysym - 0x1a1];
else if (keysym > 0x2a0 && keysym < 0x2ff)
- return keysym_to_unicode_2a1_2fe[keysym - 0x2a1];
+ return keysym_to_unicode_2a1_2fe[keysym - 0x2a1];
else if (keysym > 0x3a1 && keysym < 0x3ff)
- return keysym_to_unicode_3a2_3fe[keysym - 0x3a2];
+ return keysym_to_unicode_3a2_3fe[keysym - 0x3a2];
else if (keysym > 0x4a0 && keysym < 0x4e0)
- return keysym_to_unicode_4a1_4df[keysym - 0x4a1];
+ return keysym_to_unicode_4a1_4df[keysym - 0x4a1];
else if (keysym > 0x589 && keysym < 0x5ff)
- return keysym_to_unicode_590_5fe[keysym - 0x590];
+ return keysym_to_unicode_590_5fe[keysym - 0x590];
else if (keysym > 0x67f && keysym < 0x700)
- return keysym_to_unicode_680_6ff[keysym - 0x680];
+ return keysym_to_unicode_680_6ff[keysym - 0x680];
else if (keysym > 0x7a0 && keysym < 0x7fa)
- return keysym_to_unicode_7a1_7f9[keysym - 0x7a1];
+ return keysym_to_unicode_7a1_7f9[keysym - 0x7a1];
else if (keysym > 0x8a3 && keysym < 0x8ff)
- return keysym_to_unicode_8a4_8fe[keysym - 0x8a4];
+ return keysym_to_unicode_8a4_8fe[keysym - 0x8a4];
else if (keysym > 0x9de && keysym < 0x9f9)
- return keysym_to_unicode_9df_9f8[keysym - 0x9df];
+ return keysym_to_unicode_9df_9f8[keysym - 0x9df];
else if (keysym > 0xaa0 && keysym < 0xaff)
- return keysym_to_unicode_aa1_afe[keysym - 0xaa1];
+ return keysym_to_unicode_aa1_afe[keysym - 0xaa1];
else if (keysym > 0xcde && keysym < 0xcfb)
- return keysym_to_unicode_cdf_cfa[keysym - 0xcdf];
+ return keysym_to_unicode_cdf_cfa[keysym - 0xcdf];
else if (keysym > 0xda0 && keysym < 0xdfa)
- return keysym_to_unicode_da1_df9[keysym - 0xda1];
+ return keysym_to_unicode_da1_df9[keysym - 0xda1];
else if (keysym > 0xe9f && keysym < 0xf00)
- return keysym_to_unicode_ea0_eff[keysym - 0xea0];
+ return keysym_to_unicode_ea0_eff[keysym - 0xea0];
else if (keysym > 0x12a0 && keysym < 0x12ff)
- return keysym_to_unicode_12a1_12fe[keysym - 0x12a1];
+ return keysym_to_unicode_12a1_12fe[keysym - 0x12a1];
else if (keysym > 0x13bb && keysym < 0x13bf)
- return keysym_to_unicode_13bc_13be[keysym - 0x13bc];
+ return keysym_to_unicode_13bc_13be[keysym - 0x13bc];
else if (keysym > 0x14a0 && keysym < 0x1500)
return keysym_to_unicode_14a1_14ff[keysym - 0x14a1];
else if (keysym > 0x15cf && keysym < 0x15f7)
- return keysym_to_unicode_15d0_15f6[keysym - 0x15d0];
+ return keysym_to_unicode_15d0_15f6[keysym - 0x15d0];
else if (keysym > 0x169f && keysym < 0x16f7)
- return keysym_to_unicode_16a0_16f6[keysym - 0x16a0];
+ return keysym_to_unicode_16a0_16f6[keysym - 0x16a0];
else if (keysym > 0x1e9e && keysym < 0x1f00)
- return keysym_to_unicode_1e9f_1eff[keysym - 0x1e9f];
+ return keysym_to_unicode_1e9f_1eff[keysym - 0x1e9f];
else if (keysym > 0x209f && keysym < 0x20ad)
- return keysym_to_unicode_20a0_20ac[keysym - 0x20a0];
+ return keysym_to_unicode_20a0_20ac[keysym - 0x20a0];
else
- return 0;
+ return 0;
}
#endif /* SDL_VIDEO_DRIVER_X11 */
+
diff --git a/Engine/lib/sdl/src/video/x11/imKStoUCS.h b/Engine/lib/sdl/src/video/x11/imKStoUCS.h
index cc684c2e3..fe4381d98 100644
--- a/Engine/lib/sdl/src/video/x11/imKStoUCS.h
+++ b/Engine/lib/sdl/src/video/x11/imKStoUCS.h
@@ -1,29 +1,30 @@
#ifndef _imKStoUCS_h
#define _imKStoUCS_h
-/* Copyright (C) 1994-2003 The XFree86 Project, Inc. All Rights Reserved.
+/*
+Copyright (C) 2003-2006,2008 Jamey Sharp, Josh Triplett
+Copyright © 2009 Red Hat, Inc.
+Copyright 1990-1992,1999,2000,2004,2009,2010 Oracle and/or its affiliates.
+All rights reserved.
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is fur-
-nished to do so, subject to the following conditions:
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
-NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
-IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CON-
-NECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of the XFree86 Project shall not
-be used in advertising or otherwise to promote the sale, use or other deal-
-ings in this Software without prior written authorization from the XFree86
-Project.
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
*/
extern unsigned int X11_KeySymToUcs4(KeySym keysym);
diff --git a/Engine/lib/sdl/test/Makefile.in b/Engine/lib/sdl/test/Makefile.in
index 9a1df774e..68f0d3dab 100644
--- a/Engine/lib/sdl/test/Makefile.in
+++ b/Engine/lib/sdl/test/Makefile.in
@@ -13,7 +13,10 @@ TARGETS = \
loopwavequeue$(EXE) \
testatomic$(EXE) \
testaudioinfo$(EXE) \
+ testaudiocapture$(EXE) \
testautomation$(EXE) \
+ testbounds$(EXE) \
+ testcustomcursor$(EXE) \
testdraw2$(EXE) \
testdrawchessboard$(EXE) \
testdropfile$(EXE) \
@@ -61,6 +64,7 @@ TARGETS = \
testrendercopyex$(EXE) \
testmessage$(EXE) \
testdisplayinfo$(EXE) \
+ testqsort$(EXE) \
controllermap$(EXE) \
all: Makefile $(TARGETS)
@@ -110,6 +114,9 @@ testmultiaudio$(EXE): $(srcdir)/testmultiaudio.c
testaudiohotplug$(EXE): $(srcdir)/testaudiohotplug.c
$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
+testaudiocapture$(EXE): $(srcdir)/testaudiocapture.c
+ $(CC) -o $@ $^ $(CFLAGS) $(LIBS)
+
testatomic$(EXE): $(srcdir)/testatomic.c
$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
@@ -270,6 +277,15 @@ testmessage$(EXE): $(srcdir)/testmessage.c
testdisplayinfo$(EXE): $(srcdir)/testdisplayinfo.c
$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
+testqsort$(EXE): $(srcdir)/testqsort.c
+ $(CC) -o $@ $^ $(CFLAGS) $(LIBS)
+
+testbounds$(EXE): $(srcdir)/testbounds.c
+ $(CC) -o $@ $^ $(CFLAGS) $(LIBS)
+
+testcustomcursor$(EXE): $(srcdir)/testcustomcursor.c
+ $(CC) -o $@ $^ $(CFLAGS) $(LIBS)
+
controllermap$(EXE): $(srcdir)/controllermap.c
$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
diff --git a/Engine/lib/sdl/test/autogen.sh b/Engine/lib/sdl/test/autogen.sh
old mode 100644
new mode 100755
diff --git a/Engine/lib/sdl/test/configure b/Engine/lib/sdl/test/configure
old mode 100644
new mode 100755
diff --git a/Engine/lib/sdl/test/controllermap.c b/Engine/lib/sdl/test/controllermap.c
index 3fb30d68a..d626f9f89 100644
--- a/Engine/lib/sdl/test/controllermap.c
+++ b/Engine/lib/sdl/test/controllermap.c
@@ -26,12 +26,9 @@
#define SCREEN_HEIGHT 480
#else
#define SCREEN_WIDTH 512
-#define SCREEN_HEIGHT 317
+#define SCREEN_HEIGHT 320
#endif
-#define MAP_WIDTH 512
-#define MAP_HEIGHT 317
-
#define MARKER_BUTTON 1
#define MARKER_AXIS 2
@@ -47,7 +44,7 @@ typedef struct MappingStep
SDL_Texture *
-LoadTexture(SDL_Renderer *renderer, char *file, SDL_bool transparent)
+LoadTexture(SDL_Renderer *renderer, const char *file, SDL_bool transparent)
{
SDL_Surface *temp;
SDL_Texture *texture;
@@ -226,7 +223,7 @@ WatchJoystick(SDL_Joystick * joystick)
SDL_RenderCopy(screen, background, NULL, NULL);
SDL_SetTextureAlphaMod(marker, alpha);
SDL_SetTextureColorMod(marker, 10, 255, 21);
- SDL_RenderCopyEx(screen, marker, NULL, &dst, step->angle, NULL, 0);
+ SDL_RenderCopyEx(screen, marker, NULL, &dst, step->angle, NULL, SDL_FLIP_NONE);
SDL_RenderPresent(screen);
if (SDL_PollEvent(&event)) {
diff --git a/Engine/lib/sdl/test/gcc-fat.sh b/Engine/lib/sdl/test/gcc-fat.sh
old mode 100644
new mode 100755
diff --git a/Engine/lib/sdl/test/testatomic.c b/Engine/lib/sdl/test/testatomic.c
index 41cc9ab1b..d371ef31f 100644
--- a/Engine/lib/sdl/test/testatomic.c
+++ b/Engine/lib/sdl/test/testatomic.c
@@ -284,7 +284,7 @@ typedef struct
char cache_pad4[SDL_CACHELINE_SIZE-sizeof(SDL_SpinLock)-2*sizeof(SDL_atomic_t)];
#endif
- volatile SDL_bool active;
+ SDL_atomic_t active;
/* Only needed for the mutex test */
SDL_mutex *mutex;
@@ -305,7 +305,7 @@ static void InitEventQueue(SDL_EventQueue *queue)
SDL_AtomicSet(&queue->rwcount, 0);
SDL_AtomicSet(&queue->watcher, 0);
#endif
- queue->active = SDL_TRUE;
+ SDL_AtomicSet(&queue->active, 1);
}
static SDL_bool EnqueueEvent_LockFree(SDL_EventQueue *queue, const SDL_Event *event)
@@ -538,7 +538,7 @@ static int FIFO_Reader(void* _data)
if (DequeueEvent_LockFree(queue, &event)) {
WriterData *writer = (WriterData*)event.user.data1;
++data->counters[writer->index];
- } else if (queue->active) {
+ } else if (SDL_AtomicGet(&queue->active)) {
++data->waits;
SDL_Delay(0);
} else {
@@ -551,7 +551,7 @@ static int FIFO_Reader(void* _data)
if (DequeueEvent_Mutex(queue, &event)) {
WriterData *writer = (WriterData*)event.user.data1;
++data->counters[writer->index];
- } else if (queue->active) {
+ } else if (SDL_AtomicGet(&queue->active)) {
++data->waits;
SDL_Delay(0);
} else {
@@ -571,7 +571,7 @@ static int FIFO_Watcher(void* _data)
{
SDL_EventQueue *queue = (SDL_EventQueue *)_data;
- while (queue->active) {
+ while (SDL_AtomicGet(&queue->active)) {
SDL_AtomicLock(&queue->lock);
SDL_AtomicIncRef(&queue->watcher);
while (SDL_AtomicGet(&queue->rwcount) > 0) {
@@ -652,7 +652,7 @@ static void RunFIFOTest(SDL_bool lock_free)
}
/* Shut down the queue so readers exit */
- queue.active = SDL_FALSE;
+ SDL_AtomicSet(&queue.active, 0);
/* Wait for the readers */
while (SDL_AtomicGet(&readersRunning) > 0) {
diff --git a/Engine/lib/sdl/test/testaudiocapture.c b/Engine/lib/sdl/test/testaudiocapture.c
new file mode 100644
index 000000000..26321a71c
--- /dev/null
+++ b/Engine/lib/sdl/test/testaudiocapture.c
@@ -0,0 +1,165 @@
+/*
+ Copyright (C) 1997-2016 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely.
+*/
+#include "SDL.h"
+
+#include
+
+#ifdef __EMSCRIPTEN__
+#include
+#endif
+
+static SDL_Window *window = NULL;
+static SDL_Renderer *renderer = NULL;
+static SDL_AudioSpec spec;
+static SDL_AudioDeviceID devid_in = 0;
+static SDL_AudioDeviceID devid_out = 0;
+
+static void
+loop()
+{
+ SDL_bool please_quit = SDL_FALSE;
+ SDL_Event e;
+
+ while (SDL_PollEvent(&e)) {
+ if (e.type == SDL_QUIT) {
+ please_quit = SDL_TRUE;
+ } else if (e.type == SDL_KEYDOWN) {
+ if (e.key.keysym.sym == SDLK_ESCAPE) {
+ please_quit = SDL_TRUE;
+ }
+ } else if (e.type == SDL_MOUSEBUTTONDOWN) {
+ if (e.button.button == 1) {
+ SDL_PauseAudioDevice(devid_out, SDL_TRUE);
+ SDL_PauseAudioDevice(devid_in, SDL_FALSE);
+ }
+ } else if (e.type == SDL_MOUSEBUTTONUP) {
+ if (e.button.button == 1) {
+ SDL_PauseAudioDevice(devid_in, SDL_TRUE);
+ SDL_PauseAudioDevice(devid_out, SDL_FALSE);
+ }
+ }
+ }
+
+ if (SDL_GetAudioDeviceStatus(devid_in) == SDL_AUDIO_PLAYING) {
+ SDL_SetRenderDrawColor(renderer, 0, 255, 0, 255);
+ } else {
+ SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);
+ }
+ SDL_RenderClear(renderer);
+ SDL_RenderPresent(renderer);
+
+ if (please_quit) {
+ /* stop playing back, quit. */
+ SDL_Log("Shutting down.\n");
+ SDL_PauseAudioDevice(devid_in, 1);
+ SDL_CloseAudioDevice(devid_in);
+ SDL_PauseAudioDevice(devid_out, 1);
+ SDL_CloseAudioDevice(devid_out);
+ SDL_DestroyRenderer(renderer);
+ SDL_DestroyWindow(window);
+ SDL_Quit();
+ #ifdef __EMSCRIPTEN__
+ emscripten_cancel_main_loop();
+ #endif
+ exit(0);
+ }
+
+ /* Note that it would be easier to just have a one-line function that
+ calls SDL_QueueAudio() as a capture device callback, but we're
+ trying to test the API, so we use SDL_DequeueAudio() here. */
+ while (SDL_TRUE) {
+ Uint8 buf[1024];
+ const Uint32 br = SDL_DequeueAudio(devid_in, buf, sizeof (buf));
+ SDL_QueueAudio(devid_out, buf, br);
+ if (br < sizeof (buf)) {
+ break;
+ }
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ /* (argv[1] == NULL means "open default device.") */
+ const char *devname = argv[1];
+ SDL_AudioSpec wanted;
+ int devcount;
+ int i;
+
+ /* Enable standard application logging */
+ SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
+
+ /* Load the SDL library */
+ if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError());
+ return (1);
+ }
+
+ window = SDL_CreateWindow("testaudiocapture", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 320, 240, 0);
+ renderer = SDL_CreateRenderer(window, -1, 0);
+ SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
+ SDL_RenderClear(renderer);
+ SDL_RenderPresent(renderer);
+
+ SDL_Log("Using audio driver: %s\n", SDL_GetCurrentAudioDriver());
+
+ devcount = SDL_GetNumAudioDevices(SDL_TRUE);
+ for (i = 0; i < devcount; i++) {
+ SDL_Log(" Capture device #%d: '%s'\n", i, SDL_GetAudioDeviceName(i, SDL_TRUE));
+ }
+
+ SDL_zero(wanted);
+ wanted.freq = 44100;
+ wanted.format = AUDIO_F32SYS;
+ wanted.channels = 1;
+ wanted.samples = 4096;
+ wanted.callback = NULL;
+
+ SDL_zero(spec);
+
+ /* DirectSound can fail in some instances if you open the same hardware
+ for both capture and output and didn't open the output end first,
+ according to the docs, so if you're doing something like this, always
+ open your capture devices second in case you land in those bizarre
+ circumstances. */
+
+ SDL_Log("Opening default playback device...\n");
+ devid_out = SDL_OpenAudioDevice(NULL, SDL_FALSE, &wanted, &spec, SDL_AUDIO_ALLOW_ANY_CHANGE);
+ if (!devid_out) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open an audio device for playback: %s!\n", SDL_GetError());
+ SDL_Quit();
+ exit(1);
+ }
+
+ SDL_Log("Opening capture device %s%s%s...\n",
+ devname ? "'" : "",
+ devname ? devname : "[[default]]",
+ devname ? "'" : "");
+
+ devid_in = SDL_OpenAudioDevice(argv[1], SDL_TRUE, &spec, &spec, 0);
+ if (!devid_in) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't open an audio device for capture: %s!\n", SDL_GetError());
+ SDL_Quit();
+ exit(1);
+ }
+
+ SDL_Log("Ready! Hold down mouse or finger to record!\n");
+
+#ifdef __EMSCRIPTEN__
+ emscripten_set_main_loop(loop, 0, 1);
+#else
+ while (1) { loop(); SDL_Delay(16); }
+#endif
+
+ return 0;
+}
+
diff --git a/Engine/lib/sdl/test/testaudiohotplug.c b/Engine/lib/sdl/test/testaudiohotplug.c
index e13868ec2..73d480505 100644
--- a/Engine/lib/sdl/test/testaudiohotplug.c
+++ b/Engine/lib/sdl/test/testaudiohotplug.c
@@ -74,6 +74,12 @@ poked(int sig)
done = 1;
}
+static const char*
+devtypestr(int iscapture)
+{
+ return iscapture ? "capture" : "output";
+}
+
static void
iteration()
{
@@ -82,10 +88,21 @@ iteration()
while (SDL_PollEvent(&e)) {
if (e.type == SDL_QUIT) {
done = 1;
+ } else if (e.type == SDL_KEYUP) {
+ if (e.key.keysym.sym == SDLK_ESCAPE)
+ done = 1;
} else if (e.type == SDL_AUDIODEVICEADDED) {
- const char *name = SDL_GetAudioDeviceName(e.adevice.which, 0);
- SDL_Log("New %s audio device: %s\n", e.adevice.iscapture ? "capture" : "output", name);
- if (!e.adevice.iscapture) {
+ int index = e.adevice.which;
+ int iscapture = e.adevice.iscapture;
+ const char *name = SDL_GetAudioDeviceName(index, iscapture);
+ if (name != NULL)
+ SDL_Log("New %s audio device at index %u: %s\n", devtypestr(iscapture), (unsigned int) index, name);
+ else {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Got new %s device at index %u, but failed to get the name: %s\n",
+ devtypestr(iscapture), (unsigned int) index, SDL_GetError());
+ continue;
+ }
+ if (!iscapture) {
positions[posindex] = 0;
spec.userdata = &positions[posindex++];
spec.callback = fillerup;
@@ -99,7 +116,7 @@ iteration()
}
} else if (e.type == SDL_AUDIODEVICEREMOVED) {
dev = (SDL_AudioDeviceID) e.adevice.which;
- SDL_Log("%s device %u removed.\n", e.adevice.iscapture ? "capture" : "output", (unsigned int) dev);
+ SDL_Log("%s device %u removed.\n", devtypestr(e.adevice.iscapture), (unsigned int) dev);
SDL_CloseAudioDevice(dev);
}
}
@@ -163,6 +180,7 @@ main(int argc, char *argv[])
SDL_Log("%i: %s", i, SDL_GetAudioDriver(i));
}
+ SDL_Log("Select a driver with the SDL_AUDIODRIVER environment variable.\n");
SDL_Log("Using audio driver: %s\n", SDL_GetCurrentAudioDriver());
#ifdef __EMSCRIPTEN__
@@ -175,6 +193,8 @@ main(int argc, char *argv[])
#endif
/* Clean up on signal */
+ /* Quit audio first, then free WAV. This prevents access violations in the audio threads. */
+ SDL_QuitSubSystem(SDL_INIT_AUDIO);
SDL_FreeWAV(sound);
SDL_Quit();
return (0);
diff --git a/Engine/lib/sdl/test/testaudioinfo.c b/Engine/lib/sdl/test/testaudioinfo.c
index 53bf0f5e2..485fd0a38 100644
--- a/Engine/lib/sdl/test/testaudioinfo.c
+++ b/Engine/lib/sdl/test/testaudioinfo.c
@@ -18,7 +18,7 @@ print_devices(int iscapture)
const char *typestr = ((iscapture) ? "capture" : "output");
int n = SDL_GetNumAudioDevices(iscapture);
- SDL_Log("%s devices:\n", typestr);
+ SDL_Log("Found %d %s device%s:\n", n, typestr, n != 1 ? "s" : "");
if (n == -1)
SDL_Log(" Driver can't detect specific %s devices.\n\n", typestr);
@@ -27,7 +27,11 @@ print_devices(int iscapture)
else {
int i;
for (i = 0; i < n; i++) {
- SDL_Log(" %s\n", SDL_GetAudioDeviceName(i, iscapture));
+ const char *name = SDL_GetAudioDeviceName(i, iscapture);
+ if (name != NULL)
+ SDL_Log(" %d: %s\n", i, name);
+ else
+ SDL_Log(" %d Error: %s\n", i, SDL_GetError());
}
SDL_Log("\n");
}
@@ -55,9 +59,9 @@ main(int argc, char **argv)
int i;
SDL_Log("Built-in audio drivers:\n");
for (i = 0; i < n; ++i) {
- SDL_Log(" %s\n", SDL_GetAudioDriver(i));
+ SDL_Log(" %d: %s\n", i, SDL_GetAudioDriver(i));
}
- SDL_Log("\n");
+ SDL_Log("Select a driver with the SDL_AUDIODRIVER environment variable.\n");
}
SDL_Log("Using audio driver: %s\n\n", SDL_GetCurrentAudioDriver());
diff --git a/Engine/lib/sdl/test/testautomation_events.c b/Engine/lib/sdl/test/testautomation_events.c
index f9eb5bb9e..a0119bdbe 100644
--- a/Engine/lib/sdl/test/testautomation_events.c
+++ b/Engine/lib/sdl/test/testautomation_events.c
@@ -87,7 +87,7 @@ events_addDelEventWatch(void *arg)
/* Create user event */
event.type = SDL_USEREVENT;
- event.user.code = SDLTest_RandomSint32();;
+ event.user.code = SDLTest_RandomSint32();
event.user.data1 = (void *)&_userdataValue1;
event.user.data2 = (void *)&_userdataValue2;
@@ -137,7 +137,7 @@ events_addDelEventWatchWithUserdata(void *arg)
/* Create user event */
event.type = SDL_USEREVENT;
- event.user.code = SDLTest_RandomSint32();;
+ event.user.code = SDLTest_RandomSint32();
event.user.data1 = (void *)&_userdataValue1;
event.user.data2 = (void *)&_userdataValue2;
diff --git a/Engine/lib/sdl/test/testautomation_keyboard.c b/Engine/lib/sdl/test/testautomation_keyboard.c
index 453832e25..b2c3b9ae1 100644
--- a/Engine/lib/sdl/test/testautomation_keyboard.c
+++ b/Engine/lib/sdl/test/testautomation_keyboard.c
@@ -401,8 +401,8 @@ keyboard_setTextInputRect(void *arg)
SDL_Rect refRect;
/* Normal visible refRect, origin inside */
- refRect.x = SDLTest_RandomIntegerInRange(1, 50);;
- refRect.y = SDLTest_RandomIntegerInRange(1, 50);;
+ refRect.x = SDLTest_RandomIntegerInRange(1, 50);
+ refRect.y = SDLTest_RandomIntegerInRange(1, 50);
refRect.w = SDLTest_RandomIntegerInRange(10, 50);
refRect.h = SDLTest_RandomIntegerInRange(10, 50);
_testSetTextInputRect(refRect);
@@ -415,8 +415,8 @@ keyboard_setTextInputRect(void *arg)
_testSetTextInputRect(refRect);
/* 1Pixel refRect */
- refRect.x = SDLTest_RandomIntegerInRange(10, 50);;
- refRect.y = SDLTest_RandomIntegerInRange(10, 50);;
+ refRect.x = SDLTest_RandomIntegerInRange(10, 50);
+ refRect.y = SDLTest_RandomIntegerInRange(10, 50);
refRect.w = 1;
refRect.h = 1;
_testSetTextInputRect(refRect);
@@ -450,15 +450,15 @@ keyboard_setTextInputRect(void *arg)
_testSetTextInputRect(refRect);
/* negative refRect */
- refRect.x = SDLTest_RandomIntegerInRange(-200, -100);;
- refRect.y = SDLTest_RandomIntegerInRange(-200, -100);;
+ refRect.x = SDLTest_RandomIntegerInRange(-200, -100);
+ refRect.y = SDLTest_RandomIntegerInRange(-200, -100);
refRect.w = 50;
refRect.h = 50;
_testSetTextInputRect(refRect);
/* oversized refRect */
- refRect.x = SDLTest_RandomIntegerInRange(1, 50);;
- refRect.y = SDLTest_RandomIntegerInRange(1, 50);;
+ refRect.x = SDLTest_RandomIntegerInRange(1, 50);
+ refRect.y = SDLTest_RandomIntegerInRange(1, 50);
refRect.w = 5000;
refRect.h = 5000;
_testSetTextInputRect(refRect);
diff --git a/Engine/lib/sdl/test/testautomation_main.c b/Engine/lib/sdl/test/testautomation_main.c
index ef8f19e9e..ae060cdd1 100644
--- a/Engine/lib/sdl/test/testautomation_main.c
+++ b/Engine/lib/sdl/test/testautomation_main.c
@@ -137,7 +137,7 @@ static const SDLTest_TestCaseReference mainTest3 =
static const SDLTest_TestCaseReference mainTest4 =
{ (SDLTest_TestCaseFp)main_testImpliedJoystickQuit, "main_testImpliedJoystickQuit", "Tests that quit for gamecontroller doesn't quit joystick if you inited it explicitly", TEST_ENABLED};
-/* Sequence of Platform test cases */
+/* Sequence of Main test cases */
static const SDLTest_TestCaseReference *mainTests[] = {
&mainTest1,
&mainTest2,
@@ -146,7 +146,7 @@ static const SDLTest_TestCaseReference *mainTests[] = {
NULL
};
-/* Platform test suite (global) */
+/* Main test suite (global) */
SDLTest_TestSuiteReference mainTestSuite = {
"Main",
NULL,
diff --git a/Engine/lib/sdl/test/testautomation_sdltest.c b/Engine/lib/sdl/test/testautomation_sdltest.c
index ec1da8a50..54cd6e257 100644
--- a/Engine/lib/sdl/test/testautomation_sdltest.c
+++ b/Engine/lib/sdl/test/testautomation_sdltest.c
@@ -1093,7 +1093,7 @@ sdltest_randomIntegerInRange(void *arg)
SDLTest_AssertCheck(min <= result && result <= max, "Validated returned value; expected: [%d,%d], got: %d", min, max, result);
/* Range with max at integer limit */
- min = long_min - (Sint32)SDLTest_RandomSint16();;
+ min = long_min - (Sint32)SDLTest_RandomSint16();
max = long_max;
result = SDLTest_RandomIntegerInRange(min, max);
SDLTest_AssertPass("Call to SDLTest_RandomIntegerInRange(...,SINT32_MAX)");
diff --git a/Engine/lib/sdl/test/testautomation_stdlib.c b/Engine/lib/sdl/test/testautomation_stdlib.c
index 89245fdcb..b541995f5 100644
--- a/Engine/lib/sdl/test/testautomation_stdlib.c
+++ b/Engine/lib/sdl/test/testautomation_stdlib.c
@@ -253,6 +253,43 @@ stdlib_getsetenv(void *arg)
return TEST_COMPLETED;
}
+/**
+ * @brief Call to SDL_sscanf
+ */
+#undef SDL_sscanf
+int
+stdlib_sscanf(void *arg)
+{
+ int output;
+ int result;
+ int expected_output;
+ int expected_result;
+
+ expected_output = output = 123;
+ expected_result = -1;
+ result = SDL_sscanf("", "%i", &output);
+ SDLTest_AssertPass("Call to SDL_sscanf(\"\", \"%%i\", &output)");
+ SDLTest_AssertCheck(expected_output == output, "Check output, expected: %i, got: %i", expected_output, output);
+ SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result);
+
+ expected_output = output = 123;
+ expected_result = 0;
+ result = SDL_sscanf("a", "%i", &output);
+ SDLTest_AssertPass("Call to SDL_sscanf(\"a\", \"%%i\", &output)");
+ SDLTest_AssertCheck(expected_output == output, "Check output, expected: %i, got: %i", expected_output, output);
+ SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result);
+
+ output = 123;
+ expected_output = 2;
+ expected_result = 1;
+ result = SDL_sscanf("2", "%i", &output);
+ SDLTest_AssertPass("Call to SDL_sscanf(\"2\", \"%%i\", &output)");
+ SDLTest_AssertCheck(expected_output == output, "Check output, expected: %i, got: %i", expected_output, output);
+ SDLTest_AssertCheck(expected_result == result, "Check return value, expected: %i, got: %i", expected_result, result);
+
+ return TEST_COMPLETED;
+}
+
/* ================= Test References ================== */
/* Standard C routine test cases */
@@ -265,12 +302,15 @@ static const SDLTest_TestCaseReference stdlibTest2 =
static const SDLTest_TestCaseReference stdlibTest3 =
{ (SDLTest_TestCaseFp)stdlib_getsetenv, "stdlib_getsetenv", "Call to SDL_getenv and SDL_setenv", TEST_ENABLED };
+static const SDLTest_TestCaseReference stdlibTest4 =
+ { (SDLTest_TestCaseFp)stdlib_sscanf, "stdlib_sscanf", "Call to SDL_sscanf", TEST_ENABLED };
+
/* Sequence of Standard C routine test cases */
static const SDLTest_TestCaseReference *stdlibTests[] = {
- &stdlibTest1, &stdlibTest2, &stdlibTest3, NULL
+ &stdlibTest1, &stdlibTest2, &stdlibTest3, &stdlibTest4, NULL
};
-/* Timer test suite (global) */
+/* Standard C routine test suite (global) */
SDLTest_TestSuiteReference stdlibTestSuite = {
"Stdlib",
NULL,
diff --git a/Engine/lib/sdl/test/testbounds.c b/Engine/lib/sdl/test/testbounds.c
new file mode 100644
index 000000000..b410be96c
--- /dev/null
+++ b/Engine/lib/sdl/test/testbounds.c
@@ -0,0 +1,40 @@
+/*
+ Copyright (C) 1997-2014 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely.
+*/
+
+#include "SDL.h"
+
+int main(int argc, char **argv)
+{
+ int total, i;
+
+ if (SDL_Init(SDL_INIT_VIDEO) < 0) {
+ SDL_Log("SDL_Init(SDL_INIT_VIDEO) failed: %s", SDL_GetError());
+ return 1;
+ }
+
+ total = SDL_GetNumVideoDisplays();
+ for (i = 0; i < total; i++) {
+ SDL_Rect bounds = { -1,-1,-1,-1 }, usable = { -1,-1,-1,-1 };
+ SDL_GetDisplayBounds(i, &bounds);
+ SDL_GetDisplayUsableBounds(i, &usable);
+ SDL_Log("Display #%d ('%s'): bounds={(%d,%d),%dx%d}, usable={(%d,%d),%dx%d}",
+ i, SDL_GetDisplayName(i),
+ bounds.x, bounds.y, bounds.w, bounds.h,
+ usable.x, usable.y, usable.w, usable.h);
+ }
+
+ SDL_Quit();
+ return 0;
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
+
diff --git a/Engine/lib/sdl/test/testcustomcursor.c b/Engine/lib/sdl/test/testcustomcursor.c
new file mode 100644
index 000000000..88b5c322d
--- /dev/null
+++ b/Engine/lib/sdl/test/testcustomcursor.c
@@ -0,0 +1,216 @@
+/*
+ Copyright (C) 1997-2016 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely.
+*/
+
+#include
+#include
+
+#ifdef __EMSCRIPTEN__
+#include
+#endif
+
+#include "SDL_test_common.h"
+
+/* Stolen from the mailing list */
+/* Creates a new mouse cursor from an XPM */
+
+
+/* XPM */
+static const char *arrow[] = {
+ /* width height num_colors chars_per_pixel */
+ " 32 32 3 1",
+ /* colors */
+ "X c #000000",
+ ". c #ffffff",
+ " c None",
+ /* pixels */
+ "X ",
+ "XX ",
+ "X.X ",
+ "X..X ",
+ "X...X ",
+ "X....X ",
+ "X.....X ",
+ "X......X ",
+ "X.......X ",
+ "X........X ",
+ "X.....XXXXX ",
+ "X..X..X ",
+ "X.X X..X ",
+ "XX X..X ",
+ "X X..X ",
+ " X..X ",
+ " X..X ",
+ " X..X ",
+ " XX ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ "0,0"
+};
+
+static SDL_Cursor*
+init_color_cursor(const char *file)
+{
+ SDL_Cursor *cursor = NULL;
+ SDL_Surface *surface = SDL_LoadBMP(file);
+ if (surface) {
+ cursor = SDL_CreateColorCursor(surface, 0, 0);
+ SDL_FreeSurface(surface);
+ }
+ return cursor;
+}
+
+static SDL_Cursor*
+init_system_cursor(const char *image[])
+{
+ int i, row, col;
+ Uint8 data[4*32];
+ Uint8 mask[4*32];
+ int hot_x, hot_y;
+
+ i = -1;
+ for (row=0; row<32; ++row) {
+ for (col=0; col<32; ++col) {
+ if (col % 8) {
+ data[i] <<= 1;
+ mask[i] <<= 1;
+ } else {
+ ++i;
+ data[i] = mask[i] = 0;
+ }
+ switch (image[4+row][col]) {
+ case 'X':
+ data[i] |= 0x01;
+ mask[i] |= 0x01;
+ break;
+ case '.':
+ mask[i] |= 0x01;
+ break;
+ case ' ':
+ break;
+ }
+ }
+ }
+ sscanf(image[4+row], "%d,%d", &hot_x, &hot_y);
+ return SDL_CreateCursor(data, mask, 32, 32, hot_x, hot_y);
+}
+
+static SDLTest_CommonState *state;
+int done;
+SDL_Cursor *cursor = NULL;
+
+/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
+static void
+quit(int rc)
+{
+ SDLTest_CommonQuit(state);
+ exit(rc);
+}
+
+void
+loop()
+{
+ int i;
+ SDL_Event event;
+ /* Check for events */
+ while (SDL_PollEvent(&event)) {
+ SDLTest_CommonEvent(state, &event, &done);
+ }
+
+ for (i = 0; i < state->num_windows; ++i) {
+ SDL_Renderer *renderer = state->renderers[i];
+ SDL_RenderClear(renderer);
+ SDL_RenderPresent(renderer);
+ }
+#ifdef __EMSCRIPTEN__
+ if (done) {
+ emscripten_cancel_main_loop();
+ }
+#endif
+}
+
+int
+main(int argc, char *argv[])
+{
+ int i;
+ const char *color_cursor = NULL;
+
+ /* Enable standard application logging */
+ SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO);
+
+ /* Initialize test framework */
+ state = SDLTest_CommonCreateState(argv, SDL_INIT_VIDEO);
+ if (!state) {
+ return 1;
+ }
+ for (i = 1; i < argc;) {
+ int consumed;
+
+ consumed = SDLTest_CommonArg(state, i);
+ if (consumed == 0) {
+ color_cursor = argv[i];
+ break;
+ }
+ if (consumed < 0) {
+ SDL_Log("Usage: %s %s\n", argv[0], SDLTest_CommonUsage(state));
+ quit(1);
+ }
+ i += consumed;
+ }
+
+ if (!SDLTest_CommonInit(state)) {
+ quit(2);
+ }
+
+ for (i = 0; i < state->num_windows; ++i) {
+ SDL_Renderer *renderer = state->renderers[i];
+ SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
+ SDL_RenderClear(renderer);
+ }
+
+ if (color_cursor) {
+ cursor = init_color_cursor(color_cursor);
+ } else {
+ cursor = init_system_cursor(arrow);
+ }
+ if (!cursor) {
+ SDL_Log("Error, couldn't create cursor\n");
+ quit(2);
+ }
+ SDL_SetCursor(cursor);
+
+ /* Main render loop */
+ done = 0;
+#ifdef __EMSCRIPTEN__
+ emscripten_set_main_loop(loop, 0, 1);
+#else
+ while (!done) {
+ loop();
+ }
+#endif
+
+ SDL_FreeCursor(cursor);
+ quit(0);
+
+ /* keep the compiler happy ... */
+ return(0);
+}
diff --git a/Engine/lib/sdl/test/testdisplayinfo.c b/Engine/lib/sdl/test/testdisplayinfo.c
index c228eb6b2..f06722e88 100644
--- a/Engine/lib/sdl/test/testdisplayinfo.c
+++ b/Engine/lib/sdl/test/testdisplayinfo.c
@@ -51,11 +51,18 @@ main(int argc, char *argv[])
for (dpy = 0; dpy < num_displays; dpy++) {
const int num_modes = SDL_GetNumDisplayModes(dpy);
SDL_Rect rect = { 0, 0, 0, 0 };
+ float ddpi, hdpi, vdpi;
int m;
SDL_GetDisplayBounds(dpy, &rect);
SDL_Log("%d: \"%s\" (%dx%d, (%d, %d)), %d modes.\n", dpy, SDL_GetDisplayName(dpy), rect.w, rect.h, rect.x, rect.y, num_modes);
+ if (SDL_GetDisplayDPI(dpy, &ddpi, &hdpi, &vdpi) == -1) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, " DPI: failed to query (%s)\n", SDL_GetError());
+ } else {
+ SDL_Log(" DPI: ddpi=%f; hdpi=%f; vdpi=%f\n", ddpi, hdpi, vdpi);
+ }
+
if (SDL_GetCurrentDisplayMode(dpy, &mode) == -1) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, " CURRENT: failed to query (%s)\n", SDL_GetError());
} else {
diff --git a/Engine/lib/sdl/test/testdrawchessboard.c b/Engine/lib/sdl/test/testdrawchessboard.c
index f2a1469d4..af929e9c3 100644
--- a/Engine/lib/sdl/test/testdrawchessboard.c
+++ b/Engine/lib/sdl/test/testdrawchessboard.c
@@ -100,7 +100,7 @@ main(int argc, char *argv[])
/* Create window and renderer for given surface */
- window = SDL_CreateWindow("Chess Board", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, SDL_WINDOW_SHOWN);
+ window = SDL_CreateWindow("Chess Board", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0);
if(!window)
{
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Window creation fail : %s\n",SDL_GetError());
diff --git a/Engine/lib/sdl/test/testdropfile.c b/Engine/lib/sdl/test/testdropfile.c
index b7f215ee8..b729b2f64 100644
--- a/Engine/lib/sdl/test/testdropfile.c
+++ b/Engine/lib/sdl/test/testdropfile.c
@@ -77,9 +77,14 @@ main(int argc, char *argv[])
while (SDL_PollEvent(&event)) {
SDLTest_CommonEvent(state, &event, &done);
- if (event.type == SDL_DROPFILE) {
+ if (event.type == SDL_DROPBEGIN) {
+ SDL_Log("Drop beginning on window %u", (unsigned int) event.drop.windowID);
+ } else if (event.type == SDL_DROPCOMPLETE) {
+ SDL_Log("Drop complete on window %u", (unsigned int) event.drop.windowID);
+ } else if ((event.type == SDL_DROPFILE) || (event.type == SDL_DROPTEXT)) {
+ const char *typestr = (event.type == SDL_DROPFILE) ? "File" : "Text";
char *dropped_filedir = event.drop.file;
- SDL_Log("File dropped on window: %s", dropped_filedir);
+ SDL_Log("%s dropped on window %u: %s", typestr, (unsigned int) event.drop.windowID, dropped_filedir);
SDL_free(dropped_filedir);
}
}
diff --git a/Engine/lib/sdl/test/testfilesystem.c b/Engine/lib/sdl/test/testfilesystem.c
index abd301c0e..61a6d5a5a 100644
--- a/Engine/lib/sdl/test/testfilesystem.c
+++ b/Engine/lib/sdl/test/testfilesystem.c
@@ -32,9 +32,8 @@ main(int argc, char *argv[])
if(base_path == NULL){
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't find base path: %s\n",
SDL_GetError());
- return 0;
+ return 1;
}
-
SDL_Log("base path: '%s'\n", base_path);
SDL_free(base_path);
@@ -42,7 +41,7 @@ main(int argc, char *argv[])
if(pref_path == NULL){
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't find pref path: %s\n",
SDL_GetError());
- return 0;
+ return 1;
}
SDL_Log("pref path: '%s'\n", pref_path);
SDL_free(pref_path);
diff --git a/Engine/lib/sdl/test/testgamecontroller.c b/Engine/lib/sdl/test/testgamecontroller.c
index ec1dfd322..38d2f7708 100644
--- a/Engine/lib/sdl/test/testgamecontroller.c
+++ b/Engine/lib/sdl/test/testgamecontroller.c
@@ -29,7 +29,7 @@
#define SCREEN_HEIGHT 320
#else
#define SCREEN_WIDTH 512
-#define SCREEN_HEIGHT 317
+#define SCREEN_HEIGHT 320
#endif
/* This is indexed by SDL_GameControllerButton. */
@@ -67,7 +67,7 @@ SDL_bool done = SDL_FALSE;
SDL_Texture *background, *button, *axis;
static SDL_Texture *
-LoadTexture(SDL_Renderer *renderer, char *file, SDL_bool transparent)
+LoadTexture(SDL_Renderer *renderer, const char *file, SDL_bool transparent)
{
SDL_Surface *temp = NULL;
SDL_Texture *texture = NULL;
@@ -129,7 +129,7 @@ loop(void *arg)
for (i = 0; i < SDL_CONTROLLER_BUTTON_MAX; ++i) {
if (SDL_GameControllerGetButton(gamecontroller, (SDL_GameControllerButton)i) == SDL_PRESSED) {
const SDL_Rect dst = { button_positions[i].x, button_positions[i].y, 50, 50 };
- SDL_RenderCopyEx(screen, button, NULL, &dst, 0, NULL, 0);
+ SDL_RenderCopyEx(screen, button, NULL, &dst, 0, NULL, SDL_FLIP_NONE);
}
}
@@ -139,11 +139,11 @@ loop(void *arg)
if (value < -deadzone) {
const SDL_Rect dst = { axis_positions[i].x, axis_positions[i].y, 50, 50 };
const double angle = axis_positions[i].angle;
- SDL_RenderCopyEx(screen, axis, NULL, &dst, angle, NULL, 0);
+ SDL_RenderCopyEx(screen, axis, NULL, &dst, angle, NULL, SDL_FLIP_NONE);
} else if (value > deadzone) {
const SDL_Rect dst = { axis_positions[i].x, axis_positions[i].y, 50, 50 };
const double angle = axis_positions[i].angle + 180.0;
- SDL_RenderCopyEx(screen, axis, NULL, &dst, angle, NULL, 0);
+ SDL_RenderCopyEx(screen, axis, NULL, &dst, angle, NULL, SDL_FLIP_NONE);
}
}
@@ -181,6 +181,8 @@ WatchGameController(SDL_GameController * gamecontroller)
window = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, SCREEN_WIDTH,
SCREEN_HEIGHT, 0);
+ SDL_free(title);
+ title = NULL;
if (window == NULL) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create window: %s\n", SDL_GetError());
return SDL_FALSE;
diff --git a/Engine/lib/sdl/test/testgles.c b/Engine/lib/sdl/test/testgles.c
index 291661a09..5be48ac56 100644
--- a/Engine/lib/sdl/test/testgles.c
+++ b/Engine/lib/sdl/test/testgles.c
@@ -173,7 +173,7 @@ main(int argc, char *argv[])
quit(2);
}
- context = SDL_calloc(state->num_windows, sizeof(context));
+ context = (SDL_GLContext *)SDL_calloc(state->num_windows, sizeof(context));
if (context == NULL) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Out of memory!\n");
quit(2);
diff --git a/Engine/lib/sdl/test/testgles2.c b/Engine/lib/sdl/test/testgles2.c
index af5962ba4..45b3d79a3 100644
--- a/Engine/lib/sdl/test/testgles2.c
+++ b/Engine/lib/sdl/test/testgles2.c
@@ -546,7 +546,7 @@ main(int argc, char *argv[])
return 0;
}
- context = SDL_calloc(state->num_windows, sizeof(context));
+ context = (SDL_GLContext *)SDL_calloc(state->num_windows, sizeof(context));
if (context == NULL) {
SDL_Log("Out of memory!\n");
quit(2);
@@ -640,7 +640,7 @@ main(int argc, char *argv[])
}
}
- datas = SDL_calloc(state->num_windows, sizeof(shader_data));
+ datas = (shader_data *)SDL_calloc(state->num_windows, sizeof(shader_data));
/* Set rendering settings for each context */
for (i = 0; i < state->num_windows; ++i) {
diff --git a/Engine/lib/sdl/test/testime.c b/Engine/lib/sdl/test/testime.c
index d6e7ea1f2..39a40f82f 100644
--- a/Engine/lib/sdl/test/testime.c
+++ b/Engine/lib/sdl/test/testime.c
@@ -9,7 +9,9 @@
including commercial applications, and to alter it and redistribute it
freely.
*/
-/* A simple program to test the Input Method support in the SDL library (2.0+) */
+/* A simple program to test the Input Method support in the SDL library (2.0+)
+ If you build without SDL_ttf, you can use the GNU Unifont hex file instead.
+ Download at http://unifoundry.com/unifont.html */
#include
#include
@@ -22,19 +24,342 @@
#include "SDL_test_common.h"
-#define DEFAULT_PTSIZE 30
-#define DEFAULT_FONT "/System/Library/Fonts/åŽæ–‡ç»†é»‘.ttf"
+#define DEFAULT_PTSIZE 30
+#ifdef HAVE_SDL_TTF
+#ifdef __MACOSX__
+#define DEFAULT_FONT "/System/Library/Fonts/åŽæ–‡ç»†é»‘.ttf"
+#elif __WIN32__
+/* Some japanese font present on at least Windows 8.1. */
+#define DEFAULT_FONT "C:\\Windows\\Fonts\\yugothic.ttf"
+#else
+#define DEFAULT_FONT "NoDefaultFont.ttf"
+#endif
+#else
+#define DEFAULT_FONT "unifont-9.0.02.hex"
+#endif
#define MAX_TEXT_LENGTH 256
static SDLTest_CommonState *state;
static SDL_Rect textRect, markedRect;
-static SDL_Color lineColor = {0,0,0,0};
-static SDL_Color backColor = {255,255,255,0};
-static SDL_Color textColor = {0,0,0,0};
+static SDL_Color lineColor = {0,0,0,255};
+static SDL_Color backColor = {255,255,255,255};
+static SDL_Color textColor = {0,0,0,255};
static char text[MAX_TEXT_LENGTH], markedText[SDL_TEXTEDITINGEVENT_TEXT_SIZE];
static int cursor = 0;
#ifdef HAVE_SDL_TTF
static TTF_Font *font;
+#else
+#define UNIFONT_MAX_CODEPOINT 0x1ffff
+#define UNIFONT_NUM_GLYPHS 0x20000
+/* Using 512x512 textures that are supported everywhere. */
+#define UNIFONT_TEXTURE_WIDTH 512
+#define UNIFONT_GLYPHS_IN_ROW (UNIFONT_TEXTURE_WIDTH / 16)
+#define UNIFONT_GLYPHS_IN_TEXTURE (UNIFONT_GLYPHS_IN_ROW * UNIFONT_GLYPHS_IN_ROW)
+#define UNIFONT_NUM_TEXTURES ((UNIFONT_NUM_GLYPHS + UNIFONT_GLYPHS_IN_TEXTURE - 1) / UNIFONT_GLYPHS_IN_TEXTURE)
+#define UNIFONT_TEXTURE_SIZE (UNIFONT_TEXTURE_WIDTH * UNIFONT_TEXTURE_WIDTH * 4)
+#define UNIFONT_TEXTURE_PITCH (UNIFONT_TEXTURE_WIDTH * 4)
+#define UNIFONT_DRAW_SCALE 2
+struct UnifontGlyph {
+ Uint8 width;
+ Uint8 data[32];
+} *unifontGlyph;
+static SDL_Texture **unifontTexture;
+static Uint8 unifontTextureLoaded[UNIFONT_NUM_TEXTURES] = {0};
+
+/* Unifont loading code start */
+
+static Uint8 dehex(char c)
+{
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ else if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ else if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ return 255;
+}
+
+static Uint8 dehex2(char c1, char c2)
+{
+ return (dehex(c1) << 4) | dehex(c2);
+}
+
+static Uint8 validate_hex(const char *cp, size_t len, Uint32 *np)
+{
+ Uint32 n = 0;
+ for (; len > 0; cp++, len--)
+ {
+ Uint8 c = dehex(*cp);
+ if (c == 255)
+ return 0;
+ n = (n << 4) | c;
+ }
+ if (np != NULL)
+ *np = n;
+ return 1;
+}
+
+static void unifont_init(const char *fontname)
+{
+ Uint8 hexBuffer[65];
+ Uint32 numGlyphs = 0;
+ int lineNumber = 1;
+ size_t bytesRead;
+ SDL_RWops *hexFile;
+ const size_t unifontGlyphSize = UNIFONT_NUM_GLYPHS * sizeof(struct UnifontGlyph);
+ const size_t unifontTextureSize = UNIFONT_NUM_TEXTURES * state->num_windows * sizeof(void *);
+
+ /* Allocate memory for the glyph data so the file can be closed after initialization. */
+ unifontGlyph = (struct UnifontGlyph *)SDL_malloc(unifontGlyphSize);
+ if (unifontGlyph == NULL)
+ {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Failed to allocate %d KiB for glyph data.\n", (int)(unifontGlyphSize + 1023) / 1024);
+ exit(-1);
+ }
+ SDL_memset(unifontGlyph, 0, unifontGlyphSize);
+
+ /* Allocate memory for texture pointers for all renderers. */
+ unifontTexture = (SDL_Texture **)SDL_malloc(unifontTextureSize);
+ if (unifontTexture == NULL)
+ {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Failed to allocate %d KiB for texture pointer data.\n", (int)(unifontTextureSize + 1023) / 1024);
+ exit(-1);
+ }
+ SDL_memset(unifontTexture, 0, unifontTextureSize);
+
+ hexFile = SDL_RWFromFile(fontname, "rb");
+ if (hexFile == NULL)
+ {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Failed to open font file: %s\n", fontname);
+ exit(-1);
+ }
+
+ /* Read all the glyph data into memory to make it accessible later when textures are created. */
+ do {
+ int i, codepointHexSize;
+ size_t bytesOverread;
+ Uint8 glyphWidth;
+ Uint32 codepoint;
+
+ bytesRead = SDL_RWread(hexFile, hexBuffer, 1, 9);
+ if (numGlyphs > 0 && bytesRead == 0)
+ break; /* EOF */
+ if ((numGlyphs == 0 && bytesRead == 0) || (numGlyphs > 0 && bytesRead < 9))
+ {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unfiont: Unexpected end of hex file.\n");
+ exit(-1);
+ }
+
+ /* Looking for the colon that separates the codepoint and glyph data at position 2, 4, 6 and 8. */
+ if (hexBuffer[2] == ':')
+ codepointHexSize = 2;
+ else if (hexBuffer[4] == ':')
+ codepointHexSize = 4;
+ else if (hexBuffer[6] == ':')
+ codepointHexSize = 6;
+ else if (hexBuffer[8] == ':')
+ codepointHexSize = 8;
+ else
+ {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Could not find codepoint and glyph data separator symbol in hex file on line %d.\n", lineNumber);
+ exit(-1);
+ }
+
+ if (!validate_hex((const char *)hexBuffer, codepointHexSize, &codepoint))
+ {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Malformed hexadecimal number in hex file on line %d.\n", lineNumber);
+ exit(-1);
+ }
+ if (codepoint > UNIFONT_MAX_CODEPOINT)
+ SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "unifont: Codepoint on line %d exceeded limit of 0x%x.\n", lineNumber, UNIFONT_MAX_CODEPOINT);
+
+ /* If there was glyph data read in the last file read, move it to the front of the buffer. */
+ bytesOverread = 8 - codepointHexSize;
+ if (codepointHexSize < 8)
+ SDL_memmove(hexBuffer, hexBuffer + codepointHexSize + 1, bytesOverread);
+ bytesRead = SDL_RWread(hexFile, hexBuffer + bytesOverread, 1, 33 - bytesOverread);
+ if (bytesRead < (33 - bytesOverread))
+ {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Unexpected end of hex file.\n");
+ exit(-1);
+ }
+ if (hexBuffer[32] == '\n')
+ glyphWidth = 8;
+ else
+ {
+ glyphWidth = 16;
+ bytesRead = SDL_RWread(hexFile, hexBuffer + 33, 1, 32);
+ if (bytesRead < 32)
+ {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Unexpected end of hex file.\n");
+ exit(-1);
+ }
+ }
+
+ if (!validate_hex((const char *)hexBuffer, glyphWidth * 4, NULL))
+ {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Malformed hexadecimal glyph data in hex file on line %d.\n", lineNumber);
+ exit(-1);
+ }
+
+ if (codepoint <= UNIFONT_MAX_CODEPOINT)
+ {
+ if (unifontGlyph[codepoint].width > 0)
+ SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "unifont: Ignoring duplicate codepoint 0x%08x in hex file on line %d.\n", codepoint, lineNumber);
+ else
+ {
+ unifontGlyph[codepoint].width = glyphWidth;
+ /* Pack the hex data into a more compact form. */
+ for (i = 0; i < glyphWidth * 2; i++)
+ unifontGlyph[codepoint].data[i] = dehex2(hexBuffer[i * 2], hexBuffer[i * 2 + 1]);
+ numGlyphs++;
+ }
+ }
+
+ lineNumber++;
+ } while (bytesRead > 0);
+
+ SDL_RWclose(hexFile);
+ SDL_Log("unifont: Loaded %u glyphs.\n", numGlyphs);
+}
+
+static void unifont_make_rgba(Uint8 *src, Uint8 *dst, Uint8 width)
+{
+ int i, j;
+ Uint8 *row = dst;
+
+ for (i = 0; i < width * 2; i++)
+ {
+ Uint8 data = src[i];
+ for (j = 0; j < 8; j++)
+ {
+ if (data & 0x80)
+ {
+ row[0] = textColor.r;
+ row[1] = textColor.g;
+ row[2] = textColor.b;
+ row[3] = textColor.a;
+ }
+ else
+ {
+ row[0] = 0;
+ row[1] = 0;
+ row[2] = 0;
+ row[3] = 0;
+ }
+ data <<= 1;
+ row += 4;
+ }
+
+ if (width == 8 || (width == 16 && i % 2 == 1))
+ {
+ dst += UNIFONT_TEXTURE_PITCH;
+ row = dst;
+ }
+ }
+}
+
+static void unifont_load_texture(Uint32 textureID)
+{
+ int i;
+ Uint8 * textureRGBA;
+
+ if (textureID >= UNIFONT_NUM_TEXTURES)
+ {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Tried to load out of range texture %u.\n", textureID);
+ exit(-1);
+ }
+
+ textureRGBA = (Uint8 *)SDL_malloc(UNIFONT_TEXTURE_SIZE);
+ if (textureRGBA == NULL)
+ {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Failed to allocate %d MiB for a texture.\n", UNIFONT_TEXTURE_SIZE / 1024 / 1024);
+ exit(-1);
+ }
+ SDL_memset(textureRGBA, 0, UNIFONT_TEXTURE_SIZE);
+
+ /* Copy the glyphs into memory in RGBA format. */
+ for (i = 0; i < UNIFONT_GLYPHS_IN_TEXTURE; i++)
+ {
+ Uint32 codepoint = UNIFONT_GLYPHS_IN_TEXTURE * textureID + i;
+ if (unifontGlyph[codepoint].width > 0)
+ {
+ const Uint32 cInTex = codepoint % UNIFONT_GLYPHS_IN_TEXTURE;
+ const size_t offset = (cInTex / UNIFONT_GLYPHS_IN_ROW) * UNIFONT_TEXTURE_PITCH * 16 + (cInTex % UNIFONT_GLYPHS_IN_ROW) * 16 * 4;
+ unifont_make_rgba(unifontGlyph[codepoint].data, textureRGBA + offset, unifontGlyph[codepoint].width);
+ }
+ }
+
+ /* Create textures and upload the RGBA data from above. */
+ for (i = 0; i < state->num_windows; ++i)
+ {
+ SDL_Renderer *renderer = state->renderers[i];
+ SDL_Texture *tex = unifontTexture[UNIFONT_NUM_TEXTURES * i + textureID];
+ if (state->windows[i] == NULL || renderer == NULL || tex != NULL)
+ continue;
+ tex = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, UNIFONT_TEXTURE_WIDTH, UNIFONT_TEXTURE_WIDTH);
+ if (tex == NULL)
+ {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "unifont: Failed to create texture %u for renderer %d.\n", textureID, i);
+ exit(-1);
+ }
+ unifontTexture[UNIFONT_NUM_TEXTURES * i + textureID] = tex;
+ SDL_SetTextureBlendMode(tex, SDL_BLENDMODE_BLEND);
+ if (SDL_UpdateTexture(tex, NULL, textureRGBA, UNIFONT_TEXTURE_PITCH) != 0)
+ {
+ SDL_Log("unifont error: Failed to update texture %u data for renderer %d.\n", textureID, i);
+ }
+ }
+
+ SDL_free(textureRGBA);
+ unifontTextureLoaded[textureID] = 1;
+}
+
+static Sint32 unifont_draw_glyph(Uint32 codepoint, int rendererID, SDL_Rect *dstrect)
+{
+ SDL_Texture *texture;
+ const Uint32 textureID = codepoint / UNIFONT_GLYPHS_IN_TEXTURE;
+ SDL_Rect srcrect;
+ srcrect.w = srcrect.h = 16;
+ if (codepoint > UNIFONT_MAX_CODEPOINT)
+ return 0;
+ if (!unifontTextureLoaded[textureID])
+ unifont_load_texture(textureID);
+ texture = unifontTexture[UNIFONT_NUM_TEXTURES * rendererID + textureID];
+ if (texture != NULL)
+ {
+ const Uint32 cInTex = codepoint % UNIFONT_GLYPHS_IN_TEXTURE;
+ srcrect.x = cInTex % UNIFONT_GLYPHS_IN_ROW * 16;
+ srcrect.y = cInTex / UNIFONT_GLYPHS_IN_ROW * 16;
+ SDL_RenderCopy(state->renderers[rendererID], texture, &srcrect, dstrect);
+ }
+ return unifontGlyph[codepoint].width;
+}
+
+static void unifont_cleanup()
+{
+ int i, j;
+ for (i = 0; i < state->num_windows; ++i)
+ {
+ SDL_Renderer *renderer = state->renderers[i];
+ if (state->windows[i] == NULL || renderer == NULL)
+ continue;
+ for (j = 0; j < UNIFONT_NUM_TEXTURES; j++)
+ {
+ SDL_Texture *tex = unifontTexture[UNIFONT_NUM_TEXTURES * i + j];
+ if (tex != NULL)
+ SDL_DestroyTexture(tex);
+ }
+ }
+
+ for (j = 0; j < UNIFONT_NUM_TEXTURES; j++)
+ unifontTextureLoaded[j] = 0;
+
+ SDL_free(unifontTexture);
+ SDL_free(unifontGlyph);
+}
+
+/* Unifont code end */
#endif
size_t utf8_length(unsigned char c)
@@ -78,6 +403,30 @@ char *utf8_advance(char *p, size_t distance)
return p;
}
+Uint32 utf8_decode(char *p, size_t len)
+{
+ Uint32 codepoint = 0;
+ size_t i = 0;
+ if (!len)
+ return 0;
+
+ for (; i < len; ++i)
+ {
+ if (i == 0)
+ codepoint = (0xff >> len) & *p;
+ else
+ {
+ codepoint <<= 6;
+ codepoint |= 0x3f & *p;
+ }
+ if (!*p)
+ return 0;
+ p++;
+ }
+
+ return codepoint;
+}
+
void usage()
{
SDL_Log("usage: testime [--font fontfile]\n");
@@ -105,34 +454,61 @@ void CleanupVideo()
#ifdef HAVE_SDL_TTF
TTF_CloseFont(font);
TTF_Quit();
+#else
+ unifont_cleanup();
#endif
}
+void _Redraw(int rendererID) {
+ SDL_Renderer * renderer = state->renderers[rendererID];
+ SDL_Rect drawnTextRect, cursorRect, underlineRect;
+ drawnTextRect = textRect;
+ drawnTextRect.w = 0;
-void _Redraw(SDL_Renderer * renderer) {
- int w = 0, h = textRect.h;
- SDL_Rect cursorRect, underlineRect;
-
- SDL_SetRenderDrawColor(renderer, 255,255,255,255);
+ SDL_SetRenderDrawColor(renderer, backColor.r, backColor.g, backColor.b, backColor.a);
SDL_RenderFillRect(renderer,&textRect);
-#ifdef HAVE_SDL_TTF
if (*text)
{
+#ifdef HAVE_SDL_TTF
SDL_Surface *textSur = TTF_RenderUTF8_Blended(font, text, textColor);
- SDL_Rect dest = {textRect.x, textRect.y, textSur->w, textSur->h };
+ SDL_Texture *texture;
- SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer,textSur);
+ /* Vertically center text */
+ drawnTextRect.y = textRect.y + (textRect.h - textSur->h) / 2;
+ drawnTextRect.w = textSur->w;
+ drawnTextRect.h = textSur->h;
+
+ texture = SDL_CreateTextureFromSurface(renderer,textSur);
SDL_FreeSurface(textSur);
- SDL_RenderCopy(renderer,texture,NULL,&dest);
+ SDL_RenderCopy(renderer,texture,NULL,&drawnTextRect);
SDL_DestroyTexture(texture);
- TTF_SizeUTF8(font, text, &w, &h);
- }
-#endif
+#else
+ char *utext = text;
+ Uint32 codepoint;
+ size_t len;
+ SDL_Rect dstrect;
- markedRect.x = textRect.x + w;
- markedRect.w = textRect.w - w;
+ dstrect.x = textRect.x;
+ dstrect.y = textRect.y + (textRect.h - 16 * UNIFONT_DRAW_SCALE) / 2;
+ dstrect.w = 16 * UNIFONT_DRAW_SCALE;
+ dstrect.h = 16 * UNIFONT_DRAW_SCALE;
+ drawnTextRect.y = dstrect.y;
+ drawnTextRect.h = dstrect.h;
+
+ while ((codepoint = utf8_decode(utext, len = utf8_length(*utext))))
+ {
+ Sint32 advance = unifont_draw_glyph(codepoint, rendererID, &dstrect) * UNIFONT_DRAW_SCALE;
+ dstrect.x += advance;
+ drawnTextRect.w += advance;
+ utext += len;
+ }
+#endif
+ }
+
+ markedRect.x = textRect.x + drawnTextRect.w;
+ markedRect.w = textRect.w - drawnTextRect.w;
if (markedRect.w < 0)
{
/* Stop text input because we cannot hold any more characters */
@@ -144,49 +520,88 @@ void _Redraw(SDL_Renderer * renderer) {
SDL_StartTextInput();
}
- cursorRect = markedRect;
+ cursorRect = drawnTextRect;
+ cursorRect.x += cursorRect.w;
cursorRect.w = 2;
- cursorRect.h = h;
+ cursorRect.h = drawnTextRect.h;
- SDL_SetRenderDrawColor(renderer, 255,255,255,255);
+ drawnTextRect.x += drawnTextRect.w;
+ drawnTextRect.w = 0;
+
+ SDL_SetRenderDrawColor(renderer, backColor.r, backColor.g, backColor.b, backColor.a);
SDL_RenderFillRect(renderer,&markedRect);
if (markedText[0])
{
#ifdef HAVE_SDL_TTF
+ SDL_Surface *textSur;
+ SDL_Texture *texture;
if (cursor)
{
char *p = utf8_advance(markedText, cursor);
char c = 0;
if (!p)
- p = &markedText[strlen(markedText)];
+ p = &markedText[SDL_strlen(markedText)];
c = *p;
*p = 0;
- TTF_SizeUTF8(font, markedText, &w, 0);
- cursorRect.x += w;
+ TTF_SizeUTF8(font, markedText, &drawnTextRect.w, NULL);
+ cursorRect.x += drawnTextRect.w;
*p = c;
}
- SDL_Surface *textSur = TTF_RenderUTF8_Blended(font, markedText, textColor);
- SDL_Rect dest = {markedRect.x, markedRect.y, textSur->w, textSur->h };
- TTF_SizeUTF8(font, markedText, &w, &h);
- SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer,textSur);
+ textSur = TTF_RenderUTF8_Blended(font, markedText, textColor);
+ /* Vertically center text */
+ drawnTextRect.y = textRect.y + (textRect.h - textSur->h) / 2;
+ drawnTextRect.w = textSur->w;
+ drawnTextRect.h = textSur->h;
+
+ texture = SDL_CreateTextureFromSurface(renderer,textSur);
SDL_FreeSurface(textSur);
- SDL_RenderCopy(renderer,texture,NULL,&dest);
+ SDL_RenderCopy(renderer,texture,NULL,&drawnTextRect);
SDL_DestroyTexture(texture);
+#else
+ int i = 0;
+ char *utext = markedText;
+ Uint32 codepoint;
+ size_t len;
+ SDL_Rect dstrect;
+
+ dstrect.x = drawnTextRect.x;
+ dstrect.y = textRect.y + (textRect.h - 16 * UNIFONT_DRAW_SCALE) / 2;
+ dstrect.w = 16 * UNIFONT_DRAW_SCALE;
+ dstrect.h = 16 * UNIFONT_DRAW_SCALE;
+ drawnTextRect.y = dstrect.y;
+ drawnTextRect.h = dstrect.h;
+
+ while ((codepoint = utf8_decode(utext, len = utf8_length(*utext))))
+ {
+ Sint32 advance = unifont_draw_glyph(codepoint, rendererID, &dstrect) * UNIFONT_DRAW_SCALE;
+ dstrect.x += advance;
+ drawnTextRect.w += advance;
+ if (i < cursor)
+ cursorRect.x += advance;
+ i++;
+ utext += len;
+ }
#endif
- underlineRect = markedRect;
- underlineRect.y += (h - 2);
- underlineRect.h = 2;
- underlineRect.w = w;
+ if (cursor > 0)
+ {
+ cursorRect.y = drawnTextRect.y;
+ cursorRect.h = drawnTextRect.h;
+ }
- SDL_SetRenderDrawColor(renderer, 0,0,0,0);
- SDL_RenderFillRect(renderer,&markedRect);
+ underlineRect = markedRect;
+ underlineRect.y = drawnTextRect.y + drawnTextRect.h - 2;
+ underlineRect.h = 2;
+ underlineRect.w = drawnTextRect.w;
+
+ SDL_SetRenderDrawColor(renderer, lineColor.r, lineColor.g, lineColor.b, lineColor.a);
+ SDL_RenderFillRect(renderer, &underlineRect);
}
- SDL_SetRenderDrawColor(renderer, 0,0,0,0);
+ SDL_SetRenderDrawColor(renderer, lineColor.r, lineColor.g, lineColor.b, lineColor.a);
SDL_RenderFillRect(renderer,&cursorRect);
SDL_SetTextInputRect(&markedRect);
@@ -201,7 +616,8 @@ void Redraw() {
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 0);
SDL_RenderClear(renderer);
- _Redraw(renderer);
+ /* Sending in the window id to let the font renderers know which one we're working with. */
+ _Redraw(i);
SDL_RenderPresent(renderer);
}
@@ -259,6 +675,8 @@ int main(int argc, char *argv[]) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to find font: %s\n", TTF_GetError());
exit(-1);
}
+#else
+ unifont_init(fontname);
#endif
SDL_Log("Using font: %s\n", fontname);
@@ -288,6 +706,8 @@ int main(int argc, char *argv[]) {
Redraw();
break;
case SDLK_BACKSPACE:
+ /* Only delete text if not in editing mode. */
+ if (!markedText[0])
{
size_t textlen = SDL_strlen(text);
@@ -354,7 +774,7 @@ int main(int argc, char *argv[]) {
SDL_Log("text editing \"%s\", selected range (%d, %d)\n",
event.edit.text, event.edit.start, event.edit.length);
- strcpy(markedText, event.edit.text);
+ SDL_strlcpy(markedText, event.edit.text, SDL_TEXTEDITINGEVENT_TEXT_SIZE);
cursor = event.edit.start;
Redraw();
break;
diff --git a/Engine/lib/sdl/test/testlock.c b/Engine/lib/sdl/test/testlock.c
index 1106ec3bf..113ba0d4c 100644
--- a/Engine/lib/sdl/test/testlock.c
+++ b/Engine/lib/sdl/test/testlock.c
@@ -23,7 +23,7 @@
static SDL_mutex *mutex = NULL;
static SDL_threadID mainthread;
static SDL_Thread *threads[6];
-static volatile int doterminate = 0;
+static SDL_atomic_t doterminate;
/*
* SDL_Quit() shouldn't be used with atexit() directly because
@@ -45,7 +45,7 @@ void
terminate(int sig)
{
signal(SIGINT, terminate);
- doterminate = 1;
+ SDL_AtomicSet(&doterminate, 1);
}
void
@@ -54,7 +54,7 @@ closemutex(int sig)
SDL_threadID id = SDL_ThreadID();
int i;
SDL_Log("Process %lu: Cleaning up...\n", id == mainthread ? 0 : id);
- doterminate = 1;
+ SDL_AtomicSet(&doterminate, 1);
for (i = 0; i < 6; ++i)
SDL_WaitThread(threads[i], NULL);
SDL_DestroyMutex(mutex);
@@ -66,7 +66,7 @@ Run(void *data)
{
if (SDL_ThreadID() == mainthread)
signal(SIGTERM, closemutex);
- while (!doterminate) {
+ while (!SDL_AtomicGet(&doterminate)) {
SDL_Log("Process %lu ready to work\n", SDL_ThreadID());
if (SDL_LockMutex(mutex) < 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't lock mutex: %s", SDL_GetError());
@@ -82,7 +82,7 @@ Run(void *data)
/* If this sleep isn't done, then threads may starve */
SDL_Delay(10);
}
- if (SDL_ThreadID() == mainthread && doterminate) {
+ if (SDL_ThreadID() == mainthread && SDL_AtomicGet(&doterminate)) {
SDL_Log("Process %lu: raising SIGTERM\n", SDL_ThreadID());
raise(SIGTERM);
}
@@ -105,6 +105,8 @@ main(int argc, char *argv[])
}
atexit(SDL_Quit_Wrapper);
+ SDL_AtomicSet(&doterminate, 0);
+
if ((mutex = SDL_CreateMutex()) == NULL) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create mutex: %s\n", SDL_GetError());
exit(1);
diff --git a/Engine/lib/sdl/test/testmultiaudio.c b/Engine/lib/sdl/test/testmultiaudio.c
index 117ef2696..1b07ba9fc 100644
--- a/Engine/lib/sdl/test/testmultiaudio.c
+++ b/Engine/lib/sdl/test/testmultiaudio.c
@@ -25,7 +25,7 @@ typedef struct
{
SDL_AudioDeviceID dev;
int soundpos;
- volatile int done;
+ SDL_atomic_t done;
} callback_data;
callback_data cbd[64];
@@ -46,14 +46,14 @@ play_through_once(void *arg, Uint8 * stream, int len)
if (len > 0) {
stream += cpy;
SDL_memset(stream, spec.silence, len);
- cbd->done++;
+ SDL_AtomicSet(&cbd->done, 1);
}
}
void
loop()
{
- if(cbd[0].done) {
+ if (SDL_AtomicGet(&cbd[0].done)) {
#ifdef __EMSCRIPTEN__
emscripten_cancel_main_loop();
#endif
@@ -100,8 +100,7 @@ test_multi_audio(int devcount)
#ifdef __EMSCRIPTEN__
emscripten_set_main_loop(loop, 0, 1);
#else
- while (!cbd[0].done)
- {
+ while (!SDL_AtomicGet(&cbd[0].done)) {
#ifdef __ANDROID__
/* Empty queue, some application events would prevent pause. */
while (SDL_PollEvent(&event)){}
@@ -136,7 +135,7 @@ test_multi_audio(int devcount)
while (keep_going) {
keep_going = 0;
for (i = 0; i < devcount; i++) {
- if ((cbd[i].dev) && (!cbd[i].done)) {
+ if ((cbd[i].dev) && (!SDL_AtomicGet(&cbd[i].done))) {
keep_going = 1;
}
}
diff --git a/Engine/lib/sdl/test/testqsort.c b/Engine/lib/sdl/test/testqsort.c
new file mode 100644
index 000000000..48659f307
--- /dev/null
+++ b/Engine/lib/sdl/test/testqsort.c
@@ -0,0 +1,108 @@
+/*
+ Copyright (C) 1997-2016 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely.
+*/
+
+#include "SDL_test.h"
+
+static int
+num_compare(const void *_a, const void *_b)
+{
+ const int a = *((const int *) _a);
+ const int b = *((const int *) _b);
+ return (a < b) ? -1 : ((a > b) ? 1 : 0);
+}
+
+static void
+test_sort(const char *desc, int *nums, const int arraylen)
+{
+ int i;
+ int prev;
+
+ SDL_Log("test: %s arraylen=%d", desc, arraylen);
+
+ SDL_qsort(nums, arraylen, sizeof (nums[0]), num_compare);
+
+ prev = nums[0];
+ for (i = 1; i < arraylen; i++) {
+ const int val = nums[i];
+ if (val < prev) {
+ SDL_Log("sort is broken!");
+ return;
+ }
+ prev = val;
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ static int nums[1024 * 100];
+ static const int itervals[] = { SDL_arraysize(nums), 12 };
+ int iteration;
+ SDLTest_RandomContext rndctx;
+
+ if (argc > 1)
+ {
+ int success;
+ Uint64 seed = 0;
+ if (argv[1][0] == '0' && argv[1][1] == 'x')
+ success = SDL_sscanf(argv[1] + 2, "%llx", &seed);
+ else
+ success = SDL_sscanf(argv[1], "%llu", &seed);
+ if (!success)
+ {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Invalid seed. Use a decimal or hexadecimal number.\n");
+ return 1;
+ }
+ if (seed <= 0xffffffff)
+ {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Seed must be equal or greater than 0x100000000.\n");
+ return 1;
+ }
+ SDLTest_RandomInit(&rndctx, (unsigned int)(seed >> 32), (unsigned int)(seed & 0xffffffff));
+ }
+ else
+ {
+ SDLTest_RandomInitTime(&rndctx);
+ }
+ SDL_Log("Using random seed 0x%08x%08x\n", rndctx.x, rndctx.c);
+
+ for (iteration = 0; iteration < SDL_arraysize(itervals); iteration++) {
+ const int arraylen = itervals[iteration];
+ int i;
+
+ for (i = 0; i < arraylen; i++) {
+ nums[i] = i;
+ }
+ test_sort("already sorted", nums, arraylen);
+
+ for (i = 0; i < arraylen; i++) {
+ nums[i] = i;
+ }
+ nums[arraylen-1] = -1;
+ test_sort("already sorted except last element", nums, arraylen);
+
+ for (i = 0; i < arraylen; i++) {
+ nums[i] = (arraylen-1) - i;
+ }
+ test_sort("reverse sorted", nums, arraylen);
+
+ for (i = 0; i < arraylen; i++) {
+ nums[i] = SDLTest_RandomInt(&rndctx);
+ }
+ test_sort("random sorted", nums, arraylen);
+ }
+
+ return 0;
+}
+
+/* vi: set ts=4 sw=4 expandtab: */
+
diff --git a/Engine/lib/sdl/test/testrendercopyex.c b/Engine/lib/sdl/test/testrendercopyex.c
index 856abf7d0..e34890245 100644
--- a/Engine/lib/sdl/test/testrendercopyex.c
+++ b/Engine/lib/sdl/test/testrendercopyex.c
@@ -45,7 +45,7 @@ quit(int rc)
}
SDL_Texture *
-LoadTexture(SDL_Renderer *renderer, char *file, SDL_bool transparent)
+LoadTexture(SDL_Renderer *renderer, const char *file, SDL_bool transparent)
{
SDL_Surface *temp;
SDL_Texture *texture;
@@ -126,7 +126,7 @@ Draw(DrawState *s)
s->sprite_rect.x = (viewport.w - s->sprite_rect.w) / 2;
s->sprite_rect.y = (viewport.h - s->sprite_rect.h) / 2;
- SDL_RenderCopyEx(s->renderer, s->sprite, NULL, &s->sprite_rect, (double)s->sprite_rect.w, center, s->scale_direction);
+ SDL_RenderCopyEx(s->renderer, s->sprite, NULL, &s->sprite_rect, (double)s->sprite_rect.w, center, (SDL_RendererFlip)s->scale_direction);
SDL_SetRenderTarget(s->renderer, NULL);
SDL_RenderCopy(s->renderer, target, NULL, NULL);
diff --git a/Engine/lib/sdl/test/testshape.c b/Engine/lib/sdl/test/testshape.c
index 00750a970..476fac21e 100644
--- a/Engine/lib/sdl/test/testshape.c
+++ b/Engine/lib/sdl/test/testshape.c
@@ -71,6 +71,10 @@ int main(int argc,char** argv)
num_pictures = argc - 1;
pictures = (LoadedPicture *)SDL_malloc(sizeof(LoadedPicture)*num_pictures);
+ if (!pictures) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Could not allocate memory.");
+ exit(1);
+ }
for(i=0;inum_windows; ++i) {
+ SDL_Renderer *renderer = state->renderers[i];
+ SDL_RenderClear(renderer);
+ SDL_RenderPresent(renderer);
+ }
#ifdef __EMSCRIPTEN__
if (done) {
emscripten_cancel_main_loop();
@@ -122,7 +129,6 @@ main(int argc, char *argv[])
if (!state) {
return 1;
}
- state->skip_renderer = SDL_TRUE;
for (i = 1; i < argc;) {
int consumed;
@@ -140,6 +146,12 @@ main(int argc, char *argv[])
quit(2);
}
+ for (i = 0; i < state->num_windows; ++i) {
+ SDL_Renderer *renderer = state->renderers[i];
+ SDL_SetRenderDrawColor(renderer, 0xA0, 0xA0, 0xA0, 0xFF);
+ SDL_RenderClear(renderer);
+ }
+
/* Main render loop */
done = 0;
#ifdef __EMSCRIPTEN__
diff --git a/Engine/lib/sdl/test/torturethread.c b/Engine/lib/sdl/test/torturethread.c
index 5719a7195..6b98a0a9f 100644
--- a/Engine/lib/sdl/test/torturethread.c
+++ b/Engine/lib/sdl/test/torturethread.c
@@ -21,7 +21,7 @@
#define NUMTHREADS 10
-static char volatile time_for_threads_to_die[NUMTHREADS];
+static SDL_atomic_t time_for_threads_to_die[NUMTHREADS];
/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */
static void
@@ -58,7 +58,7 @@ ThreadFunc(void *data)
}
SDL_Log("Thread '%d' waiting for signal\n", tid);
- while (time_for_threads_to_die[tid] != 1) {
+ while (SDL_AtomicGet(&time_for_threads_to_die[tid]) != 1) {
; /* do nothing */
}
@@ -92,7 +92,7 @@ main(int argc, char *argv[])
for (i = 0; i < NUMTHREADS; i++) {
char name[64];
SDL_snprintf(name, sizeof (name), "Parent%d", i);
- time_for_threads_to_die[i] = 0;
+ SDL_AtomicSet(&time_for_threads_to_die[i], 0);
threads[i] = SDL_CreateThread(ThreadFunc, name, (void*) (uintptr_t) i);
if (threads[i] == NULL) {
@@ -102,7 +102,7 @@ main(int argc, char *argv[])
}
for (i = 0; i < NUMTHREADS; i++) {
- time_for_threads_to_die[i] = 1;
+ SDL_AtomicSet(&time_for_threads_to_die[i], 1);
}
for (i = 0; i < NUMTHREADS; i++) {
diff --git a/Engine/source/T3D/aiPlayer.cpp b/Engine/source/T3D/aiPlayer.cpp
index 88b500205..e952c2a8c 100644
--- a/Engine/source/T3D/aiPlayer.cpp
+++ b/Engine/source/T3D/aiPlayer.cpp
@@ -1043,9 +1043,9 @@ NavMesh *AIPlayer::findNavMesh() const
}
else
{
- if(getNavSize() == Small && !m->mSmallCharacters ||
- getNavSize() == Regular && !m->mRegularCharacters ||
- getNavSize() == Large && !m->mLargeCharacters)
+ if((getNavSize() == Small && !m->mSmallCharacters) ||
+ (getNavSize() == Regular && !m->mRegularCharacters) ||
+ (getNavSize() == Large && !m->mLargeCharacters))
continue;
}
if(!mesh || m->getWorldBox().getVolume() < mesh->getWorldBox().getVolume())
@@ -1317,7 +1317,7 @@ bool AIPlayer::checkInLos(GameBase* target, bool _useMuzzle, bool _checkEnabled)
return hit;
}
-DefineEngineMethod(AIPlayer, checkInLos, bool, (ShapeBase* obj, bool useMuzzle, bool checkEnabled),(NULL, false, false),
+DefineEngineMethod(AIPlayer, checkInLos, bool, (ShapeBase* obj, bool useMuzzle, bool checkEnabled),(nullAsType(), false, false),
"@brief Check whether an object is in line of sight.\n"
"@obj Object to check. (If blank, it will check the current target).\n"
"@useMuzzle Use muzzle position. Otherwise use eye position. (defaults to false).\n"
@@ -1366,7 +1366,7 @@ bool AIPlayer::checkInFoV(GameBase* target, F32 camFov, bool _checkEnabled)
return (dot > mCos(camFov));
}
-DefineEngineMethod(AIPlayer, checkInFoV, bool, (ShapeBase* obj, F32 fov, bool checkEnabled), (NULL, 45.0f, false),
+DefineEngineMethod(AIPlayer, checkInFoV, bool, (ShapeBase* obj, F32 fov, bool checkEnabled), (nullAsType(), 45.0f, false),
"@brief Check whether an object is within a specified veiw cone.\n"
"@obj Object to check. (If blank, it will check the current target).\n"
"@fov view angle in degrees.(Defaults to 45)\n"
@@ -1440,7 +1440,7 @@ F32 AIPlayer::getTargetDistance(GameBase* target, bool _checkEnabled)
return (getPosition() - target->getPosition()).len();
}
-DefineEngineMethod(AIPlayer, getTargetDistance, F32, (ShapeBase* obj, bool checkEnabled), (NULL, false),
+DefineEngineMethod(AIPlayer, getTargetDistance, F32, (ShapeBase* obj, bool checkEnabled), (nullAsType(), false),
"@brief The distance to a given object.\n"
"@obj Object to check. (If blank, it will check the current target).\n"
"@checkEnabled check whether the object can take damage and if so is still alive.(Defaults to false)\n")
diff --git a/Engine/source/T3D/camera.cpp b/Engine/source/T3D/camera.cpp
index 11914542a..a2acc3838 100644
--- a/Engine/source/T3D/camera.cpp
+++ b/Engine/source/T3D/camera.cpp
@@ -572,7 +572,7 @@ void Camera::processTick(const Move* move)
// process input/determine rotation vector
if(virtualMode != StationaryMode &&
virtualMode != TrackObjectMode &&
- (!mLocked || virtualMode != OrbitObjectMode && virtualMode != OrbitPointMode))
+ (!mLocked || ((virtualMode != OrbitObjectMode) && (virtualMode != OrbitPointMode))))
{
if(!strafeMode)
{
diff --git a/Engine/source/T3D/decal/decalManager.cpp b/Engine/source/T3D/decal/decalManager.cpp
index f992705d1..2d2491a7f 100644
--- a/Engine/source/T3D/decal/decalManager.cpp
+++ b/Engine/source/T3D/decal/decalManager.cpp
@@ -632,9 +632,9 @@ DecalInstance* DecalManager::getClosestDecal( const Point3F &pos )
}
}
- if ( !collectedInsts.empty() &&
+ if ( (!collectedInsts.empty() &&
collectedInsts[closestIndex] &&
- closestDistance < 1.0f ||
+ closestDistance < 1.0f) ||
worldInstSphere.isContained( pos ) )
return collectedInsts[closestIndex];
else
diff --git a/Engine/source/T3D/fx/fxFoliageReplicator.h b/Engine/source/T3D/fx/fxFoliageReplicator.h
index e40554454..c9f8a0804 100644
--- a/Engine/source/T3D/fx/fxFoliageReplicator.h
+++ b/Engine/source/T3D/fx/fxFoliageReplicator.h
@@ -64,16 +64,16 @@
class fxFoliageItem
{
public:
- MatrixF Transform;
- F32 Width;
- F32 Height;
- Box3F FoliageBox;
- bool Flipped;
+ MatrixF Transform;
+ F32 Width;
+ F32 Height;
+ Box3F FoliageBox;
+ bool Flipped;
F32 SwayPhase;
F32 SwayTimeRatio;
- F32 LightPhase;
+ F32 LightPhase;
F32 LightTimeRatio;
- U32 LastFrameSerialID;
+ U32 LastFrameSerialID;
};
//------------------------------------------------------------------------------
@@ -104,9 +104,9 @@ public:
Box3F QuadrantBox;
fxFoliageQuadrantNode* QuadrantChildNode[4];
Vector RenderList;
- // Used in DrawIndexPrimitive call.
- U32 startIndex;
- U32 primitiveCount;
+ // Used in DrawIndexPrimitive call.
+ U32 startIndex;
+ U32 primitiveCount;
};
@@ -152,7 +152,7 @@ protected:
void CreateFoliage(void);
void DestroyFoliage(void);
- void DestroyFoliageItems();
+ void DestroyFoliageItems();
void SyncFoliageReplicators(void);
@@ -172,11 +172,11 @@ protected:
Vector mReplicatedFoliage;
fxFoliageRenderList mFrustumRenderSet;
- GFXVertexBufferHandle mVertexBuffer;
- GFXPrimitiveBufferHandle mPrimBuffer;
+ GFXVertexBufferHandle mVertexBuffer;
+ GFXPrimitiveBufferHandle mPrimBuffer;
GFXShaderRef mShader;
ShaderData* mShaderData;
- GBitmap* mAlphaLookup;
+ GBitmap* mAlphaLookup;
MRandomLCG RandomGen;
F32 mFadeInGradient;
@@ -193,8 +193,8 @@ protected:
U32 mNextAllocatedNodeIdx; // Next Allocated Node Index.
U32 mBillboardsAcquired; // Billboards Acquired.
- // Used for alpha lookup in the pixel shader
- GFXTexHandle mAlphaTexture;
+ // Used for alpha lookup in the pixel shader
+ GFXTexHandle mAlphaTexture;
GFXStateBlockRef mPlacementSB;
GFXStateBlockRef mRenderSB;
@@ -223,15 +223,15 @@ protected:
bool mDirty;
-
+
void SetupShader();
- void SetupBuffers();
+ void SetupBuffers();
void renderObject(ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance*);
- void renderBuffers(SceneRenderState* state);
- void renderArc(const F32 fRadiusX, const F32 fRadiusY);
- void renderPlacementArea(const F32 ElapsedTime);
- void renderQuad(fxFoliageQuadrantNode* quadNode, const MatrixF& RenderTransform, const bool UseDebug);
- void computeAlphaTex();
+ void renderBuffers(SceneRenderState* state);
+ void renderArc(const F32 fRadiusX, const F32 fRadiusY);
+ void renderPlacementArea(const F32 ElapsedTime);
+ void renderQuad(fxFoliageQuadrantNode* quadNode, const MatrixF& RenderTransform, const bool UseDebug);
+ void computeAlphaTex();
public:
fxFoliageReplicator();
~fxFoliageReplicator();
@@ -325,7 +325,7 @@ public:
mUseDebugInfo = false;
mDebugBoxHeight = 1.0f;
mSeed = 1376312589;
- mFoliageFile = StringTable->insert("");
+ mFoliageFile = StringTable->EmptyString();
mFoliageTexture = GFXTexHandle();
mFoliageCount = 10;
mFoliageRetries = 100;
diff --git a/Engine/source/T3D/fx/fxShapeReplicator.h b/Engine/source/T3D/fx/fxShapeReplicator.h
index 8cd9efa4e..e83f0e113 100644
--- a/Engine/source/T3D/fx/fxShapeReplicator.h
+++ b/Engine/source/T3D/fx/fxShapeReplicator.h
@@ -153,7 +153,7 @@ public:
{
// Set Defaults.
mSeed = 1376312589;
- mShapeFile = StringTable->insert("");
+ mShapeFile = StringTable->EmptyString();
mShapeCount = 10;
mShapeRetries = 100;
mInnerRadiusX = 0;
diff --git a/Engine/source/T3D/fx/lightning.cpp b/Engine/source/T3D/fx/lightning.cpp
index 125c5891d..080bbed82 100644
--- a/Engine/source/T3D/fx/lightning.cpp
+++ b/Engine/source/T3D/fx/lightning.cpp
@@ -200,7 +200,7 @@ void LightningStrikeEvent::unpack(NetConnection* con, BitStream* stream)
{
if(!stream->readFlag())
return;
- S32 mClientId = stream->readRangedU32(0, NetConnection::MaxGhostCount);
+ mClientId = stream->readRangedU32(0, NetConnection::MaxGhostCount);
mLightning = NULL;
NetObject* pObject = con->resolveGhost(mClientId);
if (pObject)
@@ -214,10 +214,10 @@ void LightningStrikeEvent::unpack(NetConnection* con, BitStream* stream)
// target id
S32 mTargetID = stream->readRangedU32(0, NetConnection::MaxGhostCount);
- NetObject* pObject = con->resolveGhost(mTargetID);
- if( pObject != NULL )
+ NetObject* tObject = con->resolveGhost(mTargetID);
+ if(tObject != NULL )
{
- mTarget = dynamic_cast(pObject);
+ mTarget = dynamic_cast(tObject);
}
if( bool(mTarget) == false )
{
@@ -243,6 +243,7 @@ LightningData::LightningData()
dMemset( strikeTextureNames, 0, sizeof( strikeTextureNames ) );
dMemset( strikeTextures, 0, sizeof( strikeTextures ) );
dMemset( thunderSounds, 0, sizeof( thunderSounds ) );
+ mNumStrikeTextures = 0;
}
LightningData::~LightningData()
@@ -297,10 +298,14 @@ bool LightningData::preload(bool server, String &errorStr)
if( !sfxResolve( &strikeSound, sfxErrorStr ) )
Con::errorf(ConsoleLogEntry::General, "LightningData::preload: Invalid packet: %s", sfxErrorStr.c_str());
+ mNumStrikeTextures = 0;
for (U32 i = 0; i < MaxTextures; i++)
{
if (strikeTextureNames[i][0])
+ {
strikeTextures[i] = GFXTexHandle(strikeTextureNames[i], &GFXDefaultStaticDiffuseProfile, avar("%s() - strikeTextures[%d] (line %d)", __FUNCTION__, i, __LINE__));
+ mNumStrikeTextures++;
+ }
}
}
@@ -317,7 +322,11 @@ void LightningData::packData(BitStream* stream)
U32 i;
for (i = 0; i < MaxThunders; i++)
sfxWrite( stream, thunderSounds[ i ] );
- for (i = 0; i < MaxTextures; i++) {
+
+ stream->writeInt(mNumStrikeTextures, 4);
+
+ for (i = 0; i < MaxTextures; i++)
+ {
stream->writeString(strikeTextureNames[i]);
}
@@ -331,7 +340,11 @@ void LightningData::unpackData(BitStream* stream)
U32 i;
for (i = 0; i < MaxThunders; i++)
sfxRead( stream, &thunderSounds[ i ] );
- for (i = 0; i < MaxTextures; i++) {
+
+ mNumStrikeTextures = stream->readInt(4);
+
+ for (i = 0; i < MaxTextures; i++)
+ {
strikeTextureNames[i] = stream->readSTString();
}
@@ -368,16 +381,16 @@ Lightning::~Lightning()
{
while( mThunderListHead )
{
- Thunder* next = mThunderListHead->next;
+ Thunder* nextThunder = mThunderListHead->next;
delete mThunderListHead;
- mThunderListHead = next;
+ mThunderListHead = nextThunder;
}
while( mStrikeListHead )
{
- Strike* next = mStrikeListHead->next;
+ Strike* nextStrike = mStrikeListHead->next;
delete mStrikeListHead;
- mStrikeListHead = next;
+ mStrikeListHead = nextStrike;
}
}
@@ -478,11 +491,16 @@ void Lightning::renderObject(ObjectRenderInst *ri, SceneRenderState *state, Base
desc.setBlend( true, GFXBlendSrcAlpha, GFXBlendOne);
desc.setCullMode(GFXCullNone);
desc.zWriteEnable = false;
- desc.samplersDefined = true;
- desc.samplers[0].magFilter = GFXTextureFilterLinear;
- desc.samplers[0].minFilter = GFXTextureFilterLinear;
- desc.samplers[0].addressModeU = GFXAddressWrap;
- desc.samplers[0].addressModeV = GFXAddressWrap;
+ desc.vertexColorEnable = true;
+
+ if (mDataBlock->mNumStrikeTextures != 0)
+ {
+ desc.samplersDefined = true;
+ desc.samplers[0].magFilter = GFXTextureFilterLinear;
+ desc.samplers[0].minFilter = GFXTextureFilterLinear;
+ desc.samplers[0].addressModeU = GFXAddressWrap;
+ desc.samplers[0].addressModeV = GFXAddressWrap;
+ }
mLightningSB = GFX->createStateBlock(desc);
@@ -494,9 +512,16 @@ void Lightning::renderObject(ObjectRenderInst *ri, SceneRenderState *state, Base
Strike* walk = mStrikeListHead;
while (walk != NULL)
{
- GFX->setTexture(0, mDataBlock->strikeTextures[0]);
+ if (mDataBlock->mNumStrikeTextures > 1)
+ {
+ GFX->setTexture(0, mDataBlock->strikeTextures[sgLightningRand.randI(0, mDataBlock->mNumStrikeTextures - 1)]);
+ }
+ else if (mDataBlock->mNumStrikeTextures > 0)
+ {
+ GFX->setTexture(0, mDataBlock->strikeTextures[0]);
+ }
- for( U32 i=0; i<3; i++ )
+ for( U32 i=0; ibolt[i].isFading )
{
@@ -589,7 +614,7 @@ void Lightning::advanceTime(F32 dt)
while (*pWalker != NULL) {
Strike* pStrike = *pWalker;
- for( U32 i=0; i<3; i++ )
+ for( U32 i=0; ibolt[i].update( dt );
}
@@ -673,7 +698,7 @@ void Lightning::processEvent(LightningStrikeEvent* pEvent)
pStrike->currentAge = 0.0f;
pStrike->next = mStrikeListHead;
- for( U32 i=0; i<3; i++ )
+ for( U32 i=0; ifindObjects(queryBox, DAMAGEABLE_TYPEMASK,
@@ -864,6 +890,7 @@ U32 Lightning::packUpdate(NetConnection* con, U32 mask, BitStream* stream)
stream->write(color.red);
stream->write(color.green);
stream->write(color.blue);
+ stream->write(color.alpha);
stream->write(fadeColor.red);
stream->write(fadeColor.green);
stream->write(fadeColor.blue);
@@ -895,6 +922,7 @@ void Lightning::unpackUpdate(NetConnection* con, BitStream* stream)
stream->read(&color.red);
stream->read(&color.green);
stream->read(&color.blue);
+ stream->read(&color.alpha);
stream->read(&fadeColor.red);
stream->read(&fadeColor.green);
stream->read(&fadeColor.blue);
@@ -930,7 +958,7 @@ DefineEngineMethod(Lightning, strikeRandomPoint, void, (),,
object->strikeRandomPoint();
}
-DefineEngineMethod(Lightning, strikeObject, void, (ShapeBase* pSB),,
+DefineEngineMethod(Lightning, strikeObject, void, (ShapeBase* pSB), (nullAsType()),
"Creates a LightningStrikeEvent which strikes a specific object.\n"
"@note This method is currently unimplemented.\n" )
{
@@ -1154,7 +1182,7 @@ void LightningBolt::generateMinorNodes()
//----------------------------------------------------------------------------
// Recursive algo to create bolts that split off from main bolt
//----------------------------------------------------------------------------
-void LightningBolt::createSplit( const Point3F &startPoint, const Point3F &endPoint, U32 depth, F32 width )
+void LightningBolt::createSplit( const Point3F &startingPoint, const Point3F &endingPoint, U32 depth, F32 splitWidth )
{
if( depth == 0 )
return;
@@ -1163,17 +1191,17 @@ void LightningBolt::createSplit( const Point3F &startPoint, const Point3F &endPo
if( chanceToEnd > 0.70f )
return;
- if( width < 0.75f )
- width = 0.75f;
+ if(splitWidth < 0.75f )
+ splitWidth = 0.75f;
- VectorF diff = endPoint - startPoint;
+ VectorF diff = endingPoint - startingPoint;
F32 length = diff.len();
diff.normalizeSafe();
LightningBolt newBolt;
- newBolt.startPoint = startPoint;
- newBolt.endPoint = endPoint;
- newBolt.width = width;
+ newBolt.startPoint = startingPoint;
+ newBolt.endPoint = endingPoint;
+ newBolt.width = splitWidth;
newBolt.numMajorNodes = 3;
newBolt.maxMajorAngle = 30.0f;
newBolt.numMinorNodes = 3;
@@ -1184,13 +1212,13 @@ void LightningBolt::createSplit( const Point3F &startPoint, const Point3F &endPo
splitList.pushBack( newBolt );
VectorF newDir1 = MathUtils::randomDir( diff, 10.0f, 45.0f );
- Point3F newEndPoint1 = endPoint + newDir1 * gRandGen.randF( 0.5f, 1.5f ) * length;
+ Point3F newEndPoint1 = endingPoint + newDir1 * gRandGen.randF( 0.5f, 1.5f ) * length;
VectorF newDir2 = MathUtils::randomDir( diff, 10.0f, 45.0f );
- Point3F newEndPoint2 = endPoint + newDir2 * gRandGen.randF( 0.5f, 1.5f ) * length;
+ Point3F newEndPoint2 = endingPoint + newDir2 * gRandGen.randF( 0.5f, 1.5f ) * length;
- createSplit( endPoint, newEndPoint1, depth - 1, width * 0.30f );
- createSplit( endPoint, newEndPoint2, depth - 1, width * 0.30f );
+ createSplit(endingPoint, newEndPoint1, depth - 1, splitWidth * 0.30f );
+ createSplit(endingPoint, newEndPoint2, depth - 1, splitWidth * 0.30f );
}
diff --git a/Engine/source/T3D/fx/lightning.h b/Engine/source/T3D/fx/lightning.h
index 20620fca5..340d4e067 100644
--- a/Engine/source/T3D/fx/lightning.h
+++ b/Engine/source/T3D/fx/lightning.h
@@ -47,6 +47,7 @@ class ShapeBase;
class LightningStrikeEvent;
class SFXTrack;
+#define MAX_LIGHTNING 3
// -------------------------------------------------------------------------
class LightningData : public GameBaseData
@@ -70,6 +71,7 @@ class LightningData : public GameBaseData
GFXTexHandle strikeTextures[MaxTextures];
U32 numThunders;
+ U32 mNumStrikeTextures;
protected:
bool onAdd();
diff --git a/Engine/source/T3D/fx/particleEmitterNode.cpp b/Engine/source/T3D/fx/particleEmitterNode.cpp
index bb362417b..e03e5a1a7 100644
--- a/Engine/source/T3D/fx/particleEmitterNode.cpp
+++ b/Engine/source/T3D/fx/particleEmitterNode.cpp
@@ -395,7 +395,7 @@ void ParticleEmitterNode::setEmitterDataBlock(ParticleEmitterData* data)
}
-DefineEngineMethod(ParticleEmitterNode, setEmitterDataBlock, void, (ParticleEmitterData* emitterDatablock), (NULL),
+DefineEngineMethod(ParticleEmitterNode, setEmitterDataBlock, void, (ParticleEmitterData* emitterDatablock), (nullAsType()),
"Assigns the datablock for this emitter node.\n"
"@param emitterDatablock ParticleEmitterData datablock to assign\n"
"@tsexample\n"
diff --git a/Engine/source/T3D/fx/precipitation.cpp b/Engine/source/T3D/fx/precipitation.cpp
index 19855e26f..232e8ca72 100644
--- a/Engine/source/T3D/fx/precipitation.cpp
+++ b/Engine/source/T3D/fx/precipitation.cpp
@@ -129,10 +129,10 @@ PrecipitationData::PrecipitationData()
{
soundProfile = NULL;
- mDropName = StringTable->insert("");
- mDropShaderName = StringTable->insert("");
- mSplashName = StringTable->insert("");
- mSplashShaderName = StringTable->insert("");
+ mDropName = StringTable->EmptyString();
+ mDropShaderName = StringTable->EmptyString();
+ mSplashName = StringTable->EmptyString();
+ mSplashShaderName = StringTable->EmptyString();
mDropsPerSide = 4;
mSplashesPerSide = 2;
diff --git a/Engine/source/T3D/fx/ribbon.cpp b/Engine/source/T3D/fx/ribbon.cpp
index 6ebcfc932..ef5276857 100644
--- a/Engine/source/T3D/fx/ribbon.cpp
+++ b/Engine/source/T3D/fx/ribbon.cpp
@@ -57,7 +57,7 @@ RibbonData::RibbonData()
mUseFadeOut = false;
mFadeAwayStep = 0.032f;
segmentsPerUpdate = 1;
- mMatName = StringTable->insert("");
+ mMatName = StringTable->EmptyString();
mTileScale = 1.0f;
mFixedTexcoords = false;
mSegmentSkipAmount = 0;
@@ -318,7 +318,7 @@ void Ribbon::processTick(const Move* move)
safeDeleteObject();
return;
//}
- //mSegmentPoints.pop_back();
+ //mSegmentPoints.pop_back();
}
@@ -456,7 +456,7 @@ void Ribbon::setShaderParams() {
F32 length = (F32)mDataBlock->mRibbonLength;
Point3F radius(numSegments / length, numSegments, length);
MaterialParameters* matParams = mRibbonMat->getMaterialParameters();
- matParams->setSafe( mRadiusSC, radius );
+ matParams->setSafe( mRadiusSC, radius );
}
//--------------------------------------------------------------------------
diff --git a/Engine/source/T3D/fx/ribbonNode.cpp b/Engine/source/T3D/fx/ribbonNode.cpp
index 2582fbe6f..7e73fbc59 100644
--- a/Engine/source/T3D/fx/ribbonNode.cpp
+++ b/Engine/source/T3D/fx/ribbonNode.cpp
@@ -39,7 +39,6 @@ ConsoleDocClass( RibbonNodeData,
ConsoleDocClass( RibbonNode, ""
);
-
//-----------------------------------------------------------------------------
// RibbonNodeData
//-----------------------------------------------------------------------------
@@ -299,7 +298,7 @@ void RibbonNode::setRibbonDatablock(RibbonData* data)
mRibbonDatablock = data;
}
-DefineEngineMethod(RibbonNode, setRibbonDatablock, void, (RibbonData* ribbonDatablock), (0),
+DefineEngineMethod(RibbonNode, setRibbonDatablock, void, (RibbonData* ribbonDatablock), (nullAsType()),
"Assigns the datablock for this ribbon node.\n"
"@param ribbonDatablock RibbonData datablock to assign\n"
"@tsexample\n"
diff --git a/Engine/source/T3D/lightFlareData.cpp b/Engine/source/T3D/lightFlareData.cpp
index 8ea67cb7a..1eec3a923 100644
--- a/Engine/source/T3D/lightFlareData.cpp
+++ b/Engine/source/T3D/lightFlareData.cpp
@@ -440,7 +440,7 @@ void LightFlareData::prepRender(SceneRenderState *state, LightFlareState *flareS
// We can only skip rendering if the light is not
// visible, and it has elapsed the fade out time.
if (mIsZero(occlusionFade) ||
- !lightVisible && visDelta > FadeOutTime)
+ (!lightVisible && visDelta > FadeOutTime))
return;
const RectI &viewport = GFX->getViewport();
diff --git a/Engine/source/T3D/missionMarker.cpp b/Engine/source/T3D/missionMarker.cpp
index 3a043b095..1480e2f1f 100644
--- a/Engine/source/T3D/missionMarker.cpp
+++ b/Engine/source/T3D/missionMarker.cpp
@@ -225,7 +225,7 @@ ConsoleDocClass( WayPoint,
WayPoint::WayPoint()
{
- mName = StringTable->insert("");
+ mName = StringTable->EmptyString();
}
void WayPoint::setHidden(bool hidden)
@@ -256,7 +256,7 @@ void WayPoint::inspectPostApply()
{
Parent::inspectPostApply();
if(!mName || !mName[0])
- mName = StringTable->insert("");
+ mName = StringTable->EmptyString();
setMaskBits(UpdateNameMask|UpdateTeamMask);
}
@@ -281,7 +281,7 @@ void WayPoint::unpackUpdate(NetConnection * con, BitStream * stream)
void WayPoint::initPersistFields()
{
- addGroup("Misc");
+ addGroup("Misc");
addField("markerName", TypeCaseString, Offset(mName, WayPoint), "Unique name representing this waypoint");
endGroup("Misc");
Parent::initPersistFields();
@@ -363,7 +363,7 @@ bool SpawnSphere::onAdd()
if (!isGhost())
{
- onAdd_callback( getId());
+ onAdd_callback( getId());
if (mAutoSpawn)
spawnObject();
@@ -527,7 +527,7 @@ ConsoleDocClass( CameraBookmark,
CameraBookmark::CameraBookmark()
{
- mName = StringTable->insert("");
+ mName = StringTable->EmptyString();
}
bool CameraBookmark::onAdd()
@@ -571,7 +571,7 @@ void CameraBookmark::inspectPostApply()
{
Parent::inspectPostApply();
if(!mName || !mName[0])
- mName = StringTable->insert("");
+ mName = StringTable->EmptyString();
setMaskBits(UpdateNameMask);
if( isMethod("onInspectPostApply") )
@@ -595,7 +595,7 @@ void CameraBookmark::unpackUpdate(NetConnection * con, BitStream * stream)
void CameraBookmark::initPersistFields()
{
- //addGroup("Misc");
+ //addGroup("Misc");
//addField("name", TypeCaseString, Offset(mName, CameraBookmark));
//endGroup("Misc");
diff --git a/Engine/source/T3D/physics/bullet/btBody.cpp b/Engine/source/T3D/physics/bullet/btBody.cpp
index e1a84cf9f..33d0240a4 100644
--- a/Engine/source/T3D/physics/bullet/btBody.cpp
+++ b/Engine/source/T3D/physics/bullet/btBody.cpp
@@ -356,7 +356,7 @@ void BtBody::applyImpulse( const Point3F &origin, const Point3F &force )
mActor->activate();
}
-void BtBody::applyTorque(const Point3F &torque)
+void BtBody::applyTorque( const Point3F &torque )
{
AssertFatal(mActor, "BtBody::applyTorque - The actor is null!");
AssertFatal(isDynamic(), "BtBody::applyTorque - This call is only for dynamics!");
@@ -367,6 +367,24 @@ void BtBody::applyTorque(const Point3F &torque)
mActor->activate();
}
+void BtBody::applyForce( const Point3F &force )
+{
+ AssertFatal(mActor, "BtBody::applyForce - The actor is null!");
+ AssertFatal(isDynamic(), "BtBody::applyForce - This call is only for dynamics!");
+
+ if (mCenterOfMass)
+ {
+ Point3F relForce(force);
+ mCenterOfMass->mulV(relForce);
+ mActor->applyCentralForce(btCast(relForce));
+ }
+ else
+ mActor->applyCentralForce(btCast(force));
+
+ if (!mActor->isActive())
+ mActor->activate();
+}
+
Box3F BtBody::getWorldBounds()
{
btVector3 min, max;
diff --git a/Engine/source/T3D/physics/bullet/btBody.h b/Engine/source/T3D/physics/bullet/btBody.h
index c93ac5393..84b7dddc0 100644
--- a/Engine/source/T3D/physics/bullet/btBody.h
+++ b/Engine/source/T3D/physics/bullet/btBody.h
@@ -111,7 +111,8 @@ public:
F32 staticFriction );
virtual void applyCorrection( const MatrixF &xfm );
virtual void applyImpulse( const Point3F &origin, const Point3F &force );
- virtual void applyTorque(const Point3F &torque);
+ virtual void applyTorque( const Point3F &torque );
+ virtual void applyForce( const Point3F &force );
virtual void findContact(SceneObject **contactObject, VectorF *contactNormal, Vector *outOverlapObjects) const;
virtual void moveKinematicTo(const MatrixF &xfm);
diff --git a/Engine/source/T3D/physics/bullet/btWorld.cpp b/Engine/source/T3D/physics/bullet/btWorld.cpp
index 3b2a5777c..0ad7418b8 100644
--- a/Engine/source/T3D/physics/bullet/btWorld.cpp
+++ b/Engine/source/T3D/physics/bullet/btWorld.cpp
@@ -123,8 +123,8 @@ void BtWorld::tickPhysics( U32 elapsedMs )
// Convert it to seconds.
const F32 elapsedSec = (F32)elapsedMs * 0.001f;
- // Simulate... it is recommended to always use Bullet's default fixed timestep/
- mDynamicsWorld->stepSimulation( elapsedSec * mEditorTimeScale );
+ // Simulate
+ mDynamicsWorld->stepSimulation( elapsedSec * mEditorTimeScale, smPhysicsMaxSubSteps, smPhysicsStepTime);
mIsSimulating = true;
diff --git a/Engine/source/T3D/physics/physicsBody.h b/Engine/source/T3D/physics/physicsBody.h
index dd609cee7..28cf95d45 100644
--- a/Engine/source/T3D/physics/physicsBody.h
+++ b/Engine/source/T3D/physics/physicsBody.h
@@ -115,7 +115,10 @@ public:
virtual void applyImpulse( const Point3F &origin, const Point3F &force ) = 0;
///
- virtual void applyTorque(const Point3F &torque) = 0;
+ virtual void applyTorque( const Point3F &torque ) = 0;
+
+ ///
+ virtual void applyForce( const Point3F &force ) = 0;
virtual void findContact(SceneObject **contactObject,
diff --git a/Engine/source/T3D/physics/physicsShape.cpp b/Engine/source/T3D/physics/physicsShape.cpp
index c69d9458e..627b38a35 100644
--- a/Engine/source/T3D/physics/physicsShape.cpp
+++ b/Engine/source/T3D/physics/physicsShape.cpp
@@ -863,6 +863,12 @@ void PhysicsShape::applyTorque( const Point3F &torque )
mPhysicsRep->applyTorque( torque );
}
+void PhysicsShape::applyForce( const Point3F &force )
+{
+ if (mPhysicsRep && mPhysicsRep->isDynamic())
+ mPhysicsRep->applyForce( force );
+}
+
void PhysicsShape::applyRadialImpulse( const Point3F &origin, F32 radius, F32 magnitude )
{
if ( !mPhysicsRep || !mPhysicsRep->isDynamic() )
@@ -1193,4 +1199,12 @@ DefineEngineMethod( PhysicsShape, applyTorque, void, (Point3F torque), ,
"@note This value is ignored on physics shapes that are not dynamic. Wakes up the dynamic physics shape if it is sleeping.\n")
{
object->applyTorque( torque );
+}
+
+DefineEngineMethod(PhysicsShape, applyForce, void, (Point3F force), ,
+ "@brief Add a force to a dynamic physics shape.\n\n"
+ "@param force to apply to the dynamic physics shape\n"
+ "@note This value is ignored on physics shapes that are not dynamic. Wakes up the dynamic physics shape if it is sleeping.\n")
+{
+ object->applyForce( force );
}
\ No newline at end of file
diff --git a/Engine/source/T3D/physics/physicsShape.h b/Engine/source/T3D/physics/physicsShape.h
index 162a0368d..92092df64 100644
--- a/Engine/source/T3D/physics/physicsShape.h
+++ b/Engine/source/T3D/physics/physicsShape.h
@@ -247,6 +247,7 @@ public:
void applyImpulse( const Point3F &pos, const VectorF &vec );
void applyRadialImpulse( const Point3F &origin, F32 radius, F32 magnitude );
void applyTorque( const Point3F &torque );
+ void applyForce( const Point3F &force );
void setScale(const VectorF & scale);
// GameBase
diff --git a/Engine/source/T3D/physics/physicsWorld.cpp b/Engine/source/T3D/physics/physicsWorld.cpp
index 7b1f49b3a..65b254885 100644
--- a/Engine/source/T3D/physics/physicsWorld.cpp
+++ b/Engine/source/T3D/physics/physicsWorld.cpp
@@ -23,6 +23,9 @@
#include "platform/platform.h"
#include "T3D/physics/physicsWorld.h"
+//Physics timing
+F32 PhysicsWorld::smPhysicsStepTime = 1.0f / 60.f; //default 60fps
+U32 PhysicsWorld::smPhysicsMaxSubSteps = 4;
PhysicsWorld::PhysicsWorld()
: mGravity( 0, 0, -20.0f ) // NOTE: This matches the gravity used for player objects.
diff --git a/Engine/source/T3D/physics/physicsWorld.h b/Engine/source/T3D/physics/physicsWorld.h
index 115c32324..a18cffb98 100644
--- a/Engine/source/T3D/physics/physicsWorld.h
+++ b/Engine/source/T3D/physics/physicsWorld.h
@@ -111,6 +111,10 @@ public:
virtual PhysicsBody* castRay( const Point3F &start, const Point3F &end, U32 bodyTypes = BT_All ) = 0;
virtual void explosion( const Point3F &pos, F32 radius, F32 forceMagnitude ) = 0;
+
+ /// Physics timing
+ static F32 smPhysicsStepTime;
+ static U32 smPhysicsMaxSubSteps;
};
diff --git a/Engine/source/T3D/physics/physx/px.h b/Engine/source/T3D/physics/physx/px.h
deleted file mode 100644
index 856035cf7..000000000
--- a/Engine/source/T3D/physics/physx/px.h
+++ /dev/null
@@ -1,80 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2012 GarageGames, LLC
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to
-// deal in the Software without restriction, including without limitation the
-// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-// sell copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-// IN THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-//
-// This PhysX implementation for Torque was originally based on
-// the "PhysX in TGEA" resource written by Shannon Scarvaci.
-//
-// http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=12711
-//
-
-#ifndef _PHYSX_H_
-#define _PHYSX_H_
-
-/*
-#ifndef _TORQUE_TYPES_H_
-# include "platform/types.h"
-#endif
-*/
-
-#include "platform/tmm_off.h"
-
-#ifdef TORQUE_DEBUG
-#include
-#endif
-
-#if defined(TORQUE_OS_MAC) && !defined(__APPLE__)
- #define __APPLE__
-#elif defined(TORQUE_OS_LINUX) && !defined(LINUX)
- #define LINUX
-#elif defined(TORQUE_OS_WIN) && !defined(WIN32)
- #define WIN32
-#endif
-
-#ifndef NX_PHYSICS_NXPHYSICS
-#include
-#endif
-#ifndef NX_FOUNDATION_NXSTREAM
-#include
-#endif
-#ifndef NX_COOKING_H
-#include
-#endif
-#ifndef NX_FOUNDATION_NXUSEROUTPUTSTREAM
-#include
-#endif
-#ifndef NX_PHYSICS_NXBIG
-#include "NxExtended.h"
-#endif
-#include
-#include
-#include
-#include
-#include
-#include
-
-/// The single global physx sdk object for this process.
-extern NxPhysicsSDK *gPhysicsSDK;
-
-#include "platform/tmm_on.h"
-
-#endif // _PHYSX_H_
\ No newline at end of file
diff --git a/Engine/source/T3D/physics/physx/pxBody.cpp b/Engine/source/T3D/physics/physx/pxBody.cpp
deleted file mode 100644
index de889139c..000000000
--- a/Engine/source/T3D/physics/physx/pxBody.cpp
+++ /dev/null
@@ -1,404 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2012 GarageGames, LLC
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to
-// deal in the Software without restriction, including without limitation the
-// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-// sell copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-// IN THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#include "platform/platform.h"
-#include "T3D/physics/physX/pxBody.h"
-
-#include "T3D/physics/physX/px.h"
-#include "T3D/physics/physX/pxCasts.h"
-#include "T3D/physics/physX/pxWorld.h"
-#include "T3D/physics/physX/pxCollision.h"
-
-
-PxBody::PxBody() :
- mActor( NULL ),
- mMaterial( NULL ),
- mWorld( NULL ),
- mBodyFlags( 0 ),
- mIsEnabled( true )
-{
-}
-
-PxBody::~PxBody()
-{
- _releaseActor();
-}
-
-void PxBody::_releaseActor()
-{
- if ( !mActor )
- return;
-
- // This sucks, but it has to happen if we want
- // to avoid write lock errors from PhysX right now.
- mWorld->releaseWriteLock();
-
- mActor->userData = NULL;
-
- mWorld->releaseActor( *mActor );
- mActor = NULL;
- mBodyFlags = 0;
-
- if ( mMaterial )
- {
- mWorld->releaseMaterial( *mMaterial );
- mMaterial = NULL;
- }
-
- mColShape = NULL;
-}
-
-bool PxBody::init( PhysicsCollision *shape,
- F32 mass,
- U32 bodyFlags,
- SceneObject *obj,
- PhysicsWorld *world )
-{
- AssertFatal( obj, "PxBody::init - Got a null scene object!" );
- AssertFatal( world, "PxBody::init - Got a null world!" );
- AssertFatal( dynamic_cast( world ), "PxBody::init - The world is the wrong type!" );
- AssertFatal( shape, "PxBody::init - Got a null collision shape!" );
- AssertFatal( dynamic_cast( shape ), "PxBody::init - The collision shape is the wrong type!" );
- AssertFatal( !((PxCollision*)shape)->getShapes().empty(), "PxBody::init - Got empty collision shape!" );
-
- // Cleanup any previous actor.
- _releaseActor();
-
- mWorld = (PxWorld*)world;
- mColShape = (PxCollision*)shape;
- mBodyFlags = bodyFlags;
-
- NxActorDesc actorDesc;
- NxBodyDesc bodyDesc;
-
- const bool isKinematic = mBodyFlags & BF_KINEMATIC;
- const bool isTrigger = mBodyFlags & BF_TRIGGER;
- const bool isDebris = mBodyFlags & BF_DEBRIS;
-
- if ( isKinematic )
- {
- // Kinematics are dynamics... so they need
- // a body description.
- actorDesc.body = &bodyDesc;
- bodyDesc.mass = getMax( mass, 1.0f );
- bodyDesc.flags |= NX_BF_KINEMATIC;
- }
- else if ( mass > 0.0f )
- {
- // We have mass so its a dynamic.
- actorDesc.body = &bodyDesc;
- bodyDesc.mass = mass;
- }
-
- if ( isTrigger )
- actorDesc.flags |= NX_AF_DISABLE_RESPONSE;
-
- // Add all the shapes.
- const Vector &shapes = mColShape->getShapes();
- for ( U32 i=0; i < shapes.size(); i++ )
- {
- NxShapeDesc *desc = shapes[i];
-
- // If this hits then something is broken with
- // this descrption... check all the fields to be
- // sure their values are correctly filled out.
- AssertFatal( desc->isValid(), "PxBody::init - Got invalid shape description!" );
-
- if ( isTrigger )
- desc->group = 31;
-
- if ( isDebris )
- desc->group = 30;
-
- actorDesc.shapes.push_back( desc );
- }
-
- // This sucks, but it has to happen if we want
- // to avoid write lock errors from PhysX right now.
- mWorld->releaseWriteLock();
-
- mActor = mWorld->getScene()->createActor( actorDesc );
- mIsEnabled = true;
-
- if ( isDebris )
- mActor->setDominanceGroup( 31 );
-
- mUserData.setObject( obj );
- mUserData.setBody( this );
- mActor->userData = &mUserData;
-
- return true;
-}
-
-void PxBody::setMaterial( F32 restitution,
- F32 friction,
- F32 staticFriction )
-{
- AssertFatal( mActor, "PxBody::setMaterial - The actor is null!" );
-
- // If the body is dynamic then wake it up as
- // it may need to change behavior.
- if ( isDynamic() )
- mActor->wakeUp();
-
- NxMaterialDesc desc;
- desc.restitution = restitution;
- desc.dynamicFriction = friction;
- desc.staticFriction = staticFriction;
-
- // If we have a material then just update it as the shapes
- // should already have them mapped.
- if ( mMaterial )
- {
- mMaterial->loadFromDesc( desc );
- return;
- }
-
- // If we got here then create a new material and
- // assign it to all our shapes.
- mMaterial = mWorld->createMaterial( desc );
- U32 matIndex = mMaterial->getMaterialIndex();
- U32 count = mActor->getNbShapes();
- NxShape*const* shapes = mActor->getShapes();
- for ( U32 i=0; i < count; i++ )
- shapes[i]->setMaterial( matIndex );
-}
-
-void PxBody::setSleepThreshold( F32 linear, F32 angular )
-{
- AssertFatal( mActor, "PxBody::setSleepThreshold - The actor is null!" );
-
- mActor->setSleepLinearVelocity( linear );
- mActor->setSleepAngularVelocity( angular );
-}
-
-void PxBody::setDamping( F32 linear, F32 angular )
-{
- AssertFatal( mActor, "PxBody::setDamping - The actor is null!" );
- mActor->setLinearDamping( linear );
- mActor->setAngularDamping( angular );
-}
-
-void PxBody::getState( PhysicsState *outState )
-{
- AssertFatal( mActor, "PxBody::getState - The actor is null!" );
- AssertFatal( isDynamic(), "PxBody::getState - This call is only for dynamics!" );
-
- // TODO: Fix this to do what we intended... to return
- // false so that the caller can early out of the state
- // hasn't changed since the last tick.
-
- outState->position = pxCast( mActor->getGlobalPosition() );
- outState->orientation = pxCast( mActor->getGlobalOrientationQuat() );
- outState->linVelocity = pxCast( mActor->getLinearVelocity() );
- outState->angVelocity = pxCast( mActor->getAngularVelocity() );
- outState->sleeping = mActor->isSleeping();
- outState->momentum = pxCast( mActor->getLinearMomentum() );
-}
-
-F32 PxBody::getMass() const
-{
- AssertFatal( mActor, "PxBody::getCMassPosition - The actor is null!" );
- return mActor->getMass();
-}
-
-Point3F PxBody::getCMassPosition() const
-{
- AssertFatal( mActor, "PxBody::getCMassPosition - The actor is null!" );
- return pxCast( mActor->getCMassGlobalPosition() );
-}
-
-void PxBody::setLinVelocity( const Point3F &vel )
-{
- AssertFatal( mActor, "PxBody::setLinVelocity - The actor is null!" );
- AssertFatal( isDynamic(), "PxBody::setLinVelocity - This call is only for dynamics!" );
-
- mActor->setLinearVelocity( pxCast( vel ) );
-}
-
-void PxBody::setAngVelocity( const Point3F &vel )
-{
- AssertFatal( mActor, "PxBody::setAngVelocity - The actor is null!" );
- AssertFatal( isDynamic(), "PxBody::setAngVelocity - This call is only for dynamics!" );
-
- mActor->setAngularVelocity( pxCast( vel ) );
-}
-
-Point3F PxBody::getLinVelocity() const
-{
- AssertFatal( mActor, "PxBody::getLinVelocity - The actor is null!" );
- AssertFatal( isDynamic(), "PxBody::getLinVelocity - This call is only for dynamics!" );
-
- return pxCast( mActor->getLinearVelocity() );
-}
-
-Point3F PxBody::getAngVelocity() const
-{
- AssertFatal( mActor, "PxBody::getAngVelocity - The actor is null!" );
- AssertFatal( isDynamic(), "PxBody::getAngVelocity - This call is only for dynamics!" );
-
- return pxCast( mActor->getAngularVelocity() );
-}
-
-void PxBody::setSleeping( bool sleeping )
-{
- AssertFatal( mActor, "PxBody::setSleeping - The actor is null!" );
- AssertFatal( isDynamic(), "PxBody::setSleeping - This call is only for dynamics!" );
-
- if ( sleeping )
- mActor->putToSleep();
- else
- mActor->wakeUp();
-}
-
-bool PxBody::isDynamic() const
-{
- AssertFatal( mActor, "PxBody::isDynamic - The actor is null!" );
- return mActor->isDynamic() && ( mBodyFlags & BF_KINEMATIC ) == 0;
-}
-
-PhysicsWorld* PxBody::getWorld()
-{
- return mWorld;
-}
-
-PhysicsCollision* PxBody::getColShape()
-{
- return mColShape;
-}
-
-MatrixF& PxBody::getTransform( MatrixF *outMatrix )
-{
- AssertFatal( mActor, "PxBody::getTransform - The actor is null!" );
-
- mActor->getGlobalPose().getRowMajor44( *outMatrix );
-
- return *outMatrix;
-}
-
-Box3F PxBody::getWorldBounds()
-{
- AssertFatal( mActor, "PxBody::getTransform - The actor is null!" );
-
- NxBounds3 bounds;
- bounds.setEmpty();
- NxBounds3 shapeBounds;
-
- NxShape *const* pShapeArray = mActor->getShapes();
- U32 shapeCount = mActor->getNbShapes();
-
- for ( U32 i = 0; i < shapeCount; i++ )
- {
- // Get the shape's bounds.
- pShapeArray[i]->getWorldBounds( shapeBounds );
-
- // Combine them into the total bounds.
- bounds.combine( shapeBounds );
- }
-
- return pxCast( bounds );
-}
-
-void PxBody::setSimulationEnabled( bool enabled )
-{
- if ( mIsEnabled == enabled )
- return;
-
- // This sucks, but it has to happen if we want
- // to avoid write lock errors from PhysX right now.
- mWorld->releaseWriteLock();
-
- if ( enabled )
- {
- mIsEnabled = true;
- mActor->clearActorFlag( NX_AF_DISABLE_RESPONSE );
- mActor->clearActorFlag( NX_AF_DISABLE_COLLISION );
-
- // Don't clear the flag if its supposed to be kinematic.
- if ( !(mBodyFlags & BF_KINEMATIC) )
- mActor->clearBodyFlag( NX_BF_KINEMATIC );
-
- if ( isDynamic() )
- mActor->wakeUp();
- }
- else
- {
- mIsEnabled = false;
- mActor->raiseActorFlag( NX_AF_DISABLE_RESPONSE );
- mActor->raiseActorFlag( NX_AF_DISABLE_COLLISION );
- mActor->raiseBodyFlag( NX_BF_KINEMATIC );
- }
-
- NxShape *const* shapes = mActor->getShapes();
- for ( S32 i = 0; i < mActor->getNbShapes(); i++ )
- shapes[i]->setFlag( NX_SF_DISABLE_RAYCASTING, !mIsEnabled );
-}
-
-void PxBody::setTransform( const MatrixF &transform )
-{
- AssertFatal( mActor, "PxBody::setTransform - The actor is null!" );
-
- // This sucks, but it has to happen if we want
- // to avoid write lock errors from PhysX right now.
- mWorld->releaseWriteLock();
-
- NxMat34 xfm;
- xfm.setRowMajor44( transform );
- mActor->setGlobalPose( xfm );
-
- // If its dynamic we have more to do.
- if ( mActor->isDynamic() && !mActor->readBodyFlag( NX_BF_KINEMATIC ) )
- {
- mActor->setLinearVelocity( NxVec3( 0, 0, 0 ) );
- mActor->setAngularVelocity( NxVec3( 0, 0, 0 ) );
- mActor->wakeUp();
- }
-}
-
-void PxBody::applyCorrection( const MatrixF &transform )
-{
- AssertFatal( mActor, "PxBody::applyCorrection - The actor is null!" );
- AssertFatal( isDynamic(), "PxBody::applyCorrection - This call is only for dynamics!" );
-
- // This sucks, but it has to happen if we want
- // to avoid write lock errors from PhysX right now.
- mWorld->releaseWriteLock();
-
- NxMat34 xfm;
- xfm.setRowMajor44( transform );
- mActor->setGlobalPose( xfm );
-}
-
-void PxBody::applyImpulse( const Point3F &origin, const Point3F &force )
-{
- AssertFatal( mActor, "PxBody::applyImpulse - The actor is null!" );
-
- // This sucks, but it has to happen if we want
- // to avoid write lock errors from PhysX right now.
- mWorld->releaseWriteLock();
-
- if ( mIsEnabled && isDynamic() )
- mActor->addForceAtPos( pxCast( force ),
- pxCast( origin ),
- NX_IMPULSE );
-}
-
diff --git a/Engine/source/T3D/physics/physx/pxBody.h b/Engine/source/T3D/physics/physx/pxBody.h
deleted file mode 100644
index 2aeec6e0f..000000000
--- a/Engine/source/T3D/physics/physx/pxBody.h
+++ /dev/null
@@ -1,114 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2012 GarageGames, LLC
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to
-// deal in the Software without restriction, including without limitation the
-// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-// sell copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-// IN THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#ifndef _T3D_PHYSICS_PXBODY_H_
-#define _T3D_PHYSICS_PXBODY_H_
-
-#ifndef _T3D_PHYSICS_PHYSICSBODY_H_
-#include "T3D/physics/physicsBody.h"
-#endif
-#ifndef _PHYSICS_PHYSICSUSERDATA_H_
-#include "T3D/physics/physicsUserData.h"
-#endif
-#ifndef _REFBASE_H_
-#include "core/util/refBase.h"
-#endif
-#ifndef _MMATRIX_H_
-#include "math/mMatrix.h"
-#endif
-
-class PxWorld;
-class NxActor;
-class PxCollision;
-class NxMaterial;
-
-
-class PxBody : public PhysicsBody
-{
-protected:
-
- /// The physics world we are in.
- PxWorld *mWorld;
-
- /// The physics actor.
- NxActor *mActor;
-
- /// The unshared local material used on all the
- /// shapes on this actor.
- NxMaterial *mMaterial;
-
- /// We hold the collision reference as it contains
- /// allocated objects that we own and must free.
- StrongRefPtr mColShape;
-
- ///
- MatrixF mInternalTransform;
-
- /// The body flags set at creation time.
- U32 mBodyFlags;
-
- /// Is true if this body is enabled and active
- /// in the simulation of the scene.
- bool mIsEnabled;
-
- ///
- void _releaseActor();
-
-public:
-
- PxBody();
- virtual ~PxBody();
-
- // PhysicsObject
- virtual PhysicsWorld* getWorld();
- virtual void setTransform( const MatrixF &xfm );
- virtual MatrixF& getTransform( MatrixF *outMatrix );
- virtual Box3F getWorldBounds();
- virtual void setSimulationEnabled( bool enabled );
- virtual bool isSimulationEnabled() { return mIsEnabled; }
-
- // PhysicsBody
- virtual bool init( PhysicsCollision *shape,
- F32 mass,
- U32 bodyFlags,
- SceneObject *obj,
- PhysicsWorld *world );
- virtual bool isDynamic() const;
- virtual PhysicsCollision* getColShape();
- virtual void setSleepThreshold( F32 linear, F32 angular );
- virtual void setDamping( F32 linear, F32 angular );
- virtual void getState( PhysicsState *outState );
- virtual F32 getMass() const;
- virtual Point3F getCMassPosition() const;
- virtual void setLinVelocity( const Point3F &vel );
- virtual void setAngVelocity( const Point3F &vel );
- virtual Point3F getLinVelocity() const;
- virtual Point3F getAngVelocity() const;
- virtual void setSleeping( bool sleeping );
- virtual void setMaterial( F32 restitution,
- F32 friction,
- F32 staticFriction );
- virtual void applyCorrection( const MatrixF &xfm );
- virtual void applyImpulse( const Point3F &origin, const Point3F &force );
-};
-
-#endif // _T3D_PHYSICS_PXBODY_H_
diff --git a/Engine/source/T3D/physics/physx/pxCasts.h b/Engine/source/T3D/physics/physx/pxCasts.h
deleted file mode 100644
index ee9555702..000000000
--- a/Engine/source/T3D/physics/physx/pxCasts.h
+++ /dev/null
@@ -1,150 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2012 GarageGames, LLC
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to
-// deal in the Software without restriction, including without limitation the
-// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-// sell copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-// IN THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#ifndef _PHYSX_CASTS_H_
-#define _PHYSX_CASTS_H_
-
-#ifndef _MPOINT3_H_
-#include "math/mPoint3.h"
-#endif
-#ifndef _MBOX_H_
-#include "math/mBox.h"
-#endif
-#ifndef _MQUAT_H_
-#include "math/mQuat.h"
-#endif
-
-
-template inline T pxCast( const F &from );
-
-//-------------------------------------------------------------------------
-
-template<>
-inline Point3F pxCast( const NxVec3 &vec )
-{
- return Point3F( vec.x, vec.y, vec.z );
-}
-
-template<>
-inline NxVec3 pxCast( const Point3F &point )
-{
- return NxVec3( point.x, point.y, point.z );
-}
-
-//-------------------------------------------------------------------------
-
-template<>
-inline QuatF pxCast( const NxQuat &quat )
-{
- /// The Torque quat has the opposite winding order.
- return QuatF( -quat.x, -quat.y, -quat.z, quat.w );
-}
-
-template<>
-inline NxQuat pxCast( const QuatF &quat )
-{
- /// The Torque quat has the opposite winding order.
- NxQuat result;
- result.setWXYZ( quat.w, -quat.x, -quat.y, -quat.z );
- return result;
-}
-
-//-------------------------------------------------------------------------
-
-template<>
-inline NxBounds3 pxCast( const Box3F &box )
-{
- NxBounds3 bounds;
- bounds.set( box.minExtents.x,
- box.minExtents.y,
- box.minExtents.z,
- box.maxExtents.x,
- box.maxExtents.y,
- box.maxExtents.z );
- return bounds;
-}
-
-template<>
-inline Box3F pxCast( const NxBounds3 &bounds )
-{
- return Box3F( bounds.min.x,
- bounds.min.y,
- bounds.min.z,
- bounds.max.x,
- bounds.max.y,
- bounds.max.z );
-}
-
-//-------------------------------------------------------------------------
-
-template<>
-inline NxVec3 pxCast( const NxExtendedVec3 &xvec )
-{
- return NxVec3( xvec.x, xvec.y, xvec.z );
-}
-
-template<>
-inline NxExtendedVec3 pxCast( const NxVec3 &vec )
-{
- return NxExtendedVec3( vec.x, vec.y, vec.z );
-}
-
-//-------------------------------------------------------------------------
-
-template<>
-inline NxExtendedVec3 pxCast( const Point3F &point )
-{
- return NxExtendedVec3( point.x, point.y, point.z );
-}
-
-template<>
-inline Point3F pxCast( const NxExtendedVec3 &xvec )
-{
- return Point3F( xvec.x, xvec.y, xvec.z );
-}
-
-//-------------------------------------------------------------------------
-
-template<>
-inline NxBox pxCast( const NxExtendedBounds3 &exBounds )
-{
- NxExtendedVec3 center;
- exBounds.getCenter( center );
- NxVec3 extents;
- exBounds.getExtents( extents );
-
- NxBox box;
- box.center.set( center.x, center.y, center.z );
- box.extents = extents;
- box.rot.id();
-
- return box;
-}
-
-template<>
-inline NxExtendedBounds3 pxCast( const NxBox &box )
-{
- AssertFatal( false, "Casting a NxBox to NxExtendedBounds3 is impossible without losing rotation data!" );
- return NxExtendedBounds3();
-}
-
-#endif // _PHYSX_CASTS_H_
\ No newline at end of file
diff --git a/Engine/source/T3D/physics/physx/pxCloth.cpp b/Engine/source/T3D/physics/physx/pxCloth.cpp
deleted file mode 100644
index 723e71b67..000000000
--- a/Engine/source/T3D/physics/physx/pxCloth.cpp
+++ /dev/null
@@ -1,923 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2012 GarageGames, LLC
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to
-// deal in the Software without restriction, including without limitation the
-// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-// sell copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-// IN THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#include "platform/platform.h"
-#include "T3D/physics/physX/pxCloth.h"
-
-#include "console/consoleTypes.h"
-#include "scene/sceneManager.h"
-#include "scene/sceneRenderState.h"
-#include "renderInstance/renderPassManager.h"
-#include "lighting/lightQuery.h"
-#include "T3D/physics/physicsPlugin.h"
-#include "T3D/physics/physx/pxWorld.h"
-#include "T3D/physics/physx/pxStream.h"
-#include "T3D/physics/physx/pxCasts.h"
-#include "gfx/gfxDrawUtil.h"
-#include "math/mathIO.h"
-#include "core/stream/bitStream.h"
-#include "materials/materialManager.h"
-#include "materials/baseMatInstance.h"
-
-
-IMPLEMENT_CO_NETOBJECT_V1( PxCloth );
-
-ConsoleDocClass( PxCloth,
-
- "@brief Rectangular patch of cloth simulated by PhysX.\n\n"
-
- "PxCloth is affected by other objects in the simulation but does not itself "
- "affect others, it is essentially a visual effect. Eg, shooting at cloth will "
- "disturb it but will not explode the projectile.\n\n"
-
- "Be careful with the cloth size and resolution because it can easily become "
- "performance intensive to simulate. A single piece of cloth that is very "
- "large or high resolution is also much more expensive than multiple pieces "
- "that add up to the same number of verts.\n\n"
-
- "Note that most field docs have been copied from their PhysX counterpart.\n\n"
-
- "@ingroup Physics"
-);
-
-enum PxClothAttachment {};
-DefineBitfieldType( PxClothAttachment );
-
-ImplementBitfieldType( PxClothAttachment,
- "Soon to be deprecated\n"
- "@internal" )
- { 0, "Bottom Right" },
- { 1, "Bottom Left" },
- { 2, "Top Right" },
- { 3, "Top Left" },
- { 4, "Top Center" },
- { 5, "Bottom Center" },
- { 6, "Right Center" },
- { 7, "Left Center" },
- { 8, "Top Edge" },
- { 9, "Bottom Edge" },
- { 10, "Right Edge" },
- { 11, "Left Edge" }
-EndImplementBitfieldType;
-
-
-PxCloth::PxCloth()
- : mWorld( NULL ),
- mScene( NULL ),
- mMatInst( NULL )
-{
- mVertexRenderBuffer = NULL;
- mIndexRenderBuffer = NULL;
-
- mMaxVertices = 0;
- mMaxIndices = 0;
-
- mClothMesh = NULL;
- mCloth = NULL;
-
- mPatchVerts.set( 8, 8 );
- mPatchSize.set( 8.0f, 8.0f );
-
- mNetFlags.set( Ghostable | ScopeAlways );
- mTypeMask |= StaticObjectType | StaticShapeObjectType;
-
- mReceiveBuffers.setToDefault();
-
- mBendingEnabled = false;
- mDampingEnabled = false;
- mTriangleCollisionEnabled = false;
- mSelfCollisionEnabled = false;
-
- mDensity = 1.0f;
- mThickness = 0.1f;
- mFriction = 0.25f;
- mBendingStiffness = 0.5f;
- mDampingCoefficient = 0.25f;
-
- mAttachmentMask = 0;
-}
-
-PxCloth::~PxCloth()
-{
-}
-
-bool PxCloth::onAdd()
-{
- if ( !Parent::onAdd() )
- return false;
-
- // Cloth is only created on the client.
- if ( isClientObject() )
- {
- mWorld = dynamic_cast( PHYSICSMGR->getWorld( "client" ) );
-
- if ( !mWorld || !mWorld->getScene() )
- {
- Con::errorf( "PxCloth::onAdd() - PhysXWorld not initialized... cloth disabled!" );
- return true;
- }
-
- mScene = mWorld->getScene();
-
- mResetXfm = getTransform();
-
- _createClothPatch();
-
- PhysicsPlugin::getPhysicsResetSignal().notify( this, &PxCloth::onPhysicsReset, 1053.0f );
- }
-
- // On the server we use the static update
- // to setup the bounds of the cloth.
- if ( isServerObject() )
- _updateStaticCloth();
-
- addToScene();
-
- // Also the server object never ticks.
- if ( isServerObject() )
- setProcessTick( false );
-
- return true;
-}
-
-void PxCloth::onRemove()
-{
- SAFE_DELETE( mMatInst );
-
- if ( isClientObject() )
- {
- _releaseCloth();
- _releaseMesh();
-
- PhysicsPlugin::getPhysicsResetSignal().remove( this, &PxCloth::onPhysicsReset );
- }
-
- removeFromScene();
-
- Parent::onRemove();
-}
-
-void PxCloth::onPhysicsReset( PhysicsResetEvent reset )
-{
- // Store the reset transform for later use.
- if ( reset == PhysicsResetEvent_Store )
- mResetXfm = getTransform();
-
- // Recreate the cloth at the last reset position.
- _recreateCloth( mResetXfm );
-}
-
-void PxCloth::initPersistFields()
-{
- Parent::initPersistFields();
-
- addField( "material", TypeMaterialName, Offset( mMaterialName, PxCloth ),
- "@brief Name of the material to render.\n\n" );
-
- addField( "samples", TypePoint2I, Offset( mPatchVerts, PxCloth ),
- "@brief The number of cloth vertices in width and length.\n\n"
- "At least two verts should be defined.\n\n");
-
- addField( "size", TypePoint2F, Offset( mPatchSize, PxCloth ),
- "@brief The width and height of the cloth.\n\n" );
-
- addField( "bending", TypeBool, Offset( mBendingEnabled, PxCloth ),
- "@brief Enables or disables bending resistance.\n\n"
- "Set the bending resistance through PxCloth::bendingStiffness." );
-
- addField( "damping", TypeBool, Offset( mDampingEnabled, PxCloth ),
- "@brief Enable/disable damping of internal velocities.\n\n" );
-
- addField( "triangleCollision", TypeBool, Offset( mTriangleCollisionEnabled, PxCloth ),
- "@brief Not supported in current release (according to PhysX docs).\n\n"
- "Enables or disables collision detection of cloth triangles against the scene. "
- "If not set, only collisions of cloth particles are detected. If set, "
- "collisions of cloth triangles are detected as well." );
-
- addField( "selfCollision", TypeBool, Offset( mSelfCollisionEnabled, PxCloth ),
- "@brief Enables or disables self-collision handling within a single piece of cloth.\n\n" );
-
- addField( "density", TypeF32, Offset( mDensity, PxCloth ),
- "@brief Density of the cloth (Mass per Area).\n\n" );
-
- addField( "thickness", TypeF32, Offset( mThickness, PxCloth ),
- "@brief Value representing how thick the cloth is.\n\n"
- "The thickness is usually a fraction of the overall extent of the cloth and "
- "should not be set to a value greater than that. A good value is the maximal "
- "distance between two adjacent cloth particles in their rest pose. Visual "
- "artifacts or collision problems may appear if the thickness is too small.\n\n" );
-
- addField( "friction", TypeF32, Offset( mFriction, PxCloth ),
- "@brief Friction coefficient in the range 0 to 1.\n\n"
- "Defines the damping of the velocities of cloth particles that are in contact." );
-
- addField( "bendingStiffness", TypeF32, Offset( mBendingStiffness, PxCloth ),
- "@brief Bending stiffness of the cloth in the range 0 to 1.\n\n" );
-
- addField( "dampingCoefficient", TypeF32, Offset( mDampingCoefficient, PxCloth ),
- "@brief Spring damping of the cloth in the range 0 to 1.\n\n" );
-
- addField( "attachments", TYPEID< PxClothAttachment >(), Offset( mAttachmentMask, PxCloth ),
- "@brief Optional way to specify cloth verts that will be attached to the world position "
- "it is created at.\n\n" );
-
- // Cloth doesn't support scale.
- removeField( "scale" );
-}
-
-void PxCloth::inspectPostApply()
-{
- Parent::inspectPostApply();
-
- // Must have at least 2 verts.
- mPatchVerts.x = getMax( 2, mPatchVerts.x );
- mPatchVerts.y = getMax( 2, mPatchVerts.y );
- if ( isServerObject() )
- _updateStaticCloth();
-
- setMaskBits( TransformMask | MaterialMask | ClothMask );
-}
-
-U32 PxCloth::packUpdate( NetConnection *conn, U32 mask, BitStream *stream )
-{
- U32 retMask = Parent::packUpdate( conn, mask, stream );
-
- if ( stream->writeFlag( mask & TransformMask ) )
- mathWrite( *stream, getTransform() );
-
- if ( stream->writeFlag( mask & MaterialMask ) )
- stream->write( mMaterialName );
-
- if ( stream->writeFlag( mask & ClothMask ) )
- {
- mathWrite( *stream, mPatchVerts );
- mathWrite( *stream, mPatchSize );
-
- stream->write( mAttachmentMask );
-
- stream->writeFlag( mBendingEnabled );
- stream->writeFlag( mDampingEnabled );
- stream->writeFlag( mTriangleCollisionEnabled );
- stream->writeFlag( mSelfCollisionEnabled );
- stream->write( mThickness );
- stream->write( mFriction );
- stream->write( mBendingStiffness );
- stream->write( mDampingCoefficient );
-
- stream->write( mDensity );
- }
-
- return retMask;
-}
-
-void PxCloth::unpackUpdate( NetConnection *conn, BitStream *stream )
-{
- Parent::unpackUpdate( conn, stream );
-
- // TransformMask
- if ( stream->readFlag() )
- {
- MatrixF mat;
- mathRead( *stream, &mat );
- setTransform( mat );
- }
-
- // MaterialMask
- if ( stream->readFlag() )
- {
- stream->read( &mMaterialName );
- SAFE_DELETE( mMatInst );
- }
-
- // ClothMask
- if ( stream->readFlag() )
- {
- Point2I patchVerts;
- Point2F patchSize;
- mathRead( *stream, &patchVerts );
- mathRead( *stream, &patchSize );
-
- if ( patchVerts != mPatchVerts ||
- !patchSize.equal( mPatchSize ) )
- {
- mPatchVerts = patchVerts;
- mPatchSize = patchSize;
- _releaseMesh();
- }
-
- U32 attachMask;
- stream->read( &attachMask );
- if ( attachMask != mAttachmentMask )
- {
- mAttachmentMask = attachMask;
- _releaseCloth();
- }
-
- mBendingEnabled = stream->readFlag();
- mDampingEnabled = stream->readFlag();
- mTriangleCollisionEnabled = stream->readFlag();
- mSelfCollisionEnabled = stream->readFlag();
- stream->read( &mThickness );
- stream->read( &mFriction );
- stream->read( &mBendingStiffness );
- stream->read( &mDampingCoefficient );
-
- F32 density;
- stream->read( &density );
- if ( density != mDensity )
- {
- mDensity = density;
- _releaseCloth();
- }
-
- if ( isClientObject() &&
- isProperlyAdded() &&
- mWorld &&
- !mCloth )
- {
- _createClothPatch();
- }
-
- _updateClothProperties();
- }
-}
-
-void PxCloth::_recreateCloth( const MatrixF &transform )
-{
- if ( !mWorld )
- return;
-
- mWorld->getPhysicsResults();
-
- Parent::setTransform( transform );
-
- _createClothPatch();
-}
-
-void PxCloth::setTransform( const MatrixF &mat )
-{
- Parent::setTransform( mat );
- setMaskBits( TransformMask );
-
- // Only need to do this if we're on the server
- // or if we're not currently ticking physics.
- if ( !mWorld || !mWorld->isEnabled() )
- _updateStaticCloth();
-}
-
-void PxCloth::setScale( const VectorF &scale )
-{
- // Cloth doesn't support scale as it has plenty
- // of complications... sharing meshes, thickness,
- // transform origin, etc.
- return;
-}
-
-void PxCloth::prepRenderImage( SceneRenderState *state )
-{
- if ( mIsVBDirty )
- _updateVBIB();
-
- // Recreate the material if we need to.
- if ( !mMatInst )
- _initMaterial();
-
- // If we don't have a material instance after the override then
- // we can skip rendering all together.
- BaseMatInstance *matInst = state->getOverrideMaterial( mMatInst );
- if ( !matInst )
- return;
-
- MeshRenderInst *ri = state->getRenderPass()->allocInst();
-
- // If we need lights then set them up.
- if ( matInst->isForwardLit() )
- {
- LightQuery query;
- query.init( getWorldSphere() );
- query.getLights( ri->lights, 8 );
- }
-
- ri->projection = state->getRenderPass()->allocSharedXform(RenderPassManager::Projection);
- ri->objectToWorld = &MatrixF::Identity;
-
- ri->worldToCamera = state->getRenderPass()->allocSharedXform(RenderPassManager::View);
- ri->type = RenderPassManager::RIT_Mesh;
-
- ri->primBuff = &mPrimBuffer;
- ri->vertBuff = &mVB;
-
- ri->matInst = matInst;
- ri->prim = state->getRenderPass()->allocPrim();
- ri->prim->type = GFXTriangleList;
- ri->prim->minIndex = 0;
- ri->prim->startIndex = 0;
- ri->prim->numPrimitives = mNumIndices / 3;
-
- ri->prim->startVertex = 0;
- ri->prim->numVertices = mNumVertices;
-
- ri->defaultKey = matInst->getStateHint();
- ri->defaultKey2 = (U32)ri->vertBuff;
-
- state->getRenderPass()->addInst( ri );
-}
-
-void PxCloth::_releaseMesh()
-{
- if ( !mClothMesh )
- return;
-
- _releaseCloth();
-
- mWorld->releaseClothMesh( *mClothMesh );
- mClothMesh = NULL;
-
- delete [] mVertexRenderBuffer;
- mVertexRenderBuffer = NULL;
- delete [] mIndexRenderBuffer;
- mIndexRenderBuffer = NULL;
-}
-
-void PxCloth::_releaseCloth()
-{
- if ( !mCloth )
- return;
-
- mWorld->releaseCloth( *mCloth );
- mCloth = NULL;
-}
-
-void PxCloth::_initClothMesh()
-{
- // Make sure we can change the world.
- mWorld->releaseWriteLock();
-
- _releaseMesh();
-
- // Must have at least 2 verts.
- mPatchVerts.x = getMax( 2, mPatchVerts.x );
- mPatchVerts.y = getMax( 2, mPatchVerts.y );
-
- // Generate a uniform cloth patch,
- // w and h are the width and height,
- // d is the distance between vertices.
- mNumVertices = mPatchVerts.x * mPatchVerts.y;
- mNumIndices = (mPatchVerts.x-1) * (mPatchVerts.y-1) * 2;
-
- NxClothMeshDesc desc;
- desc.numVertices = mNumVertices;
- desc.numTriangles = mNumIndices;
- desc.pointStrideBytes = sizeof(NxVec3);
- desc.triangleStrideBytes = 3*sizeof(NxU32);
- desc.points = (NxVec3*)dMalloc(sizeof(NxVec3)*desc.numVertices);
- desc.triangles = (NxU32*)dMalloc(sizeof(NxU32)*desc.numTriangles*3);
- desc.flags = 0;
-
- U32 i,j;
- NxVec3 *p = (NxVec3*)desc.points;
-
- F32 patchWidth = mPatchSize.x / (F32)( mPatchVerts.x - 1 );
- F32 patchHeight = mPatchSize.y / (F32)( mPatchVerts.y - 1 );
-
- for (i = 0; i < mPatchVerts.y; i++)
- {
- for (j = 0; j < mPatchVerts.x; j++)
- {
- p->set( patchWidth * j, 0.0f, patchHeight * i );
- p++;
- }
- }
-
- NxU32 *id = (NxU32*)desc.triangles;
-
- for (i = 0; i < mPatchVerts.y-1; i++)
- {
- for (j = 0; j < mPatchVerts.x-1; j++)
- {
- NxU32 i0 = i * mPatchVerts.x + j;
- NxU32 i1 = i0 + 1;
- NxU32 i2 = i0 + mPatchVerts.x;
- NxU32 i3 = i2 + 1;
- if ( (j+i) % 2 )
- {
- *id++ = i0;
- *id++ = i2;
- *id++ = i1;
- *id++ = i1;
- *id++ = i2;
- *id++ = i3;
- }
- else
- {
- *id++ = i0;
- *id++ = i2;
- *id++ = i3;
- *id++ = i0;
- *id++ = i3;
- *id++ = i1;
- }
- }
- }
-
- NxCookingInterface *cooker = PxWorld::getCooking();
- cooker->NxInitCooking();
-
- // Ok... cook the mesh!
- NxCookingParams params;
- params.targetPlatform = PLATFORM_PC;
- params.skinWidth = 0.01f;
- params.hintCollisionSpeed = false;
-
- cooker->NxSetCookingParams( params );
-
- PxMemStream cooked;
-
- if ( cooker->NxCookClothMesh( desc, cooked ) )
- {
- cooked.resetPosition();
- mClothMesh = gPhysicsSDK->createClothMesh( cooked );
- }
-
- cooker->NxCloseCooking();
-
- NxVec3 *ppoints = (NxVec3*)desc.points;
- NxU32 *triangs = (NxU32*)desc.triangles;
-
- dFree( ppoints );
- dFree( triangs );
-
- if ( mClothMesh )
- _initReceiveBuffers();
-}
-
-void PxCloth::_initReceiveBuffers()
-{
- // here we setup the buffers through which the SDK returns the dynamic cloth data
- // we reserve more memory for vertices than the initial mesh takes
- // because tearing creates new vertices
- // the SDK only tears cloth as long as there is room in these buffers
-
- mMaxVertices = 3 * mNumVertices;
- mMaxIndices = 3 * mNumIndices;
-
- // Allocate Render Buffer for Vertices if it hasn't been done before
- mVertexRenderBuffer = new GFXVertexPNTT[mMaxVertices];
- mIndexRenderBuffer = new U16[mMaxIndices];
-
- mReceiveBuffers.verticesPosBegin = &(mVertexRenderBuffer[0].point);
- mReceiveBuffers.verticesNormalBegin = &(mVertexRenderBuffer[0].normal);
- mReceiveBuffers.verticesPosByteStride = sizeof(GFXVertexPNTT);
- mReceiveBuffers.verticesNormalByteStride = sizeof(GFXVertexPNTT);
- mReceiveBuffers.maxVertices = mMaxVertices;
- mReceiveBuffers.numVerticesPtr = &mNumVertices;
-
- // the number of triangles is constant, even if the cloth is torn
- mReceiveBuffers.indicesBegin = &mIndexRenderBuffer[0];
- mReceiveBuffers.indicesByteStride = sizeof(NxU16);
- mReceiveBuffers.maxIndices = mMaxIndices;
- mReceiveBuffers.numIndicesPtr = &mNumIndices;
-
- // Set up texture coords.
-
- F32 dx = 1.0f / (F32)(mPatchVerts.x-1);
- F32 dy = 1.0f / (F32)(mPatchVerts.y-1);
-
- F32 *coord = (F32*)&mVertexRenderBuffer[0].texCoord;
- for ( U32 i = 0; i < mPatchVerts.y; i++)
- {
- for ( U32 j = 0; j < mPatchVerts.x; j++)
- {
- coord[0] = j*dx;
- coord[1] = i*-dy;
- coord += sizeof( GFXVertexPNTT ) / sizeof( F32 );
- }
- }
-
- // the parent index information would be needed if we used textured cloth
- //mReceiveBuffers.parentIndicesBegin = (U32*)malloc(sizeof(U32)*mMaxVertices);
- //mReceiveBuffers.parentIndicesByteStride = sizeof(U32);
- //mReceiveBuffers.maxParentIndices = mMaxVertices;
- //mReceiveBuffers.numParentIndicesPtr = &mNumParentIndices;
-
- mMeshDirtyFlags = 0;
- mReceiveBuffers.dirtyBufferFlagsPtr = &mMeshDirtyFlags;
-
- // init the buffers in case we want to draw the mesh
- // before the SDK as filled in the correct values
-
- mReceiveBuffers.flags |= NX_MDF_16_BIT_INDICES;
-}
-
-bool PxCloth::_createClothPatch()
-{
- // Make sure we have a mesh.
- if ( !mClothMesh )
- {
- _initClothMesh();
- if ( !mClothMesh )
- return false;
- }
-
- // Make sure we can change the world.
- mWorld->releaseWriteLock();
-
- _releaseCloth();
-
- NxClothDesc desc;
- desc.globalPose.setRowMajor44( getTransform() );
- desc.thickness = mThickness;
- desc.density = mDensity;
- desc.bendingStiffness = mBendingStiffness;
- desc.dampingCoefficient = mDampingCoefficient;
- desc.friction = mFriction;
-
- if ( mBendingEnabled )
- desc.flags |= NX_CLF_BENDING;
- if ( mDampingEnabled )
- desc.flags |= NX_CLF_DAMPING;
- if ( mTriangleCollisionEnabled )
- desc.flags |= NX_CLF_TRIANGLE_COLLISION;
- if ( mSelfCollisionEnabled )
- desc.flags |= NX_CLF_SELFCOLLISION;
-
- desc.clothMesh = mClothMesh;
- desc.meshData = mReceiveBuffers;
-
- if ( !desc.isValid() )
- return false;
-
- mCloth = mScene->createCloth( desc );
- mIsVBDirty = true;
-
- _updateStaticCloth();
- _setupAttachments();
-
- return true;
-}
-
-void PxCloth::_updateClothProperties()
-{
- if ( !mCloth )
- return;
-
- mCloth->setThickness( mThickness );
- mCloth->setBendingStiffness( mBendingStiffness );
- mCloth->setDampingCoefficient( mDampingCoefficient );
- mCloth->setFriction( mFriction );
-
- NxU32 flags = NX_CLF_GRAVITY; // TODO: Expose this?
- if ( mBendingEnabled )
- flags |= NX_CLF_BENDING;
- if ( mDampingEnabled )
- flags |= NX_CLF_DAMPING;
- if ( mTriangleCollisionEnabled )
- flags |= NX_CLF_TRIANGLE_COLLISION;
- if ( mSelfCollisionEnabled )
- flags |= NX_CLF_SELFCOLLISION;
- mCloth->setFlags( flags );
-}
-
-void PxCloth::_initMaterial()
-{
- SAFE_DELETE( mMatInst );
-
- Material *material = NULL;
- if (mMaterialName.isNotEmpty() )
- Sim::findObject( mMaterialName, material );
-
- if ( material )
- mMatInst = material->createMatInstance();
- else
- mMatInst = MATMGR->createMatInstance( "WarningMaterial" );
-
- GFXStateBlockDesc desc;
- desc.setCullMode( GFXCullNone );
- mMatInst->addStateBlockDesc( desc );
-
- mMatInst->init( MATMGR->getDefaultFeatures(), getGFXVertexFormat() );
-}
-
-void PxCloth::_updateVBIB()
-{
- PROFILE_SCOPE( PxCloth_UpdateVBIB );
-
- mIsVBDirty = false;
-
- // Don't set the VB if the vertex count is the same!
- if ( mVB.isNull() || mVB->mNumVerts < mNumVertices )
- mVB.set( GFX, mNumVertices, GFXBufferTypeDynamic );
-
- GFXVertexPNTT *vert = mVertexRenderBuffer;
- GFXVertexPNTT *secondVert = NULL;
-
- for ( U32 i = 0; i < mNumVertices; i++ )
- {
- if ( i % (U32)mPatchSize.x == 0 && i != 0 )
- {
- secondVert = vert;
- secondVert--;
- vert->tangent = -(vert->point - secondVert->point);
- }
- else
- {
- secondVert = vert;
- secondVert++;
- vert->tangent = vert->point - secondVert->point;
- }
-
- vert->tangent.normalize();
- vert++;
- }
-
- GFXVertexPNTT *vpPtr = mVB.lock();
- dMemcpy( vpPtr, mVertexRenderBuffer, sizeof( GFXVertexPNTT ) * mNumVertices );
- mVB.unlock();
-
- if ( mPrimBuffer.isNull() || mPrimBuffer->mIndexCount < mNumIndices )
- mPrimBuffer.set( GFX, mNumIndices, 0, GFXBufferTypeDynamic );
-
- U16 *pbPtr;
- mPrimBuffer.lock( &pbPtr );
- dMemcpy( pbPtr, mIndexRenderBuffer, sizeof( U16 ) * mNumIndices );
- mPrimBuffer.unlock();
-}
-
-void PxCloth::_updateStaticCloth()
-{
- // Setup the unsimulated world bounds.
- mObjBox.set( 0, mThickness * -0.5f, 0,
- mPatchSize.x, mThickness * 0.5f, mPatchSize.y );
- resetWorldBox();
-
- // If we don't have render buffers then we're done.
- if ( !mVertexRenderBuffer || !mIndexRenderBuffer )
- return;
-
- // Make sure the VBs are updated.
- mIsVBDirty = true;
-
- F32 patchWidth = mPatchSize.x / (F32)(mPatchVerts.x-1);
- F32 patchHeight = mPatchSize.y / (F32)(mPatchVerts.y-1);
-
- Point3F normal( 0, 1, 0 );
- getTransform().mulV( normal );
-
- GFXVertexPNTT *vert = mVertexRenderBuffer;
-
- for (U32 y = 0; y < mPatchVerts.y; y++)
- {
- for (U32 x = 0; x < mPatchVerts.x; x++)
- {
- vert->point.set( patchWidth * x, 0.0f, patchHeight * y );
- getTransform().mulP( vert->point );
- vert->normal = normal;
- vert++;
- }
- }
-
- U16 *index = mIndexRenderBuffer;
- mNumIndices = (mPatchVerts.x-1) * (mPatchVerts.y-1) * 6;
- U16 yOffset = mPatchVerts.x;
-
- for (U32 y = 0; y < mPatchVerts.y-1; y++)
- {
- for (U32 x = 0; x < mPatchVerts.x-1; x++)
- {
- U16 base = x + ( yOffset * y );
-
- index[0] = base;
- index[1] = base + 1;
- index[2] = base + 1 + yOffset;
-
- index[3] = base + 1 + yOffset;
- index[4] = base + yOffset;
- index[5] = base;
-
- index += 6;
- }
- }
-}
-
-void PxCloth::processTick( const Move *move )
-{
- // Make sure the cloth is created.
- if ( !mCloth )
- return;
-
- // TODO: Remove this hack!
- const bool enableWind = Con::getBoolVariable( "$PxCloth::enableWind", false );
-
- if ( enableWind )
- {
- NxVec3 windVec( 25.0f + NxMath::rand(-5.0f, 5.0f),
- NxMath::rand(-5.0f, 5.0f),
- NxMath::rand(-5.0f, 5.0f) );
-
- mCloth->setWindAcceleration( windVec );
-
- // Wake the cloth!
- mCloth->wakeUp();
- }
- else
- mCloth->setWindAcceleration( NxVec3( 0, 0, 0 ) );
-
- // Update bounds.
- if ( mWorld->getEnabled() )
- {
- NxBounds3 box;
- mCloth->getWorldBounds( box );
-
- Point3F min = pxCast( box.min );
- Point3F max = pxCast( box.max );
-
- mWorldBox.set( min, max );
- mObjBox = mWorldBox;
-
- getWorldTransform().mul( mObjBox );
- }
- else
- {
- mObjBox.set( 0, mThickness * -0.5f, 0,
- mPatchSize.x, mThickness * 0.5f, mPatchSize.y );
- }
-
- resetWorldBox();
-
- // Update the VB on the next render.
- mIsVBDirty = true;
-}
-
-void PxCloth::interpolateTick( F32 delta )
-{
- // Nothing to do for now!
-}
-
-bool PxCloth::onNewDataBlock( GameBaseData *dptr, bool reload )
-{
- return false;
-}
-
-void PxCloth::_setupAttachments()
-{
- if ( !mCloth || !mWorld )
- return;
-
- // Set up attachments
- // Bottom right = bit 0
- // Bottom left = bit 1
- // Top right = bit 2
- // Top left = bit 3
-
- if ( mAttachmentMask & BIT( 0 ) )
- mCloth->attachVertexToGlobalPosition( 0, mCloth->getPosition( 0 ) );
- if ( mAttachmentMask & BIT( 1 ) )
- mCloth->attachVertexToGlobalPosition( mPatchVerts.x-1, mCloth->getPosition( mPatchVerts.x-1 ) );
- if ( mAttachmentMask & BIT( 2 ) )
- mCloth->attachVertexToGlobalPosition( mPatchVerts.x * mPatchVerts.y - mPatchVerts.x, mCloth->getPosition( mPatchVerts.x * mPatchVerts.y - mPatchVerts.x ) );
- if ( mAttachmentMask & BIT( 3 ) )
- mCloth->attachVertexToGlobalPosition( mPatchVerts.x * mPatchVerts.y - 1, mCloth->getPosition( mPatchVerts.x * mPatchVerts.y - 1 ) );
- if ( mAttachmentMask & BIT( 4 ) )
- mCloth->attachVertexToGlobalPosition( mPatchVerts.x * mPatchVerts.y - (mPatchVerts.x/2), mCloth->getPosition( mPatchVerts.x * mPatchVerts.y - (mPatchVerts.x/2) ) );
- if ( mAttachmentMask & BIT( 5 ) )
- mCloth->attachVertexToGlobalPosition( (mPatchVerts.x/2), mCloth->getPosition( (mPatchVerts.x/2) ) );
- if ( mAttachmentMask & BIT( 6 ) )
- mCloth->attachVertexToGlobalPosition( mPatchVerts.x * (mPatchVerts.y/2), mCloth->getPosition( mPatchVerts.x * (mPatchVerts.y/2) ) );
- if ( mAttachmentMask & BIT( 7 ) )
- mCloth->attachVertexToGlobalPosition( mPatchVerts.x * (mPatchVerts.y/2) + (mPatchVerts.x-1), mCloth->getPosition( mPatchVerts.x * (mPatchVerts.y/2) + (mPatchVerts.x-1) ) );
-
- if ( mAttachmentMask & BIT( 8 ) )
- for ( U32 i = mPatchVerts.x * mPatchVerts.y - mPatchVerts.x; i < mPatchVerts.x * mPatchVerts.y; i++ )
- mCloth->attachVertexToGlobalPosition( i, mCloth->getPosition( i ) );
-
- if ( mAttachmentMask & BIT( 9 ) )
- for ( U32 i = 0; i < mPatchVerts.x; i++ )
- mCloth->attachVertexToGlobalPosition( i, mCloth->getPosition( i ) );
-
- if ( mAttachmentMask & BIT( 10 ) )
- for ( U32 i = 0; i < mPatchVerts.x * mPatchVerts.y; i+=mPatchVerts.x )
- mCloth->attachVertexToGlobalPosition( i, mCloth->getPosition( i ) );
-
- if ( mAttachmentMask & BIT( 11 ) )
- for ( U32 i = mPatchVerts.x-1; i < mPatchVerts.x * mPatchVerts.y; i+=mPatchVerts.x )
- mCloth->attachVertexToGlobalPosition( i, mCloth->getPosition( i ) );
-}
\ No newline at end of file
diff --git a/Engine/source/T3D/physics/physx/pxCloth.h b/Engine/source/T3D/physics/physx/pxCloth.h
deleted file mode 100644
index 5df158861..000000000
--- a/Engine/source/T3D/physics/physx/pxCloth.h
+++ /dev/null
@@ -1,176 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2012 GarageGames, LLC
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to
-// deal in the Software without restriction, including without limitation the
-// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-// sell copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-// IN THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#ifndef _PXCLOTH_H_
-#define _PXCLOTH_H_
-
-#ifndef _GAMEBASE_H_
-#include "T3D/gameBase/gameBase.h"
-#endif
-#ifndef _GFXPRIMITIVEBUFFER_H_
-#include "gfx/gfxPrimitiveBuffer.h"
-#endif
-#ifndef _GFXVERTEXBUFFER_H_
-#include "gfx/gfxVertexBuffer.h"
-#endif
-#ifndef _PHYSX_H_
-#include "T3D/physics/physx/px.h"
-#endif
-#ifndef _T3D_PHYSICS_PHYSICSPLUGIN_H_
-#include "T3D/physics/physicsPlugin.h"
-#endif
-
-class Material;
-class BaseMatInstance;
-class PxWorld;
-class NxScene;
-class NxClothMesh;
-class NxCloth;
-
-
-class PxCloth : public GameBase
-{
- typedef GameBase Parent;
-
- enum MaskBits
- {
- TransformMask = Parent::NextFreeMask << 0,
- ClothMask = Parent::NextFreeMask << 1,
- MaterialMask = Parent::NextFreeMask << 3,
- NextFreeMask = Parent::NextFreeMask << 4
- };
-
-public:
-
- PxCloth();
- virtual ~PxCloth();
-
- DECLARE_CONOBJECT( PxCloth );
-
- // SimObject
- virtual bool onAdd();
- virtual void onRemove();
- static void initPersistFields();
- virtual void inspectPostApply();
- void onPhysicsReset( PhysicsResetEvent reset );
-
- // NetObject
- virtual U32 packUpdate( NetConnection *conn, U32 mask, BitStream *stream );
- virtual void unpackUpdate( NetConnection *conn, BitStream *stream );
-
- // SceneObject
- virtual void setTransform( const MatrixF &mat );
- virtual void setScale( const VectorF &scale );
- virtual void prepRenderImage( SceneRenderState *state );
-
- // GameBase
- virtual bool onNewDataBlock( GameBaseData *dptr, bool reload );
- virtual void processTick( const Move *move );
- virtual void interpolateTick( F32 delta );
-
-protected:
-
- PxWorld *mWorld;
-
- NxScene *mScene;
-
- /// Cooked cloth collision mesh.
- NxClothMesh *mClothMesh;
-
- /// The cloth actor used
- NxCloth *mCloth;
-
- NxMeshData mReceiveBuffers;
-
- bool mBendingEnabled;
- bool mDampingEnabled;
- bool mTriangleCollisionEnabled;
- bool mSelfCollisionEnabled;
-
- F32 mDensity;
- F32 mThickness;
- F32 mFriction;
- F32 mBendingStiffness;
- F32 mStretchingStiffness;
- F32 mDampingCoefficient;
- F32 mCollisionResponseCoefficient;
- F32 mAttachmentResponseCoefficient;
-
- U32 mAttachmentMask;
-
- static EnumTable mAttachmentFlagTable;
-
- String mMaterialName;
- SimObjectPtr mMaterial;
- BaseMatInstance *mMatInst;
-
- String lookupName;
-
- /// The output verts from the PhysX simulation.
- GFXVertexPNTT *mVertexRenderBuffer;
-
- /// The output indices from the PhysX simulation.
- U16 *mIndexRenderBuffer;
-
- U32 mMaxVertices;
- U32 mMaxIndices;
-
- /// The number of indices in the cloth which
- /// is updated by the PhysX simulation.
- U32 mNumIndices;
-
- /// The number of verts in the cloth which
- /// is updated by the PhysX simulation.
- U32 mNumVertices;
-
- U32 mMeshDirtyFlags;
- bool mIsVBDirty;
-
- GFXPrimitiveBufferHandle mPrimBuffer;
- GFXVertexBufferHandle mVB;
-
- Point2I mPatchVerts;
- Point2F mPatchSize;
-
- MatrixF mResetXfm;
-
- void _initMaterial();
-
- void _releaseMesh();
- void _releaseCloth();
-
- bool _createClothPatch();
-
- void _recreateCloth( const MatrixF &transform );
-
- void _updateClothProperties();
-
- void _initClothMesh();
- void _initReceiveBuffers();
- void _setupAttachments();
-
- void _updateStaticCloth();
-
- void _updateVBIB();
-};
-
-#endif // _PXCLOTH_H_
\ No newline at end of file
diff --git a/Engine/source/T3D/physics/physx/pxCollision.cpp b/Engine/source/T3D/physics/physx/pxCollision.cpp
deleted file mode 100644
index b08636d64..000000000
--- a/Engine/source/T3D/physics/physx/pxCollision.cpp
+++ /dev/null
@@ -1,291 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2012 GarageGames, LLC
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to
-// deal in the Software without restriction, including without limitation the
-// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-// sell copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-// IN THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#include "platform/platform.h"
-#include "T3D/physics/physX/pxCollision.h"
-
-#include "math/mPoint3.h"
-#include "math/mMatrix.h"
-#include "T3D/physics/physX/px.h"
-#include "T3D/physics/physX/pxCasts.h"
-#include "T3D/physics/physX/pxWorld.h"
-#include "T3D/physics/physX/pxStream.h"
-
-
-PxCollision::PxCollision()
-{
-}
-
-PxCollision::~PxCollision()
-{
- // We may be deleteting SDK data... so make
- // sure we have the the scene write lock.
- PxWorld::releaseWriteLocks();
-
- for ( U32 i=0; i < mColShapes.size(); i++ )
- {
- // Check for special types which need cleanup.
- NxShapeDesc *desc = mColShapes[i];
-
- if ( desc->getType() == NX_SHAPE_CONVEX )
- gPhysicsSDK->releaseConvexMesh( *((NxConvexShapeDesc*)desc)->meshData );
- else if ( desc->getType() == NX_SHAPE_MESH )
- gPhysicsSDK->releaseTriangleMesh( *((NxTriangleMeshShapeDesc*)desc)->meshData );
- else if ( desc->getType() == NX_SHAPE_HEIGHTFIELD )
- gPhysicsSDK->releaseHeightField( *((NxHeightFieldShapeDesc*)desc)->heightField );
-
- // Delete the descriptor.
- delete desc;
- }
-
- mColShapes.clear();
-}
-
-void PxCollision::addPlane( const PlaneF &plane )
-{
- NxBoxShapeDesc *desc = new NxBoxShapeDesc;
- desc->skinWidth = 0.01f;
- desc->dimensions.set( 10000.0f, 10000.0f, 100.0f );
- desc->localPose.t.z = -100.0f;
-
- // TODO: Fix rotation to match plane normal!
- //boxDesc->localPose.M.setColumn( 0, NxVec3( plane.x, plane.y, plane.z ) );
- //boxDesc->localPose.M.setColumn( 1, NxVec3( plane.x, plane.y, plane.z ) );
- //boxDesc->localPose.M.setColumn( 2, NxVec3( plane.x, plane.y, plane.z ) );
-
- mColShapes.push_back( desc );
-}
-
-void PxCollision::addBox( const Point3F &halfWidth,
- const MatrixF &localXfm )
-{
- NxBoxShapeDesc *desc = new NxBoxShapeDesc;
- desc->skinWidth = 0.01f;
- desc->dimensions.set( halfWidth.x, halfWidth.y, halfWidth.z );
- desc->localPose.setRowMajor44( localXfm );
- mColShapes.push_back( desc );
-}
-
-void PxCollision::addSphere( F32 radius,
- const MatrixF &localXfm )
-{
- NxSphereShapeDesc *desc = new NxSphereShapeDesc;
- desc->skinWidth = 0.01f;
- desc->radius = radius;
- desc->localPose.setRowMajor44( localXfm );
- mColShapes.push_back( desc );
-}
-
-void PxCollision::addCapsule( F32 radius,
- F32 height,
- const MatrixF &localXfm )
-{
- NxCapsuleShapeDesc *desc = new NxCapsuleShapeDesc;
- desc->skinWidth = 0.01f;
- desc->radius = radius;
- desc->height = height;
- desc->localPose.setRowMajor44( localXfm );
- mColShapes.push_back( desc );
-}
-
-bool PxCollision::addConvex( const Point3F *points,
- U32 count,
- const MatrixF &localXfm )
-{
- // Mesh cooking requires that both
- // scenes not be write locked!
- PxWorld::releaseWriteLocks();
-
- NxCookingInterface *cooker = PxWorld::getCooking();
- cooker->NxInitCooking();
-
- NxConvexMeshDesc meshDesc;
- meshDesc.numVertices = count;
- meshDesc.pointStrideBytes = sizeof(Point3F);
- meshDesc.points = points;
- meshDesc.flags = NX_CF_COMPUTE_CONVEX | NX_CF_INFLATE_CONVEX;
-
- // Cook it!
- NxCookingParams params;
- #ifdef TORQUE_OS_XENON
- params.targetPlatform = PLATFORM_XENON;
- #else
- params.targetPlatform = PLATFORM_PC;
- #endif
- params.skinWidth = 0.01f;
- params.hintCollisionSpeed = true;
- cooker->NxSetCookingParams( params );
-
- PxMemStream stream;
- bool cooked = cooker->NxCookConvexMesh( meshDesc, stream );
- cooker->NxCloseCooking();
-
- if ( !cooked )
- return false;
-
- stream.resetPosition();
- NxConvexMesh *meshData = gPhysicsSDK->createConvexMesh( stream );
- if ( !meshData )
- return false;
-
- NxConvexShapeDesc *desc = new NxConvexShapeDesc;
- desc->skinWidth = 0.01f;
- desc->meshData = meshData;
- desc->localPose.setRowMajor44( localXfm );
- mColShapes.push_back( desc );
-
- return true;
-}
-
-bool PxCollision::addTriangleMesh( const Point3F *vert,
- U32 vertCount,
- const U32 *index,
- U32 triCount,
- const MatrixF &localXfm )
-{
- // Mesh cooking requires that both
- // scenes not be write locked!
- PxWorld::releaseWriteLocks();
-
- NxCookingInterface *cooker = PxWorld::getCooking();
- cooker->NxInitCooking();
-
- NxTriangleMeshDesc meshDesc;
- meshDesc.numVertices = vertCount;
- meshDesc.numTriangles = triCount;
- meshDesc.pointStrideBytes = sizeof(Point3F);
- meshDesc.triangleStrideBytes = 3*sizeof(U32);
- meshDesc.points = vert;
- meshDesc.triangles = index;
- meshDesc.flags = NX_MF_FLIPNORMALS;
-
- // Cook it!
- NxCookingParams params;
- #ifdef TORQUE_OS_XENON
- params.targetPlatform = PLATFORM_XENON;
- #else
- params.targetPlatform = PLATFORM_PC;
- #endif
- params.skinWidth = 0.01f;
- params.hintCollisionSpeed = true;
- cooker->NxSetCookingParams( params );
-
- PxMemStream stream;
- bool cooked = cooker->NxCookTriangleMesh( meshDesc, stream );
- cooker->NxCloseCooking();
- if ( !cooked )
- return false;
-
- stream.resetPosition();
- NxTriangleMesh *meshData = gPhysicsSDK->createTriangleMesh( stream );
- if ( !meshData )
- return false;
-
- NxTriangleMeshShapeDesc *desc = new NxTriangleMeshShapeDesc;
- desc->skinWidth = 0.01f;
- desc->meshData = meshData;
- desc->localPose.setRowMajor44( localXfm );
- mColShapes.push_back( desc );
-
- return true;
-}
-
-bool PxCollision::addHeightfield( const U16 *heights,
- const bool *holes,
- U32 blockSize,
- F32 metersPerSample,
- const MatrixF &localXfm )
-{
- // Since we're creating SDK level data we
- // have to have access to all active worlds.
- PxWorld::releaseWriteLocks();
-
- // Init the heightfield description.
- NxHeightFieldDesc heightFieldDesc;
- heightFieldDesc.nbColumns = blockSize;
- heightFieldDesc.nbRows = blockSize;
- heightFieldDesc.thickness = -10.0f;
- heightFieldDesc.convexEdgeThreshold = 0;
-
- // Allocate the samples.
- heightFieldDesc.samples = new NxU32[ blockSize * blockSize ];
- heightFieldDesc.sampleStride = sizeof(NxU32);
- NxU8 *currentByte = (NxU8*)heightFieldDesc.samples;
-
- for ( U32 row = 0; row < blockSize; row++ )
- {
- const U32 tess = ( row + 1 ) % 2;
-
- for ( U32 column = 0; column < blockSize; column++ )
- {
- NxHeightFieldSample *currentSample = (NxHeightFieldSample*)currentByte;
-
- U32 index = ( blockSize - row - 1 ) + ( column * blockSize );
- currentSample->height = heights[ index ];
-
- if ( holes && holes[ getMax( (S32)index - 1, 0 ) ] ) // row index for holes adjusted so PhysX collision shape better matches rendered terrain
- {
- currentSample->materialIndex0 = 0;
- currentSample->materialIndex1 = 0;
- }
- else
- {
- currentSample->materialIndex0 = 1; //materialIds[0];
- currentSample->materialIndex1 = 1; //materialIds[0];
- }
-
- currentSample->tessFlag = ( column + tess ) % 2;
-
- currentByte += heightFieldDesc.sampleStride;
- }
- }
-
- // Build it.
- NxHeightFieldShapeDesc *desc = new NxHeightFieldShapeDesc;
- desc->heightField = gPhysicsSDK->createHeightField( heightFieldDesc );
-
- // Destroy the temp sample array.
- delete [] heightFieldDesc.samples;
-
- // TerrainBlock uses a 11.5 fixed point height format
- // giving it a maximum height range of 0 to 2048.
- desc->heightScale = 0.03125f;
-
- desc->rowScale = metersPerSample;
- desc->columnScale = metersPerSample;
- desc->materialIndexHighBits = 0;
- desc->skinWidth = 0.01f;
-
- // Use the local pose to align the heightfield
- // to what Torque will expect.
- NxMat33 rotX;
- rotX.rotX( Float_HalfPi );
- NxMat33 rotZ;
- rotZ.rotZ( Float_Pi );
- NxMat34 rot;
- rot.M.multiply( rotZ, rotX );
- rot.t.set( ( blockSize - 1 ) * metersPerSample, 0, 0 );
- desc->localPose = rot;
-
- mColShapes.push_back( desc );
- return true;
-}
diff --git a/Engine/source/T3D/physics/physx/pxCollision.h b/Engine/source/T3D/physics/physx/pxCollision.h
deleted file mode 100644
index 54263b792..000000000
--- a/Engine/source/T3D/physics/physx/pxCollision.h
+++ /dev/null
@@ -1,78 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2012 GarageGames, LLC
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to
-// deal in the Software without restriction, including without limitation the
-// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-// sell copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-// IN THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#ifndef _T3D_PHYSICS_PXCOLLISION_H_
-#define _T3D_PHYSICS_PXCOLLISION_H_
-
-#ifndef _T3D_PHYSICS_PHYSICSCOLLISION_H_
-#include "T3D/physics/physicsCollision.h"
-#endif
-#ifndef _TVECTOR_H_
-#include "core/util/tVector.h"
-#endif
-
-class NxShapeDesc;
-
-
-class PxCollision : public PhysicsCollision
-{
-protected:
-
- /// The collision representation.
- Vector mColShapes;
-
- /// Helper for adding shapes.
- //void _addShape( btCollisionShape *shape, const MatrixF &localXfm );
-
-public:
-
- PxCollision();
- virtual ~PxCollision();
-
- /// Return the PhysX shape descriptions.
- const Vector& getShapes() const { return mColShapes; }
-
- // PhysicsCollision
- virtual void addPlane( const PlaneF &plane );
- virtual void addBox( const Point3F &halfWidth,
- const MatrixF &localXfm );
- virtual void addSphere( F32 radius,
- const MatrixF &localXfm );
- virtual void addCapsule( F32 radius,
- F32 height,
- const MatrixF &localXfm );
- virtual bool addConvex( const Point3F *points,
- U32 count,
- const MatrixF &localXfm );
- virtual bool addTriangleMesh( const Point3F *vert,
- U32 vertCount,
- const U32 *index,
- U32 triCount,
- const MatrixF &localXfm );
- virtual bool addHeightfield( const U16 *heights,
- const bool *holes,
- U32 blockSize,
- F32 metersPerSample,
- const MatrixF &localXfm );
-};
-
-#endif // _T3D_PHYSICS_PXCOLLISION_H_
\ No newline at end of file
diff --git a/Engine/source/T3D/physics/physx/pxContactReporter.cpp b/Engine/source/T3D/physics/physx/pxContactReporter.cpp
deleted file mode 100644
index 33b1c3dab..000000000
--- a/Engine/source/T3D/physics/physx/pxContactReporter.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2012 GarageGames, LLC
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to
-// deal in the Software without restriction, including without limitation the
-// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-// sell copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-// IN THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#include "platform/platform.h"
-#include "T3D/physics/physX/pxContactReporter.h"
-
-#include "T3D/physics/physX/pxCasts.h"
-#include "T3D/physics/physicsUserData.h"
-#include "T3D/physics/physX/pxMultiActor.h"
-#include "platform/profiler.h"
-
-
-PxContactReporter::PxContactReporter()
-{
-}
-
-PxContactReporter::~PxContactReporter()
-{
-}
-
-void PxContactReporter::onContactNotify( NxContactPair &pair, NxU32 events )
-{
- PROFILE_SCOPE( PxContactReporter_OnContactNotify );
-
- // For now we only care about start touch events.
- if ( !( events & NX_NOTIFY_ON_START_TOUCH ) )
- return;
-
- // Skip if either actor is deleted.
- if ( pair.isDeletedActor[0] || pair.isDeletedActor[1] )
- return;
-
- NxActor *actor0 = pair.actors[0];
- NxActor *actor1 = pair.actors[1];
-
- PhysicsUserData *userData0 = PhysicsUserData::cast( actor0->userData );
- PhysicsUserData *userData1 = PhysicsUserData::cast( actor1->userData );
-
- // Early out if we don't have user data or signals to notify.
- if ( ( !userData0 || userData0->getContactSignal().isEmpty() ) &&
- ( !userData1 || userData1->getContactSignal().isEmpty() ) )
- return;
-
- // Get an average contact point.
- U32 points = 0;
- NxVec3 hitPoint( 0.0f );
- NxContactStreamIterator iter( pair.stream );
- while( iter.goNextPair() )
- {
- while( iter.goNextPatch() )
- {
- while( iter.goNextPoint() )
- {
- hitPoint += iter.getPoint();
- ++points;
- }
- }
- }
- hitPoint /= (F32)points;
-
- if ( userData0 )
- userData0->getContactSignal().trigger( userData0,
- userData1,
- pxCast( hitPoint ),
- pxCast( pair.sumNormalForce ) );
-
- if ( userData1 )
- userData1->getContactSignal().trigger( userData1,
- userData0,
- pxCast( hitPoint ),
- pxCast( -pair.sumNormalForce ) );
-}
-
-bool PxUserNotify::onJointBreak( NxReal breakingForce, NxJoint &brokenJoint )
-{
- PROFILE_SCOPE( PxUserNotify_OnJointBreak );
-
- PxUserData *userData = PxUserData::getData( brokenJoint );
-
- if ( userData )
- userData->getOnJointBreakSignal().trigger( breakingForce, brokenJoint );
-
- // NOTE: Returning true here will tell the
- // PhysX SDK to delete the joint, which will
- // cause MANY problems if any of the user app's
- // objects still hold references to it.
-
- return false;
-}
\ No newline at end of file
diff --git a/Engine/source/T3D/physics/physx/pxContactReporter.h b/Engine/source/T3D/physics/physx/pxContactReporter.h
deleted file mode 100644
index 883d61b9c..000000000
--- a/Engine/source/T3D/physics/physx/pxContactReporter.h
+++ /dev/null
@@ -1,54 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2012 GarageGames, LLC
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to
-// deal in the Software without restriction, including without limitation the
-// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-// sell copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-// IN THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#ifndef _PXCONTACTREPORTER_H_
-#define _PXCONTACTREPORTER_H_
-
-#ifndef _PHYSX_H_
-#include "T3D/physics/physX/px.h"
-#endif
-
-
-class PxContactReporter : public NxUserContactReport
-{
-protected:
-
- virtual void onContactNotify( NxContactPair& pair, NxU32 events );
-
-public:
-
- PxContactReporter();
- virtual ~PxContactReporter();
-};
-
-
-
-class PxUserNotify : public NxUserNotify
-{
-public:
- virtual bool onJointBreak( NxReal breakingForce, NxJoint &brokenJoint );
- virtual void onWake( NxActor **actors, NxU32 count ) {}
- virtual void onSleep ( NxActor **actors, NxU32 count ) {}
-};
-
-
-#endif // _PXCONTACTREPORTER_H_
diff --git a/Engine/source/T3D/physics/physx/pxFluid.cpp b/Engine/source/T3D/physics/physx/pxFluid.cpp
deleted file mode 100644
index efe5d453b..000000000
--- a/Engine/source/T3D/physics/physx/pxFluid.cpp
+++ /dev/null
@@ -1,310 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2012 GarageGames, LLC
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to
-// deal in the Software without restriction, including without limitation the
-// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-// sell copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-// IN THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#include "platform/platform.h"
-#include "T3D/physics/physx/pxFluid.h"
-
-#include "console/consoleTypes.h"
-#include "scene/sceneRenderState.h"
-#include "renderInstance/renderPassManager.h"
-#include "T3D/physics/physicsPlugin.h"
-#include "T3D/physics/physx/pxWorld.h"
-#include "T3D/physics/physx/pxCasts.h"
-#include "gfx/gfxDrawUtil.h"
-#include "math/mathIO.h"
-#include "core/stream/bitStream.h"
-
-
-IMPLEMENT_CO_NETOBJECT_V1( PxFluid );
-
-ConsoleDocClass( PxFluid,
- "@brief Experimental and unfinished Torque wrapper class for NxFluid.\n\n"
- "@internal\n"
-);
-
-PxFluid::PxFluid()
- : mWorld( NULL ),
- mScene( NULL ),
- mParticles( NULL ),
- mFluid( NULL ),
- mEmitter( NULL ),
- mParticleCount( 0 )
-{
- mNetFlags.set( Ghostable | ScopeAlways );
- mTypeMask |= StaticObjectType | StaticShapeObjectType;
-}
-
-PxFluid::~PxFluid()
-{
-
-}
-
-bool PxFluid::onAdd()
-{
- if ( !Parent::onAdd() )
- return false;
-
- mWorld = dynamic_cast( PHYSICSMGR->getWorld( isServerObject() ? "server" : "client" ) );
-
- if ( !mWorld || !mWorld->getScene() )
- {
- Con::errorf( "PxMultiActor::onAdd() - PhysXWorld not initialized!" );
- return false;
- }
-
- mScene = mWorld->getScene();
-
- if ( isClientObject() )
- _createFluid();
-
- Point3F halfScale = Point3F::One * 0.5f;
- mObjBox.minExtents = -halfScale;
- mObjBox.maxExtents = halfScale;
- resetWorldBox();
-
- addToScene();
-
- return true;
-}
-
-void PxFluid::onRemove()
-{
- if ( isClientObject() )
- _destroyFluid();
-
- removeFromScene();
-
- Parent::onRemove();
-}
-
-void PxFluid::initPersistFields()
-{
- Parent::initPersistFields();
-}
-
-void PxFluid::inspectPostApply()
-{
- Parent::inspectPostApply();
-
- setMaskBits( UpdateMask );
-}
-
-U32 PxFluid::packUpdate( NetConnection *conn, U32 mask, BitStream *stream )
-{
- U32 retMask = Parent::packUpdate( conn, mask, stream );
-
- if ( stream->writeFlag( mask & UpdateMask ) )
- {
- mathWrite( *stream, getTransform() );
- mathWrite( *stream, getScale() );
-
- stream->write( mEmitter ? mEmitter->getRate() : 0 );
- }
-
- stream->writeFlag( isProperlyAdded() && mask & ResetMask );
-
- return retMask;
-}
-
-void PxFluid::unpackUpdate( NetConnection *conn, BitStream *stream )
-{
- Parent::unpackUpdate( conn, stream );
-
- // UpdateMask
- if ( stream->readFlag() )
- {
- MatrixF mat;
- mathRead( *stream, &mat );
- Point3F scale;
- mathRead( *stream, &scale );
-
- setScale( scale );
- setTransform( mat );
-
- F32 rate;
- stream->read( &rate );
- setRate( rate );
- }
-
- // ResetMask
- if ( stream->readFlag() )
- resetParticles();
-}
-
-void PxFluid::setTransform( const MatrixF &mat )
-{
- Parent::setTransform( mat );
-
- if ( mEmitter )
- {
- NxMat34 nxMat;
- nxMat.setRowMajor44( mat );
- mEmitter->setGlobalPose( nxMat );
- }
-}
-
-void PxFluid::setScale( const VectorF &scale )
-{
- Point3F lastScale = getScale();
-
- Point3F halfScale = Point3F::One * 0.5f;
- mObjBox.minExtents = -halfScale;
- mObjBox.maxExtents = halfScale;
- resetWorldBox();
-
- Parent::setScale( scale );
-
- if ( lastScale != getScale() &&
- mEmitter )
- {
- _destroyFluid();
- _createFluid();
- }
-}
-
-void PxFluid::prepRenderImage( SceneRenderState *state )
-{
- if ( !state->isDiffusePass() )
- return;
-
- ObjectRenderInst *ri = state->getRenderPass()->allocInst();
- ri->renderDelegate.bind( this, &PxFluid::renderObject );
- ri->type = RenderPassManager::RIT_Object;
- state->getRenderPass()->addInst( ri );
-}
-
-void PxFluid::resetParticles()
-{
- if ( mEmitter )
- mEmitter->resetEmission( MAX_PARTICLES );
- setMaskBits( ResetMask );
-}
-
-void PxFluid::setRate( F32 rate )
-{
- if ( mEmitter )
- mEmitter->setRate( rate );
- setMaskBits( UpdateMask );
-}
-
-void PxFluid::renderObject( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat )
-{
- GFXStateBlockDesc desc;
- desc.setBlend( true );
- desc.setZReadWrite( true, false );
-
- for ( U32 i = 0; i < mParticleCount; i++ )
- {
- FluidParticle &particle = mParticles[i];
- Point3F pnt = pxCast( particle.position );
-
- Box3F box( 0.2f );
- box.minExtents += pnt;
- box.maxExtents += pnt;
-
- GFX->getDrawUtil()->drawCube( desc, box, ColorI::BLUE );
- }
-}
-
-void PxFluid::_createFluid()
-{
- /*
- // Set structure to pass particles, and receive them after every simulation step
- NxParticleData particleData;
- particleData.numParticlesPtr = &mParticleCount;
- particleData.bufferPos = &mParticles[0].position.x;
- particleData.bufferPosByteStride = sizeof(FluidParticle);
- particleData.bufferVel = &mParticles[0].velocity.x;
- particleData.bufferVelByteStride = sizeof(FluidParticle);
- particleData.bufferLife = &mParticles[0].lifetime;
- particleData.bufferLifeByteStride = sizeof(FluidParticle);
-
- // Create a fluid descriptor
- NxFluidDesc fluidDesc;
- fluidDesc.kernelRadiusMultiplier = 2.3f;
- fluidDesc.restParticlesPerMeter = 10.0f;
- fluidDesc.stiffness = 200.0f;
- fluidDesc.viscosity = 22.0f;
- fluidDesc.restDensity = 1000.0f;
- fluidDesc.damping = 0.0f;
- fluidDesc.simulationMethod = NX_F_SPH;
- fluidDesc.initialParticleData = particleData;
- fluidDesc.particlesWriteData = particleData;
- */
-
- NxFluidDesc fluidDesc;
- fluidDesc.setToDefault();
- fluidDesc.simulationMethod = NX_F_SPH;
- fluidDesc.maxParticles = MAX_PARTICLES;
- fluidDesc.restParticlesPerMeter = 50;
- fluidDesc.stiffness = 1;
- fluidDesc.viscosity = 6;
- fluidDesc.flags = NX_FF_VISUALIZATION|NX_FF_ENABLED;
-
- mParticles = new FluidParticle[MAX_PARTICLES];
- dMemset( mParticles, 0, sizeof(FluidParticle) * MAX_PARTICLES );
-
- NxParticleData &particleData = fluidDesc.particlesWriteData;
-
- particleData.numParticlesPtr = &mParticleCount;
- particleData.bufferPos = &mParticles[0].position.x;
- particleData.bufferPosByteStride = sizeof(FluidParticle);
- particleData.bufferVel = &mParticles[0].velocity.x;
- particleData.bufferVelByteStride = sizeof(FluidParticle);
- particleData.bufferLife = &mParticles[0].lifetime;
- particleData.bufferLifeByteStride = sizeof(FluidParticle);
-
- mFluid = mScene->createFluid( fluidDesc );
-
-
- //Create Emitter.
- NxFluidEmitterDesc emitterDesc;
- emitterDesc.setToDefault();
- emitterDesc.dimensionX = getScale().x;
- emitterDesc.dimensionY = getScale().y;
- emitterDesc.relPose.setColumnMajor44( getTransform() );
- emitterDesc.rate = 5.0f;
- emitterDesc.randomAngle = 0.1f;
- emitterDesc.fluidVelocityMagnitude = 6.5f;
- emitterDesc.maxParticles = 0;
- emitterDesc.particleLifetime = 4.0f;
- emitterDesc.type = NX_FE_CONSTANT_FLOW_RATE;
- emitterDesc.shape = NX_FE_ELLIPSE;
- mEmitter = mFluid->createEmitter(emitterDesc);
-}
-
-void PxFluid::_destroyFluid()
-{
- delete[] mParticles;
- mScene->releaseFluid( *mFluid );
- mEmitter = NULL;
-}
-
-ConsoleMethod( PxFluid, resetParticles, void, 2, 2, "" )
-{
- object->resetParticles();
-}
-
-ConsoleMethod( PxFluid, setRate, void, 2, 2, "" )
-{
- object->setRate( dAtof(argv[2]) );
-}
\ No newline at end of file
diff --git a/Engine/source/T3D/physics/physx/pxFluid.h b/Engine/source/T3D/physics/physx/pxFluid.h
deleted file mode 100644
index ae7fe4f3c..000000000
--- a/Engine/source/T3D/physics/physx/pxFluid.h
+++ /dev/null
@@ -1,107 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2012 GarageGames, LLC
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to
-// deal in the Software without restriction, including without limitation the
-// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-// sell copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-// IN THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#ifndef _PXFLUID_H_
-#define _PXFLUID_H_
-
-#ifndef _SCENEOBJECT_H_
-#include "scene/sceneObject.h"
-#endif
-#ifndef _PHYSX_H_
-#include "T3D/physics/physx/px.h"
-#endif
-
-class BaseMatInstance;
-class PxWorld;
-class NxScene;
-
-
-class PxFluid : public SceneObject
-{
- typedef SceneObject Parent;
-
-protected:
-
- enum NetMasks
- {
- UpdateMask = Parent::NextFreeMask,
- ResetMask = Parent::NextFreeMask << 1,
- NextFreeMask = Parent::NextFreeMask << 2
- };
-
- struct FluidParticle
- {
- NxVec3 position;
- NxVec3 velocity;
- NxReal density;
- NxReal lifetime;
- NxU32 id;
- NxVec3 collisionNormal;
- };
-
- #define MAX_PARTICLES 100
-
-public:
-
- PxFluid();
- virtual ~PxFluid();
-
- DECLARE_CONOBJECT( PxFluid );
-
- // SimObject
- virtual bool onAdd();
- virtual void onRemove();
- static void initPersistFields();
- virtual void inspectPostApply();
-
- // NetObject
- virtual U32 packUpdate( NetConnection *conn, U32 mask, BitStream *stream );
- virtual void unpackUpdate( NetConnection *conn, BitStream *stream );
-
- // SceneObject
- virtual void setTransform( const MatrixF &mat );
- virtual void setScale( const VectorF &scale );
- virtual void prepRenderImage( SceneRenderState *state );
-
- void resetParticles();
- void setRate( F32 rate );
-
-protected:
-
- void renderObject( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat );
-
- void _createFluid();
- void _destroyFluid();
-
-protected:
-
- PxWorld *mWorld;
- NxScene *mScene;
-
- FluidParticle *mParticles;
- //NxParticleData *mParticleData;
- NxFluid *mFluid;
- U32 mParticleCount;
- NxFluidEmitter *mEmitter;
-};
-
-#endif // _PXFLUID_H_
\ No newline at end of file
diff --git a/Engine/source/T3D/physics/physx/pxMaterial.cpp b/Engine/source/T3D/physics/physx/pxMaterial.cpp
deleted file mode 100644
index 9a5656394..000000000
--- a/Engine/source/T3D/physics/physx/pxMaterial.cpp
+++ /dev/null
@@ -1,150 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2012 GarageGames, LLC
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to
-// deal in the Software without restriction, including without limitation the
-// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-// sell copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-// IN THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#include "platform/platform.h"
-#include "T3D/physics/physX/px.h"
-
-#include "T3D/physics/physX/pxMaterial.h"
-
-#include "T3D/physics/physX/pxWorld.h"
-#include "T3D/physics/physicsPlugin.h"
-#include "console/consoleTypes.h"
-#include "core/stream/bitStream.h"
-
-
-IMPLEMENT_CO_DATABLOCK_V1( PxMaterial );
-
-ConsoleDocClass( PxMaterial,
-
- "@brief Defines a PhysX material assignable to a PxMaterial.\n\n"
-
- "When two actors collide, the collision behavior that results depends on the material properties "
- "of the actors' surfaces. For example, the surface properties determine if the actors will or will "
- "not bounce, or if they will slide or stick. Currently, the only special feature supported by materials "
- "is anisotropic friction, but according to Nvidia, other effects such as moving surfaces and more types "
- "of friction are slotted for future release.\n\n"
-
- "For more information, refer to Nvidia's PhysX docs.\n\n"
-
- "@ingroup Physics"
-);
-
-PxMaterial::PxMaterial()
-: mNxMat( NULL ),
- mNxMatId( -1 ),
- restitution( 0.0f ),
- staticFriction( 0.1f ),
- dynamicFriction( 0.95f ),
- mServer( false )
-{
-}
-
-PxMaterial::~PxMaterial()
-{
-}
-
-void PxMaterial::consoleInit()
-{
- Parent::consoleInit();
-}
-
-void PxMaterial::initPersistFields()
-{
- Parent::initPersistFields();
-
- addGroup("PxMaterial");
-
- addField( "restitution", TypeF32, Offset( restitution, PxMaterial ),
- "@brief Coeffecient of a bounce applied to the shape in response to a collision.\n\n"
- "A value of 0 makes the object bounce as little as possible, while higher values up to 1.0 result in more bounce.\n\n"
- "@note Values close to or above 1.0 may cause stability problems and/or increasing energy.");
- addField( "staticFriction", TypeF32, Offset( staticFriction, PxMaterial ),
- "@brief Coefficient of static %friction to be applied.\n\n"
- "Static %friction determines the force needed to start moving an at-rest object in contact with a surface. "
- "If the force applied onto shape cannot overcome the force of static %friction, the shape will remain at rest. "
- "A higher coefficient will require a larger force to start motion. "
- "@note This value should be larger than 0.\n\n");
- addField( "dynamicFriction", TypeF32, Offset( dynamicFriction, PxMaterial ),
- "@brief Coefficient of dynamic %friction to be applied.\n\n"
- "Dynamic %friction reduces the velocity of a moving object while it is in contact with a surface. "
- "A higher coefficient will result in a larger reduction in velocity. "
- "A shape's dynamicFriction should be equal to or larger than 0.\n\n");
-
- endGroup("PxMaterial");
-}
-
-void PxMaterial::onStaticModified( const char *slotName, const char *newValue )
-{
- if ( isProperlyAdded() && mNxMat != NULL )
- {
- mNxMat->setRestitution( restitution );
- mNxMat->setStaticFriction( staticFriction );
- mNxMat->setDynamicFriction( dynamicFriction );
- }
-}
-
-bool PxMaterial::preload( bool server, String &errorBuffer )
-{
- mServer = server;
-
- PxWorld *world = dynamic_cast( PHYSICSMGR->getWorld( server ? "server" : "client" ) );
-
- if ( !world )
- {
- // TODO: Error... in error buffer?
- return false;
- }
-
- NxMaterialDesc material;
- material.restitution = restitution;
- material.staticFriction = staticFriction;
- material.dynamicFriction = dynamicFriction;
-
- mNxMat = world->createMaterial( material );
- mNxMatId = mNxMat->getMaterialIndex();
-
- if ( mNxMatId == -1 )
- {
- errorBuffer = "PxMaterial::preload() - unable to create material!";
- return false;
- }
-
- return Parent::preload( server, errorBuffer );
-}
-
-void PxMaterial::packData( BitStream* stream )
-{
- Parent::packData( stream );
-
- stream->write( restitution );
- stream->write( staticFriction );
- stream->write( dynamicFriction );
-}
-
-void PxMaterial::unpackData( BitStream* stream )
-{
- Parent::unpackData( stream );
-
- stream->read( &restitution );
- stream->read( &staticFriction );
- stream->read( &dynamicFriction );
-}
diff --git a/Engine/source/T3D/physics/physx/pxMaterial.h b/Engine/source/T3D/physics/physx/pxMaterial.h
deleted file mode 100644
index b1e0dd7f0..000000000
--- a/Engine/source/T3D/physics/physx/pxMaterial.h
+++ /dev/null
@@ -1,69 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2012 GarageGames, LLC
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to
-// deal in the Software without restriction, including without limitation the
-// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-// sell copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-// IN THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#ifndef _PHYSX_MATERIAL_H
-#define _PHYSX_MATERIAL_H
-
-#ifndef _SIMBASE_H_
-#include "console/simBase.h"
-#endif
-#ifndef _DYNAMIC_CONSOLETYPES_H_
-#include "console/dynamicTypes.h"
-#endif
-
-class NxMaterial;
-
-class PxMaterial : public SimDataBlock
-{
- typedef SimDataBlock Parent;
-
-protected:
-
- F32 restitution;
- F32 staticFriction;
- F32 dynamicFriction;
-
- NxMaterial *mNxMat;
- S32 mNxMatId;
-
- bool mServer;
-
-public:
-
- DECLARE_CONOBJECT( PxMaterial );
-
- PxMaterial();
- ~PxMaterial();
-
- static void consoleInit();
- static void initPersistFields();
- virtual void onStaticModified( const char *slotName, const char *newValue );
-
- bool preload( bool server, String &errorBuffer );
- virtual void packData( BitStream* stream );
- virtual void unpackData( BitStream* stream );
-
- S32 getMaterialId() const { return mNxMatId; }
-
-};
-
-#endif // _PHYSX_MATERIAL_H
\ No newline at end of file
diff --git a/Engine/source/T3D/physics/physx/pxMultiActor.cpp b/Engine/source/T3D/physics/physx/pxMultiActor.cpp
deleted file mode 100644
index 6abdcdaad..000000000
--- a/Engine/source/T3D/physics/physx/pxMultiActor.cpp
+++ /dev/null
@@ -1,2651 +0,0 @@
-//-----------------------------------------------------------------------------
-// Copyright (c) 2012 GarageGames, LLC
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to
-// deal in the Software without restriction, including without limitation the
-// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
-// sell copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
-// IN THE SOFTWARE.
-//-----------------------------------------------------------------------------
-
-#include "platform/platform.h"
-#include "T3D/physics/physX/pxMultiActor.h"
-
-#include "console/consoleTypes.h"
-#include "core/stream/fileStream.h"
-#include "core/stream/bitStream.h"
-#include "core/resourceManager.h"
-#include "core/strings/stringUnit.h"
-#include "sim/netConnection.h"
-#include "math/mathIO.h"
-#include "math/mathUtils.h"
-#include "gfx/gfxTransformSaver.h"
-#include "gfx/gfxDrawUtil.h"
-#include "gfx/primBuilder.h"
-#include "collision/collision.h"
-#include "collision/abstractPolyList.h"
-#include "ts/tsShapeInstance.h"
-#include "ts/tsPartInstance.h"
-#include "lighting/lightManager.h"
-#include "scene/sceneManager.h"
-#include "scene/sceneRenderState.h"
-#include "scene/sceneObjectLightingPlugin.h"
-#include "T3D/objectTypes.h"
-#include "T3D/containerQuery.h"
-#include "T3D/fx/particleEmitter.h"
-#include "T3D/debris.h"
-#include "renderInstance/renderPassManager.h"
-#include "gui/worldEditor/editor.h" // For gEditingMission
-#include "T3D/physics/physX/px.h"
-#include "T3D/physics/physX/pxWorld.h"
-#include "T3D/physics/physX/pxMaterial.h"
-#include "T3D/physics/physX/pxCasts.h"
-#include "T3D/physics/physx/pxUtils.h"
-#include "sfx/sfxSystem.h"
-
-#include
-#include
-#include
-
-
-class PxMultiActor_Notify : public NXU_userNotify
-{
-protected:
-
- Vector mActors;
-
- Vector mShapes;
-
- Vector mJoints;
-
- const NxMat34 mTransform;
-
- const Point3F mScale;
-
- F32 mMassScale;
-
- NxCompartment *mCompartment;
-
- PxMaterial *mMaterial;
-
- Vector *mActorUserProperties;
-
- Vector *mJointUserProperties;
-
-public:
-
- void NXU_notifyJoint( NxJoint *joint, const char *userProperties )
- {
- if ( mJointUserProperties )
- mJointUserProperties->push_back( userProperties );
- mJoints.push_back( joint );
- }
-
- bool NXU_preNotifyJoint( NxJointDesc &joint, const char *userProperties )
- {
- joint.localAnchor[0].x *= mScale.x;
- joint.localAnchor[0].y *= mScale.y;
- joint.localAnchor[0].z *= mScale.z;
-
- joint.localAnchor[1].x *= mScale.x;
- joint.localAnchor[1].y *= mScale.y;
- joint.localAnchor[1].z *= mScale.z;
-
- // The PhysX exporter from 3dsMax doesn't allow creation
- // of fixed joints. It also doesn't seem to export the
- // joint names! So look for joints which all all the
- // motion axes are locked... make those fixed joints.
- if ( joint.getType() == NX_JOINT_D6 )
- {
- NxD6JointDesc *d6Joint = static_cast( &joint );
-
- if ( d6Joint->xMotion == NX_D6JOINT_MOTION_LOCKED &&
- d6Joint->yMotion == NX_D6JOINT_MOTION_LOCKED &&
- d6Joint->zMotion == NX_D6JOINT_MOTION_LOCKED &&
- d6Joint->swing1Motion == NX_D6JOINT_MOTION_LOCKED &&
- d6Joint->swing2Motion == NX_D6JOINT_MOTION_LOCKED &&
- d6Joint->twistMotion == NX_D6JOINT_MOTION_LOCKED )
- {
- // Ok... build a new fixed joint.
- NxFixedJointDesc fixed;
- fixed.actor[0] = joint.actor[0];
- fixed.actor[1] = joint.actor[1];
- fixed.localNormal[0] = joint.localNormal[0];
- fixed.localNormal[1] = joint.localNormal[1];
- fixed.localAxis[0] = joint.localAxis[0];
- fixed.localAxis[1] = joint.localAxis[1];
- fixed.localAnchor[0] = joint.localAnchor[0];
- fixed.localAnchor[1] = joint.localAnchor[1];
- fixed.maxForce = joint.maxForce;
- fixed.maxTorque = joint.maxTorque;
- fixed.name = joint.name;
- fixed.userData = joint.userData;
- fixed.jointFlags = joint.jointFlags;
-
- // What scene are we adding this to?
- NxActor *actor = fixed.actor[0] ? fixed.actor[0] : fixed.actor[1];
- NxScene &scene = actor->getScene();
-
- NxJoint* theJoint = scene.createJoint( fixed );
- mJoints.push_back( theJoint );
- if ( mJointUserProperties )
- mJointUserProperties->push_back( userProperties );
-
- // Don't generate this joint.
- return false;
- }
- }
-
- return true;
- }
-
- void NXU_notifyActor( NxActor *actor, const char *userProperties )
- {
- mActors.push_back( actor );
-
- // Save the shapes.
- for ( U32 i=0; i < actor->getNbShapes(); i++ )
- mShapes.push_back( actor->getShapes()[i] );
-
- mActorUserProperties->push_back( userProperties );
- };
-
- bool NXU_preNotifyMaterial( NxMaterialDesc &t, const char *userProperties )
- {
- // Don't generate materials if we have one defined!
- return !mMaterial;
- }
-
- bool NXU_preNotifyActor( NxActorDesc &actor, const char *userProperties )
- {
- // Set the right compartment.
- actor.compartment = mCompartment;
-
- if ( actor.shapes.size() == 0 )
- Con::warnf( "PxMultiActor_Notify::NXU_preNotifyActor, got an actor (%s) with no shapes, was this intentional?", actor.name );
-
- // For every shape, cast to its particular type
- // and apply the scale to size, mass and localPosition.
- for( S32 i = 0; i < actor.shapes.size(); i++ )
- {
- // If we have material then set it.
- if ( mMaterial )
- actor.shapes[i]->materialIndex = mMaterial->getMaterialId();
-
- switch( actor.shapes[i]->getType() )
- {
- case NX_SHAPE_BOX:
- {
- NxBoxShapeDesc *boxDesc = (NxBoxShapeDesc*)actor.shapes[i];
-
- boxDesc->mass *= mMassScale;
-
- boxDesc->dimensions.x *= mScale.x;
- boxDesc->dimensions.y *= mScale.y;
- boxDesc->dimensions.z *= mScale.z;
-
- boxDesc->localPose.t.x *= mScale.x;
- boxDesc->localPose.t.y *= mScale.y;
- boxDesc->localPose.t.z *= mScale.z;
- break;
- }
-
- case NX_SHAPE_SPHERE:
- {
- NxSphereShapeDesc *sphereDesc = (NxSphereShapeDesc*)actor.shapes[i];
-
- sphereDesc->mass *= mMassScale;
-
- // TODO: Spheres do not work with non-uniform
- // scales very well... how do we fix this?
- sphereDesc->radius *= mScale.x;
-
- sphereDesc->localPose.t.x *= mScale.x;
- sphereDesc->localPose.t.y *= mScale.y;
- sphereDesc->localPose.t.z *= mScale.z;
- break;
- }
-
- case NX_SHAPE_CAPSULE:
- {
- NxCapsuleShapeDesc *capsuleDesc = (NxCapsuleShapeDesc*)actor.shapes[i];
-
- capsuleDesc->mass *= mMassScale;
-
- // TODO: Capsules do not work with non-uniform
- // scales very well... how do we fix this?
- capsuleDesc->radius *= mScale.x;
- capsuleDesc->height *= mScale.y;
-
- capsuleDesc->localPose.t.x *= mScale.x;
- capsuleDesc->localPose.t.y *= mScale.y;
- capsuleDesc->localPose.t.z *= mScale.z;
- break;
- }
-
- default:
- {
- static String lookup[] =
- {
- "PLANE",
- "SPHERE",
- "BOX",
- "CAPSULE",
- "WHEEL",
- "CONVEX",
- "MESH",
- "HEIGHTFIELD"
- };
-
- Con::warnf( "PxMultiActor_Notify::NXU_preNotifyActor, unsupported shape type (%s), on Actor (%s)", lookup[actor.shapes[i]->getType()].c_str(), actor.name );
-
- delete actor.shapes[i];
- actor.shapes.erase( actor.shapes.begin() + i );
- --i;
- break;
- }
- }
- }
-
- NxBodyDesc *body = const_cast( actor.body );
- if ( body )
- {
- // Must scale all of these parameters, else there will be odd results!
- body->mass *= mMassScale;
- body->massLocalPose.t.multiply( mMassScale, body->massLocalPose.t );
- body->massSpaceInertia.multiply( mMassScale, body->massSpaceInertia );
-
- // Ragdoll damping!
- //body->sleepDamping = 1.7f;
- //body->linearDamping = 0.4f;
- //body->angularDamping = 0.08f;
- //body->wakeUpCounter = 0.3f;
- }
-
- return true;
- };
-
-public:
-
- PxMultiActor_Notify( NxCompartment *compartment,
- PxMaterial *material,
- const NxMat34& mat,
- const Point3F& scale,
- Vector *actorProps = NULL,
- Vector *jointProps = NULL )
- : mCompartment( compartment ),
- mMaterial( material ),
- mScale( scale ),
- mTransform( mat ),
- mActorUserProperties( actorProps ),
- mJointUserProperties( jointProps )
- {
- const F32 unit = VectorF( 1.0f, 1.0f, 1.0f ).len();
- mMassScale = mScale.len() / unit;
- }
-
- virtual ~PxMultiActor_Notify()
- {
- }
-
- const Vector& getActors() { return mActors; }
- const Vector& getShapes() { return mShapes; }
- const Vector& getJoints() { return mJoints; }
-};
-
-ConsoleDocClass( PxMultiActorData,
-
- "@brief Defines the properties of a type of PxMultiActor.\n\n"
-
- "Usually it is prefered to use PhysicsShape rather than PxMultiActor because "
- "a PhysicsShape is not PhysX specific and can be much easier to setup.\n\n"
-
- "For more information, refer to Nvidia's PhysX docs.\n\n"
-
- "@ingroup Physics"
-);
-
-IMPLEMENT_CO_DATABLOCK_V1(PxMultiActorData);
-
-PxMultiActorData::PxMultiActorData()
- : material( NULL ),
- collection( NULL ),
- waterDragScale( 1.0f ),
- buoyancyDensity( 1.0f ),
- angularDrag( 0.0f ),
- linearDrag( 0.0f ),
- clientOnly( false ),
- singlePlayerOnly( false ),
- shapeName( StringTable->insert( "" ) ),
- physXStream( StringTable->insert( "" ) ),
- breakForce( 0.0f )
-{
- for ( S32 i = 0; i < MaxCorrectionNodes; i++ )
- correctionNodeNames[i] = StringTable->insert( "" );
-
- for ( S32 i = 0; i < MaxCorrectionNodes; i++ )
- correctionNodes[i] = -1;
-
- for ( S32 i = 0; i < NumMountPoints; i++ )
- {
- mountNodeNames[i] = StringTable->insert( "" );
- mountPointNode[i] = -1;
- }
-}
-
-PxMultiActorData::~PxMultiActorData()
-{
- if ( collection )
- NXU::releaseCollection( collection );
-}
-
-void PxMultiActorData::initPersistFields()
-{
- Parent::initPersistFields();
-
- addGroup("Media");
- addField( "shapeName", TypeFilename, Offset( shapeName, PxMultiActorData ),
- "@brief Path to the .DAE or .DTS file to render.\n\n");
- endGroup("Media");
-
- // PhysX collision properties.
- addGroup( "Physics" );
-
- addField( "physXStream", TypeFilename, Offset( physXStream, PxMultiActorData ),
- "@brief .XML file containing data such as actors, shapes, and joints.\n\n"
- "These files can be created using a free PhysX plugin for 3DS Max.\n\n");
- addField( "material", TYPEID< PxMaterial >(), Offset( material, PxMultiActorData ),
- "@brief An optional PxMaterial to be used for the PxMultiActor.\n\n"
- "Defines properties such as friction and restitution. "
- "Unrelated to the material used for rendering. The physXStream will contain "
- "defined materials that can be customized in 3DS Max. "
- "To override the material for all physics shapes in the physXStream, specify a material here.\n\n");
-
- addField( "noCorrection", TypeBool, Offset( noCorrection, PxMultiActorData ),
- "@hide" );
-
- UTF8 buff[256];
- for ( S32 i=0; i < MaxCorrectionNodes; i++ )
- {
- //dSprintf( buff, sizeof(buff), "correctionNode%d", i );
- addField( buff, TypeString, Offset( correctionNodeNames[i], PxMultiActorData ), "@hide" );
- }
-
- for ( S32 i=0; i < NumMountPoints; i++ )
- {
- //dSprintf( buff, sizeof(buff), "mountNode%d", i );
- addField( buff, TypeString, Offset( mountNodeNames[i], PxMultiActorData ), "@hide" );
- }
-
- addField( "angularDrag", TypeF32, Offset( angularDrag, PxMultiActorData ),
- "@brief Value used to help calculate rotational drag force while submerged in water.\n\n");
- addField( "linearDrag", TypeF32, Offset( linearDrag, PxMultiActorData ),
- "@brief Value used to help calculate linear drag force while submerged in water.\n\n");
- addField( "waterDragScale", TypeF32, Offset( waterDragScale, PxMultiActorData ),
- "@brief Scale to apply to linear and angular dampening while submerged in water.\n\n ");
- addField( "buoyancyDensity", TypeF32, Offset( buoyancyDensity, PxMultiActorData ),
- "@brief The density used to calculate buoyant forces.\n\n"
- "The result of the calculated buoyancy is relative to the density of the WaterObject the PxMultiActor is within.\n\n"
- "@note This value is necessary because Torque 3D does its own buoyancy simulation. It is not handled by PhysX."
- "@see WaterObject::density");
-
- endGroup( "Physics" );
-
- addField( "clientOnly", TypeBool, Offset( clientOnly, PxMultiActorData ),
- "@hide");
- addField( "singlePlayerOnly", TypeBool, Offset( singlePlayerOnly, PxMultiActorData ),
- "@hide");
- addField( "breakForce", TypeF32, Offset( breakForce, PxMultiActorData ),
- "@brief Force required to break an actor.\n\n"
- "This value does not apply to joints. "
- "If an actor is associated with a joint it will break whenever the joint does. "
- "This allows an actor \"not\" associated with a joint to also be breakable.\n\n");
-}
-
-void PxMultiActorData::packData(BitStream* stream)
-{
- Parent::packData(stream);
-
- stream->writeString( shapeName );
- stream->writeString( physXStream );
-
- if( stream->writeFlag( material ) )
- stream->writeRangedU32( packed ? SimObjectId( material ) : material->getId(),
- DataBlockObjectIdFirst, DataBlockObjectIdLast );
-
- if ( !stream->writeFlag( noCorrection ) )
- {
- // Write the correction node indices for the client.
- for ( S32 i = 0; i < MaxCorrectionNodes; i++ )
- stream->write( correctionNodes[i] );
- }
-
- for ( S32 i = 0; i < NumMountPoints; i++ )
- stream->write( mountPointNode[i] );
-
- stream->write( waterDragScale );
- stream->write( buoyancyDensity );
- stream->write( angularDrag );
- stream->write( linearDrag );
-
- stream->writeFlag( clientOnly );
- stream->writeFlag( singlePlayerOnly );
- stream->write( breakForce );
-}
-
-void PxMultiActorData::unpackData(BitStream* stream)
-{
- Parent::unpackData(stream);
-
- shapeName = stream->readSTString();
- physXStream = stream->readSTString();
-
- if( stream->readFlag() )
- material = (PxMaterial*)stream->readRangedU32( DataBlockObjectIdFirst, DataBlockObjectIdLast );
-
- noCorrection = stream->readFlag();
- if ( !noCorrection )
- {
- for ( S32 i = 0; i < MaxCorrectionNodes; i++ )
- stream->read( &correctionNodes[i] );
- }
-
- for ( S32 i = 0; i < NumMountPoints; i++ )
- stream->read( &mountPointNode[i] );
-
- stream->read( &waterDragScale );
- stream->read( &buoyancyDensity );
- stream->read( &angularDrag );
- stream->read( &linearDrag );
-
- clientOnly = stream->readFlag();
- singlePlayerOnly = stream->readFlag();
- stream->read( &breakForce );
-}
-
-bool PxMultiActorData::preload( bool server, String &errorBuffer )
-{
- if ( !Parent::preload( server, errorBuffer ) )
- return false;
-
- // If the stream is null, exit.
- if ( !physXStream || !physXStream[0] )
- {
- errorBuffer = "PxMultiActorData::preload: physXStream is unset!";
- return false;
- }
-
- // Set up our buffer for the binary stream filename path.
- UTF8 binPhysXStream[260] = { 0 };
- const UTF8* ext = dStrrchr( physXStream, '.' );
-
- // Copy the xml stream path except for the extension.
- if ( ext )
- dStrncpy( binPhysXStream, physXStream, getMin( 260, ext - physXStream ) );
- else
- dStrncpy( binPhysXStream, physXStream, 260 );
-
- // Concatenate the binary extension.
- dStrcat( binPhysXStream, ".nxb" );
-
- // Get the modified times of the two files.
- FileTime xmlTime = {0}, binTime = {0};
- Platform::getFileTimes( physXStream, NULL, &xmlTime );
- Platform::getFileTimes( binPhysXStream, NULL, &binTime );
-
- // If the binary is newer... load that.
- if ( Platform::compareFileTimes( binTime, xmlTime ) >= 0 )
- _loadCollection( binPhysXStream, true );
-
- // If the binary failed... then load the xml.
- if ( !collection )
- {
- _loadCollection( physXStream, false );
-
- // If loaded... resave the xml in binary format
- // for quicker subsequent loads.
- if ( collection )
- NXU::saveCollection( collection, binPhysXStream, NXU::FT_BINARY );
- }
-
- // If it still isn't loaded then we've failed!
- if ( !collection )
- {
- errorBuffer = String::ToString( "PxMultiActorDatas::preload: could not load '%s'!", physXStream );
- return false;
- }
-
- if (!shapeName || shapeName[0] == '\0')
- {
- errorBuffer = "PxMultiActorDatas::preload: no shape name!";
- return false;
- }
-
- shape = ResourceManager::get().load( shapeName );
-
- if (bool(shape) == false)
- {
- errorBuffer = String::ToString( "PxMultiActorData::preload: unable to load shape: %s", shapeName );
- return false;
- }
-
- // Find the client side material.
- if ( !server && material )
- Sim::findObject( SimObjectId(material), material );
-
- // Get the ignore node indexes from the names.
- for ( S32 i = 0; i < MaxCorrectionNodes; i++ )
- {
- if( !correctionNodeNames[i] || !correctionNodeNames[i][0] )
- continue;
-
- correctionNodes[i] = shape->findNode( correctionNodeNames[i] );
- }
-
- // Resolve mount point node indexes
- for ( S32 i = 0; i < NumMountPoints; i++)
- {
- char fullName[256];
-
- if ( !mountNodeNames[i] || !mountNodeNames[i][0] )
- {
- dSprintf(fullName,sizeof(fullName),"mount%d",i);
- mountPointNode[i] = shape->findNode(fullName);
- }
- else
- mountPointNode[i] = shape->findNode(mountNodeNames[i]);
- }
-
- // Register for file change notification to reload the collection
- if ( server )
- Torque::FS::AddChangeNotification( physXStream, this, &PxMultiActorData::_onFileChanged );
-
- return true;
-}
-
-void PxMultiActorData::_onFileChanged( const Torque::Path &path )
-{
- reload();
-}
-
-void PxMultiActorData::reload()
-{
- bool result = _loadCollection( physXStream, false );
-
- if ( !result )
- Con::errorf( "PxMultiActorData::reload(), _loadCollection failed..." );
-
- // Inform MultiActors who use this datablock to reload.
- mReloadSignal.trigger();
-}
-
-bool PxMultiActorData::_loadCollection( const UTF8 *path, bool isBinary )
-{
- if ( collection )
- {
- NXU::releaseCollection( collection );
- collection = NULL;
- }
-
- FileStream fs;
- if ( !fs.open( path, Torque::FS::File::Read ) )
- return false;
-
- // Load the data into memory.
- U32 size = fs.getStreamSize();
- FrameTemp buff( size );
- fs.read( size, buff );
-
- // If the stream didn't read anything, there's a problem.
- if ( size <= 0 )
- return false;
-
- // Ok... try to load it.
- collection = NXU::loadCollection( path,
- isBinary ? NXU::FT_BINARY : NXU::FT_XML,
- buff,
- size );
-
- return collection != NULL;
-}
-
-
-bool PxMultiActorData::createActors( NxScene *scene,
- NxCompartment *compartment,
- const NxMat34 *nxMat,
- const Point3F& scale,
- Vector