diff --git a/README.md b/README.md index 63383f609..5691cb487 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 1778. +This is the source code for early-access 1780. ## Legal Notice diff --git a/externals/SDL/CMakeLists.txt b/externals/SDL/CMakeLists.txt index 358f32f3a..92ed7995d 100755 --- a/externals/SDL/CMakeLists.txt +++ b/externals/SDL/CMakeLists.txt @@ -1202,22 +1202,20 @@ elseif(UNIX AND NOT APPLE AND NOT ANDROID AND NOT RISCOS) CheckRPI() CheckX11() CheckDirectFB() - CheckOpenGLX11() - CheckOpenGLESX11() + # Need to check for EGL first because KMSDRM and Wayland depends on it. + CheckEGL() + CheckKMSDRM() + CheckGLX() + CheckOpenGL() + CheckOpenGLES() CheckWayland() CheckVivante() - # Need to check EGL before checking KMSDRM because KMSDRM depends on it. - CheckEGLKMSDRM() - CheckKMSDRM() - CheckOpenGLKMSDRM() endif() if(UNIX) file(GLOB CORE_UNIX_SOURCES ${SDL2_SOURCE_DIR}/src/core/unix/*.c) set(SOURCE_FILES ${SOURCE_FILES} ${CORE_UNIX_SOURCES}) - endif() - if(LINUX) check_c_source_compiles(" #include #ifndef EVIOCGNAME @@ -1225,16 +1223,28 @@ elseif(UNIX AND NOT APPLE AND NOT ANDROID AND NOT RISCOS) #endif int main(int argc, char** argv) {}" HAVE_INPUT_EVENTS) - check_c_source_compiles(" - #include - #include + if(LINUX) + check_c_source_compiles(" + #include + #include - int main(int argc, char **argv) - { - struct kbentry kbe; - kbe.kb_table = KG_CTRL; - ioctl(0, KDGKBENT, &kbe); - }" HAVE_INPUT_KD) + int main(int argc, char **argv) + { + struct kbentry kbe; + kbe.kb_table = KG_CTRL; + ioctl(0, KDGKBENT, &kbe); + }" HAVE_INPUT_KD) + elseif(FREEBSD) + check_c_source_compiles(" + #include + #include + + int main(int argc, char **argv) + { + accentmap_t accTable; + ioctl(0, KDENABIO, 1); + }" HAVE_INPUT_KBIO) + endif() if(HAVE_INPUT_EVENTS) set(SDL_INPUT_LINUXEV 1) @@ -1250,11 +1260,16 @@ elseif(UNIX AND NOT APPLE AND NOT ANDROID AND NOT RISCOS) if(HAVE_INPUT_KD) set(SDL_INPUT_LINUXKD 1) endif() + + if(HAVE_INPUT_KBIO) + set(SDL_INPUT_FBSDKBIO 1) + endif() check_include_file("libudev.h" HAVE_LIBUDEV_H) check_include_file("sys/inotify.h" HAVE_SYS_INOTIFY_H) check_symbol_exists(inotify_init "sys/inotify.h" HAVE_INOTIFY_INIT) check_symbol_exists(inotify_init1 "sys/inotify.h" HAVE_INOTIFY_INIT1) + if(HAVE_SYS_INOTIFY_H AND HAVE_INOTIFY_INIT) set(HAVE_INOTIFY 1) endif() @@ -1280,6 +1295,16 @@ elseif(UNIX AND NOT APPLE AND NOT ANDROID AND NOT RISCOS) set(SDL_USE_IME TRUE) add_definitions(-DSDL_USE_IME) # !!! FIXME: why isn't this a definition and not in SDL_config.h.cmake? endif() + + if(FREEBSD AND NOT HAVE_INOTIFY) + pkg_search_module(INOTIFY libinotify) + if(INOTIFY_FOUND) + set(HAVE_INOTIFY 1) + include_directories(${INOTIFY_INCLUDE_DIRS}) + list(APPEND EXTRA_LIBS ${INOTIFY_LIBRARIES}) + endif() + endif() + if(HAVE_LIBUNWIND_H) # We've already found the header, so REQUIRE the lib to be present pkg_search_module(UNWIND REQUIRED libunwind) @@ -1312,6 +1337,10 @@ elseif(UNIX AND NOT APPLE AND NOT ANDROID AND NOT RISCOS) set(SOURCE_FILES ${SOURCE_FILES} "${SDL2_SOURCE_DIR}/src/core/linux/SDL_evdev.c") set(SOURCE_FILES ${SOURCE_FILES} "${SDL2_SOURCE_DIR}/src/core/linux/SDL_evdev_kbd.c") endif() + + if(HAVE_INPUT_KBIO) + set(SOURCE_FILES ${SOURCE_FILES} "${SDL2_SOURCE_DIR}/src/core/freebsd/SDL_evdev_kbd_freebsd.c") + endif() # Always compiled for Linux, unconditionally: set(SOURCE_FILES ${SOURCE_FILES} "${SDL2_SOURCE_DIR}/src/core/linux/SDL_evdev_capabilities.c") diff --git a/externals/SDL/INSTALL.txt b/externals/SDL/INSTALL.txt index 0ba3388db..e5fa585a0 100755 --- a/externals/SDL/INSTALL.txt +++ b/externals/SDL/INSTALL.txt @@ -29,12 +29,13 @@ To compile and install SDL: 2. Look at the example programs in ./test, and check out the online documentation at https://wiki.libsdl.org/ - 3. Join the SDL developer mailing list by sending E-mail to - sdl-request@libsdl.org - and put "subscribe" in the subject of the message. + 3. Join the SDL developer discussions, sign up on + https://discourse.libsdl.org/ + and go to the development forum + https://discourse.libsdl.org/c/sdl-development/6 - Or alternatively you can use the web interface: - https://www.libsdl.org/mailing-list.php + 4. Sign up for the announcement list through the web interface: + https://www.libsdl.org/mailing-list.php That's it! Sam Lantinga diff --git a/externals/SDL/Makefile.os2 b/externals/SDL/Makefile.os2 index 60dd9f6e1..f6fc5c3db 100755 --- a/externals/SDL/Makefile.os2 +++ b/externals/SDL/Makefile.os2 @@ -62,6 +62,8 @@ SRCS+= SDL_sysloadso.c SRCS+= SDL_sysfilesystem.c SRCS+= SDL_os2joystick.c SDL_syshaptic.c SDL_sysjoystick.c SRCS+= SDL_virtualjoystick.c +SRCS+= SDL_hidapi.c +SRCS+= SDL_hidapijoystick.c SDL_hidapi_rumble.c SDL_hidapi_gamecube.c SDL_hidapi_ps4.c SDL_hidapi_ps5.c SDL_hidapi_stadia.c SDL_hidapi_switch.c SDL_hidapi_xbox360.c SDL_hidapi_xbox360w.c SDL_hidapi_xboxone.c SDL_hidapi_steam.c SRCS+= SDL_dummyaudio.c SDL_diskaudio.c SRCS+= SDL_nullvideo.c SDL_nullframebuffer.c SDL_nullevents.c SRCS+= SDL_dummysensor.c @@ -84,7 +86,7 @@ MOBJS= $(MSRCS:.c=.obj) .c: ./src;./src/dynapi;./src/audio;./src/cpuinfo;./src/events;./src/file;./src/haptic;./src/joystick;./src/power;./src/render;./src/render/software;./src/sensor;./src/stdlib;./src/thread;./src/timer;./src/video;./src/video/yuv2rgb;./src/atomic;./src/audio/disk; .c: ./src/haptic/dummy;./src/joystick/dummy;./src/joystick/virtual;./src/audio/dummy;./src/video/dummy;./src/sensor/dummy; .c: ./src/core/os2;./src/core/os2/geniconv;./src/audio/os2;./src/loadso/os2;./src/filesystem/os2;./src/joystick/os2;./src/thread/os2;./src/timer/os2;./src/video/os2; -.c: ./src/locale/;./src/locale/unix;./src/misc;./src/misc/dummy +.c: ./src/locale/;./src/locale/unix;./src/misc;./src/misc/dummy;./src/joystick/hidapi;./src/hidapi all: $(DLLFILE) $(LIBFILE) .symbolic @@ -123,6 +125,10 @@ SDL_blendpoint.obj: SDL_blendpoint.c SDL_RLEaccel.obj: SDL_RLEaccel.c wcc386 $(CFLAGS) -wcd=201 -fo=$^@ $< +# c99 mode needed because of structs with flexible array members in libusb.h +SDL_hidapi.obj: SDL_hidapi.c + wcc386 $(CFLAGS) -za99 -I"src/hidapi/hidapi" -fo=$^@ $< + .c: ./src/libm; $(LIBM): $(MOBJS) wlib -q -b -n -c -pa -s -t -zld -ii -io $@ $(MOBJS) diff --git a/externals/SDL/build-scripts/clang++-fat.sh b/externals/SDL/build-scripts/clang++-fat.sh new file mode 100755 index 000000000..d337109f9 --- /dev/null +++ b/externals/SDL/build-scripts/clang++-fat.sh @@ -0,0 +1,102 @@ +#!/bin/sh +# +# Build Universal binaries on Mac OS X, thanks Ryan! +# +# Usage: ./configure CXX="sh clang++-fat.sh" && make && rm -rf arm64 x64 + +DEVELOPER="`xcode-select -print-path`/Platforms/MacOSX.platform/Developer" + +# Intel 64-bit compiler flags (10.6 runtime compatibility) +CLANG_COMPILE_X64="clang++ -arch x86_64 -mmacosx-version-min=10.6 \ +-I/usr/local/include" + +CLANG_LINK_X64="-mmacosx-version-min=10.6" + +# ARM 64-bit compiler flags (11.0 runtime compatibility) +CLANG_COMPILE_ARM64="clang++ -arch arm64 -mmacosx-version-min=11.0 \ +-I/usr/local/include" + +CLANG_LINK_ARM64="-mmacosx-version-min=11.0" + + +# Output both Intel and ARM object files +args="$*" +compile=yes +link=yes +while test x$1 != x; do + case $1 in + --version) exec clang++ $1;; + -v) exec clang++ $1;; + -V) exec clang++ $1;; + -print-prog-name=*) exec clang++ $1;; + -print-search-dirs) exec clang++ $1;; + -E) CLANG_COMPILE_ARM64="$CLANG_COMPILE_ARM64 -E" + CLANG_COMPILE_X64="$CLANG_COMPILE_X64 -E" + compile=no; link=no;; + -c) link=no;; + -o) output=$2;; + *.c|*.cc|*.cpp|*.S|*.m|*.mm) source=$1;; + esac + shift +done +if test x$link = xyes; then + CLANG_COMPILE_ARM64="$CLANG_COMPILE_ARM64 $CLANG_LINK_ARM64" + CLANG_COMPILE_X64="$CLANG_COMPILE_X64 $CLANG_LINK_X64" +fi +if test x"$output" = x; then + if test x$link = xyes; then + output=a.out + elif test x$compile = xyes; then + output=`echo $source | sed -e 's|.*/||' -e 's|\(.*\)\.[^\.]*|\1|'`.o + fi +fi + +# Compile ARM 64-bit +if test x"$output" != x; then + dir=arm64/`dirname $output` + if test -d $dir; then + : + else + mkdir -p $dir + fi +fi +set -- $args +while test x$1 != x; do + if test -f "arm64/$1" && test "$1" != "$output"; then + arm64_args="$arm64_args arm64/$1" + else + arm64_args="$arm64_args $1" + fi + shift +done +$CLANG_COMPILE_ARM64 $arm64_args || exit $? +if test x"$output" != x; then + cp $output arm64/$output +fi + +# Compile Intel 64-bit +if test x"$output" != x; then + dir=x64/`dirname $output` + if test -d $dir; then + : + else + mkdir -p $dir + fi +fi +set -- $args +while test x$1 != x; do + if test -f "x64/$1" && test "$1" != "$output"; then + x64_args="$x64_args x64/$1" + else + x64_args="$x64_args $1" + fi + shift +done +$CLANG_COMPILE_X64 $x64_args || exit $? +if test x"$output" != x; then + cp $output x64/$output +fi + +if test x"$output" != x; then + lipo -create -o $output arm64/$output x64/$output +fi diff --git a/externals/SDL/build-scripts/clang-fat.sh b/externals/SDL/build-scripts/clang-fat.sh new file mode 100755 index 000000000..38c07275d --- /dev/null +++ b/externals/SDL/build-scripts/clang-fat.sh @@ -0,0 +1,105 @@ +#!/bin/sh +# +# Build Universal binaries on Mac OS X, thanks Ryan! +# +# Usage: ./configure CC="sh clang-fat.sh" && make && rm -rf arm64 x64 + +DEVELOPER="`xcode-select -print-path`/Platforms/MacOSX.platform/Developer" + +# Intel 64-bit compiler flags (10.6 runtime compatibility) +CLANG_COMPILE_X64="clang -arch x86_64 -mmacosx-version-min=10.6 \ +-DMAC_OS_X_VERSION_MIN_REQUIRED=1060 \ +-I/usr/local/include" + +CLANG_LINK_X64="-mmacosx-version-min=10.6" + +# ARM 64-bit compiler flags (11.0 runtime compatibility) +CLANG_COMPILE_ARM64="clang -arch arm64 -mmacosx-version-min=11.0 \ +-I/usr/local/include" + +CLANG_LINK_ARM64="-mmacosx-version-min=11.0" + + +# Output both Intel and ARM object files +args="$*" +compile=yes +link=yes +while test x$1 != x; do + case $1 in + --version) exec clang $1;; + -v) exec clang $1;; + -V) exec clang $1;; + -print-prog-name=*) exec clang $1;; + -print-search-dirs) exec clang $1;; + -E) CLANG_COMPILE_X64="$CLANG_COMPILE_X64 -E" + CLANG_COMPILE_ARM64="$CLANG_COMPILE_ARM64 -E" + compile=no; link=no;; + -c) link=no;; + -o) output=$2;; + *.c|*.cc|*.cpp|*.S|*.m|*.mm) source=$1;; + esac + shift +done +if test x$link = xyes; then + CLANG_COMPILE_X64="$CLANG_COMPILE_X64 $CLANG_LINK_X64" + CLANG_COMPILE_ARM64="$CLANG_COMPILE_ARM64 $CLANG_LINK_ARM64" +fi +if test x"$output" = x; then + if test x$link = xyes; then + output=a.out + elif test x$compile = xyes; then + output=`echo $source | sed -e 's|.*/||' -e 's|\(.*\)\.[^\.]*|\1|'`.o + fi +fi + +# Compile Intel 64-bit +if test x"$output" != x; then + dir=x64/`dirname $output` + if test -d $dir; then + : + else + mkdir -p $dir + fi +fi +set -- $args +while test x$1 != x; do + if test -f "x64/$1" && test "$1" != "$output"; then + x64_args="$x64_args x64/$1" + else + x64_args="$x64_args $1" + fi + shift +done +$CLANG_COMPILE_X64 $x64_args || exit $? +if test x"$output" != x; then + cp $output x64/$output +fi + +# Compile ARM 64-bit +if test x"$output" != x; then + dir=arm64/`dirname $output` + if test -d $dir; then + : + else + mkdir -p $dir + fi +fi +set -- $args +while test x$1 != x; do + if test -f "arm64/$1" && test "$1" != "$output"; then + arm64_args="$arm64_args arm64/$1" + else + arm64_args="$arm64_args $1" + fi + shift +done +$CLANG_COMPILE_ARM64 $arm64_args || exit $? +if test x"$output" != x; then + cp $output arm64/$output +fi + + +if test x"$output" != x; then + lipo -create -o $output arm64/$output x64/$output +fi + diff --git a/externals/SDL/build-scripts/config.guess b/externals/SDL/build-scripts/config.guess index 35741ebfc..c75dbb4b9 100755 --- a/externals/SDL/build-scripts/config.guess +++ b/externals/SDL/build-scripts/config.guess @@ -2,7 +2,7 @@ # Attempt to guess a canonical system name. # Copyright 1992-2021 Free Software Foundation, Inc. -timestamp='2021-01-25' +timestamp='2021-04-21' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -261,6 +261,10 @@ case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE" exit ;; + *:SecBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/SecBSD.//'` + echo "$UNAME_MACHINE_ARCH"-unknown-secbsd"$UNAME_RELEASE" + exit ;; *:LibertyBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'` echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE" @@ -949,7 +953,7 @@ EOF if test "$?" = 0 ; then LIBC=gnulibc1 ; fi echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; - arc:Linux:*:* | arceb:Linux:*:*) + arc:Linux:*:* | arceb:Linux:*:* | arc64:Linux:*:*) echo "$UNAME_MACHINE"-unknown-linux-"$LIBC" exit ;; arm*:Linux:*:*) diff --git a/externals/SDL/build-scripts/config.sub b/externals/SDL/build-scripts/config.sub index 1703a5f17..a525aab00 100755 --- a/externals/SDL/build-scripts/config.sub +++ b/externals/SDL/build-scripts/config.sub @@ -2,7 +2,7 @@ # Configuration validation subroutine script. # Copyright 1992-2021 Free Software Foundation, Inc. -timestamp='2021-01-08' +timestamp='2021-04-30' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -1165,7 +1165,7 @@ case $cpu-$vendor in | alphapca5[67] | alpha64pca5[67] \ | am33_2.0 \ | amdgcn \ - | arc | arceb \ + | arc | arceb | arc64 \ | arm | arm[lb]e | arme[lb] | armv* \ | avr | avr32 \ | asmjs \ @@ -1204,9 +1204,13 @@ case $cpu-$vendor in | mips64vr5900 | mips64vr5900el \ | mipsisa32 | mipsisa32el \ | mipsisa32r2 | mipsisa32r2el \ + | mipsisa32r3 | mipsisa32r3el \ + | mipsisa32r5 | mipsisa32r5el \ | mipsisa32r6 | mipsisa32r6el \ | mipsisa64 | mipsisa64el \ | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64r3 | mipsisa64r3el \ + | mipsisa64r5 | mipsisa64r5el \ | mipsisa64r6 | mipsisa64r6el \ | mipsisa64sb1 | mipsisa64sb1el \ | mipsisa64sr71k | mipsisa64sr71kel \ @@ -1707,12 +1711,12 @@ case $os in | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \ | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \ | mirbsd* | netbsd* | dicos* | openedition* | ose* \ - | bitrig* | openbsd* | solidbsd* | libertybsd* | os108* \ + | bitrig* | openbsd* | secbsd* | solidbsd* | libertybsd* | os108* \ | ekkobsd* | freebsd* | riscix* | lynxos* | os400* \ | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \ | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \ | udi* | lites* | ieee* | go32* | aux* | hcos* \ - | chorusrdb* | cegcc* | glidix* \ + | chorusrdb* | cegcc* | glidix* | serenity* \ | cygwin* | msys* | pe* | moss* | proelf* | rtems* \ | midipix* | mingw32* | mingw64* | mint* \ | uxpv* | beos* | mpeix* | udk* | moxiebox* \ diff --git a/externals/SDL/cmake/sdlchecks.cmake b/externals/SDL/cmake/sdlchecks.cmake index f21a9005d..d3f6cec1f 100755 --- a/externals/SDL/cmake/sdlchecks.cmake +++ b/externals/SDL/cmake/sdlchecks.cmake @@ -593,6 +593,10 @@ macro(CheckX11) set(CMAKE_REQUIRED_LIBRARIES) endif() endif() + if(NOT HAVE_VIDEO_X11) + # Prevent Mesa from including X11 headers + list(APPEND EXTRA_CFLAGS "-DMESA_EGL_NO_X11_HEADERS -DEGL_NO_X11") + endif() endmacro() macro(WaylandProtocolGen _SCANNER _CODE_MODE _XML _PROTL) @@ -627,7 +631,7 @@ macro(CheckWayland) pkg_check_modules(WAYLAND wayland-client wayland-scanner wayland-egl wayland-cursor egl xkbcommon) pkg_check_modules(WAYLAND_SCANNER_1_15 "wayland-scanner>=1.15") - if(WAYLAND_FOUND) + if(WAYLAND_FOUND AND HAVE_VIDEO_OPENGL_EGL) execute_process( COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=wayland_scanner wayland-scanner WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" @@ -778,15 +782,47 @@ macro(CheckVivante) endmacro(CheckVivante) # Requires: -# - libglvnd -macro(CheckOpenGLKMSDRM) - if(VIDEO_OPENGL AND HAVE_VIDEO_KMSDRM) +# - nada +macro(CheckGLX) + if(VIDEO_OPENGL) + check_c_source_compiles(" + #include + int main(int argc, char** argv) {}" HAVE_VIDEO_OPENGL_GLX) + if(HAVE_VIDEO_OPENGL_GLX) + set(SDL_VIDEO_OPENGL_GLX 1) + endif() + endif() +endmacro() + +# Requires: +# - PkgCheckModules +macro(CheckEGL) + if (VIDEO_OPENGL OR VIDEO_OPENGLES) + pkg_check_modules(EGL egl) + string(REPLACE "-D_THREAD_SAFE;" "-D_THREAD_SAFE=1;" EGL_CFLAGS "${EGL_CFLAGS}") + set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${EGL_CFLAGS}") + check_c_source_compiles(" + #define EGL_API_FB + #define MESA_EGL_NO_X11_HEADERS + #define EGL_NO_X11 + #include + #include + int main (int argc, char** argv) {}" HAVE_VIDEO_OPENGL_EGL) + if(HAVE_VIDEO_OPENGL_EGL) + set(SDL_VIDEO_OPENGL_EGL 1) + endif() + endif() +endmacro() + +# Requires: +# - nada +macro(CheckOpenGL) + if(VIDEO_OPENGL) check_c_source_compiles(" #include + #include int main(int argc, char** argv) {}" HAVE_VIDEO_OPENGL) - if(HAVE_VIDEO_OPENGL) - set(HAVE_VIDEO_OPENGL TRUE) set(SDL_VIDEO_OPENGL 1) set(SDL_VIDEO_RENDER_OGL 1) endif() @@ -795,80 +831,26 @@ endmacro() # Requires: # - nada -macro(CheckOpenGLX11) - if(VIDEO_OPENGL) - check_c_source_compiles(" - #include - #include - int main(int argc, char** argv) {}" HAVE_VIDEO_OPENGL) - - if(HAVE_VIDEO_OPENGL) - set(HAVE_VIDEO_OPENGL TRUE) - set(SDL_VIDEO_OPENGL 1) - set(SDL_VIDEO_OPENGL_GLX 1) - set(SDL_VIDEO_RENDER_OGL 1) - endif() - endif() -endmacro() - -# Requires: -# - PkgCheckModules -macro(CheckEGL) - pkg_check_modules(EGL egl) - string(REPLACE "-D_THREAD_SAFE;" "-D_THREAD_SAFE=1;" EGL_CFLAGS "${EGL_CFLAGS}") -endmacro() - -# Requires: -# - PkgCheckModules -macro(CheckEGLKMSDRM) - if (HAVE_VIDEO_OPENGLES OR HAVE_VIDEO_OPENGL) - CheckEGL() - set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${EGL_CFLAGS}") - check_c_source_compiles(" - #define EGL_API_FB - #define MESA_EGL_NO_X11_HEADERS - #define EGL_NO_X11 - #include - #include - int main (int argc, char** argv) {}" HAVE_VIDEO_OPENGL_EGL) - if(HAVE_VIDEO_OPENGL_EGL) - set(SDL_VIDEO_OPENGL_EGL 1) - endif() - endif() -endmacro() - -# Requires: -# - PkgCheckModules -macro(CheckOpenGLESX11) - CheckEGL() - set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} ${EGL_CFLAGS}") +macro(CheckOpenGLES) if(VIDEO_OPENGLES) check_c_source_compiles(" - #define EGL_API_FB - #include - int main (int argc, char** argv) {}" HAVE_VIDEO_OPENGL_EGL) - if(HAVE_VIDEO_OPENGL_EGL) - set(SDL_VIDEO_OPENGL_EGL 1) - endif() - check_c_source_compiles(" - #include - #include - int main (int argc, char** argv) {}" HAVE_VIDEO_OPENGLES_V1) + #include + #include + int main (int argc, char** argv) {}" HAVE_VIDEO_OPENGLES_V1) if(HAVE_VIDEO_OPENGLES_V1) set(HAVE_VIDEO_OPENGLES TRUE) set(SDL_VIDEO_OPENGL_ES 1) set(SDL_VIDEO_RENDER_OGL_ES 1) endif() check_c_source_compiles(" - #include - #include - int main (int argc, char** argv) {}" HAVE_VIDEO_OPENGLES_V2) + #include + #include + int main (int argc, char** argv) {}" HAVE_VIDEO_OPENGLES_V2) if(HAVE_VIDEO_OPENGLES_V2) set(HAVE_VIDEO_OPENGLES TRUE) set(SDL_VIDEO_OPENGL_ES2 1) set(SDL_VIDEO_RENDER_OGL_ES2 1) endif() - endif() endmacro() diff --git a/externals/SDL/configure b/externals/SDL/configure index 80a528f94..dea2e5351 100755 --- a/externals/SDL/configure +++ b/externals/SDL/configure @@ -1666,7 +1666,7 @@ Optional Features: --enable-video-directfb use DirectFB video driver [default=no] --enable-directfb-shared dynamically load directfb support [default=yes] - --enable-video-kmsdrm use KMSDRM video driver [default=no] + --enable-video-kmsdrm use KMSDRM video driver [default=yes] --enable-kmsdrm-shared dynamically load kmsdrm support [default=yes] --enable-video-dummy use dummy video driver [default=yes] --enable-video-opengl include OpenGL support [default=yes] @@ -22052,7 +22052,7 @@ CheckKMSDRM() if test "${enable_video_kmsdrm+set}" = set; then : enableval=$enable_video_kmsdrm; else - enable_video_kmsdrm=no + enable_video_kmsdrm=yes fi diff --git a/externals/SDL/configure.ac b/externals/SDL/configure.ac index 6ec90c4a8..15e5f2f09 100755 --- a/externals/SDL/configure.ac +++ b/externals/SDL/configure.ac @@ -2194,8 +2194,8 @@ dnl Find KMSDRM CheckKMSDRM() { AC_ARG_ENABLE(video-kmsdrm, -[AS_HELP_STRING([--enable-video-kmsdrm], [use KMSDRM video driver [default=no]])], - , enable_video_kmsdrm=no) +[AS_HELP_STRING([--enable-video-kmsdrm], [use KMSDRM video driver [default=yes]])], + , enable_video_kmsdrm=yes) if test x$enable_video = xyes && \ test x$enable_video_kmsdrm = xyes && \ diff --git a/externals/SDL/docs/README-android.md b/externals/SDL/docs/README-android.md index 1c03a7d08..fb835a5aa 100755 --- a/externals/SDL/docs/README-android.md +++ b/externals/SDL/docs/README-android.md @@ -243,6 +243,16 @@ your thread automatically anyway (when you make an SDL call), but it'll never detach it. +If you ever want to use JNI in a native thread (created by "SDL_CreateThread()"), +it won't be able to find your java class and method because of the java class loader +which is different for native threads, than for java threads (eg your "main()"). + +the work-around is to find class/method, in you "main()" thread, and to use them +in your native thread. + +see: +https://developer.android.com/training/articles/perf-jni#faq:-why-didnt-findclass-find-my-class + Using STL ================================================================================ diff --git a/externals/SDL/docs/README-ios.md b/externals/SDL/docs/README-ios.md index f6f570d44..cab3af419 100755 --- a/externals/SDL/docs/README-ios.md +++ b/externals/SDL/docs/README-ios.md @@ -1,7 +1,6 @@ iOS ====== -============================================================================== Building the Simple DirectMedia Layer for iOS 5.1+ ============================================================================== @@ -9,7 +8,7 @@ Requirements: Mac OS X 10.8 or later and the iOS 7+ SDK. Instructions: -1. Open SDL.xcodeproj (located in Xcode-iOS/SDL) in Xcode. +1. Open SDL.xcodeproj (located in Xcode/SDL) in Xcode. 2. Select your desired target, and hit build. There are three build targets: @@ -21,7 +20,6 @@ There are three build targets: Package a project template together with the SDL for iPhone static libraries and copies of the SDL headers. The template includes proper references to the SDL library and headers, skeleton code for a basic SDL program, and placeholder graphics for the application icon and startup screen. -============================================================================== Build SDL for iOS from the command line ============================================================================== @@ -41,7 +39,6 @@ by setting the MIN_OS_VERSION variable, ie: MIN_OS_VERSION=4.2 ./iosbuild.sh -============================================================================== Using the Simple DirectMedia Layer for iOS ============================================================================== @@ -59,7 +56,7 @@ Here is a more manual method: 4. Remove the ApplicationDelegate.h and ApplicationDelegate.m files -- SDL for iOS provides its own UIApplicationDelegate. Remove MainWindow.xib -- SDL for iOS produces its user interface programmatically. 5. Delete the contents of main.m and program your app as a regular SDL program instead. You may replace main.m with your own main.c, but you must tell Xcode not to use the project prefix file, as it includes Objective-C code. -============================================================================== + Notes -- Retina / High-DPI and window sizes ============================================================================== @@ -88,7 +85,7 @@ orthographic projection matrix using the size in screen coordinates (SDL_GetWindowSize()) can be used in order to display content at the same scale no matter whether a Retina device is used or not. -============================================================================== + Notes -- Application events ============================================================================== @@ -151,7 +148,6 @@ e.g. } -============================================================================== Notes -- Accelerometer as Joystick ============================================================================== @@ -159,7 +155,7 @@ SDL for iPhone supports polling the built in accelerometer as a joystick device. The main thing to note when using the accelerometer with SDL is that while the iPhone natively reports accelerometer as floating point values in units of g-force, SDL_JoystickGetAxis() reports joystick values as signed integers. Hence, in order to convert between the two, some clamping and scaling is necessary on the part of the iPhone SDL joystick driver. To convert SDL_JoystickGetAxis() reported values BACK to units of g-force, simply multiply the values by SDL_IPHONE_MAX_GFORCE / 0x7FFF. -============================================================================== + Notes -- OpenGL ES ============================================================================== @@ -179,7 +175,7 @@ OpenGL ES on iOS doesn't use the traditional system-framebuffer setup provided i The above objects can be obtained via SDL_GetWindowWMInfo() (in SDL_syswm.h). -============================================================================== + Notes -- Keyboard ============================================================================== @@ -195,7 +191,6 @@ SDL_bool SDL_IsTextInputActive() -- returns whether or not text events are enabled (and the onscreen keyboard is visible) -============================================================================== Notes -- Reading and Writing files ============================================================================== @@ -215,7 +210,7 @@ When your SDL based iPhone application starts up, it sets the working directory More information on this subject is available here: http://developer.apple.com/library/ios/#documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/Introduction/Introduction.html -============================================================================== + Notes -- iPhone SDL limitations ============================================================================== @@ -228,7 +223,7 @@ Textures: Loading Shared Objects: This is disabled by default since it seems to break the terms of the iOS SDK agreement for iOS versions prior to iOS 8. It can be re-enabled in SDL_config_iphoneos.h. -============================================================================== + Notes -- CoreBluetooth.framework ============================================================================== @@ -244,7 +239,7 @@ to your Info.plist: NSBluetoothPeripheralUsageDescription MyApp would like to remain connected to nearby bluetooth Game Controllers and Game Pads even when you're not using the app. -============================================================================== + Game Center ============================================================================== @@ -282,7 +277,7 @@ e.g. return 0; } -============================================================================== + Deploying to older versions of iOS ============================================================================== diff --git a/externals/SDL/docs/README-kmsbsd.md b/externals/SDL/docs/README-kmsbsd.md index e731c7c09..01db5e8aa 100755 --- a/externals/SDL/docs/README-kmsbsd.md +++ b/externals/SDL/docs/README-kmsbsd.md @@ -1,7 +1,7 @@ KMSDRM on *BSD ================================================== -KMSDRM is supported on FreeBSD and OpenBSD. DragonFlyBSD is not tested yet, but should work. NetBSD isn't supported yet because the application will crash when creating the KMSDRM screen. +KMSDRM is supported on FreeBSD and OpenBSD. DragonFlyBSD works but requires being a root user. NetBSD isn't supported yet because the application will crash when creating the KMSDRM screen. WSCONS support has been brought back, but only as an input backend. It will not be brought back as a video backend to ease maintenance. diff --git a/externals/SDL/include/SDL_config.h.cmake b/externals/SDL/include/SDL_config.h.cmake index 0446547e0..8463f47b1 100755 --- a/externals/SDL/include/SDL_config.h.cmake +++ b/externals/SDL/include/SDL_config.h.cmake @@ -302,6 +302,7 @@ /* Enable various input drivers */ #cmakedefine SDL_INPUT_LINUXEV @SDL_INPUT_LINUXEV@ #cmakedefine SDL_INPUT_LINUXKD @SDL_INPUT_LINUXKD@ +#cmakedefine SDL_INPUT_FBSDKBIO @SDL_INPUT_FBSDKBIO@ #cmakedefine SDL_JOYSTICK_ANDROID @SDL_JOYSTICK_ANDROID@ #cmakedefine SDL_JOYSTICK_HAIKU @SDL_JOYSTICK_HAIKU@ #cmakedefine SDL_JOYSTICK_DINPUT @SDL_JOYSTICK_DINPUT@ diff --git a/externals/SDL/include/SDL_hints.h b/externals/SDL/include/SDL_hints.h index fdaf89610..ad66ddd1a 100755 --- a/externals/SDL/include/SDL_hints.h +++ b/externals/SDL/include/SDL_hints.h @@ -1659,6 +1659,17 @@ extern "C" { */ #define SDL_HINT_PREFERRED_LOCALES "SDL_PREFERRED_LOCALES" +/** + * \brief Mark X11 windows as override-redirect. + * + * If set, this _might_ increase framerate at the expense of the desktop + * not working as expected. Override-redirect windows aren't noticed by the + * window manager at all. + * + * You should probably only use this for fullscreen windows, and you probably + * shouldn't even use it for that. But it's here if you want to try! + */ +#define SDL_HINT_X11_FORCE_OVERRIDE_REDIRECT "SDL_X11_FORCE_OVERRIDE_REDIRECT" /** * \brief An enumeration of hint priorities diff --git a/externals/SDL/include/SDL_stdinc.h b/externals/SDL/include/SDL_stdinc.h index d286e68a9..0cbbb436b 100755 --- a/externals/SDL/include/SDL_stdinc.h +++ b/externals/SDL/include/SDL_stdinc.h @@ -481,16 +481,28 @@ SDL_FORCE_INLINE void SDL_memset4(void *dst, Uint32 val, size_t dwords) size_t _n = (dwords + 3) / 4; Uint32 *_p = SDL_static_cast(Uint32 *, dst); Uint32 _val = (val); - if (dwords == 0) + if (dwords == 0) { return; - switch (dwords % 4) - { + } + + /* !!! FIXME: there are better ways to do this, but this is just to clean this up for now. */ + #ifdef __clang__ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wimplicit-fallthrough" + #endif + + switch (dwords % 4) { case 0: do { *_p++ = _val; /* fallthrough */ case 3: *_p++ = _val; /* fallthrough */ case 2: *_p++ = _val; /* fallthrough */ case 1: *_p++ = _val; /* fallthrough */ } while ( --_n ); } + + #ifdef __clang__ + #pragma clang diagnostic pop + #endif + #endif } diff --git a/externals/SDL/include/SDL_test_common.h b/externals/SDL/include/SDL_test_common.h index 6e4344fdf..8a92c05cb 100755 --- a/externals/SDL/include/SDL_test_common.h +++ b/externals/SDL/include/SDL_test_common.h @@ -206,6 +206,14 @@ void SDLTest_CommonEvent(SDLTest_CommonState * state, SDL_Event * event, int *do */ void SDLTest_CommonQuit(SDLTest_CommonState * state); +/** + * \brief Draws various window information (position, size, etc.) to the renderer. + * + * \param renderer The renderer to draw to. + * \param window The window whose information should be displayed. + * + */ +void SDLTest_CommonDrawWindowInfo(SDL_Renderer * renderer, SDL_Window * window); /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/externals/SDL/include/SDL_thread.h b/externals/SDL/include/SDL_thread.h index be0601cc9..513d5dfcb 100755 --- a/externals/SDL/include/SDL_thread.h +++ b/externals/SDL/include/SDL_thread.h @@ -35,6 +35,17 @@ #include "SDL_atomic.h" #include "SDL_mutex.h" +#if defined(__WIN32__) +#include /* _beginthreadex() and _endthreadex() */ +#endif +#if defined(__OS2__) /* for _beginthread() and _endthread() */ +#ifndef __EMX__ +#include +#else +#include +#endif +#endif + #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ #ifdef __cplusplus @@ -99,7 +110,6 @@ typedef int (SDLCALL * SDL_ThreadFunction) (void *data); * library! */ #define SDL_PASSED_BEGINTHREAD_ENDTHREAD -#include /* _beginthreadex() and _endthreadex() */ typedef uintptr_t (__cdecl * pfnSDL_CurrentBeginThread) (void *, unsigned, unsigned (__stdcall *func)(void *), @@ -148,12 +158,6 @@ SDL_CreateThreadWithStackSize(int (SDLCALL * fn) (void *), */ #define SDL_PASSED_BEGINTHREAD_ENDTHREAD -#ifndef __EMX__ -#include -#else -#include -#endif - typedef int (*pfnSDL_CurrentBeginThread)(void (*func)(void *), void *, unsigned, void * /*arg*/); typedef void (*pfnSDL_CurrentEndThread)(void); diff --git a/externals/SDL/include/SDL_video.h b/externals/SDL/include/SDL_video.h index 0c05a0937..896f30321 100755 --- a/externals/SDL/include/SDL_video.h +++ b/externals/SDL/include/SDL_video.h @@ -65,6 +65,7 @@ typedef struct * \sa SDL_CreateWindow() * \sa SDL_CreateWindowFrom() * \sa SDL_DestroyWindow() + * \sa SDL_FlashWindow() * \sa SDL_GetWindowData() * \sa SDL_GetWindowFlags() * \sa SDL_GetWindowGrab() @@ -1509,6 +1510,18 @@ extern DECLSPEC int SDLCALL SDL_SetWindowHitTest(SDL_Window * window, SDL_HitTest callback, void *callback_data); +/** + * Request a window to give a signal, e.g. a visual signal, to demand attention from the user. + * + * \returns 0 on success or a negative error code on failure; call + * SDL_GetError() for more information. + * + * \param window the window to request the flashing for + * \param flash_count number of times the window gets flashed on systems that support flashing the + * window multiple times, like Windows, else it is ignored + */ +extern DECLSPEC int SDLCALL SDL_FlashWindow(SDL_Window * window, Uint32 flash_count); + /** * Destroy a window. * diff --git a/externals/SDL/src/audio/coreaudio/SDL_coreaudio.m b/externals/SDL/src/audio/coreaudio/SDL_coreaudio.m index f84a1c558..8dbd1dd3d 100755 --- a/externals/SDL/src/audio/coreaudio/SDL_coreaudio.m +++ b/externals/SDL/src/audio/coreaudio/SDL_coreaudio.m @@ -601,7 +601,7 @@ inputCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer } /* ignore unless we're active. */ - if (!SDL_AtomicGet(&this->paused) && SDL_AtomicGet(&this->enabled) && !SDL_AtomicGet(&this->paused)) { + if (!SDL_AtomicGet(&this->paused) && SDL_AtomicGet(&this->enabled)) { const Uint8 *ptr = (const Uint8 *) inBuffer->mAudioData; UInt32 remaining = inBuffer->mAudioDataByteSize; while (remaining > 0) { diff --git a/externals/SDL/src/audio/wasapi/SDL_wasapi.c b/externals/SDL/src/audio/wasapi/SDL_wasapi.c index ec0347b82..72b2ca911 100755 --- a/externals/SDL/src/audio/wasapi/SDL_wasapi.c +++ b/externals/SDL/src/audio/wasapi/SDL_wasapi.c @@ -137,7 +137,7 @@ WASAPI_AddDevice(const SDL_bool iscapture, const char *devname, WAVEFORMATEXTENS deviceid_list = devidlist; SDL_zero(spec); - spec.channels = fmt->Format.nChannels; + spec.channels = (Uint8)fmt->Format.nChannels; spec.freq = fmt->Format.nSamplesPerSec; spec.format = WaveFormatToSDLFormat((WAVEFORMATEX *) fmt); SDL_AddAudioDevice(iscapture, devname, &spec, (void *) devid); diff --git a/externals/SDL/src/audio/winmm/SDL_winmm.c b/externals/SDL/src/audio/winmm/SDL_winmm.c index 5d221f665..8e0685d04 100755 --- a/externals/SDL/src/audio/winmm/SDL_winmm.c +++ b/externals/SDL/src/audio/winmm/SDL_winmm.c @@ -86,7 +86,7 @@ static void DetectWave##typ##Devs(void) { \ * is not provided by the caps struct! At best, we get possible \ * sample formats, but not an _active_ format. \ */ \ - spec.channels = caps.wChannels; \ + spec.channels = (Uint8)caps.wChannels; \ SDL_AddAudioDevice((int) iscapture, name, &spec, (void *) ((size_t) i+1)); \ SDL_free(name); \ } \ diff --git a/externals/SDL/src/core/linux/SDL_udev.c b/externals/SDL/src/core/linux/SDL_udev.c index 8eaf2f204..e5a663064 100755 --- a/externals/SDL/src/core/linux/SDL_udev.c +++ b/externals/SDL/src/core/linux/SDL_udev.c @@ -451,9 +451,6 @@ SDL_UDEV_Poll(void) if (action) { if (SDL_strcmp(action, "add") == 0) { - /* Wait for the device to finish initialization */ - SDL_Delay(100); - device_event(SDL_UDEV_DEVICEADDED, dev); } else if (SDL_strcmp(action, "remove") == 0) { device_event(SDL_UDEV_DEVICEREMOVED, dev); diff --git a/externals/SDL/src/core/openbsd/SDL_wscons_kbd.c b/externals/SDL/src/core/openbsd/SDL_wscons_kbd.c index 23c8bd0dc..8d62a6cc8 100755 --- a/externals/SDL/src/core/openbsd/SDL_wscons_kbd.c +++ b/externals/SDL/src/core/openbsd/SDL_wscons_kbd.c @@ -255,6 +255,7 @@ static struct wscons_keycode_to_SDL { {KS_Num_Lock, SDL_SCANCODE_NUMLOCKCLEAR}, {KS_Caps_Lock, SDL_SCANCODE_CAPSLOCK}, {KS_BackSpace, SDL_SCANCODE_BACKSPACE}, + {KS_space, SDL_SCANCODE_SPACE}, {KS_Delete, SDL_SCANCODE_BACKSPACE}, {KS_Home, SDL_SCANCODE_HOME}, {KS_End, SDL_SCANCODE_END}, diff --git a/externals/SDL/src/core/openbsd/SDL_wscons_mouse.c b/externals/SDL/src/core/openbsd/SDL_wscons_mouse.c index 4df927be2..da8e9e285 100755 --- a/externals/SDL/src/core/openbsd/SDL_wscons_mouse.c +++ b/externals/SDL/src/core/openbsd/SDL_wscons_mouse.c @@ -103,12 +103,12 @@ void updateMouse(SDL_WSCONS_mouse_input_data* inputData) break; case WSCONS_EVENT_MOUSE_DELTA_X: { - SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 1, events[i].value * 2, 0); + SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 1, events[i].value, 0); break; } case WSCONS_EVENT_MOUSE_DELTA_Y: { - SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 1, 0, -events[i].value * 2); + SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 1, 0, -events[i].value); break; } case WSCONS_EVENT_MOUSE_DELTA_W: diff --git a/externals/SDL/src/core/winrt/SDL_winrtapp_direct3d.cpp b/externals/SDL/src/core/winrt/SDL_winrtapp_direct3d.cpp index 0018604d1..9c115c6d6 100755 --- a/externals/SDL/src/core/winrt/SDL_winrtapp_direct3d.cpp +++ b/externals/SDL/src/core/winrt/SDL_winrtapp_direct3d.cpp @@ -729,15 +729,18 @@ void SDL_WinRTApp::OnExiting(Platform::Object^ sender, Platform::Object^ args) static void WINRT_LogPointerEvent(const char * header, Windows::UI::Core::PointerEventArgs ^ args, Windows::Foundation::Point transformedPoint) { + Uint8 button, pressed; Windows::UI::Input::PointerPoint ^ pt = args->CurrentPoint; - SDL_Log("%s: Position={%f,%f}, Transformed Pos={%f, %f}, MouseWheelDelta=%d, FrameId=%d, PointerId=%d, SDL button=%d\n", + WINRT_GetSDLButtonForPointerPoint(pt, &button, &pressed); + SDL_Log("%s: Position={%f,%f}, Transformed Pos={%f, %f}, MouseWheelDelta=%d, FrameId=%d, PointerId=%d, SDL button=%d pressed=%d\n", header, pt->Position.X, pt->Position.Y, transformedPoint.X, transformedPoint.Y, pt->Properties->MouseWheelDelta, pt->FrameId, pt->PointerId, - WINRT_GetSDLButtonForPointerPoint(pt)); + button, + pressed); } void SDL_WinRTApp::OnPointerPressed(CoreWindow^ sender, PointerEventArgs^ args) diff --git a/externals/SDL/src/dynapi/SDL_dynapi_overrides.h b/externals/SDL/src/dynapi/SDL_dynapi_overrides.h index 157730806..99662c036 100755 --- a/externals/SDL/src/dynapi/SDL_dynapi_overrides.h +++ b/externals/SDL/src/dynapi/SDL_dynapi_overrides.h @@ -811,3 +811,4 @@ #define SDL_GetAudioDeviceSpec SDL_GetAudioDeviceSpec_REAL #define SDL_TLSCleanup SDL_TLSCleanup_REAL #define SDL_SetWindowAlwaysOnTop SDL_SetWindowAlwaysOnTop_REAL +#define SDL_FlashWindow SDL_FlashWindow_REAL diff --git a/externals/SDL/src/dynapi/SDL_dynapi_procs.h b/externals/SDL/src/dynapi/SDL_dynapi_procs.h index a3113d1da..17e7eb317 100755 --- a/externals/SDL/src/dynapi/SDL_dynapi_procs.h +++ b/externals/SDL/src/dynapi/SDL_dynapi_procs.h @@ -876,3 +876,4 @@ SDL_DYNAPI_PROC(int,SDL_AndroidShowToast,(const char *a, int b, int c, int d, in SDL_DYNAPI_PROC(int,SDL_GetAudioDeviceSpec,(int a, int b, SDL_AudioSpec *c),(a,b,c),return) SDL_DYNAPI_PROC(void,SDL_TLSCleanup,(void),(),) SDL_DYNAPI_PROC(void,SDL_SetWindowAlwaysOnTop,(SDL_Window *a, SDL_bool b),(a,b),) +SDL_DYNAPI_PROC(int,SDL_FlashWindow,(SDL_Window *a, Uint32 b),(a, b),return) diff --git a/externals/SDL/src/events/SDL_events.c b/externals/SDL/src/events/SDL_events.c index ec8c0b185..458d8a8c1 100755 --- a/externals/SDL/src/events/SDL_events.c +++ b/externals/SDL/src/events/SDL_events.c @@ -586,6 +586,24 @@ SDL_CutEvent(SDL_EventEntry *entry) SDL_AtomicAdd(&SDL_EventQ.count, -1); } +static int +SDL_SendWakeupEvent() +{ + SDL_VideoDevice *_this = SDL_GetVideoDevice(); + if (!_this || !_this->SendWakeupEvent) { + return 0; + } + if (!_this->wakeup_lock || SDL_LockMutex(_this->wakeup_lock) == 0) { + if (_this->wakeup_window) { + _this->SendWakeupEvent(_this, _this->wakeup_window); + } + if (_this->wakeup_lock) { + SDL_UnlockMutex(_this->wakeup_lock); + } + } + return 0; +} + /* Lock the event queue, take a peep at it, and unlock it */ int SDL_PeepEvents(SDL_Event * events, int numevents, SDL_eventaction action, @@ -662,6 +680,11 @@ SDL_PeepEvents(SDL_Event * events, int numevents, SDL_eventaction action, } else { return SDL_SetError("Couldn't lock event queue"); } + + if (used > 0 && action == SDL_ADDEVENT) { + SDL_SendWakeupEvent(); + } + return (used); } @@ -759,6 +782,78 @@ SDL_PollEvent(SDL_Event * event) return SDL_WaitEventTimeout(event, 0); } +static int +SDL_WaitEventTimeout_Device(_THIS, SDL_Window *wakeup_window, SDL_Event * event, int timeout) +{ + /* Release any keys held down from last frame */ + SDL_ReleaseAutoReleaseKeys(); + + for (;;) { + if (!_this->wakeup_lock || SDL_LockMutex(_this->wakeup_lock) == 0) { + int status = SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT); + /* If status == 0 we are going to block so wakeup will be needed. */ + if (status == 0) { + _this->wakeup_window = wakeup_window; + } else { + _this->wakeup_window = NULL; + } + if (_this->wakeup_lock) { + SDL_UnlockMutex(_this->wakeup_lock); + } + if (status < 0) { + /* Got an error: return */ + break; + } + if (status > 0) { + /* There is an event, we can return. */ + SDL_SendPendingSignalEvents(); /* in case we had a signal handler fire, etc. */ + return 1; + } + /* No events found in the queue, call WaitEventTimeout to wait for an event. */ + status = _this->WaitEventTimeout(_this, timeout); + /* Set wakeup_window to NULL without holding the lock. */ + _this->wakeup_window = NULL; + if (status <= 0) { + /* There is either an error or the timeout is elapsed: return */ + return status; + } + /* An event was found and pumped into the SDL events queue. Continue the loop + to let SDL_PeepEvents pick it up .*/ + } + } + return 0; +} + +static int +SDL_events_need_polling() { + SDL_bool need_polling = SDL_FALSE; + +#if !SDL_JOYSTICK_DISABLED + need_polling = \ + (!SDL_disabled_events[SDL_JOYAXISMOTION >> 8] || SDL_JoystickEventState(SDL_QUERY)) \ + && (SDL_NumJoysticks() > 0); +#endif + +#if !SDL_SENSOR_DISABLED + need_polling = need_polling || (!SDL_disabled_events[SDL_SENSORUPDATE >> 8] && \ + (SDL_NumSensors() > 0)); +#endif + + return need_polling; +} + +static SDL_Window * +SDL_find_active_window(SDL_VideoDevice * _this) +{ + SDL_Window *window; + for (window = _this->windows; window; window = window->next) { + if (!window->is_destroying) { + return window; + } + } + return NULL; +} + int SDL_WaitEvent(SDL_Event * event) { @@ -768,11 +863,27 @@ SDL_WaitEvent(SDL_Event * event) int SDL_WaitEventTimeout(SDL_Event * event, int timeout) { + SDL_VideoDevice *_this = SDL_GetVideoDevice(); + SDL_Window *wakeup_window; Uint32 expiration = 0; if (timeout > 0) expiration = SDL_GetTicks() + timeout; + if (timeout != 0 && _this && _this->WaitEventTimeout && _this->SendWakeupEvent && !SDL_events_need_polling()) { + /* Look if a shown window is available to send the wakeup event. */ + wakeup_window = SDL_find_active_window(_this); + if (wakeup_window) { + int status = SDL_WaitEventTimeout_Device(_this, wakeup_window, event, timeout); + + /* There may be implementation-defined conditions where the backend cannot + reliably wait for the next event. If that happens, fall back to polling. */ + if (status >= 0) { + return status; + } + } + } + for (;;) { SDL_PumpEvents(); switch (SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT)) { diff --git a/externals/SDL/src/haptic/windows/SDL_dinputhaptic.c b/externals/SDL/src/haptic/windows/SDL_dinputhaptic.c index 9da6f7b27..523793ebe 100755 --- a/externals/SDL/src/haptic/windows/SDL_dinputhaptic.c +++ b/externals/SDL/src/haptic/windows/SDL_dinputhaptic.c @@ -61,7 +61,7 @@ static BOOL CALLBACK EnumHapticsCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext) { (void) pContext; - SDL_DINPUT_MaybeAddDevice(pdidInstance); + SDL_DINPUT_HapticMaybeAddDevice(pdidInstance); return DIENUM_CONTINUE; /* continue enumerating */ } @@ -117,7 +117,7 @@ SDL_DINPUT_HapticInit(void) } int -SDL_DINPUT_MaybeAddDevice(const DIDEVICEINSTANCE * pdidInstance) +SDL_DINPUT_HapticMaybeAddDevice(const DIDEVICEINSTANCE * pdidInstance) { HRESULT ret; LPDIRECTINPUTDEVICE8 device; @@ -176,7 +176,7 @@ SDL_DINPUT_MaybeAddDevice(const DIDEVICEINSTANCE * pdidInstance) } int -SDL_DINPUT_MaybeRemoveDevice(const DIDEVICEINSTANCE * pdidInstance) +SDL_DINPUT_HapticMaybeRemoveDevice(const DIDEVICEINSTANCE * pdidInstance) { SDL_hapticlist_item *item; SDL_hapticlist_item *prev = NULL; @@ -419,7 +419,6 @@ SDL_DINPUT_HapticOpen(SDL_Haptic * haptic, SDL_hapticlist_item *item) { HRESULT ret; LPDIRECTINPUTDEVICE8 device; - LPDIRECTINPUTDEVICE8 device8; /* Open the device */ ret = IDirectInput8_CreateDevice(dinput, &item->instance.guidInstance, @@ -429,19 +428,8 @@ SDL_DINPUT_HapticOpen(SDL_Haptic * haptic, SDL_hapticlist_item *item) return -1; } - /* Now get the IDirectInputDevice8 interface, instead. */ - ret = IDirectInputDevice8_QueryInterface(device, - &IID_IDirectInputDevice8, - (LPVOID *)&device8); - /* Done with the temporary one now. */ - IDirectInputDevice8_Release(device); - if (FAILED(ret)) { - DI_SetError("Querying DirectInput interface", ret); - return -1; - } - - if (SDL_DINPUT_HapticOpenFromDevice(haptic, device8, SDL_FALSE) < 0) { - IDirectInputDevice8_Release(device8); + if (SDL_DINPUT_HapticOpenFromDevice(haptic, device, SDL_FALSE) < 0) { + IDirectInputDevice8_Release(device); return -1; } return 0; @@ -713,7 +701,7 @@ SDL_SYS_ToDIEFFECT(SDL_Haptic * haptic, DIEFFECT * dest, /* Specifics */ periodic->dwMagnitude = CONVERT(SDL_abs(hap_periodic->magnitude)); periodic->lOffset = CONVERT(hap_periodic->offset); - periodic->dwPhase = + periodic->dwPhase = (hap_periodic->phase + (hap_periodic->magnitude < 0 ? 18000 : 0)) % 36000; periodic->dwPeriod = hap_periodic->period * 1000; dest->cbTypeSpecificParams = sizeof(DIPERIODIC); @@ -1200,13 +1188,13 @@ SDL_DINPUT_HapticInit(void) } int -SDL_DINPUT_MaybeAddDevice(const DIDEVICEINSTANCE * pdidInstance) +SDL_DINPUT_HapticMaybeAddDevice(const DIDEVICEINSTANCE * pdidInstance) { return SDL_Unsupported(); } int -SDL_DINPUT_MaybeRemoveDevice(const DIDEVICEINSTANCE * pdidInstance) +SDL_DINPUT_HapticMaybeRemoveDevice(const DIDEVICEINSTANCE * pdidInstance) { return SDL_Unsupported(); } diff --git a/externals/SDL/src/haptic/windows/SDL_dinputhaptic_c.h b/externals/SDL/src/haptic/windows/SDL_dinputhaptic_c.h index 3766ff7f3..2056ad85d 100755 --- a/externals/SDL/src/haptic/windows/SDL_dinputhaptic_c.h +++ b/externals/SDL/src/haptic/windows/SDL_dinputhaptic_c.h @@ -25,8 +25,8 @@ extern int SDL_DINPUT_HapticInit(void); -extern int SDL_DINPUT_MaybeAddDevice(const DIDEVICEINSTANCE *pdidInstance); -extern int SDL_DINPUT_MaybeRemoveDevice(const DIDEVICEINSTANCE *pdidInstance); +extern int SDL_DINPUT_HapticMaybeAddDevice(const DIDEVICEINSTANCE *pdidInstance); +extern int SDL_DINPUT_HapticMaybeRemoveDevice(const DIDEVICEINSTANCE *pdidInstance); extern int SDL_DINPUT_HapticOpen(SDL_Haptic * haptic, SDL_hapticlist_item *item); extern int SDL_DINPUT_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick); extern int SDL_DINPUT_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick); diff --git a/externals/SDL/src/haptic/windows/SDL_xinputhaptic.c b/externals/SDL/src/haptic/windows/SDL_xinputhaptic.c index 79b4b4cf7..9ee2d82d6 100755 --- a/externals/SDL/src/haptic/windows/SDL_xinputhaptic.c +++ b/externals/SDL/src/haptic/windows/SDL_xinputhaptic.c @@ -50,14 +50,14 @@ SDL_XINPUT_HapticInit(void) if (loaded_xinput) { DWORD i; for (i = 0; i < XUSER_MAX_COUNT; i++) { - SDL_XINPUT_MaybeAddDevice(i); + SDL_XINPUT_HapticMaybeAddDevice(i); } } return 0; } int -SDL_XINPUT_MaybeAddDevice(const DWORD dwUserid) +SDL_XINPUT_HapticMaybeAddDevice(const DWORD dwUserid) { const Uint8 userid = (Uint8)dwUserid; SDL_hapticlist_item *item; @@ -106,7 +106,7 @@ SDL_XINPUT_MaybeAddDevice(const DWORD dwUserid) } int -SDL_XINPUT_MaybeRemoveDevice(const DWORD dwUserid) +SDL_XINPUT_HapticMaybeRemoveDevice(const DWORD dwUserid) { const Uint8 userid = (Uint8)dwUserid; SDL_hapticlist_item *item; @@ -377,13 +377,13 @@ SDL_XINPUT_HapticInit(void) } int -SDL_XINPUT_MaybeAddDevice(const DWORD dwUserid) +SDL_XINPUT_HapticMaybeAddDevice(const DWORD dwUserid) { return SDL_Unsupported(); } int -SDL_XINPUT_MaybeRemoveDevice(const DWORD dwUserid) +SDL_XINPUT_HapticMaybeRemoveDevice(const DWORD dwUserid) { return SDL_Unsupported(); } diff --git a/externals/SDL/src/haptic/windows/SDL_xinputhaptic_c.h b/externals/SDL/src/haptic/windows/SDL_xinputhaptic_c.h index 98e9e4344..83686efd0 100755 --- a/externals/SDL/src/haptic/windows/SDL_xinputhaptic_c.h +++ b/externals/SDL/src/haptic/windows/SDL_xinputhaptic_c.h @@ -25,8 +25,8 @@ extern int SDL_XINPUT_HapticInit(void); -extern int SDL_XINPUT_MaybeAddDevice(const DWORD dwUserid); -extern int SDL_XINPUT_MaybeRemoveDevice(const DWORD dwUserid); +extern int SDL_XINPUT_HapticMaybeAddDevice(const DWORD dwUserid); +extern int SDL_XINPUT_HapticMaybeRemoveDevice(const DWORD dwUserid); extern int SDL_XINPUT_HapticOpen(SDL_Haptic * haptic, SDL_hapticlist_item *item); extern int SDL_XINPUT_JoystickSameHaptic(SDL_Haptic * haptic, SDL_Joystick * joystick); extern int SDL_XINPUT_HapticOpenFromJoystick(SDL_Haptic * haptic, SDL_Joystick * joystick); diff --git a/externals/SDL/src/hidapi/libusb/hid.c b/externals/SDL/src/hidapi/libusb/hid.c index 1175da99c..acbffab77 100755 --- a/externals/SDL/src/hidapi/libusb/hid.c +++ b/externals/SDL/src/hidapi/libusb/hid.c @@ -480,6 +480,7 @@ static void usb_string_cache_destroy() usb_string_cache = NULL; usb_string_cache_size = 0; + usb_string_cache_insert_pos = 0; } static struct usb_string_cache_entry *usb_string_cache_insert() @@ -732,8 +733,12 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, if (dev_vid && dev_pid) { string_cache = usb_string_cache_find(&desc, handle); if (string_cache) { - cur_dev->manufacturer_string = wcsdup(string_cache->vendor); - cur_dev->product_string = wcsdup(string_cache->product); + if (string_cache->vendor) { + cur_dev->manufacturer_string = wcsdup(string_cache->vendor); + } + if (string_cache->product) { + cur_dev->product_string = wcsdup(string_cache->product); + } } } else { if (desc.iManufacturer > 0) diff --git a/externals/SDL/src/hidapi/mac/hid.c b/externals/SDL/src/hidapi/mac/hid.c index bdaa612ac..26eab235b 100755 --- a/externals/SDL/src/hidapi/mac/hid.c +++ b/externals/SDL/src/hidapi/mac/hid.c @@ -488,6 +488,15 @@ struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, continue; } +#if defined(SDL_JOYSTICK_MFI) + // We want to prefer Game Controller support where available, + // as Apple will likely be requiring that for supported devices. + extern SDL_bool IOS_SupportedHIDDevice(IOHIDDeviceRef device); + if (IOS_SupportedHIDDevice(dev)) { + continue; + } +#endif + dev_vid = get_vendor_id(dev); dev_pid = get_product_id(dev); diff --git a/externals/SDL/src/joystick/SDL_gamecontrollerdb.h b/externals/SDL/src/joystick/SDL_gamecontrollerdb.h index 069720a83..6e9d667e6 100755 --- a/externals/SDL/src/joystick/SDL_gamecontrollerdb.h +++ b/externals/SDL/src/joystick/SDL_gamecontrollerdb.h @@ -526,6 +526,7 @@ static const char *s_ControllerMappings [] = "05000000a00500003232000001000000,8BitDo Zero Gamepad,a:b1,b:b0,back:b10,dpdown:b122,dpleft:b119,dpright:b120,dpup:b117,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000a00500003232000008010000,8BitDo Zero Gamepad,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000a00500003232000008010000,8BitDo Zero Gamepad,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", + "03000000c82d00000031000011010000,8Bitdo Receiver,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,", "03000000c82d00001290000011010000,8Bitdo SN30 Gamepad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "03000000c82d00001290000011010000,8Bitdo SN30 Gamepad,a:b1,b:b0,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b4,y:b3,hint:!SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", "05000000c82d00006228000000010000,8Bitdo SN30 Gamepad,a:b0,b:b1,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b11,x:b3,y:b4,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", @@ -536,6 +537,10 @@ static const char *s_ControllerMappings [] = "030000006f0e00003901000000430000,Afterglow Prismatic 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,", "030000006f0e00001302000000010000,Afterglow,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,", "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,", + "03000000503200000110000000000000,Atari Classic Controller,a:b0,x:b1,back:b2,guide:b4,start:b3,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2", + "05000000503200000110000000000000,Atari Classic Controller,a:b0,x:b1,back:b2,guide:b4,start:b3,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2", + "03000000503200000210000000000000,Atari Game Controller,a:b0,b:b1,x:b3,y:b2,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5", + "05000000503200000210000000000000,Atari Game Controller,a:b0,b:b1,x:b3,y:b2,back:b6,guide:b8,start:b7,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5", "05000000491900000204000021000000,Amazon Fire Game Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b17,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b12,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,", "05000000710100001904000000010000,Amazon Luna Gamepad,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,", "03000000790000003018000011010000,Arcade Fightstick F300,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,start:b9,x:b0,y:b3,", @@ -673,6 +678,7 @@ static const char *s_ControllerMappings [] = "030000004c050000e60c000011010000,PS5 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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", "050000004c050000e60c000000010000,PS5 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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", "030000004c050000da0c000011010000,Playstation Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,", + "03000000c62400003a54000001010000,PowerA XBox One Controller,a:b0,b:b1,back:b6,dpdown:h0.7,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,", "03000000c62400000053000000010000,PowerA,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,", "03000000300f00001211000011010000,QanBa Arcade JoyStick,a:b2,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b9,x:b1,y:b3,", "030000008916000001fd000024010000,Razer Onza Classic Edition,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,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,", @@ -767,6 +773,7 @@ static const char *s_ControllerMappings [] = "050000006964726f69643a636f6e0000,idroid:con,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,", "03000000b50700001503000010010000,impact,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,", "030000009b2800000300000001010000,raphnet.net 4nes4snes v1.5,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,", + "03000000120c0000f70e000011010000,Brook Universal Fighting Board,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:,lefty:,rightx:,righty:,lefttrigger:b6,righttrigger:b7,", #endif #if defined(__ANDROID__) "05000000c82d000006500000ffff3f00,8BitDo M30 Gamepad,a:b0,b:b1,back:b4,guide:b17,leftshoulder:b9,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a4,start:b6,x:b2,y:b3,hint:SDL_GAMECONTROLLER_USE_BUTTON_LABELS:=1,", diff --git a/externals/SDL/src/joystick/SDL_joystick.c b/externals/SDL/src/joystick/SDL_joystick.c index 8cf47c745..9281473e0 100755 --- a/externals/SDL/src/joystick/SDL_joystick.c +++ b/externals/SDL/src/joystick/SDL_joystick.c @@ -2062,6 +2062,8 @@ static SDL_bool SDL_IsJoystickProductWheel(Uint32 vidpid) MAKE_VIDPID(0x044f, 0xb65d), /* Thrustmaster Wheel FFB */ MAKE_VIDPID(0x044f, 0xb66d), /* Thrustmaster Wheel FFB */ MAKE_VIDPID(0x044f, 0xb677), /* Thrustmaster T150 */ + MAKE_VIDPID(0x044f, 0xb66e), /* Thrustmaster T300RS */ + MAKE_VIDPID(0x044f, 0xb65e), /* Thrustmaster T500RS */ MAKE_VIDPID(0x044f, 0xb664), /* Thrustmaster TX (initial mode) */ MAKE_VIDPID(0x044f, 0xb669), /* Thrustmaster TX (active mode) */ }; diff --git a/externals/SDL/src/joystick/controller_type.h b/externals/SDL/src/joystick/controller_type.h index 742da6793..d9c73cd43 100755 --- a/externals/SDL/src/joystick/controller_type.h +++ b/externals/SDL/src/joystick/controller_type.h @@ -187,7 +187,7 @@ static const ControllerDescription_t arrControllers[] = { { MAKE_CONTROLLER_ID( 0x045e, 0x028f ), k_eControllerType_XBox360Controller, "Xbox 360 Controller" }, // Microsoft X-Box 360 pad v2 { MAKE_CONTROLLER_ID( 0x045e, 0x0291 ), k_eControllerType_XBox360Controller, "Xbox 360 Wireless Controller" }, // Xbox 360 Wireless Receiver (XBOX) { MAKE_CONTROLLER_ID( 0x045e, 0x02a0 ), k_eControllerType_XBox360Controller, NULL }, // Microsoft X-Box 360 Big Button IR - { MAKE_CONTROLLER_ID( 0x045e, 0x02a1 ), k_eControllerType_XBox360Controller, NULL }, // Microsoft X-Box 360 pad + { MAKE_CONTROLLER_ID( 0x045e, 0x02a1 ), k_eControllerType_XBox360Controller, NULL }, // Microsoft X-Box 360 Wireless Controller with XUSB driver on Windows { MAKE_CONTROLLER_ID( 0x045e, 0x02a9 ), k_eControllerType_XBox360Controller, "Xbox 360 Wireless Controller" }, // Xbox 360 Wireless Receiver (third party knockoff) { MAKE_CONTROLLER_ID( 0x045e, 0x0719 ), k_eControllerType_XBox360Controller, "Xbox 360 Wireless Controller" }, // Xbox 360 Wireless Receiver { MAKE_CONTROLLER_ID( 0x046d, 0xc21d ), k_eControllerType_XBox360Controller, NULL }, // Logitech Gamepad F310 @@ -322,11 +322,11 @@ static const ControllerDescription_t arrControllers[] = { { MAKE_CONTROLLER_ID( 0x045e, 0x02e3 ), k_eControllerType_XBoxOneController, "Xbox One Elite Controller" }, // Microsoft X-Box One Elite pad { MAKE_CONTROLLER_ID( 0x045e, 0x02ea ), k_eControllerType_XBoxOneController, "Xbox One S Controller" }, // Microsoft X-Box One S pad { MAKE_CONTROLLER_ID( 0x045e, 0x02fd ), k_eControllerType_XBoxOneController, "Xbox One S Controller" }, // Microsoft X-Box One S pad (Bluetooth) - { MAKE_CONTROLLER_ID( 0x045e, 0x02ff ), k_eControllerType_XBoxOneController, NULL }, // Microsoft X-Box One controller with the RAWINPUT driver on Windows + { MAKE_CONTROLLER_ID( 0x045e, 0x02ff ), k_eControllerType_XBoxOneController, NULL }, // Microsoft X-Box One controller with XBOXGIP driver on Windows { MAKE_CONTROLLER_ID( 0x045e, 0x0b00 ), k_eControllerType_XBoxOneController, "Xbox One Elite 2 Controller" }, // Microsoft X-Box One Elite Series 2 pad { MAKE_CONTROLLER_ID( 0x045e, 0x0b05 ), k_eControllerType_XBoxOneController, "Xbox One Elite 2 Controller" }, // Microsoft X-Box One Elite Series 2 pad (Bluetooth) - { MAKE_CONTROLLER_ID( 0x045e, 0x0b12 ), k_eControllerType_XBoxOneController, "Xbox One Series X Controller" }, // Microsoft X-Box One Elite Series X pad - { MAKE_CONTROLLER_ID( 0x045e, 0x0b13 ), k_eControllerType_XBoxOneController, "Xbox One Series X Controller" }, // Microsoft X-Box One Elite Series X pad (Bluetooth) + { MAKE_CONTROLLER_ID( 0x045e, 0x0b12 ), k_eControllerType_XBoxOneController, "Xbox One Series X Controller" }, // Microsoft X-Box One Series X pad + { MAKE_CONTROLLER_ID( 0x045e, 0x0b13 ), k_eControllerType_XBoxOneController, "Xbox One Series X Controller" }, // Microsoft X-Box One Series X pad (Bluetooth) { MAKE_CONTROLLER_ID( 0x0738, 0x4a01 ), k_eControllerType_XBoxOneController, NULL }, // Mad Catz FightStick TE 2 { MAKE_CONTROLLER_ID( 0x0e6f, 0x0139 ), k_eControllerType_XBoxOneController, "PDP Xbox One Afterglow" }, // PDP Afterglow Wired Controller for Xbox One { MAKE_CONTROLLER_ID( 0x0e6f, 0x013B ), k_eControllerType_XBoxOneController, "PDP Xbox One Face-Off Controller" }, // PDP Face-Off Gamepad for Xbox One diff --git a/externals/SDL/src/joystick/hidapi/SDL_hidapi_ps5.c b/externals/SDL/src/joystick/hidapi/SDL_hidapi_ps5.c index aa1967c83..6df4acec1 100755 --- a/externals/SDL/src/joystick/hidapi/SDL_hidapi_ps5.c +++ b/externals/SDL/src/joystick/hidapi/SDL_hidapi_ps5.c @@ -709,7 +709,7 @@ HIDAPI_DriverPS5_RumbleJoystickTriggers(SDL_HIDAPI_Device *device, SDL_Joystick static SDL_bool HIDAPI_DriverPS5_HasJoystickLED(SDL_HIDAPI_Device *device, SDL_Joystick *joystick) { - return SDL_FALSE; + return SDL_TRUE; } static int diff --git a/externals/SDL/src/joystick/hidapi/SDL_hidapi_switch.c b/externals/SDL/src/joystick/hidapi/SDL_hidapi_switch.c index fe527aa12..5df45fa34 100755 --- a/externals/SDL/src/joystick/hidapi/SDL_hidapi_switch.c +++ b/externals/SDL/src/joystick/hidapi/SDL_hidapi_switch.c @@ -717,11 +717,7 @@ static Sint16 ApplyStickCalibrationCentered(SDL_DriverSwitch_Context *ctx, int n ctx->m_StickExtents[nStick].axis[nAxis].sMin = sRawValue; } - if (sRawValue > 0) { - return (Sint16)HIDAPI_RemapVal(sRawValue, 0, ctx->m_StickExtents[nStick].axis[nAxis].sMax, 0, SDL_MAX_SINT16); - } else { - return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_StickExtents[nStick].axis[nAxis].sMin, 0, SDL_MIN_SINT16, 0); - } + return (Sint16)HIDAPI_RemapVal(sRawValue, ctx->m_StickExtents[nStick].axis[nAxis].sMin, ctx->m_StickExtents[nStick].axis[nAxis].sMax, SDL_MIN_SINT16, SDL_MAX_SINT16); } static Sint16 ApplyStickCalibration(SDL_DriverSwitch_Context *ctx, int nStick, int nAxis, Sint16 sRawValue) diff --git a/externals/SDL/src/joystick/hidapi/SDL_hidapijoystick.c b/externals/SDL/src/joystick/hidapi/SDL_hidapijoystick.c index e3f99bc98..2e3bf5b47 100755 --- a/externals/SDL/src/joystick/hidapi/SDL_hidapijoystick.c +++ b/externals/SDL/src/joystick/hidapi/SDL_hidapijoystick.c @@ -1086,12 +1086,12 @@ HIDAPI_IsEquivalentToDevice(Uint16 vendor_id, Uint16 product_id, SDL_HIDAPI_Devi if (vendor_id == USB_VENDOR_MICROSOFT) { /* If we're looking for the wireless XBox 360 controller, also look for the dongle */ - if (product_id == 0x02a1 && device->product_id == 0x0719) { + if (product_id == USB_PRODUCT_XBOX360_XUSB_CONTROLLER && device->product_id == USB_PRODUCT_XBOX360_WIRELESS_RECEIVER) { return SDL_TRUE; } /* If we're looking for the raw input Xbox One controller, match it against any other Xbox One controller */ - if (product_id == USB_PRODUCT_XBOX_ONE_RAW_INPUT_CONTROLLER && + if (product_id == USB_PRODUCT_XBOX_ONE_XBOXGIP_CONTROLLER && SDL_GetJoystickGameControllerType(device->name, device->vendor_id, device->product_id, device->interface_number, device->interface_class, device->interface_subclass, device->interface_protocol) == SDL_CONTROLLER_TYPE_XBOXONE) { return SDL_TRUE; } diff --git a/externals/SDL/src/joystick/linux/SDL_sysjoystick.c b/externals/SDL/src/joystick/linux/SDL_sysjoystick.c index bb51fa68a..25146d10a 100755 --- a/externals/SDL/src/joystick/linux/SDL_sysjoystick.c +++ b/externals/SDL/src/joystick/linux/SDL_sysjoystick.c @@ -127,6 +127,14 @@ FixupDeviceInfoForMapping(int fd, struct input_id *inpid) inpid->version = 0x0902; } } + + /* For Atari vcs modern and classic controllers have the version reflecting + * firmware version, but the mapping stays stable so ignore + * version information */ + if (inpid->vendor == 0x3250 + && (inpid->product == 0x1001 || inpid->product == 0x1002)) { + inpid->version = 0; + } } #ifdef SDL_JOYSTICK_HIDAPI diff --git a/externals/SDL/src/joystick/usb_ids.h b/externals/SDL/src/joystick/usb_ids.h index db81d123a..b823f1b2d 100755 --- a/externals/SDL/src/joystick/usb_ids.h +++ b/externals/SDL/src/joystick/usb_ids.h @@ -51,6 +51,8 @@ #define USB_PRODUCT_SONY_DS4_DONGLE 0x0ba0 #define USB_PRODUCT_SONY_DS4_SLIM 0x09cc #define USB_PRODUCT_SONY_DS5 0x0ce6 +#define USB_PRODUCT_XBOX360_XUSB_CONTROLLER 0x02a1 /* XUSB driver software PID */ +#define USB_PRODUCT_XBOX360_WIRELESS_RECEIVER 0x0719 #define USB_PRODUCT_XBOX_ONE_ELITE_SERIES_1 0x02e3 #define USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2 0x0b00 #define USB_PRODUCT_XBOX_ONE_ELITE_SERIES_2_BLUETOOTH 0x0b05 @@ -60,7 +62,7 @@ #define USB_PRODUCT_XBOX_ONE_SERIES_X 0x0b12 #define USB_PRODUCT_XBOX_ONE_SERIES_X_BLUETOOTH 0x0b13 #define USB_PRODUCT_XBOX_ONE_SERIES_X_POWERA 0x2001 -#define USB_PRODUCT_XBOX_ONE_RAW_INPUT_CONTROLLER 0x02ff +#define USB_PRODUCT_XBOX_ONE_XBOXGIP_CONTROLLER 0x02ff /* XBOXGIP driver software PID */ #define USB_PRODUCT_XBOX_ONE_XINPUT_CONTROLLER 0x02fe /* Made up product ID for XInput */ /* USB usage pages */ diff --git a/externals/SDL/src/joystick/windows/SDL_dinputjoystick.c b/externals/SDL/src/joystick/windows/SDL_dinputjoystick.c index 4c934a206..98c6499ed 100755 --- a/externals/SDL/src/joystick/windows/SDL_dinputjoystick.c +++ b/externals/SDL/src/joystick/windows/SDL_dinputjoystick.c @@ -45,8 +45,6 @@ extern HWND SDL_HelperWindow; /* local variables */ static SDL_bool coinitialized = SDL_FALSE; static LPDIRECTINPUT8 dinput = NULL; -static PRAWINPUTDEVICELIST SDL_RawDevList = NULL; -static UINT SDL_RawDevListCount = 0; /* Taken from Wine - Thanks! */ static DIOBJECTDATAFORMAT dfDIJoystick2[] = { @@ -235,210 +233,104 @@ SetDIerror(const char *function, HRESULT code) return SDL_SetError("%s() DirectX error 0x%8.8lx", function, code); } -#if 0 /* Microsoft recommended implementation, but slower than checking raw devices */ -#define COBJMACROS -#include -#include - -static const IID CLSID_WbemLocator = { 0x4590f811, 0x1d3a, 0x11d0,{ 0x89, 0x1f, 0x00, 0xaa, 0x00, 0x4b, 0x2e, 0x24 } }; -static const IID IID_IWbemLocator = { 0xdc12a687, 0x737f, 0x11cf,{ 0x88, 0x4d, 0x00, 0xaa, 0x00, 0x4b, 0x2e, 0x24 } }; - static SDL_bool -WIN_IsXInputDevice(const TCHAR *name, const GUID* pGuidProductFromDirectInput) +SDL_IsXInputDevice(Uint16 vendor_id, Uint16 product_id, const char* hidPath) { - IWbemLocator* pIWbemLocator = NULL; - IEnumWbemClassObject* pEnumDevices = NULL; - IWbemClassObject* pDevices[20]; - IWbemServices* pIWbemServices = NULL; - BSTR bstrNamespace = NULL; - BSTR bstrDeviceID = NULL; - BSTR bstrClassName = NULL; - DWORD uReturned = 0; - SDL_bool bIsXinputDevice = SDL_FALSE; - UINT iDevice = 0; - VARIANT var; - HRESULT hr; + SDL_GameControllerType type; if (!SDL_XINPUT_Enabled()) { return SDL_FALSE; } - if (SDL_tcsstr(name, TEXT(" XINPUT ")) != NULL) { - /* This is a duplicate interface for a controller that will show up with XInput, - e.g. Xbox One Elite Series 2 in Bluetooth mode. - */ + type = SDL_GetJoystickGameControllerType("", vendor_id, product_id, -1, 0, 0, 0); + if (type == SDL_CONTROLLER_TYPE_XBOX360 || + type == SDL_CONTROLLER_TYPE_XBOXONE || + (vendor_id == 0x28DE && product_id == 0x11FF)) { return SDL_TRUE; } - SDL_zeroa(pDevices); - - // Create WMI - hr = CoCreateInstance(&CLSID_WbemLocator, - NULL, - CLSCTX_INPROC_SERVER, - &IID_IWbemLocator, - (LPVOID*)&pIWbemLocator); - if (FAILED(hr) || pIWbemLocator == NULL) - goto LCleanup; - - bstrNamespace = SysAllocString(L"\\\\.\\root\\cimv2"); if (bstrNamespace == NULL) goto LCleanup; - bstrClassName = SysAllocString(L"Win32_PNPEntity"); if (bstrClassName == NULL) goto LCleanup; - bstrDeviceID = SysAllocString(L"DeviceID"); if (bstrDeviceID == NULL) goto LCleanup; - - // Connect to WMI - hr = IWbemLocator_ConnectServer(pIWbemLocator, bstrNamespace, NULL, NULL, 0L, - 0L, NULL, NULL, &pIWbemServices); - if (FAILED(hr) || pIWbemServices == NULL) { - goto LCleanup; - } - - // Switch security level to IMPERSONATE. - CoSetProxyBlanket((IUnknown *)pIWbemServices, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, - RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE); - - hr = IWbemServices_CreateInstanceEnum(pIWbemServices, bstrClassName, 0, NULL, &pEnumDevices); - if (FAILED(hr) || pEnumDevices == NULL) - goto LCleanup; - - // Loop over all devices - for (;;) { - // Get 20 at a time - hr = IEnumWbemClassObject_Next(pEnumDevices, 10000, SDL_arraysize(pDevices), pDevices, &uReturned); - if (FAILED(hr)) { - goto LCleanup; - } - if (uReturned == 0) { - break; - } - - for (iDevice = 0; iDevice < uReturned; iDevice++) { - // For each device, get its device ID - hr = IWbemClassObject_Get(pDevices[iDevice], bstrDeviceID, 0L, &var, NULL, NULL); - if (SUCCEEDED(hr) && var.vt == VT_BSTR && var.bstrVal != NULL) { - // Check if the device ID contains "IG_". If it does, then it's an XInput device - // This information can not be found from DirectInput - if (SDL_wcsstr(var.bstrVal, L"IG_")) { - char *bstrVal = WIN_StringToUTF8W(var.bstrVal); - - // If it does, then get the VID/PID from var.bstrVal - DWORD dwPid = 0, dwVid = 0, dwVidPid; - const char *strVid, *strPid; - strVid = SDL_strstr(bstrVal, "VID_"); - if (strVid && SDL_sscanf(strVid, "VID_%4X", &dwVid) != 1) - dwVid = 0; - strPid = SDL_strstr(bstrVal, "PID_"); - if (strPid && SDL_sscanf(strPid, "PID_%4X", &dwPid) != 1) - dwPid = 0; - - SDL_free(bstrVal); - - // Compare the VID/PID to the DInput device - dwVidPid = MAKELONG(dwVid, dwPid); - if (dwVidPid == pGuidProductFromDirectInput->Data1) { - bIsXinputDevice = SDL_TRUE; - goto LCleanup; - } - } - } - IWbemClassObject_Release(pDevices[iDevice]); - } - } - -LCleanup: - if (bstrNamespace) { - SysFreeString(bstrNamespace); - } - if (bstrDeviceID) { - SysFreeString(bstrDeviceID); - } - if (bstrClassName) { - SysFreeString(bstrClassName); - } - for (iDevice = 0; iDevice < SDL_arraysize(pDevices); iDevice++) { - if (pDevices[iDevice]) { - IWbemClassObject_Release(pDevices[iDevice]); - } - } - if (pEnumDevices) { - IEnumWbemClassObject_Release(pEnumDevices); - } - if (pIWbemLocator) { - IWbemLocator_Release(pIWbemLocator); - } - if (pIWbemServices) { - IWbemServices_Release(pIWbemServices); - } - - return bIsXinputDevice; -} -#endif /* 0 */ - -static SDL_bool -SDL_IsXInputDevice(const TCHAR *name, const GUID* pGuidProductFromDirectInput) -{ - UINT i; - - if (!SDL_XINPUT_Enabled()) { - return SDL_FALSE; - } - - if (SDL_tcsstr(name, TEXT(" XINPUT ")) != NULL) { - /* This is a duplicate interface for a controller that will show up with XInput, - e.g. Xbox One Elite Series 2 in Bluetooth mode. - */ + /* If device path contains "IG_" then its an XInput device */ + /* See: https://docs.microsoft.com/windows/win32/xinput/xinput-and-directinput */ + if (SDL_strstr(hidPath, "IG_") != NULL) { return SDL_TRUE; } - if (SDL_memcmp(&pGuidProductFromDirectInput->Data4[2], "PIDVID", 6) == 0) { - Uint16 vendor_id = (Uint16)LOWORD(pGuidProductFromDirectInput->Data1); - Uint16 product_id = (Uint16)HIWORD(pGuidProductFromDirectInput->Data1); - SDL_GameControllerType type = SDL_GetJoystickGameControllerType("", vendor_id, product_id, -1, 0, 0, 0); - if (type == SDL_CONTROLLER_TYPE_XBOX360 || - type == SDL_CONTROLLER_TYPE_XBOXONE || - (vendor_id == 0x28DE && product_id == 0x11FF)) { - return SDL_TRUE; - } - } - - /* Go through RAWINPUT (WinXP and later) to find HID devices. */ - /* Cache this if we end up using it. */ - if (SDL_RawDevList == NULL) { - if ((GetRawInputDeviceList(NULL, &SDL_RawDevListCount, sizeof(RAWINPUTDEVICELIST)) == -1) || (!SDL_RawDevListCount)) { - return SDL_FALSE; /* oh well. */ - } - - SDL_RawDevList = (PRAWINPUTDEVICELIST)SDL_malloc(sizeof(RAWINPUTDEVICELIST) * SDL_RawDevListCount); - if (SDL_RawDevList == NULL) { - SDL_OutOfMemory(); - return SDL_FALSE; - } - - if (GetRawInputDeviceList(SDL_RawDevList, &SDL_RawDevListCount, sizeof(RAWINPUTDEVICELIST)) == -1) { - SDL_free(SDL_RawDevList); - SDL_RawDevList = NULL; - return SDL_FALSE; /* oh well. */ - } - } - - for (i = 0; i < SDL_RawDevListCount; i++) { - RID_DEVICE_INFO rdi; - char devName[MAX_PATH]; - UINT rdiSize = sizeof(rdi); - UINT nameSize = SDL_arraysize(devName); - - rdi.cbSize = sizeof(rdi); - if ((SDL_RawDevList[i].dwType == RIM_TYPEHID) && - (GetRawInputDeviceInfoA(SDL_RawDevList[i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) != ((UINT)-1)) && - (MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) == ((LONG)pGuidProductFromDirectInput->Data1)) && - (GetRawInputDeviceInfoA(SDL_RawDevList[i].hDevice, RIDI_DEVICENAME, devName, &nameSize) != ((UINT)-1)) && - (SDL_strstr(devName, "IG_") != NULL)) { - return SDL_TRUE; - } - } - return SDL_FALSE; } +static SDL_bool +QueryDeviceName(LPDIRECTINPUTDEVICE8 device, char** device_name) +{ + DIPROPSTRING dipstr; + + if (!device || !device_name) { + return SDL_FALSE; + } + + dipstr.diph.dwSize = sizeof(dipstr); + dipstr.diph.dwHeaderSize = sizeof(dipstr.diph); + dipstr.diph.dwObj = 0; + dipstr.diph.dwHow = DIPH_DEVICE; + + if (FAILED(IDirectInputDevice8_GetProperty(device, DIPROP_PRODUCTNAME, &dipstr.diph))) { + return SDL_FALSE; + } + + *device_name = WIN_StringToUTF8(dipstr.wsz); + + return SDL_TRUE; +} + +static SDL_bool +QueryDevicePath(LPDIRECTINPUTDEVICE8 device, char** device_path) +{ + DIPROPGUIDANDPATH dippath; + + if (!device || !device_path) { + return SDL_FALSE; + } + + dippath.diph.dwSize = sizeof(dippath); + dippath.diph.dwHeaderSize = sizeof(dippath.diph); + dippath.diph.dwObj = 0; + dippath.diph.dwHow = DIPH_DEVICE; + + if (FAILED(IDirectInputDevice8_GetProperty(device, DIPROP_GUIDANDPATH, &dippath.diph))) { + return SDL_FALSE; + } + + *device_path = WIN_StringToUTF8W(dippath.wszPath); + + /* Normalize path to upper case. */ + SDL_strupr(*device_path); + + return SDL_TRUE; +} + +static SDL_bool +QueryDeviceInfo(LPDIRECTINPUTDEVICE8 device, Uint16* vendor_id, Uint16* product_id) +{ + DIPROPDWORD dipdw; + + if (!device || !vendor_id || !product_id) { + return SDL_FALSE; + } + + dipdw.diph.dwSize = sizeof(dipdw); + dipdw.diph.dwHeaderSize = sizeof(dipdw.diph); + dipdw.diph.dwObj = 0; + dipdw.diph.dwHow = DIPH_DEVICE; + + if (FAILED(IDirectInputDevice8_GetProperty(device, DIPROP_VIDPID, &dipdw.diph))) { + return SDL_FALSE; + } + + *vendor_id = LOWORD(dipdw.dwData); + *product_id = HIWORD(dipdw.dwData); + + return SDL_TRUE; +} + void FreeRumbleEffectData(DIEFFECT *effect) { if (!effect) { @@ -533,88 +425,49 @@ SDL_DINPUT_JoystickInit(void) /* helper function for direct input, gets called for each connected joystick */ static BOOL CALLBACK -EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext) +EnumJoysticksCallback(LPCDIDEVICEINSTANCE pDeviceInstance, LPVOID pContext) { - JoyStick_DeviceData *pNewJoystick; +#define CHECK(exp) { if(!(exp)) goto err; } + JoyStick_DeviceData *pNewJoystick = NULL; JoyStick_DeviceData *pPrevJoystick = NULL; - const DWORD devtype = (pdidInstance->dwDevType & 0xFF); Uint16 *guid16; Uint16 vendor = 0; Uint16 product = 0; Uint16 version = 0; - WCHAR hidPath[MAX_PATH]; - char *name; + char *hidPath = NULL; + char *name = NULL; + LPDIRECTINPUTDEVICE8 device = NULL; - if (devtype == DI8DEVTYPE_SUPPLEMENTAL) { - /* Add any supplemental devices that should be ignored here */ -#define MAKE_TABLE_ENTRY(VID, PID) ((((DWORD)PID)<<16)|VID) - static DWORD ignored_devices[] = { - MAKE_TABLE_ENTRY(0, 0) - }; -#undef MAKE_TABLE_ENTRY - unsigned int i; + /* We are only supporting HID devices. */ + CHECK((pDeviceInstance->dwDevType & DIDEVTYPE_HID) != 0); - for (i = 0; i < SDL_arraysize(ignored_devices); ++i) { - if (pdidInstance->guidProduct.Data1 == ignored_devices[i]) { - return DIENUM_CONTINUE; - } - } - } + CHECK(SUCCEEDED(IDirectInput8_CreateDevice(dinput, &pDeviceInstance->guidInstance, &device, NULL))); + CHECK(QueryDeviceName(device, &name)); + CHECK(QueryDevicePath(device, &hidPath)); + CHECK(QueryDeviceInfo(device, &vendor, &product)); - if (SDL_IsXInputDevice(pdidInstance->tszProductName, &pdidInstance->guidProduct)) { - return DIENUM_CONTINUE; /* ignore XInput devices here, keep going. */ - } + CHECK(!SDL_IsXInputDevice(vendor, product, hidPath)); - { - HRESULT result; - LPDIRECTINPUTDEVICE8 device; - LPDIRECTINPUTDEVICE8 InputDevice; - DIPROPGUIDANDPATH dipdw2; - - result = IDirectInput8_CreateDevice(dinput, &(pdidInstance->guidInstance), &device, NULL); - if (FAILED(result)) { - return DIENUM_CONTINUE; /* better luck next time? */ - } - - /* Now get the IDirectInputDevice8 interface, instead. */ - result = IDirectInputDevice8_QueryInterface(device, &IID_IDirectInputDevice8, (LPVOID *)&InputDevice); - /* We are done with this object. Use the stored one from now on. */ - IDirectInputDevice8_Release(device); - if (FAILED(result)) { - return DIENUM_CONTINUE; /* better luck next time? */ - } - dipdw2.diph.dwSize = sizeof(dipdw2); - dipdw2.diph.dwHeaderSize = sizeof(dipdw2.diph); - dipdw2.diph.dwObj = 0; // device property - dipdw2.diph.dwHow = DIPH_DEVICE; - - result = IDirectInputDevice8_GetProperty(InputDevice, DIPROP_GUIDANDPATH, &dipdw2.diph); - IDirectInputDevice8_Release(InputDevice); - if (FAILED(result)) { - return DIENUM_CONTINUE; /* better luck next time? */ - } - - /* Get device path, compare that instead of GUID, additionally update GUIDs of joysticks with matching paths, in case they're not open yet. */ - SDL_wcslcpy(hidPath, dipdw2.wszPath, SDL_arraysize(hidPath)); - } - - pNewJoystick = *(JoyStick_DeviceData **)pContext; + pNewJoystick = *(JoyStick_DeviceData**)pContext; while (pNewJoystick) { - if (SDL_wcscmp(pNewJoystick->hidPath, hidPath) == 0) { + /* update GUIDs of joysticks with matching paths, in case they're not open yet */ + if (SDL_strcmp(pNewJoystick->hidPath, hidPath) == 0) { /* if we are replacing the front of the list then update it */ - if (pNewJoystick == *(JoyStick_DeviceData **)pContext) { - *(JoyStick_DeviceData **)pContext = pNewJoystick->pNext; - } else if (pPrevJoystick) { + if (pNewJoystick == *(JoyStick_DeviceData**)pContext) { + *(JoyStick_DeviceData**)pContext = pNewJoystick->pNext; + } + else if (pPrevJoystick) { pPrevJoystick->pNext = pNewJoystick->pNext; } /* Update with new guid/etc, if it has changed */ - SDL_memcpy(&pNewJoystick->dxdevice, pdidInstance, sizeof(DIDEVICEINSTANCE)); + SDL_memcpy(&pNewJoystick->dxdevice, pDeviceInstance, sizeof(DIDEVICEINSTANCE)); pNewJoystick->pNext = SYS_Joystick; SYS_Joystick = pNewJoystick; - return DIENUM_CONTINUE; /* already have this joystick loaded, just keep going */ + pNewJoystick = NULL; + CHECK(FALSE); } pPrevJoystick = pNewJoystick; @@ -622,31 +475,18 @@ EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext) } pNewJoystick = (JoyStick_DeviceData *)SDL_malloc(sizeof(JoyStick_DeviceData)); - if (!pNewJoystick) { - return DIENUM_CONTINUE; /* better luck next time? */ - } + CHECK(pNewJoystick); SDL_zerop(pNewJoystick); - SDL_wcslcpy(pNewJoystick->hidPath, hidPath, SDL_arraysize(pNewJoystick->hidPath)); - SDL_memcpy(&pNewJoystick->dxdevice, pdidInstance, sizeof(DIDEVICEINSTANCE)); + SDL_strlcpy(pNewJoystick->hidPath, hidPath, SDL_arraysize(pNewJoystick->hidPath)); + SDL_memcpy(&pNewJoystick->dxdevice, pDeviceInstance, sizeof(DIDEVICEINSTANCE)); SDL_memset(pNewJoystick->guid.data, 0, sizeof(pNewJoystick->guid.data)); - if (SDL_memcmp(&pdidInstance->guidProduct.Data4[2], "PIDVID", 6) == 0) { - vendor = (Uint16)LOWORD(pdidInstance->guidProduct.Data1); - product = (Uint16)HIWORD(pdidInstance->guidProduct.Data1); - } - - name = WIN_StringToUTF8(pdidInstance->tszProductName); pNewJoystick->joystickname = SDL_CreateJoystickName(vendor, product, NULL, name); - SDL_free(name); - - if (!pNewJoystick->joystickname) { - SDL_free(pNewJoystick); - return DIENUM_CONTINUE; /* better luck next time? */ - } + CHECK(pNewJoystick->joystickname); guid16 = (Uint16 *)pNewJoystick->guid.data; - if (SDL_memcmp(&pdidInstance->guidProduct.Data4[2], "PIDVID", 6) == 0) { + if (vendor && product) { *guid16++ = SDL_SwapLE16(SDL_HARDWARE_BUS_USB); *guid16++ = 0; *guid16++ = SDL_SwapLE16(vendor); @@ -661,127 +501,102 @@ EnumJoysticksCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext) SDL_strlcpy((char*)guid16, pNewJoystick->joystickname, sizeof(pNewJoystick->guid.data) - 4); } - if (SDL_ShouldIgnoreJoystick(pNewJoystick->joystickname, pNewJoystick->guid)) { - SDL_free(pNewJoystick->joystickname); - SDL_free(pNewJoystick); - return DIENUM_CONTINUE; - } + CHECK(!SDL_ShouldIgnoreJoystick(pNewJoystick->joystickname, pNewJoystick->guid)); #ifdef SDL_JOYSTICK_HIDAPI - if (HIDAPI_IsDevicePresent(vendor, product, 0, pNewJoystick->joystickname)) { - /* The HIDAPI driver is taking care of this device */ - SDL_free(pNewJoystick->joystickname); - SDL_free(pNewJoystick); - return DIENUM_CONTINUE; - } + CHECK(!HIDAPI_IsDevicePresent(vendor, product, version, pNewJoystick->joystickname)); #endif #ifdef SDL_JOYSTICK_RAWINPUT - if (RAWINPUT_IsDevicePresent(vendor, product, 0, pNewJoystick->joystickname)) { - /* The RAWINPUT driver is taking care of this device */ - SDL_free(pNewJoystick); - return DIENUM_CONTINUE; - } + CHECK(!RAWINPUT_IsDevicePresent(vendor, product, version, pNewJoystick->joystickname)); #endif WINDOWS_AddJoystickDevice(pNewJoystick); + pNewJoystick = NULL; + +err: + if (pNewJoystick) { + SDL_free(pNewJoystick->joystickname); + SDL_free(pNewJoystick); + } + + SDL_free(hidPath); + SDL_free(name); + + if (device) { + IDirectInputDevice8_Release(device); + } return DIENUM_CONTINUE; /* get next device, please */ +#undef CHECK } void SDL_DINPUT_JoystickDetect(JoyStick_DeviceData **pContext) { IDirectInput8_EnumDevices(dinput, DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, pContext, DIEDFL_ATTACHEDONLY); - - if (SDL_RawDevList) { - SDL_free(SDL_RawDevList); /* in case we used this in DirectInput detection */ - SDL_RawDevList = NULL; - } - SDL_RawDevListCount = 0; } -typedef struct +SDL_bool +SDL_DINPUT_JoystickPresent(Uint16 vendor_id, Uint16 product_id, Uint16 version_number) { - Uint16 vendor; - Uint16 product; - Uint16 version; - SDL_bool present; -} EnumJoystickPresentData; - -static BOOL CALLBACK -EnumJoystickPresentCallback(const DIDEVICEINSTANCE * pdidInstance, VOID * pContext) -{ - EnumJoystickPresentData *data = (EnumJoystickPresentData *)pContext; + JoyStick_DeviceData* joystick = SYS_Joystick; Uint16 vendor = 0; Uint16 product = 0; Uint16 version = 0; - if (SDL_memcmp(&pdidInstance->guidProduct.Data4[2], "PIDVID", 6) == 0) { - vendor = (Uint16)LOWORD(pdidInstance->guidProduct.Data1); - product = (Uint16)HIWORD(pdidInstance->guidProduct.Data1); - if (data->vendor == vendor && data->product == product && data->version == version) { - data->present = SDL_TRUE; - return DIENUM_STOP; + while (joystick) { + SDL_GetJoystickGUIDInfo(joystick->guid, &vendor, &product, &version); + + if (!joystick->bXInputDevice && + vendor == vendor_id && + product == product_id && + version == version_number) { + return SDL_TRUE; } - } - return DIENUM_CONTINUE; -} -SDL_bool -SDL_DINPUT_JoystickPresent(Uint16 vendor, Uint16 product, Uint16 version) -{ - EnumJoystickPresentData data; - - if (dinput == NULL) { - return SDL_FALSE; + joystick = joystick->pNext; } - data.vendor = vendor; - data.product = product; - data.version = version; - data.present = SDL_FALSE; - IDirectInput8_EnumDevices(dinput, DI8DEVCLASS_GAMECTRL, EnumJoystickPresentCallback, &data, DIEDFL_ATTACHEDONLY); - - return data.present; + return SDL_FALSE; } static BOOL CALLBACK -EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef) +EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE pDeviceObject, LPVOID pContext) { - SDL_Joystick *joystick = (SDL_Joystick *)pvRef; + SDL_Joystick *joystick = (SDL_Joystick *)pContext; HRESULT result; input_t *in = &joystick->hwdata->Inputs[joystick->hwdata->NumInputs]; - if (dev->dwType & DIDFT_BUTTON) { + if (pDeviceObject->dwType & DIDFT_BUTTON) { in->type = BUTTON; in->num = joystick->nbuttons; in->ofs = DIJOFS_BUTTON(in->num); joystick->nbuttons++; - } else if (dev->dwType & DIDFT_POV) { + } else if (pDeviceObject->dwType & DIDFT_POV) { in->type = HAT; in->num = joystick->nhats; in->ofs = DIJOFS_POV(in->num); joystick->nhats++; - } else if (dev->dwType & DIDFT_AXIS) { + } else if (pDeviceObject->dwType & DIDFT_AXIS) { DIPROPRANGE diprg; DIPROPDWORD dilong; in->type = AXIS; in->num = joystick->naxes; - if (!SDL_memcmp(&dev->guidType, &GUID_XAxis, sizeof(dev->guidType))) + if (!SDL_memcmp(&pDeviceObject->guidType, &GUID_XAxis, sizeof(pDeviceObject->guidType))) in->ofs = DIJOFS_X; - else if (!SDL_memcmp(&dev->guidType, &GUID_YAxis, sizeof(dev->guidType))) + else if (!SDL_memcmp(&pDeviceObject->guidType, &GUID_YAxis, sizeof(pDeviceObject->guidType))) in->ofs = DIJOFS_Y; - else if (!SDL_memcmp(&dev->guidType, &GUID_ZAxis, sizeof(dev->guidType))) + else if (!SDL_memcmp(&pDeviceObject->guidType, &GUID_ZAxis, sizeof(pDeviceObject->guidType))) in->ofs = DIJOFS_Z; - else if (!SDL_memcmp(&dev->guidType, &GUID_RxAxis, sizeof(dev->guidType))) + else if (!SDL_memcmp(&pDeviceObject->guidType, &GUID_RxAxis, sizeof(pDeviceObject->guidType))) in->ofs = DIJOFS_RX; - else if (!SDL_memcmp(&dev->guidType, &GUID_RyAxis, sizeof(dev->guidType))) + else if (!SDL_memcmp(&pDeviceObject->guidType, &GUID_RyAxis, sizeof(pDeviceObject->guidType))) in->ofs = DIJOFS_RY; - else if (!SDL_memcmp(&dev->guidType, &GUID_RzAxis, sizeof(dev->guidType))) + else if (!SDL_memcmp(&pDeviceObject->guidType, &GUID_RzAxis, sizeof(pDeviceObject->guidType))) in->ofs = DIJOFS_RZ; - else if (!SDL_memcmp(&dev->guidType, &GUID_Slider, sizeof(dev->guidType))) { + else if (!SDL_memcmp(&pDeviceObject->guidType, &GUID_Slider, sizeof(pDeviceObject->guidType))) { in->ofs = DIJOFS_SLIDER(joystick->hwdata->NumSliders); ++joystick->hwdata->NumSliders; } else { @@ -790,7 +605,7 @@ EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef) diprg.diph.dwSize = sizeof(diprg); diprg.diph.dwHeaderSize = sizeof(diprg.diph); - diprg.diph.dwObj = dev->dwType; + diprg.diph.dwObj = pDeviceObject->dwType; diprg.diph.dwHow = DIPH_BYID; diprg.lMin = SDL_JOYSTICK_AXIS_MIN; diprg.lMax = SDL_JOYSTICK_AXIS_MAX; @@ -805,7 +620,7 @@ EnumDevObjectsCallback(LPCDIDEVICEOBJECTINSTANCE dev, LPVOID pvRef) /* Set dead zone to 0. */ dilong.diph.dwSize = sizeof(dilong); dilong.diph.dwHeaderSize = sizeof(dilong.diph); - dilong.diph.dwObj = dev->dwType; + dilong.diph.dwObj = pDeviceObject->dwType; dilong.diph.dwHow = DIPH_BYID; dilong.dwData = 0; result = @@ -882,7 +697,6 @@ int SDL_DINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickdevice) { HRESULT result; - LPDIRECTINPUTDEVICE8 device; DIPROPDWORD dipdw; joystick->hwdata->buffered = SDL_TRUE; @@ -894,23 +708,13 @@ SDL_DINPUT_JoystickOpen(SDL_Joystick * joystick, JoyStick_DeviceData *joystickde result = IDirectInput8_CreateDevice(dinput, - &(joystickdevice->dxdevice.guidInstance), &device, NULL); + &joystickdevice->dxdevice.guidInstance, + &joystick->hwdata->InputDevice, + NULL); if (FAILED(result)) { return SetDIerror("IDirectInput::CreateDevice", result); } - /* Now get the IDirectInputDevice8 interface, instead. */ - result = IDirectInputDevice8_QueryInterface(device, - &IID_IDirectInputDevice8, - (LPVOID *)& joystick-> - hwdata->InputDevice); - /* We are done with this object. Use the stored one from now on. */ - IDirectInputDevice8_Release(device); - - if (FAILED(result)) { - return SetDIerror("IDirectInputDevice8::QueryInterface", result); - } - /* Acquire shared access. Exclusive access is required for forces, * though. */ result = diff --git a/externals/SDL/src/joystick/windows/SDL_rawinputjoystick.c b/externals/SDL/src/joystick/windows/SDL_rawinputjoystick.c index be292720d..e6d3318dd 100755 --- a/externals/SDL/src/joystick/windows/SDL_rawinputjoystick.c +++ b/externals/SDL/src/joystick/windows/SDL_rawinputjoystick.c @@ -891,7 +891,7 @@ RAWINPUT_IsDevicePresent(Uint16 vendor_id, Uint16 product_id, Uint16 version, co /* The Xbox One controller shows up as a hardcoded raw input VID/PID */ if (name && SDL_strcmp(name, "Xbox One Game Controller") == 0 && device->vendor_id == USB_VENDOR_MICROSOFT && - device->product_id == USB_PRODUCT_XBOX_ONE_RAW_INPUT_CONTROLLER) { + device->product_id == USB_PRODUCT_XBOX_ONE_XBOXGIP_CONTROLLER) { return SDL_TRUE; } diff --git a/externals/SDL/src/joystick/windows/SDL_windowsjoystick.c b/externals/SDL/src/joystick/windows/SDL_windowsjoystick.c index c2eebeef3..7a2310a5a 100755 --- a/externals/SDL/src/joystick/windows/SDL_windowsjoystick.c +++ b/externals/SDL/src/joystick/windows/SDL_windowsjoystick.c @@ -429,11 +429,11 @@ WINDOWS_JoystickDetect(void) if (pCurList->bXInputDevice) { #if SDL_HAPTIC_XINPUT - SDL_XINPUT_MaybeRemoveDevice(pCurList->XInputUserId); + SDL_XINPUT_HapticMaybeRemoveDevice(pCurList->XInputUserId); #endif } else { #if SDL_HAPTIC_DINPUT - SDL_DINPUT_MaybeRemoveDevice(&pCurList->dxdevice); + SDL_DINPUT_HapticMaybeRemoveDevice(&pCurList->dxdevice); #endif } @@ -449,11 +449,11 @@ WINDOWS_JoystickDetect(void) if (pCurList->send_add_event) { if (pCurList->bXInputDevice) { #if SDL_HAPTIC_XINPUT - SDL_XINPUT_MaybeAddDevice(pCurList->XInputUserId); + SDL_XINPUT_HapticMaybeAddDevice(pCurList->XInputUserId); #endif } else { #if SDL_HAPTIC_DINPUT - SDL_DINPUT_MaybeAddDevice(&pCurList->dxdevice); + SDL_DINPUT_HapticMaybeAddDevice(&pCurList->dxdevice); #endif } diff --git a/externals/SDL/src/joystick/windows/SDL_windowsjoystick_c.h b/externals/SDL/src/joystick/windows/SDL_windowsjoystick_c.h index 35507757c..93fd288bc 100755 --- a/externals/SDL/src/joystick/windows/SDL_windowsjoystick_c.h +++ b/externals/SDL/src/joystick/windows/SDL_windowsjoystick_c.h @@ -37,7 +37,7 @@ typedef struct JoyStick_DeviceData BYTE SubType; Uint8 XInputUserId; DIDEVICEINSTANCE dxdevice; - WCHAR hidPath[MAX_PATH]; + char hidPath[MAX_PATH]; struct JoyStick_DeviceData *pNext; } JoyStick_DeviceData; diff --git a/externals/SDL/src/test/SDL_test_common.c b/externals/SDL/src/test/SDL_test_common.c index 0b5bc0e62..9ff04c520 100755 --- a/externals/SDL/src/test/SDL_test_common.c +++ b/externals/SDL/src/test/SDL_test_common.c @@ -629,6 +629,170 @@ SDLTest_CommonDefaultArgs(SDLTest_CommonState *state, const int argc, char **arg return SDL_TRUE; } +static void +SDLTest_PrintDisplayOrientation(char* text, size_t maxlen, SDL_DisplayOrientation orientation) +{ + switch (orientation) { + case SDL_ORIENTATION_UNKNOWN: + SDL_snprintfcat(text, maxlen, "UNKNOWN"); + break; + case SDL_ORIENTATION_LANDSCAPE: + SDL_snprintfcat(text, maxlen, "LANDSCAPE"); + break; + case SDL_ORIENTATION_LANDSCAPE_FLIPPED: + SDL_snprintfcat(text, maxlen, "LANDSCAPE_FLIPPED"); + break; + case SDL_ORIENTATION_PORTRAIT: + SDL_snprintfcat(text, maxlen, "PORTRAIT"); + break; + case SDL_ORIENTATION_PORTRAIT_FLIPPED: + SDL_snprintfcat(text, maxlen, "PORTRAIT_FLIPPED"); + break; + default: + SDL_snprintfcat(text, maxlen, "0x%8.8x", orientation); + break; + } +} + +static void +SDLTest_PrintWindowFlag(char* text, size_t maxlen, Uint32 flag) +{ + switch (flag) { + case SDL_WINDOW_FULLSCREEN: + SDL_snprintfcat(text, maxlen, "FULLSCREEN"); + break; + case SDL_WINDOW_OPENGL: + SDL_snprintfcat(text, maxlen, "OPENGL"); + break; + case SDL_WINDOW_SHOWN: + SDL_snprintfcat(text, maxlen, "SHOWN"); + break; + case SDL_WINDOW_HIDDEN: + SDL_snprintfcat(text, maxlen, "HIDDEN"); + break; + case SDL_WINDOW_BORDERLESS: + SDL_snprintfcat(text, maxlen, "BORDERLESS"); + break; + case SDL_WINDOW_RESIZABLE: + SDL_snprintfcat(text, maxlen, "RESIZABLE"); + break; + case SDL_WINDOW_MINIMIZED: + SDL_snprintfcat(text, maxlen, "MINIMIZED"); + break; + case SDL_WINDOW_MAXIMIZED: + SDL_snprintfcat(text, maxlen, "MAXIMIZED"); + break; + case SDL_WINDOW_MOUSE_GRABBED: + SDL_snprintfcat(text, maxlen, "MOUSE_GRABBED"); + break; + case SDL_WINDOW_INPUT_FOCUS: + SDL_snprintfcat(text, maxlen, "INPUT_FOCUS"); + break; + case SDL_WINDOW_MOUSE_FOCUS: + SDL_snprintfcat(text, maxlen, "MOUSE_FOCUS"); + break; + case SDL_WINDOW_FULLSCREEN_DESKTOP: + SDL_snprintfcat(text, maxlen, "FULLSCREEN_DESKTOP"); + break; + case SDL_WINDOW_FOREIGN: + SDL_snprintfcat(text, maxlen, "FOREIGN"); + break; + case SDL_WINDOW_ALLOW_HIGHDPI: + SDL_snprintfcat(text, maxlen, "ALLOW_HIGHDPI"); + break; + case SDL_WINDOW_MOUSE_CAPTURE: + SDL_snprintfcat(text, maxlen, "MOUSE_CAPTURE"); + break; + case SDL_WINDOW_ALWAYS_ON_TOP: + SDL_snprintfcat(text, maxlen, "ALWAYS_ON_TOP"); + break; + case SDL_WINDOW_SKIP_TASKBAR: + SDL_snprintfcat(text, maxlen, "SKIP_TASKBAR"); + break; + case SDL_WINDOW_UTILITY: + SDL_snprintfcat(text, maxlen, "UTILITY"); + break; + case SDL_WINDOW_TOOLTIP: + SDL_snprintfcat(text, maxlen, "TOOLTIP"); + break; + case SDL_WINDOW_POPUP_MENU: + SDL_snprintfcat(text, maxlen, "POPUP_MENU"); + break; + case SDL_WINDOW_KEYBOARD_GRABBED: + SDL_snprintfcat(text, maxlen, "KEYBOARD_GRABBED"); + break; + case SDL_WINDOW_VULKAN: + SDL_snprintfcat(text, maxlen, "VULKAN"); + break; + case SDL_WINDOW_METAL: + SDL_snprintfcat(text, maxlen, "METAL"); + break; + default: + SDL_snprintfcat(text, maxlen, "0x%8.8x", flag); + break; + } +} + +static void +SDLTest_PrintWindowFlags(char* text, size_t maxlen, Uint32 flags) +{ + const Uint32 window_flags[] = { + SDL_WINDOW_FULLSCREEN, + SDL_WINDOW_OPENGL, + SDL_WINDOW_SHOWN, + SDL_WINDOW_HIDDEN, + SDL_WINDOW_BORDERLESS, + SDL_WINDOW_RESIZABLE, + SDL_WINDOW_MINIMIZED, + SDL_WINDOW_MAXIMIZED, + SDL_WINDOW_MOUSE_GRABBED, + SDL_WINDOW_INPUT_FOCUS, + SDL_WINDOW_MOUSE_FOCUS, + SDL_WINDOW_FULLSCREEN_DESKTOP, + SDL_WINDOW_FOREIGN, + SDL_WINDOW_ALLOW_HIGHDPI, + SDL_WINDOW_MOUSE_CAPTURE, + SDL_WINDOW_ALWAYS_ON_TOP, + SDL_WINDOW_SKIP_TASKBAR, + SDL_WINDOW_UTILITY, + SDL_WINDOW_TOOLTIP, + SDL_WINDOW_POPUP_MENU, + SDL_WINDOW_KEYBOARD_GRABBED, + SDL_WINDOW_VULKAN, + SDL_WINDOW_METAL + }; + + int i; + int count = 0; + for (i = 0; i < (sizeof(window_flags) / sizeof(window_flags[0])); ++i) { + const Uint32 flag = window_flags[i]; + if ((flags & flag) == flag) { + if (count > 0) { + SDL_snprintfcat(text, maxlen, " | "); + } + SDLTest_PrintWindowFlag(text, maxlen, flag); + ++count; + } + } +} + +static void +SDLTest_PrintButtonMask(char* text, size_t maxlen, Uint32 flags) +{ + int i; + int count = 0; + for (i = 1; i <= 32; ++i) { + const Uint32 flag = SDL_BUTTON(i); + if ((flags & flag) == flag) { + if (count > 0) { + SDL_snprintfcat(text, maxlen, " | "); + } + SDL_snprintfcat(text, maxlen, "SDL_BUTTON(%d)", i); + ++count; + } + } +} + static void SDLTest_PrintRendererFlag(char *text, size_t maxlen, Uint32 flag) { @@ -1990,4 +2154,115 @@ SDLTest_CommonQuit(SDLTest_CommonState * state) SDLTest_LogAllocations(); } +void +SDLTest_CommonDrawWindowInfo(SDL_Renderer * renderer, SDL_Window * window) +{ + char text[1024]; + int textY = 0; + const int lineHeight = 10; + int x, y, w, h; + SDL_Rect rect; + SDL_DisplayMode mode; + float ddpi, hdpi, vdpi; + Uint32 flags; + const int windowDisplayIndex = SDL_GetWindowDisplayIndex(window); + + /* Renderer */ + + if (0 == SDL_GetRendererOutputSize(renderer, &w, &h)) { + SDL_snprintf(text, sizeof(text), "SDL_GetRendererOutputSize: %dx%d", w, h); + SDLTest_DrawString(renderer, 0, textY, text); + textY += lineHeight; + } + + SDL_RenderGetViewport(renderer, &rect); + SDL_snprintf(text, sizeof(text), "SDL_RenderGetViewport: %d,%d, %dx%d", + rect.x, rect.y, rect.w, rect.h); + SDLTest_DrawString(renderer, 0, textY, text); + textY += lineHeight; + + /* Window */ + + SDLTest_DrawString(renderer, 0, textY, "----"); + textY += lineHeight; + + SDL_GetWindowPosition(window, &x, &y); + SDL_snprintf(text, sizeof(text), "SDL_GetWindowPosition: %d,%d", x, y); + SDLTest_DrawString(renderer, 0, textY, text); + textY += lineHeight; + + SDL_GetWindowSize(window, &w, &h); + SDL_snprintf(text, sizeof(text), "SDL_GetWindowSize: %dx%d", w, h); + SDLTest_DrawString(renderer, 0, textY, text); + textY += lineHeight; + + SDL_snprintf(text, sizeof(text), "SDL_GetWindowFlags: "); + SDLTest_PrintWindowFlags(text, sizeof(text), SDL_GetWindowFlags(window)); + SDLTest_DrawString(renderer, 0, textY, text); + textY += lineHeight; + + /* Display */ + + SDLTest_DrawString(renderer, 0, textY, "----"); + textY += lineHeight; + + SDL_snprintf(text, sizeof(text), "SDL_GetWindowDisplayIndex: %d", windowDisplayIndex); + SDLTest_DrawString(renderer, 0, textY, text); + textY += lineHeight; + + SDL_snprintf(text, sizeof(text), "SDL_GetDisplayName: %s", SDL_GetDisplayName(windowDisplayIndex)); + SDLTest_DrawString(renderer, 0, textY, text); + textY += lineHeight; + + if (0 == SDL_GetDisplayBounds(windowDisplayIndex, &rect)) { + SDL_snprintf(text, sizeof(text), "SDL_GetDisplayBounds: %d,%d, %dx%d", + rect.x, rect.y, rect.w, rect.h); + SDLTest_DrawString(renderer, 0, textY, text); + textY += lineHeight; + } + + if (0 == SDL_GetCurrentDisplayMode(windowDisplayIndex, &mode)) { + SDL_snprintf(text, sizeof(text), "SDL_GetCurrentDisplayMode: %dx%d@%d", + mode.w, mode.h, mode.refresh_rate); + SDLTest_DrawString(renderer, 0, textY, text); + textY += lineHeight; + } + + if (0 == SDL_GetDesktopDisplayMode(windowDisplayIndex, &mode)) { + SDL_snprintf(text, sizeof(text), "SDL_GetDesktopDisplayMode: %dx%d@%d", + mode.w, mode.h, mode.refresh_rate); + SDLTest_DrawString(renderer, 0, textY, text); + textY += lineHeight; + } + + if (0 == SDL_GetDisplayDPI(windowDisplayIndex, &ddpi, &hdpi, &vdpi)) { + SDL_snprintf(text, sizeof(text), "SDL_GetDisplayDPI: ddpi: %f, hdpi: %f, vdpi: %f", + ddpi, hdpi, vdpi); + SDLTest_DrawString(renderer, 0, textY, text); + textY += lineHeight; + } + + SDL_snprintf(text, sizeof(text), "SDL_GetDisplayOrientation: "); + SDLTest_PrintDisplayOrientation(text, sizeof(text), SDL_GetDisplayOrientation(windowDisplayIndex)); + SDLTest_DrawString(renderer, 0, textY, text); + textY += lineHeight; + + /* Mouse */ + + SDLTest_DrawString(renderer, 0, textY, "----"); + textY += lineHeight; + + flags = SDL_GetMouseState(&x, &y); + SDL_snprintf(text, sizeof(text), "SDL_GetMouseState: %d,%d ", x, y); + SDLTest_PrintButtonMask(text, sizeof(text), flags); + SDLTest_DrawString(renderer, 0, textY, text); + textY += lineHeight; + + flags = SDL_GetGlobalMouseState(&x, &y); + SDL_snprintf(text, sizeof(text), "SDL_GetGlobalMouseState: %d,%d ", x, y); + SDLTest_PrintButtonMask(text, sizeof(text), flags); + SDLTest_DrawString(renderer, 0, textY, text); + textY += lineHeight; +} + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/externals/SDL/src/video/SDL_bmp.c b/externals/SDL/src/video/SDL_bmp.c index 67445c771..ecf31aff4 100755 --- a/externals/SDL/src/video/SDL_bmp.c +++ b/externals/SDL/src/video/SDL_bmp.c @@ -407,14 +407,20 @@ SDL_LoadBMP_RW(SDL_RWops * src, int freesrc) goto done; } - /* - | guich: always use 1< palette->ncolors) { + biClrUsed = 1 << biBitCount; /* try forcing it? */ + if (biClrUsed > palette->ncolors) { + SDL_SetError("Unsupported or incorrect biClrUsed field"); + was_error = SDL_TRUE; + goto done; + } + } + + if (biSize == 12) { for (i = 0; i < (int) biClrUsed; ++i) { SDL_RWread(src, &palette->colors[i].b, 1, 1); SDL_RWread(src, &palette->colors[i].g, 1, 1); diff --git a/externals/SDL/src/video/SDL_egl.c b/externals/SDL/src/video/SDL_egl.c index 8fecaff14..459273509 100755 --- a/externals/SDL/src/video/SDL_egl.c +++ b/externals/SDL/src/video/SDL_egl.c @@ -1089,7 +1089,16 @@ SDL_EGL_MakeCurrent(_THIS, EGLSurface egl_surface, SDL_GLContext context) if (!_this->egl_data) { return SDL_SetError("OpenGL not initialized"); } - + + if (!_this->egl_data->eglMakeCurrent) { + if (!egl_surface && !context) { + /* Can't do the nothing there is to do? Probably trying to cleanup a failed startup, just return. */ + return 0; + } else { + return SDL_SetError("OpenGL not initialized"); /* something clearly went wrong somewhere. */ + } + } + /* The android emulator crashes badly if you try to eglMakeCurrent * with a valid context and invalid surface, so we have to check for both here. */ @@ -1101,7 +1110,7 @@ SDL_EGL_MakeCurrent(_THIS, EGLSurface egl_surface, SDL_GLContext context) return SDL_EGL_SetError("Unable to make EGL context current", "eglMakeCurrent"); } } - + return 0; } diff --git a/externals/SDL/src/video/SDL_sysvideo.h b/externals/SDL/src/video/SDL_sysvideo.h index 682e52592..086166d24 100755 --- a/externals/SDL/src/video/SDL_sysvideo.h +++ b/externals/SDL/src/video/SDL_sysvideo.h @@ -240,6 +240,7 @@ struct SDL_VideoDevice int (*UpdateWindowFramebuffer) (_THIS, SDL_Window * window, const SDL_Rect * rects, int numrects); void (*DestroyWindowFramebuffer) (_THIS, SDL_Window * window); void (*OnWindowEnter) (_THIS, SDL_Window * window); + int (*FlashWindow) (_THIS, SDL_Window * window, Uint32 flash_count); /* * * */ /* @@ -290,6 +291,8 @@ struct SDL_VideoDevice /* * Event manager functions */ + int (*WaitEventTimeout) (_THIS, int timeout); + void (*SendWakeupEvent) (_THIS, SDL_Window *window); void (*PumpEvents) (_THIS); /* Suspend the screensaver */ @@ -324,6 +327,8 @@ struct SDL_VideoDevice /* Data common to all drivers */ SDL_bool is_dummy; SDL_bool suspend_screensaver; + SDL_Window *wakeup_window; + SDL_mutex *wakeup_lock; /* Initialized only if WaitEventTimeout/SendWakeupEvent are supported */ int num_displays; SDL_VideoDisplay *displays; SDL_Window *windows; diff --git a/externals/SDL/src/video/SDL_video.c b/externals/SDL/src/video/SDL_video.c index a5cbe6962..d029f4673 100755 --- a/externals/SDL/src/video/SDL_video.c +++ b/externals/SDL/src/video/SDL_video.c @@ -2792,6 +2792,18 @@ SDL_GetGrabbedWindow(void) return _this->grabbed_window; } +int +SDL_FlashWindow(SDL_Window * window, Uint32 flash_count) +{ + CHECK_WINDOW_MAGIC(window, -1); + + if (_this->FlashWindow) { + return _this->FlashWindow(_this, window, flash_count); + } + + return SDL_Unsupported(); +} + void SDL_OnWindowShown(SDL_Window * window) { diff --git a/externals/SDL/src/video/cocoa/SDL_cocoaclipboard.m b/externals/SDL/src/video/cocoa/SDL_cocoaclipboard.m index a091d8feb..bfd35f055 100755 --- a/externals/SDL/src/video/cocoa/SDL_cocoaclipboard.m +++ b/externals/SDL/src/video/cocoa/SDL_cocoaclipboard.m @@ -32,10 +32,14 @@ Cocoa_SetClipboardText(_THIS, const char *text) SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; NSPasteboard *pasteboard; NSString *format = NSPasteboardTypeString; + NSString *nsstr = [NSString stringWithUTF8String:text]; + if (nsstr == nil) { + return SDL_SetError("Couldn't create NSString; is your string data in UTF-8 format?"); + } pasteboard = [NSPasteboard generalPasteboard]; data->clipboard_count = [pasteboard declareTypes:[NSArray arrayWithObject:format] owner:nil]; - [pasteboard setString:[NSString stringWithUTF8String:text] forType:format]; + [pasteboard setString:nsstr forType:format]; return 0; }} @@ -61,7 +65,7 @@ Cocoa_GetClipboardText(_THIS) } else { utf8 = [string UTF8String]; } - text = SDL_strdup(utf8); + text = SDL_strdup(utf8 ? utf8 : ""); } else { text = SDL_strdup(""); } diff --git a/externals/SDL/src/video/cocoa/SDL_cocoaevents.h b/externals/SDL/src/video/cocoa/SDL_cocoaevents.h index ece463c19..f4694269c 100755 --- a/externals/SDL/src/video/cocoa/SDL_cocoaevents.h +++ b/externals/SDL/src/video/cocoa/SDL_cocoaevents.h @@ -25,6 +25,8 @@ extern void Cocoa_RegisterApp(void); extern void Cocoa_PumpEvents(_THIS); +extern int Cocoa_WaitEventTimeout(_THIS, int timeout); +extern void Cocoa_SendWakeupEvent(_THIS, SDL_Window *window); extern void Cocoa_SuspendScreenSaver(_THIS); #endif /* SDL_cocoaevents_h_ */ diff --git a/externals/SDL/src/video/cocoa/SDL_cocoaevents.m b/externals/SDL/src/video/cocoa/SDL_cocoaevents.m index f496cb24f..732786988 100755 --- a/externals/SDL/src/video/cocoa/SDL_cocoaevents.m +++ b/externals/SDL/src/video/cocoa/SDL_cocoaevents.m @@ -35,6 +35,9 @@ #ifndef NSAppKitVersionNumber10_8 #define NSAppKitVersionNumber10_8 1187 #endif +#ifndef MAC_OS_X_VERSION_10_12 +#define NSEventTypeApplicationDefined NSApplicationDefined +#endif static SDL_Window *FindSDLWindowForNSWindow(NSWindow *win) { @@ -512,9 +515,8 @@ Cocoa_RegisterApp(void) } }} -void -Cocoa_PumpEvents(_THIS) -{ @autoreleasepool +int +Cocoa_PumpEventsUntilDate(_THIS, NSDate *expiration, bool accumulate) { #if MAC_OS_X_VERSION_MIN_REQUIRED < 1070 /* Update activity every 30 seconds to prevent screensaver */ @@ -530,9 +532,9 @@ Cocoa_PumpEvents(_THIS) #endif for ( ; ; ) { - NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny untilDate:[NSDate distantPast] inMode:NSDefaultRunLoopMode dequeue:YES ]; + NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny untilDate:expiration inMode:NSDefaultRunLoopMode dequeue:YES ]; if ( event == nil ) { - break; + return 0; } if (!s_bShouldHandleEventsInSDLApplication) { @@ -541,7 +543,52 @@ Cocoa_PumpEvents(_THIS) // Pass events down to SDLApplication to be handled in sendEvent: [NSApp sendEvent:event]; + if ( !accumulate) { + break; + } } + return 1; +} + +int +Cocoa_WaitEventTimeout(_THIS, int timeout) +{ @autoreleasepool +{ + if (timeout > 0) { + NSDate *limitDate = [NSDate dateWithTimeIntervalSinceNow: (double) timeout / 1000.0]; + return Cocoa_PumpEventsUntilDate(_this, limitDate, false); + } else if (timeout == 0) { + return Cocoa_PumpEventsUntilDate(_this, [NSDate distantPast], false); + } else { + while (Cocoa_PumpEventsUntilDate(_this, [NSDate distantFuture], false) == 0) { + } + } + return 1; +}} + +void +Cocoa_PumpEvents(_THIS) +{ @autoreleasepool +{ + Cocoa_PumpEventsUntilDate(_this, [NSDate distantPast], true); +}} + +void Cocoa_SendWakeupEvent(_THIS, SDL_Window *window) +{ @autoreleasepool +{ + NSWindow *nswindow = ((SDL_WindowData *) window->driverdata)->nswindow; + + NSEvent* event = [NSEvent otherEventWithType: NSEventTypeApplicationDefined + location: NSMakePoint(0,0) + modifierFlags: 0 + timestamp: 0.0 + windowNumber: nswindow.windowNumber + context: nil + subtype: 0 + data1: 0 + data2: 0]; + + [NSApp postEvent: event atStart: YES]; }} void diff --git a/externals/SDL/src/video/cocoa/SDL_cocoavideo.m b/externals/SDL/src/video/cocoa/SDL_cocoavideo.m index 5019d3e7c..f16b8aa66 100755 --- a/externals/SDL/src/video/cocoa/SDL_cocoavideo.m +++ b/externals/SDL/src/video/cocoa/SDL_cocoavideo.m @@ -38,6 +38,9 @@ static void Cocoa_VideoQuit(_THIS); static void Cocoa_DeleteDevice(SDL_VideoDevice * device) { + if (device->wakeup_lock) { + SDL_DestroyMutex(device->wakeup_lock); + } SDL_free(device->driverdata); SDL_free(device); } @@ -63,6 +66,7 @@ Cocoa_CreateDevice(int devindex) return NULL; } device->driverdata = data; + device->wakeup_lock = SDL_CreateMutex(); /* Set the function pointers */ device->VideoInit = Cocoa_VideoInit; @@ -73,6 +77,8 @@ Cocoa_CreateDevice(int devindex) device->GetDisplayModes = Cocoa_GetDisplayModes; device->SetDisplayMode = Cocoa_SetDisplayMode; device->PumpEvents = Cocoa_PumpEvents; + device->WaitEventTimeout = Cocoa_WaitEventTimeout; + device->SendWakeupEvent = Cocoa_SendWakeupEvent; device->SuspendScreenSaver = Cocoa_SuspendScreenSaver; device->CreateSDLWindow = Cocoa_CreateWindow; diff --git a/externals/SDL/src/video/kmsdrm/SDL_kmsdrmopengles.c b/externals/SDL/src/video/kmsdrm/SDL_kmsdrmopengles.c index ee7e3923d..55a53df76 100755 --- a/externals/SDL/src/video/kmsdrm/SDL_kmsdrmopengles.c +++ b/externals/SDL/src/video/kmsdrm/SDL_kmsdrmopengles.c @@ -97,6 +97,11 @@ KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window) { even if you do async flips. */ uint32_t flip_flags = DRM_MODE_PAGE_FLIP_EVENT; + /* Recreate the GBM / EGL surfaces if the display mode has changed */ + if (windata->egl_surface_dirty) { + KMSDRM_CreateSurfaces(_this, window); + } + /* Wait for confirmation that the next front buffer has been flipped, at which point the previous front buffer can be released */ if (!KMSDRM_WaitPageflip(_this, windata)) { @@ -136,64 +141,58 @@ KMSDRM_GLES_SwapWindow(_THIS, SDL_Window * window) { return 0; } - /* Do we have a modeset pending? If so, configure the new mode on the CRTC. - Has to be done before next pageflip issues, so the buffer with the - new size is big enough for preventing CRTC from reading out of bounds. */ - if (dispdata->modeset_pending) { - + if (!windata->bo) { + /* On the first swap, immediately present the new front buffer. Before + drmModePageFlip can be used the CRTC has to be configured to use + the current connector and mode with drmModeSetCrtc */ ret = KMSDRM_drmModeSetCrtc(viddata->drm_fd, dispdata->crtc->crtc_id, fb_info->fb_id, 0, 0, &dispdata->connector->connector_id, 1, &dispdata->mode); - dispdata->modeset_pending = SDL_FALSE; - if (ret) { SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not set videomode on CRTC."); return 0; } - - /* It's OK to return now if we have done a drmModeSetCrtc(), - it has done the pageflip and blocked until it was done. */ - return 1; - } - - /* Issue pageflip on the next front buffer. - Remember: drmModePageFlip() never blocks, it just issues the flip, - which will be done during the next vblank, or immediately if - we pass the DRM_MODE_PAGE_FLIP_ASYNC flag. - Since calling drmModePageFlip() will return EBUSY if we call it - without having completed the last issued flip, we must pass the - DRM_MODE_PAGE_FLIP_ASYNC if we don't block on EGL (egl_swapinterval = 0). - That makes it flip immediately, without waiting for the next vblank - to do so, so even if we don't block on EGL, the flip will have completed - when we get here again. */ - - if (_this->egl_data->egl_swapinterval == 0 && viddata->async_pageflip_support) { - flip_flags |= DRM_MODE_PAGE_FLIP_ASYNC; - } - - ret = KMSDRM_drmModePageFlip(viddata->drm_fd, dispdata->crtc->crtc_id, - fb_info->fb_id, flip_flags, &windata->waiting_for_flip); - - if (ret == 0) { - windata->waiting_for_flip = SDL_TRUE; } else { - SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not queue pageflip: %d", ret); - } + /* On subsequent swaps, queue the new front buffer to be flipped during + the next vertical blank - /* Wait immediately for vsync (as if we only had two buffers). - Even if we are already doing a WaitPageflip at the begining of this - function, this is NOT redundant because here we wait immediately - after submitting the image to the screen, reducing lag, and if - we have waited here, there won't be a pending pageflip so the - WaitPageflip at the beggining of this function will be a no-op. - Just leave it here and don't worry. - Run your SDL2 program with "SDL_KMSDRM_DOUBLE_BUFFER=1 " - to enable this. */ - if (windata->double_buffer) { - if (!KMSDRM_WaitPageflip(_this, windata)) { - SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Immediate wait for previous pageflip failed"); - return 0; + Remember: drmModePageFlip() never blocks, it just issues the flip, + which will be done during the next vblank, or immediately if + we pass the DRM_MODE_PAGE_FLIP_ASYNC flag. + Since calling drmModePageFlip() will return EBUSY if we call it + without having completed the last issued flip, we must pass the + DRM_MODE_PAGE_FLIP_ASYNC if we don't block on EGL (egl_swapinterval = 0). + That makes it flip immediately, without waiting for the next vblank + to do so, so even if we don't block on EGL, the flip will have completed + when we get here again. */ + if (_this->egl_data->egl_swapinterval == 0 && viddata->async_pageflip_support) { + flip_flags |= DRM_MODE_PAGE_FLIP_ASYNC; + } + + ret = KMSDRM_drmModePageFlip(viddata->drm_fd, dispdata->crtc->crtc_id, + fb_info->fb_id, flip_flags, &windata->waiting_for_flip); + + if (ret == 0) { + windata->waiting_for_flip = SDL_TRUE; + } else { + SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Could not queue pageflip: %d", ret); + } + + /* Wait immediately for vsync (as if we only had two buffers). + Even if we are already doing a WaitPageflip at the begining of this + function, this is NOT redundant because here we wait immediately + after submitting the image to the screen, reducing lag, and if + we have waited here, there won't be a pending pageflip so the + WaitPageflip at the beggining of this function will be a no-op. + Just leave it here and don't worry. + Run your SDL2 program with "SDL_KMSDRM_DOUBLE_BUFFER=1 " + to enable this. */ + if (windata->double_buffer) { + if (!KMSDRM_WaitPageflip(_this, windata)) { + SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Immediate wait for previous pageflip failed"); + return 0; + } } } diff --git a/externals/SDL/src/video/kmsdrm/SDL_kmsdrmvideo.c b/externals/SDL/src/video/kmsdrm/SDL_kmsdrmvideo.c index ee8451fa6..56c5ef972 100755 --- a/externals/SDL/src/video/kmsdrm/SDL_kmsdrmvideo.c +++ b/externals/SDL/src/video/kmsdrm/SDL_kmsdrmvideo.c @@ -551,7 +551,6 @@ void KMSDRM_AddDisplay (_THIS, drmModeConnector *connector, drmModeRes *resource /* Initialize some of the members of the new display's driverdata to sane values. */ - dispdata->modeset_pending = SDL_FALSE; dispdata->cursor_bo = NULL; /* Since we create and show the default cursor on KMSDRM_InitMouse(), @@ -907,6 +906,7 @@ KMSDRM_CreateSurfaces(_THIS, SDL_Window * window) { SDL_VideoData *viddata = ((SDL_VideoData *)_this->driverdata); SDL_WindowData *windata = (SDL_WindowData *)window->driverdata; + SDL_DisplayData *dispdata = (SDL_DisplayData *)SDL_GetDisplayForWindow(window)->driverdata; uint32_t surface_fmt = GBM_FORMAT_ARGB8888; uint32_t surface_flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING; @@ -929,7 +929,8 @@ KMSDRM_CreateSurfaces(_THIS, SDL_Window * window) } windata->gs = KMSDRM_gbm_surface_create(viddata->gbm_dev, - windata->surface_w, windata->surface_h, surface_fmt, surface_flags); + dispdata->mode.hdisplay, dispdata->mode.vdisplay, + surface_fmt, surface_flags); if (!windata->gs) { return SDL_SetError("Could not create GBM surface"); @@ -951,6 +952,8 @@ KMSDRM_CreateSurfaces(_THIS, SDL_Window * window) egl_context = (EGLContext)SDL_GL_GetCurrentContext(); ret = SDL_EGL_MakeCurrent(_this, windata->egl_surface, egl_context); + windata->egl_surface_dirty = SDL_FALSE; + cleanup: if (ret) { @@ -1069,14 +1072,14 @@ KMSDRM_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode) /* Take note of the new mode to be set, and leave the CRTC modeset pending so it's done in SwapWindow. */ dispdata->mode = conn->modes[modedata->mode_index]; - dispdata->modeset_pending = SDL_TRUE; for (i = 0; i < viddata->num_windows; i++) { SDL_Window *window = viddata->windows[i]; + SDL_WindowData *windata = (SDL_WindowData *)window->driverdata; - if (KMSDRM_CreateSurfaces(_this, window)) { - return -1; - } + /* Can't recreate EGL surfaces right now, need to wait until SwapWindow + so the correct thread-local surface and context state are available */ + windata->egl_surface_dirty = SDL_TRUE; /* Tell app about the window resize */ SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, mode->w, mode->h); @@ -1246,18 +1249,11 @@ KMSDRM_CreateWindow(_THIS, SDL_Window * window) window->windowed.w, window->windowed.h, 0 ); if (mode) { - windata->surface_w = mode->hdisplay; - windata->surface_h = mode->vdisplay; dispdata->mode = *mode; } else { - windata->surface_w = dispdata->original_mode.hdisplay; - windata->surface_h = dispdata->original_mode.vdisplay; dispdata->mode = dispdata->original_mode; } - /* Take note to do the modesettng on the CRTC in SwapWindow. */ - dispdata->modeset_pending = SDL_TRUE; - /* Create the window surfaces with the size we have just chosen. Needs the window diverdata in place. */ if ((ret = KMSDRM_CreateSurfaces(_this, window))) { @@ -1267,7 +1263,7 @@ KMSDRM_CreateWindow(_THIS, SDL_Window * window) /* Tell app about the size we have determined for the window, so SDL pre-scales to that size for us. */ SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, - windata->surface_w, windata->surface_h); + dispdata->mode.hdisplay, dispdata->mode.vdisplay); } /* NON-Vulkan block ends. */ @@ -1310,67 +1306,48 @@ KMSDRM_CreateWindow(_THIS, SDL_Window * window) /* To be used by SetWindowSize() and SetWindowFullscreen(). */ /*****************************************************************************/ void -KMSDRM_ReconfigureWindow( _THIS, SDL_Window * window) { - - SDL_WindowData *windata = (SDL_WindowData *) window->driverdata; +KMSDRM_ReconfigureWindow( _THIS, SDL_Window * window) +{ SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window); SDL_DisplayData *dispdata = display->driverdata; - uint32_t refresh_rate = 0; - if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == - SDL_WINDOW_FULLSCREEN_DESKTOP) + if ((window->flags & SDL_WINDOW_FULLSCREEN) == + SDL_WINDOW_FULLSCREEN) + { + /* Nothing to do, honor the most recent mode requested by the user */ + } + else if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == + SDL_WINDOW_FULLSCREEN_DESKTOP) { - /* Update the current mode to the desktop mode. */ - windata->surface_w = dispdata->original_mode.hdisplay; - windata->surface_h = dispdata->original_mode.vdisplay; dispdata->mode = dispdata->original_mode; - } else { - drmModeModeInfo *mode; - /* Refresh rate is only important for fullscreen windows. */ - if ((window->flags & SDL_WINDOW_FULLSCREEN) == - SDL_WINDOW_FULLSCREEN) - { - refresh_rate = (uint32_t)window->fullscreen_mode.refresh_rate; - } - /* Try to find a valid video mode matching the size of the window. */ mode = KMSDRM_GetClosestDisplayMode(display, - window->windowed.w, window->windowed.h, refresh_rate ); + window->windowed.w, window->windowed.h, 0); if (mode) { /* If matching mode found, recreate the GBM surface with the size of that mode and configure it on the CRTC. */ - windata->surface_w = mode->hdisplay; - windata->surface_h = mode->vdisplay; dispdata->mode = *mode; } else { /* If not matching mode found, recreate the GBM surfaces with the size of the mode that was originally configured on the CRTC, and setup that mode on the CRTC. */ - windata->surface_w = dispdata->original_mode.hdisplay; - windata->surface_h = dispdata->original_mode.vdisplay; dispdata->mode = dispdata->original_mode; } - - /* Tell app about the size we have determined for the window, - so SDL pre-scales to that size for us. */ - SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, - windata->surface_w, windata->surface_h); } /* Recreate the GBM (and EGL) surfaces, and mark the CRTC mode/fb setting as pending so it's done on SwapWindow. */ KMSDRM_CreateSurfaces(_this, window); - dispdata->modeset_pending = SDL_TRUE; /* Tell app about the size we have determined for the window, so SDL pre-scales to that size for us. */ SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED, - windata->surface_w, windata->surface_h); + dispdata->mode.hdisplay, dispdata->mode.vdisplay); } int diff --git a/externals/SDL/src/video/kmsdrm/SDL_kmsdrmvideo.h b/externals/SDL/src/video/kmsdrm/SDL_kmsdrmvideo.h index 1006ee99c..c82a849df 100755 --- a/externals/SDL/src/video/kmsdrm/SDL_kmsdrmvideo.h +++ b/externals/SDL/src/video/kmsdrm/SDL_kmsdrmvideo.h @@ -80,8 +80,6 @@ typedef struct SDL_DisplayData uint64_t cursor_w, cursor_h; SDL_bool default_cursor_init; - SDL_bool modeset_pending; - } SDL_DisplayData; typedef struct SDL_WindowData @@ -99,13 +97,7 @@ typedef struct SDL_WindowData SDL_bool double_buffer; EGLSurface egl_surface; - - /* The size we chose for the GBM surface. REMEMBER that the CRTC must always have - a mode with the same size configured before trying to flip to a buffer of that - surface or drmModePageFlip() will return -28. */ - uint32_t surface_w; - uint32_t surface_h; - + SDL_bool egl_surface_dirty; } SDL_WindowData; typedef struct KMSDRM_FBInfo diff --git a/externals/SDL/src/video/wayland/SDL_waylandvideo.c b/externals/SDL/src/video/wayland/SDL_waylandvideo.c index 759e0b16a..7503d81c8 100755 --- a/externals/SDL/src/video/wayland/SDL_waylandvideo.c +++ b/externals/SDL/src/video/wayland/SDL_waylandvideo.c @@ -51,6 +51,7 @@ #include "xdg-decoration-unstable-v1-client-protocol.h" #include "keyboard-shortcuts-inhibit-unstable-v1-client-protocol.h" #include "idle-inhibit-unstable-v1-client-protocol.h" +#include "xdg-activation-v1-client-protocol.h" #define WAYLANDVID_DRIVER_NAME "wayland" @@ -199,6 +200,7 @@ Wayland_CreateDevice(int devindex) device->CreateSDLWindow = Wayland_CreateWindow; device->ShowWindow = Wayland_ShowWindow; device->HideWindow = Wayland_HideWindow; + device->RaiseWindow = Wayland_RaiseWindow; device->SetWindowFullscreen = Wayland_SetWindowFullscreen; device->MaximizeWindow = Wayland_MaximizeWindow; device->MinimizeWindow = Wayland_MinimizeWindow; @@ -214,6 +216,7 @@ Wayland_CreateDevice(int devindex) device->SetWindowTitle = Wayland_SetWindowTitle; device->DestroyWindow = Wayland_DestroyWindow; device->SetWindowHitTest = Wayland_SetWindowHitTest; + device->FlashWindow = Wayland_FlashWindow; device->SetClipboardText = Wayland_SetClipboardText; device->GetClipboardText = Wayland_GetClipboardText; @@ -463,6 +466,8 @@ display_handle_global(void *data, struct wl_registry *registry, uint32_t id, d->key_inhibitor_manager = wl_registry_bind(d->registry, id, &zwp_keyboard_shortcuts_inhibit_manager_v1_interface, 1); } else if (strcmp(interface, "zwp_idle_inhibit_manager_v1") == 0) { d->idle_inhibit_manager = wl_registry_bind(d->registry, id, &zwp_idle_inhibit_manager_v1_interface, 1); + } else if (strcmp(interface, "xdg_activation_v1") == 0) { + d->activation_manager = wl_registry_bind(d->registry, id, &xdg_activation_v1_interface, 1); } else if (strcmp(interface, "wl_data_device_manager") == 0) { Wayland_add_data_device_manager(d, id, version); } else if (strcmp(interface, "zxdg_decoration_manager_v1") == 0) { @@ -583,6 +588,9 @@ Wayland_VideoQuit(_THIS) Wayland_display_destroy_pointer_constraints(data); Wayland_display_destroy_relative_pointer_manager(data); + if (data->activation_manager) + xdg_activation_v1_destroy(data->activation_manager); + if (data->idle_inhibit_manager) zwp_idle_inhibit_manager_v1_destroy(data->idle_inhibit_manager); diff --git a/externals/SDL/src/video/wayland/SDL_waylandvideo.h b/externals/SDL/src/video/wayland/SDL_waylandvideo.h index 930ccf54b..0c6957f00 100755 --- a/externals/SDL/src/video/wayland/SDL_waylandvideo.h +++ b/externals/SDL/src/video/wayland/SDL_waylandvideo.h @@ -69,6 +69,7 @@ typedef struct { struct zxdg_decoration_manager_v1 *decoration_manager; struct zwp_keyboard_shortcuts_inhibit_manager_v1 *key_inhibitor_manager; struct zwp_idle_inhibit_manager_v1 *idle_inhibit_manager; + struct xdg_activation_v1 *activation_manager; EGLDisplay edpy; EGLContext context; diff --git a/externals/SDL/src/video/wayland/SDL_waylandwindow.c b/externals/SDL/src/video/wayland/SDL_waylandwindow.c index 54502308c..35ee3a207 100755 --- a/externals/SDL/src/video/wayland/SDL_waylandwindow.c +++ b/externals/SDL/src/video/wayland/SDL_waylandwindow.c @@ -37,6 +37,7 @@ #include "xdg-shell-unstable-v6-client-protocol.h" #include "xdg-decoration-unstable-v1-client-protocol.h" #include "idle-inhibit-unstable-v1-client-protocol.h" +#include "xdg-activation-v1-client-protocol.h" static float get_window_scale_factor(SDL_Window *window) { return ((SDL_WindowData*)window->driverdata)->scale_factor; @@ -272,9 +273,12 @@ handle_configure_zxdg_toplevel(void *data, enum zxdg_toplevel_v6_state *state; SDL_bool fullscreen = SDL_FALSE; + SDL_bool maximized = SDL_FALSE; wl_array_for_each(state, states) { if (*state == ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN) { fullscreen = SDL_TRUE; + } else if (*state == ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED) { + maximized = SDL_TRUE; } } @@ -283,6 +287,7 @@ handle_configure_zxdg_toplevel(void *data, /* We might need to re-enter fullscreen after being restored from minimized */ SDL_WaylandOutputData *driverdata = (SDL_WaylandOutputData *) SDL_GetDisplayForWindow(window)->driverdata; SetFullscreen(window, driverdata->output); + fullscreen = SDL_TRUE; } if (width == 0 || height == 0) { @@ -310,6 +315,19 @@ handle_configure_zxdg_toplevel(void *data, } } + /* Always send a maximized/restore event; if the event is redundant it will + * automatically be discarded (see src/events/SDL_windowevents.c). + * + * No, we do not get minimize events from zxdg-shell. + */ + if (!fullscreen) { + SDL_SendWindowEvent(window, + maximized ? + SDL_WINDOWEVENT_MAXIMIZED : + SDL_WINDOWEVENT_RESTORED, + 0, 0); + } + if (width == 0 || height == 0) { wind->resize.width = window->w; wind->resize.height = window->h; @@ -388,9 +406,12 @@ handle_configure_xdg_toplevel(void *data, enum xdg_toplevel_state *state; SDL_bool fullscreen = SDL_FALSE; + SDL_bool maximized = SDL_FALSE; wl_array_for_each(state, states) { if (*state == XDG_TOPLEVEL_STATE_FULLSCREEN) { fullscreen = SDL_TRUE; + } else if (*state == XDG_TOPLEVEL_STATE_MAXIMIZED) { + maximized = SDL_TRUE; } } @@ -399,6 +420,7 @@ handle_configure_xdg_toplevel(void *data, /* We might need to re-enter fullscreen after being restored from minimized */ SDL_WaylandOutputData *driverdata = (SDL_WaylandOutputData *) SDL_GetDisplayForWindow(window)->driverdata; SetFullscreen(window, driverdata->output); + fullscreen = SDL_TRUE; } if (width == 0 || height == 0) { @@ -426,6 +448,19 @@ handle_configure_xdg_toplevel(void *data, } } + /* Always send a maximized/restore event; if the event is redundant it will + * automatically be discarded (see src/events/SDL_windowevents.c) + * + * No, we do not get minimize events from xdg-shell. + */ + if (!fullscreen) { + SDL_SendWindowEvent(window, + maximized ? + SDL_WINDOWEVENT_MAXIMIZED : + SDL_WINDOWEVENT_RESTORED, + 0, 0); + } + if (width == 0 || height == 0) { wind->resize.width = window->w; wind->resize.height = window->h; @@ -682,11 +717,6 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window) data->shell_surface.xdg.roleobj.toplevel = xdg_surface_get_toplevel(data->shell_surface.xdg.surface); xdg_toplevel_set_app_id(data->shell_surface.xdg.roleobj.toplevel, c->classname); xdg_toplevel_add_listener(data->shell_surface.xdg.roleobj.toplevel, &toplevel_listener_xdg, data); - - /* Create the window decorations */ - if (c->decoration_manager) { - data->server_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(c->decoration_manager, data->shell_surface.xdg.roleobj.toplevel); - } } else if (c->shell.zxdg) { data->shell_surface.zxdg.surface = zxdg_shell_v6_get_xdg_surface(c->shell.zxdg, data->surface); zxdg_surface_v6_set_user_data(data->shell_surface.zxdg.surface, data); @@ -705,7 +735,6 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window) /* Restore state that was set prior to this call */ Wayland_SetWindowTitle(_this, window); - Wayland_SetWindowBordered(_this, window, (window->flags & SDL_WINDOW_BORDERLESS) == 0); if (window->flags & SDL_WINDOW_MAXIMIZED) { Wayland_MaximizeWindow(_this, window); } @@ -724,6 +753,11 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window) WAYLAND_wl_display_dispatch(c->display); } } + + /* Create the window decorations */ + if (data->shell_surface.xdg.roleobj.toplevel && c->decoration_manager) { + data->server_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(c->decoration_manager, data->shell_surface.xdg.roleobj.toplevel); + } } else if (c->shell.zxdg) { if (data->shell_surface.zxdg.surface) { while (!data->shell_surface.zxdg.initial_configure_seen) { @@ -732,6 +766,31 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window) } } } + + /* Unlike the rest of window state we have to set this _after_ flushing the + * display, because we need to create the decorations before possibly hiding + * them immediately afterward. But don't call it redundantly, the protocol + * may not interpret a redundant call nicely and cause weird stuff to happen + */ + if (window->flags & SDL_WINDOW_BORDERLESS) { + Wayland_SetWindowBordered(_this, window, SDL_FALSE); + } + + /* We're finally done putting the window together, raise if possible */ + if (c->activation_manager) { + /* Note that we don't check for empty strings, as that is still + * considered a valid activation token! + */ + const char *activation_token = SDL_getenv("XDG_ACTIVATION_TOKEN"); + if (activation_token) { + xdg_activation_v1_activate(c->activation_manager, + activation_token, + data->surface); + + /* Clear this variable, per the protocol's request */ + unsetenv("XDG_ACTIVATION_TOKEN"); + } + } } void Wayland_HideWindow(_THIS, SDL_Window *window) @@ -770,6 +829,107 @@ void Wayland_HideWindow(_THIS, SDL_Window *window) } } +static void +handle_xdg_activation_done(void *data, + struct xdg_activation_token_v1 *xdg_activation_token_v1, + const char *token) +{ + SDL_WindowData *window = data; + if (xdg_activation_token_v1 == window->activation_token) { + xdg_activation_v1_activate(window->waylandData->activation_manager, + token, + window->surface); + xdg_activation_token_v1_destroy(window->activation_token); + window->activation_token = NULL; + } +} + +static const struct xdg_activation_token_v1_listener activation_listener_xdg = { + handle_xdg_activation_done +}; + +/* The xdg-activation protocol considers "activation" to be one of two things: + * + * 1: Raising a window to the top and flashing the titlebar + * 2: Flashing the titlebar while keeping the window where it is + * + * As you might expect from Wayland, the general policy is to go with #2 unless + * the client can prove to the compositor beyond a reasonable doubt that raising + * the window will not be malicuous behavior. + * + * For SDL this means RaiseWindow and FlashWindow both use the same protocol, + * but in different ways: RaiseWindow will provide as _much_ information as + * possible while FlashWindow will provide as _little_ information as possible, + * to nudge the compositor into doing what we want. + * + * This isn't _strictly_ what the protocol says will happen, but this is what + * current implementations are doing (as of writing, YMMV in the far distant + * future). + * + * -flibit + */ +static void +Wayland_activate_window(SDL_VideoData *data, SDL_WindowData *wind, + struct wl_surface *surface, + uint32_t serial, struct wl_seat *seat) +{ + if (data->activation_manager) { + if (wind->activation_token != NULL) { + /* We're about to overwrite this with a new request */ + xdg_activation_token_v1_destroy(wind->activation_token); + } + + wind->activation_token = xdg_activation_v1_get_activation_token(data->activation_manager); + xdg_activation_token_v1_add_listener(wind->activation_token, + &activation_listener_xdg, + wind); + + /* Note that we are not setting the app_id or serial here. + * + * Hypothetically we could set the app_id from data->classname, but + * that part of the API is for _external_ programs, not ourselves. + * + * -flibit + */ + if (surface != NULL) { + xdg_activation_token_v1_set_surface(wind->activation_token, surface); + } + if (seat != NULL) { + xdg_activation_token_v1_set_serial(wind->activation_token, serial, seat); + } + xdg_activation_token_v1_commit(wind->activation_token); + } +} + +void +Wayland_RaiseWindow(_THIS, SDL_Window *window) +{ + SDL_WindowData *wind = window->driverdata; + + /* FIXME: This Raise event is arbitrary and doesn't come from an event, so + * it's actually very likely that this token will be ignored! Maybe add + * support for passing serials (and the associated seat) so this can have + * a better chance of actually raising the window. + * -flibit + */ + Wayland_activate_window(_this->driverdata, + wind, + wind->surface, + 0, + NULL); +} + +int +Wayland_FlashWindow(_THIS, SDL_Window *window, Uint32 flash_count) +{ + Wayland_activate_window(_this->driverdata, + window->driverdata, + NULL, + 0, + NULL); + return 0; +} + #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH static void SDLCALL QtExtendedSurface_OnHintChanged(void *userdata, const char *name, @@ -1235,6 +1395,10 @@ void Wayland_DestroyWindow(_THIS, SDL_Window *window) zwp_idle_inhibitor_v1_destroy(wind->idle_inhibitor); } + if (wind->activation_token) { + xdg_activation_token_v1_destroy(wind->activation_token); + } + SDL_free(wind->outputs); if (wind->frame_callback) { diff --git a/externals/SDL/src/video/wayland/SDL_waylandwindow.h b/externals/SDL/src/video/wayland/SDL_waylandwindow.h index 4aa1040d6..320fd3e51 100755 --- a/externals/SDL/src/video/wayland/SDL_waylandwindow.h +++ b/externals/SDL/src/video/wayland/SDL_waylandwindow.h @@ -67,6 +67,7 @@ typedef struct { struct zxdg_toplevel_decoration_v1 *server_decoration; struct zwp_keyboard_shortcuts_inhibitor_v1 *key_inhibitor; struct zwp_idle_inhibitor_v1 *idle_inhibitor; + struct xdg_activation_token_v1 *activation_token; SDL_atomic_t swap_interval_ready; @@ -89,6 +90,7 @@ typedef struct { extern void Wayland_ShowWindow(_THIS, SDL_Window *window); extern void Wayland_HideWindow(_THIS, SDL_Window *window); +extern void Wayland_RaiseWindow(_THIS, SDL_Window *window); extern void Wayland_SetWindowFullscreen(_THIS, SDL_Window * window, SDL_VideoDisplay * _display, SDL_bool fullscreen); @@ -111,6 +113,7 @@ extern void Wayland_SuspendScreenSaver(_THIS); extern SDL_bool Wayland_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info); extern int Wayland_SetWindowHitTest(SDL_Window *window, SDL_bool enabled); +extern int Wayland_FlashWindow(_THIS, SDL_Window * window, Uint32 flash_count); extern void Wayland_HandlePendingResize(SDL_Window *window); diff --git a/externals/SDL/src/video/windows/SDL_windowsevents.c b/externals/SDL/src/video/windows/SDL_windowsevents.c index 0fbe012aa..2d47759f0 100755 --- a/externals/SDL/src/video/windows/SDL_windowsevents.c +++ b/externals/SDL/src/video/windows/SDL_windowsevents.c @@ -428,6 +428,23 @@ static SDL_MOUSE_EVENT_SOURCE GetMouseMessageSource() return SDL_MOUSE_EVENT_SOURCE_MOUSE; } +static SDL_WindowData * +WIN_GetWindowDataFromHWND(HWND hwnd) +{ + SDL_VideoDevice *_this = SDL_GetVideoDevice(); + SDL_Window *window; + + if (_this) { + for (window = _this->windows; window; window = window->next) { + SDL_WindowData *data = (SDL_WindowData *)window->driverdata; + if (data && data->hwnd == hwnd) { + return data; + } + } + } + return NULL; +} + LRESULT CALLBACK WIN_KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam) { @@ -510,7 +527,11 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) } /* Get the window data for the window */ - data = (SDL_WindowData *) GetProp(hwnd, TEXT("SDL_WindowData")); + data = WIN_GetWindowDataFromHWND(hwnd); + if (!data) { + /* Fallback */ + data = (SDL_WindowData *) GetProp(hwnd, TEXT("SDL_WindowData")); + } if (!data) { return CallWindowProc(DefWindowProc, hwnd, msg, wParam, lParam); } @@ -693,8 +714,8 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) /* Mouse data (ignoring synthetic mouse events generated for touchscreens) */ if (inp.header.dwType == RIM_TYPEMOUSE) { - if (GetMouseMessageSource() == SDL_MOUSE_EVENT_SOURCE_TOUCH || - (GetMessageExtraInfo() & 0x82) == 0x82) { + if (SDL_GetNumTouchDevices() > 0 && + (GetMouseMessageSource() == SDL_MOUSE_EVENT_SOURCE_TOUCH || (GetMessageExtraInfo() & 0x82) == 0x82)) { break; } if (isRelative) { @@ -1255,6 +1276,49 @@ void SDL_SetWindowsMessageHook(SDL_WindowsMessageHook callback, void *userdata) g_WindowsMessageHookData = userdata; } +int +WIN_WaitEventTimeout(_THIS, int timeout) +{ + MSG msg; + if (g_WindowsEnableMessageLoop) { + BOOL message_result; + UINT_PTR timer_id = 0; + if (timeout > 0) { + timer_id = SetTimer(NULL, 0, timeout, NULL); + message_result = GetMessage(&msg, 0, 0, 0); + KillTimer(NULL, timer_id); + } else if (timeout == 0) { + message_result = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE); + } else { + message_result = GetMessage(&msg, 0, 0, 0); + } + if (message_result) { + if (msg.message == WM_TIMER && msg.hwnd == NULL && msg.wParam == timer_id) { + return 0; + } + if (g_WindowsMessageHook) { + g_WindowsMessageHook(g_WindowsMessageHookData, msg.hwnd, msg.message, msg.wParam, msg.lParam); + } + /* Always translate the message in case it's a non-SDL window (e.g. with Qt integration) */ + TranslateMessage(&msg); + DispatchMessage(&msg); + return 1; + } else { + return 0; + } + } else { + /* Fail the wait so the caller falls back to polling */ + return -1; + } +} + +void +WIN_SendWakeupEvent(_THIS, SDL_Window *window) +{ + SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + PostMessage(data->hwnd, data->videodata->_SDL_WAKEUP, 0, 0); +} + void WIN_PumpEvents(_THIS) { diff --git a/externals/SDL/src/video/windows/SDL_windowsevents.h b/externals/SDL/src/video/windows/SDL_windowsevents.h index fcd716dcf..93b41e4dc 100755 --- a/externals/SDL/src/video/windows/SDL_windowsevents.h +++ b/externals/SDL/src/video/windows/SDL_windowsevents.h @@ -31,6 +31,8 @@ extern LRESULT CALLBACK WIN_KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lP extern LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); extern void WIN_PumpEvents(_THIS); +extern void WIN_SendWakeupEvent(_THIS, SDL_Window *window); +extern int WIN_WaitEventTimeout(_THIS, int timeout); #endif /* SDL_windowsevents_h_ */ diff --git a/externals/SDL/src/video/windows/SDL_windowsvideo.c b/externals/SDL/src/video/windows/SDL_windowsvideo.c index 8eb32b2ef..a80c20c7a 100755 --- a/externals/SDL/src/video/windows/SDL_windowsvideo.c +++ b/externals/SDL/src/video/windows/SDL_windowsvideo.c @@ -87,7 +87,9 @@ WIN_DeleteDevice(SDL_VideoDevice * device) if (data->shcoreDLL) { SDL_UnloadObject(data->shcoreDLL); } - + if (device->wakeup_lock) { + SDL_DestroyMutex(device->wakeup_lock); + } SDL_free(device->driverdata); SDL_free(device); } @@ -113,6 +115,7 @@ WIN_CreateDevice(int devindex) return NULL; } device->driverdata = data; + device->wakeup_lock = SDL_CreateMutex(); data->userDLL = SDL_LoadObject("USER32.DLL"); if (data->userDLL) { @@ -139,6 +142,8 @@ WIN_CreateDevice(int devindex) device->GetDisplayModes = WIN_GetDisplayModes; device->SetDisplayMode = WIN_SetDisplayMode; device->PumpEvents = WIN_PumpEvents; + device->WaitEventTimeout = WIN_WaitEventTimeout; + device->SendWakeupEvent = WIN_SendWakeupEvent; device->SuspendScreenSaver = WIN_SuspendScreenSaver; device->CreateSDLWindow = WIN_CreateWindow; @@ -171,6 +176,7 @@ WIN_CreateDevice(int devindex) device->OnWindowEnter = WIN_OnWindowEnter; device->SetWindowHitTest = WIN_SetWindowHitTest; device->AcceptDragAndDrop = WIN_AcceptDragAndDrop; + device->FlashWindow = WIN_FlashWindow; device->shape_driver.CreateShaper = Win32_CreateShaper; device->shape_driver.SetWindowShape = Win32_SetWindowShape; @@ -226,6 +232,8 @@ VideoBootStrap WINDOWS_bootstrap = { int WIN_VideoInit(_THIS) { + SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; + if (WIN_InitModes(_this) < 0) { return -1; } @@ -236,6 +244,8 @@ WIN_VideoInit(_THIS) SDL_AddHintCallback(SDL_HINT_WINDOWS_ENABLE_MESSAGELOOP, UpdateWindowsEnableMessageLoop, NULL); SDL_AddHintCallback(SDL_HINT_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN, UpdateWindowFrameUsableWhileCursorHidden, NULL); + data->_SDL_WAKEUP = RegisterWindowMessageA("_SDL_WAKEUP"); + return 0; } diff --git a/externals/SDL/src/video/windows/SDL_windowsvideo.h b/externals/SDL/src/video/windows/SDL_windowsvideo.h index c7c4caaf2..5f4bd4a6c 100755 --- a/externals/SDL/src/video/windows/SDL_windowsvideo.h +++ b/externals/SDL/src/video/windows/SDL_windowsvideo.h @@ -190,6 +190,7 @@ typedef struct SDL_VideoData TSFSink *ime_ippasink; BYTE pre_hook_key_state[256]; + UINT _SDL_WAKEUP; } SDL_VideoData; extern SDL_bool g_WindowsEnableMessageLoop; diff --git a/externals/SDL/src/video/windows/SDL_windowswindow.c b/externals/SDL/src/video/windows/SDL_windowswindow.c index 51d0c1111..16401a57b 100755 --- a/externals/SDL/src/video/windows/SDL_windowswindow.c +++ b/externals/SDL/src/video/windows/SDL_windowswindow.c @@ -1084,6 +1084,24 @@ WIN_AcceptDragAndDrop(SDL_Window * window, SDL_bool accept) DragAcceptFiles(data->hwnd, accept ? TRUE : FALSE); } +int +WIN_FlashWindow(_THIS, SDL_Window * window, Uint32 flash_count) +{ + HWND hwnd; + FLASHWINFO desc; + + hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; + desc.cbSize = sizeof(desc); + desc.hwnd = hwnd; + desc.dwFlags = FLASHW_TRAY; + desc.uCount = flash_count; /* flash x times */ + desc.dwTimeout = 0; + + FlashWindowEx(&desc); + + return 0; +} + #endif /* SDL_VIDEO_DRIVER_WINDOWS */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/externals/SDL/src/video/windows/SDL_windowswindow.h b/externals/SDL/src/video/windows/SDL_windowswindow.h index fe7f825ff..1e8f3d318 100755 --- a/externals/SDL/src/video/windows/SDL_windowswindow.h +++ b/externals/SDL/src/video/windows/SDL_windowswindow.h @@ -86,6 +86,7 @@ extern void WIN_OnWindowEnter(_THIS, SDL_Window * window); extern void WIN_UpdateClipCursor(SDL_Window *window); extern int WIN_SetWindowHitTest(SDL_Window *window, SDL_bool enabled); extern void WIN_AcceptDragAndDrop(SDL_Window * window, SDL_bool accept); +extern int WIN_FlashWindow(_THIS, SDL_Window * window, Uint32 flash_count); #endif /* SDL_windowswindow_h_ */ diff --git a/externals/SDL/src/video/winrt/SDL_winrtevents_c.h b/externals/SDL/src/video/winrt/SDL_winrtevents_c.h index 910dc6a64..a95e9656a 100755 --- a/externals/SDL/src/video/winrt/SDL_winrtevents_c.h +++ b/externals/SDL/src/video/winrt/SDL_winrtevents_c.h @@ -53,7 +53,7 @@ typedef enum { extern Windows::Foundation::Point WINRT_TransformCursorPosition(SDL_Window * window, Windows::Foundation::Point rawPosition, WINRT_CursorNormalizationType normalization); -extern Uint8 WINRT_GetSDLButtonForPointerPoint(Windows::UI::Input::PointerPoint ^pt); +extern SDL_bool WINRT_GetSDLButtonForPointerPoint(Windows::UI::Input::PointerPoint ^pt, Uint8 *button, Uint8 *pressed); extern void WINRT_ProcessPointerPressedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint); extern void WINRT_ProcessPointerMovedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint); extern void WINRT_ProcessPointerReleasedEvent(SDL_Window *window, Windows::UI::Input::PointerPoint ^pointerPoint); diff --git a/externals/SDL/src/video/winrt/SDL_winrtpointerinput.cpp b/externals/SDL/src/video/winrt/SDL_winrtpointerinput.cpp index 6959be71d..1639083f0 100755 --- a/externals/SDL/src/video/winrt/SDL_winrtpointerinput.cpp +++ b/externals/SDL/src/video/winrt/SDL_winrtpointerinput.cpp @@ -116,8 +116,8 @@ WINRT_TransformCursorPosition(SDL_Window * window, return outputPosition; } -Uint8 -WINRT_GetSDLButtonForPointerPoint(Windows::UI::Input::PointerPoint ^pt) +SDL_bool +WINRT_GetSDLButtonForPointerPoint(Windows::UI::Input::PointerPoint ^pt, Uint8 *button, Uint8 *pressed) { using namespace Windows::UI::Input; @@ -128,30 +128,42 @@ WINRT_GetSDLButtonForPointerPoint(Windows::UI::Input::PointerPoint ^pt) { case PointerUpdateKind::LeftButtonPressed: case PointerUpdateKind::LeftButtonReleased: - return SDL_BUTTON_LEFT; + *button = SDL_BUTTON_LEFT; + *pressed = (pt->Properties->PointerUpdateKind == PointerUpdateKind::LeftButtonPressed); + return SDL_TRUE; case PointerUpdateKind::RightButtonPressed: case PointerUpdateKind::RightButtonReleased: - return SDL_BUTTON_RIGHT; + *button = SDL_BUTTON_RIGHT; + *pressed = (pt->Properties->PointerUpdateKind == PointerUpdateKind::RightButtonPressed); + return SDL_TRUE; case PointerUpdateKind::MiddleButtonPressed: case PointerUpdateKind::MiddleButtonReleased: - return SDL_BUTTON_MIDDLE; + *button = SDL_BUTTON_MIDDLE; + *pressed = (pt->Properties->PointerUpdateKind == PointerUpdateKind::MiddleButtonPressed); + return SDL_TRUE; case PointerUpdateKind::XButton1Pressed: case PointerUpdateKind::XButton1Released: - return SDL_BUTTON_X1; + *button = SDL_BUTTON_X1; + *pressed = (pt->Properties->PointerUpdateKind == PointerUpdateKind::XButton1Pressed); + return SDL_TRUE; case PointerUpdateKind::XButton2Pressed: case PointerUpdateKind::XButton2Released: - return SDL_BUTTON_X2; + *button = SDL_BUTTON_X2; + *pressed = (pt->Properties->PointerUpdateKind == PointerUpdateKind::XButton2Pressed); + return SDL_TRUE; default: break; } #endif - return 0; + *button = 0; + *pressed = 0; + return SDL_FALSE; } //const char * @@ -211,9 +223,10 @@ void WINRT_ProcessPointerPressedEvent(SDL_Window *window, Windows::UI::Input::Po return; } - Uint8 button = WINRT_GetSDLButtonForPointerPoint(pointerPoint); - if ( ! WINRT_IsTouchEvent(pointerPoint)) { + Uint8 button, pressed; + WINRT_GetSDLButtonForPointerPoint(pointerPoint, &button, &pressed); + SDL_assert(pressed == 1); SDL_SendMouseButton(window, 0, SDL_PRESSED, button); } else { Windows::Foundation::Point normalizedPoint = WINRT_TransformCursorPosition(window, pointerPoint->Position, NormalizeZeroToOne); @@ -241,6 +254,12 @@ WINRT_ProcessPointerMovedEvent(SDL_Window *window, Windows::UI::Input::PointerPo Windows::Foundation::Point windowPoint = WINRT_TransformCursorPosition(window, pointerPoint->Position, TransformToSDLWindowSize); if ( ! WINRT_IsTouchEvent(pointerPoint)) { + /* For some odd reason Moved events are used for multiple mouse buttons */ + Uint8 button, pressed; + if (WINRT_GetSDLButtonForPointerPoint(pointerPoint, &button, &pressed)) { + SDL_SendMouseButton(window, 0, pressed, button); + } + SDL_SendMouseMotion(window, 0, 0, (int)windowPoint.X, (int)windowPoint.Y); } else { SDL_SendTouchMotion( @@ -259,9 +278,10 @@ void WINRT_ProcessPointerReleasedEvent(SDL_Window *window, Windows::UI::Input::P return; } - Uint8 button = WINRT_GetSDLButtonForPointerPoint(pointerPoint); - if (!WINRT_IsTouchEvent(pointerPoint)) { + Uint8 button, pressed; + WINRT_GetSDLButtonForPointerPoint(pointerPoint, &button, &pressed); + SDL_assert(pressed == 0); SDL_SendMouseButton(window, 0, SDL_RELEASED, button); } else { Windows::Foundation::Point normalizedPoint = WINRT_TransformCursorPosition(window, pointerPoint->Position, NormalizeZeroToOne); diff --git a/externals/SDL/src/video/x11/SDL_x11events.c b/externals/SDL/src/video/x11/SDL_x11events.c index 37c76c5e9..8c654f23d 100755 --- a/externals/SDL/src/video/x11/SDL_x11events.c +++ b/externals/SDL/src/video/x11/SDL_x11events.c @@ -670,42 +670,35 @@ isReparentNotify(Display *display, XEvent *ev, XPointer arg) } static void -X11_DispatchEvent(_THIS) +X11_DispatchEvent(_THIS, XEvent *xevent) { SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata; + XkbEvent* xkbEvent = (XkbEvent*) xevent; Display *display; SDL_WindowData *data; - XEvent xevent; - XkbEvent* xkbEvent; int orig_event_type; KeyCode orig_keycode; XClientMessageEvent m; int i; - if (!videodata) { - return; - } + SDL_assert(videodata != NULL); display = videodata->display; - SDL_zero(xevent); /* valgrind fix. --ryan. */ - X11_XNextEvent(display, &xevent); - xkbEvent = (XkbEvent*) &xevent; - /* Save the original keycode for dead keys, which are filtered out by the XFilterEvent() call below. */ - orig_event_type = xevent.type; + orig_event_type = xevent->type; if (orig_event_type == KeyPress || orig_event_type == KeyRelease) { - orig_keycode = xevent.xkey.keycode; + orig_keycode = xevent->xkey.keycode; } else { orig_keycode = 0; } /* filter events catchs XIM events and sends them to the correct handler */ - if (X11_XFilterEvent(&xevent, None) == True) { + if (X11_XFilterEvent(xevent, None) == True) { #if 0 printf("Filtered event type = %d display = %d window = %d\n", - xevent.type, xevent.xany.display, xevent.xany.window); + xevent->type, xevent->xany.display, xevent->xany.window); #endif /* Make sure dead key press/release events are sent */ /* But only if we're using one of the DBus IMEs, otherwise @@ -714,7 +707,7 @@ X11_DispatchEvent(_THIS) #if defined(HAVE_IBUS_IBUS_H) || defined(HAVE_FCITX) SDL_Scancode scancode = videodata->key_layout[orig_keycode]; videodata->filter_code = orig_keycode; - videodata->filter_time = xevent.xkey.time; + videodata->filter_time = xevent->xkey.time; if (orig_event_type == KeyPress) { SDL_SendKeyboardKey(SDL_PRESSED, scancode); @@ -727,8 +720,8 @@ X11_DispatchEvent(_THIS) } #if SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS - if(xevent.type == GenericEvent) { - X11_HandleGenericEvent(videodata, &xevent); + if(xevent->type == GenericEvent) { + X11_HandleGenericEvent(videodata, xevent); return; } #endif @@ -739,18 +732,18 @@ X11_DispatchEvent(_THIS) SDL_VERSION(&wmmsg.version); wmmsg.subsystem = SDL_SYSWM_X11; - wmmsg.msg.x11.event = xevent; + wmmsg.msg.x11.event = *xevent; SDL_SendSysWMEvent(&wmmsg); } #if 0 printf("type = %d display = %d window = %d\n", - xevent.type, xevent.xany.display, xevent.xany.window); + xevent->type, xevent->xany.display, xevent->xany.window); #endif if ((videodata->clipboard_window != None) && - (videodata->clipboard_window == xevent.xany.window)) { - X11_HandleClipboardEvent(_this, &xevent); + (videodata->clipboard_window == xevent->xany.window)) { + X11_HandleClipboardEvent(_this, xevent); return; } @@ -758,7 +751,7 @@ X11_DispatchEvent(_THIS) if (videodata && videodata->windowlist) { for (i = 0; i < videodata->numwindows; ++i) { if ((videodata->windowlist[i] != NULL) && - (videodata->windowlist[i]->xwindow == xevent.xany.window)) { + (videodata->windowlist[i]->xwindow == xevent->xany.window)) { data = videodata->windowlist[i]; break; } @@ -766,19 +759,19 @@ X11_DispatchEvent(_THIS) } if (!data) { /* The window for KeymapNotify, etc events is 0 */ - if (xevent.type == KeymapNotify) { + if (xevent->type == KeymapNotify) { if (SDL_GetKeyboardFocus() != NULL) { X11_ReconcileKeyboardState(_this); } - } else if (xevent.type == MappingNotify || xkbEvent->any.xkb_type == XkbStateNotify) { + } else if (xevent->type == MappingNotify || xkbEvent->any.xkb_type == XkbStateNotify) { /* Has the keyboard layout changed? */ - const int request = xevent.xmapping.request; + const int request = xevent->xmapping.request; #ifdef DEBUG_XEVENTS printf("window %p: MappingNotify!\n", data); #endif if ((request == MappingKeyboard) || (request == MappingModifier)) { - X11_XRefreshKeyboardMapping(&xevent.xmapping); + X11_XRefreshKeyboardMapping(&xevent->xmapping); } X11_UpdateKeymap(_this); @@ -787,28 +780,28 @@ X11_DispatchEvent(_THIS) return; } - switch (xevent.type) { + switch (xevent->type) { /* 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, - xevent.xcrossing.y, - xevent.xcrossing.mode); - if (xevent.xcrossing.mode == NotifyGrab) + xevent->xcrossing.x, + xevent->xcrossing.y, + xevent->xcrossing.mode); + if (xevent->xcrossing.mode == NotifyGrab) printf("Mode: NotifyGrab\n"); - if (xevent.xcrossing.mode == NotifyUngrab) + if (xevent->xcrossing.mode == NotifyUngrab) printf("Mode: NotifyUngrab\n"); #endif SDL_SetMouseFocus(data->window); - mouse->last_x = xevent.xcrossing.x; - mouse->last_y = xevent.xcrossing.y; + 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); + SDL_SendMouseMotion(data->window, 0, 0, xevent->xcrossing.x, xevent->xcrossing.y); } /* We ungrab in LeaveNotify, so we may need to grab again here */ @@ -819,21 +812,21 @@ X11_DispatchEvent(_THIS) case LeaveNotify:{ #ifdef DEBUG_XEVENTS printf("window %p: LeaveNotify! (%d,%d,%d)\n", data, - xevent.xcrossing.x, - xevent.xcrossing.y, - xevent.xcrossing.mode); - if (xevent.xcrossing.mode == NotifyGrab) + xevent->xcrossing.x, + xevent->xcrossing.y, + xevent->xcrossing.mode); + if (xevent->xcrossing.mode == NotifyGrab) printf("Mode: NotifyGrab\n"); - if (xevent.xcrossing.mode == NotifyUngrab) + if (xevent->xcrossing.mode == NotifyUngrab) printf("Mode: NotifyUngrab\n"); #endif if (!SDL_GetMouse()->relative_mode) { - SDL_SendMouseMotion(data->window, 0, 0, xevent.xcrossing.x, xevent.xcrossing.y); + SDL_SendMouseMotion(data->window, 0, 0, xevent->xcrossing.x, xevent->xcrossing.y); } - if (xevent.xcrossing.mode != NotifyGrab && - xevent.xcrossing.mode != NotifyUngrab && - xevent.xcrossing.detail != NotifyInferior) { + if (xevent->xcrossing.mode != NotifyGrab && + xevent->xcrossing.mode != NotifyUngrab && + xevent->xcrossing.detail != NotifyInferior) { /* In order for interaction with the window decorations and menu to work properly on Mutter, we need to ungrab the keyboard when the the mouse leaves. */ @@ -848,7 +841,7 @@ X11_DispatchEvent(_THIS) /* Gaining input focus? */ case FocusIn:{ - if (xevent.xfocus.mode == NotifyGrab || xevent.xfocus.mode == NotifyUngrab) { + if (xevent->xfocus.mode == NotifyGrab || xevent->xfocus.mode == NotifyUngrab) { /* Someone is handling a global hotkey, ignore it */ #ifdef DEBUG_XEVENTS printf("window %p: FocusIn (NotifyGrab/NotifyUngrab, ignoring)\n", data); @@ -856,7 +849,7 @@ X11_DispatchEvent(_THIS) break; } - if (xevent.xfocus.detail == NotifyInferior || xevent.xfocus.detail == NotifyPointer) { + if (xevent->xfocus.detail == NotifyInferior || xevent->xfocus.detail == NotifyPointer) { #ifdef DEBUG_XEVENTS printf("window %p: FocusIn (NotifyInferior/NotifyPointer, ignoring)\n", data); #endif @@ -882,14 +875,14 @@ X11_DispatchEvent(_THIS) /* Losing input focus? */ case FocusOut:{ - if (xevent.xfocus.mode == NotifyGrab || xevent.xfocus.mode == NotifyUngrab) { + if (xevent->xfocus.mode == NotifyGrab || xevent->xfocus.mode == NotifyUngrab) { /* Someone is handling a global hotkey, ignore it */ #ifdef DEBUG_XEVENTS printf("window %p: FocusOut (NotifyGrab/NotifyUngrab, ignoring)\n", data); #endif break; } - if (xevent.xfocus.detail == NotifyInferior || xevent.xfocus.detail == NotifyPointer) { + if (xevent->xfocus.detail == NotifyInferior || xevent->xfocus.detail == NotifyPointer) { /* We still have focus if a child gets focus. We also don't care about the position of the pointer when the keyboard focus changed. */ @@ -917,20 +910,20 @@ X11_DispatchEvent(_THIS) /* Key press? */ case KeyPress:{ - KeyCode keycode = xevent.xkey.keycode; + KeyCode keycode = xevent->xkey.keycode; KeySym keysym = NoSymbol; char text[SDL_TEXTINPUTEVENT_TEXT_SIZE]; Status status = 0; SDL_bool handled_by_ime = SDL_FALSE; #ifdef DEBUG_XEVENTS - printf("window %p: KeyPress (X11 keycode = 0x%X)\n", data, xevent.xkey.keycode); + printf("window %p: KeyPress (X11 keycode = 0x%X)\n", data, xevent->xkey.keycode); #endif #if 1 if (videodata->key_layout[keycode] == SDL_SCANCODE_UNKNOWN && keycode) { int min_keycode, max_keycode; X11_XDisplayKeycodes(display, &min_keycode, &max_keycode); - keysym = X11_KeyCodeToSym(_this, keycode, xevent.xkey.state >> 13); + 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 forums/mailing list X11 KeyCode %d (%d), X11 KeySym 0x%lX (%s).\n", keycode, keycode - min_keycode, keysym, @@ -941,13 +934,13 @@ X11_DispatchEvent(_THIS) SDL_zeroa(text); #ifdef X_HAVE_UTF8_STRING if (data->ic) { - X11_Xutf8LookupString(data->ic, &xevent.xkey, text, sizeof(text), + X11_Xutf8LookupString(data->ic, &xevent->xkey, text, sizeof(text), &keysym, &status); } else { - X11_XLookupString(&xevent.xkey, text, sizeof(text), &keysym, NULL); + X11_XLookupString(&xevent->xkey, text, sizeof(text), &keysym, NULL); } #else - X11_XLookupString(&xevent.xkey, text, sizeof(text), &keysym, NULL); + X11_XLookupString(&xevent->xkey, text, sizeof(text), &keysym, NULL); #endif #ifdef SDL_USE_IME @@ -957,7 +950,7 @@ X11_DispatchEvent(_THIS) #endif if (!handled_by_ime) { /* Don't send the key if it looks like a duplicate of a filtered key sent by an IME */ - if (xevent.xkey.keycode != videodata->filter_code || xevent.xkey.time != videodata->filter_time) { + if (xevent->xkey.keycode != videodata->filter_code || xevent->xkey.time != videodata->filter_time) { SDL_SendKeyboardKey(SDL_PRESSED, videodata->key_layout[keycode]); } if(*text) { @@ -965,18 +958,18 @@ X11_DispatchEvent(_THIS) } } - X11_UpdateUserTime(data, xevent.xkey.time); + X11_UpdateUserTime(data, xevent->xkey.time); } break; /* Key release? */ case KeyRelease:{ - KeyCode keycode = xevent.xkey.keycode; + KeyCode keycode = xevent->xkey.keycode; #ifdef DEBUG_XEVENTS - printf("window %p: KeyRelease (X11 keycode = 0x%X)\n", data, xevent.xkey.keycode); + printf("window %p: KeyRelease (X11 keycode = 0x%X)\n", data, xevent->xkey.keycode); #endif - if (X11_KeyRepeat(display, &xevent)) { + if (X11_KeyRepeat(display, xevent)) { /* We're about to get a repeated key down, ignore the key up */ break; } @@ -992,8 +985,8 @@ X11_DispatchEvent(_THIS) printf("window %p: UnmapNotify!\n", data); #endif - if (X11_XCheckIfEvent(display, &ev, &isReparentNotify, (XPointer)&xevent.xunmap)) { - X11_XCheckIfEvent(display, &ev, &isMapNotify, (XPointer)&xevent.xunmap); + if (X11_XCheckIfEvent(display, &ev, &isReparentNotify, (XPointer)&xevent->xunmap)) { + X11_XCheckIfEvent(display, &ev, &isMapNotify, (XPointer)&xevent->xunmap); } else { X11_DispatchUnmapNotify(data); } @@ -1013,27 +1006,27 @@ X11_DispatchEvent(_THIS) case ConfigureNotify:{ #ifdef DEBUG_XEVENTS printf("window %p: ConfigureNotify! (position: %d,%d, size: %dx%d)\n", data, - xevent.xconfigure.x, xevent.xconfigure.y, - xevent.xconfigure.width, xevent.xconfigure.height); + xevent->xconfigure.x, xevent->xconfigure.y, + xevent->xconfigure.width, xevent->xconfigure.height); #endif /* Real configure notify events are relative to the parent, synthetic events are absolute. */ - if (!xevent.xconfigure.send_event) { + 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, + 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) { + 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, xevent.xconfigure.y); + xevent->xconfigure.x, xevent->xconfigure.y); #ifdef SDL_USE_IME if(SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE){ /* Update IME candidate list position */ @@ -1041,13 +1034,13 @@ X11_DispatchEvent(_THIS) } #endif } - if (xevent.xconfigure.width != data->last_xconfigure.width || - xevent.xconfigure.height != data->last_xconfigure.height) { + if (xevent->xconfigure.width != data->last_xconfigure.width || + xevent->xconfigure.height != data->last_xconfigure.height) { SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESIZED, - xevent.xconfigure.width, - xevent.xconfigure.height); + xevent->xconfigure.width, + xevent->xconfigure.height); } - data->last_xconfigure = xevent.xconfigure; + data->last_xconfigure = xevent->xconfigure; } break; @@ -1056,11 +1049,11 @@ X11_DispatchEvent(_THIS) static int xdnd_version=0; - if (xevent.xclient.message_type == videodata->XdndEnter) { + if (xevent->xclient.message_type == videodata->XdndEnter) { - SDL_bool use_list = xevent.xclient.data.l[1] & 1; - data->xdnd_source = xevent.xclient.data.l[0]; - xdnd_version = (xevent.xclient.data.l[1] >> 24); + SDL_bool use_list = xevent->xclient.data.l[1] & 1; + data->xdnd_source = xevent->xclient.data.l[0]; + xdnd_version = (xevent->xclient.data.l[1] >> 24); #ifdef DEBUG_XEVENTS printf("XID of source window : %ld\n", data->xdnd_source); printf("Protocol version to use : %d\n", xdnd_version); @@ -1076,15 +1069,15 @@ X11_DispatchEvent(_THIS) X11_XFree(p.data); } else { /* pick from list of three */ - data->xdnd_req = X11_PickTargetFromAtoms(display, xevent.xclient.data.l[2], xevent.xclient.data.l[3], xevent.xclient.data.l[4]); + data->xdnd_req = X11_PickTargetFromAtoms(display, xevent->xclient.data.l[2], xevent->xclient.data.l[3], xevent->xclient.data.l[4]); } } - else if (xevent.xclient.message_type == videodata->XdndPosition) { + else if (xevent->xclient.message_type == videodata->XdndPosition) { #ifdef DEBUG_XEVENTS Atom act= videodata->XdndActionCopy; if(xdnd_version >= 2) { - act = xevent.xclient.data.l[4]; + act = xevent->xclient.data.l[4]; } printf("Action requested by user is : %s\n", X11_XGetAtomName(display , act)); #endif @@ -1093,8 +1086,8 @@ X11_DispatchEvent(_THIS) /* reply with status */ memset(&m, 0, sizeof(XClientMessageEvent)); m.type = ClientMessage; - m.display = xevent.xclient.display; - m.window = xevent.xclient.data.l[0]; + m.display = xevent->xclient.display; + m.window = xevent->xclient.data.l[0]; m.message_type = videodata->XdndStatus; m.format=32; m.data.l[0] = data->xwindow; @@ -1103,47 +1096,47 @@ X11_DispatchEvent(_THIS) m.data.l[3] = 0; m.data.l[4] = videodata->XdndActionCopy; /* we only accept copying anyway */ - X11_XSendEvent(display, xevent.xclient.data.l[0], False, NoEventMask, (XEvent*)&m); + X11_XSendEvent(display, xevent->xclient.data.l[0], False, NoEventMask, (XEvent*)&m); X11_XFlush(display); } - else if(xevent.xclient.message_type == videodata->XdndDrop) { + else if(xevent->xclient.message_type == videodata->XdndDrop) { if (data->xdnd_req == None) { /* say again - not interested! */ memset(&m, 0, sizeof(XClientMessageEvent)); m.type = ClientMessage; - m.display = xevent.xclient.display; - m.window = xevent.xclient.data.l[0]; + m.display = xevent->xclient.display; + m.window = xevent->xclient.data.l[0]; m.message_type = videodata->XdndFinished; m.format=32; m.data.l[0] = data->xwindow; m.data.l[1] = 0; m.data.l[2] = None; /* fail! */ - X11_XSendEvent(display, xevent.xclient.data.l[0], False, NoEventMask, (XEvent*)&m); + X11_XSendEvent(display, xevent->xclient.data.l[0], False, NoEventMask, (XEvent*)&m); } else { /* convert */ if(xdnd_version >= 1) { - X11_XConvertSelection(display, videodata->XdndSelection, data->xdnd_req, videodata->PRIMARY, data->xwindow, xevent.xclient.data.l[2]); + X11_XConvertSelection(display, videodata->XdndSelection, data->xdnd_req, videodata->PRIMARY, data->xwindow, xevent->xclient.data.l[2]); } else { X11_XConvertSelection(display, videodata->XdndSelection, data->xdnd_req, videodata->PRIMARY, data->xwindow, CurrentTime); } } } - else if ((xevent.xclient.message_type == videodata->WM_PROTOCOLS) && - (xevent.xclient.format == 32) && - (xevent.xclient.data.l[0] == videodata->_NET_WM_PING)) { + else if ((xevent->xclient.message_type == videodata->WM_PROTOCOLS) && + (xevent->xclient.format == 32) && + (xevent->xclient.data.l[0] == videodata->_NET_WM_PING)) { Window root = DefaultRootWindow(display); #ifdef DEBUG_XEVENTS printf("window %p: _NET_WM_PING\n", data); #endif - xevent.xclient.window = root; - X11_XSendEvent(display, root, False, SubstructureRedirectMask | SubstructureNotifyMask, &xevent); + xevent->xclient.window = root; + X11_XSendEvent(display, root, False, SubstructureRedirectMask | SubstructureNotifyMask, xevent); break; } - else if ((xevent.xclient.message_type == videodata->WM_PROTOCOLS) && - (xevent.xclient.format == 32) && - (xevent.xclient.data.l[0] == videodata->WM_DELETE_WINDOW)) { + else if ((xevent->xclient.message_type == videodata->WM_PROTOCOLS) && + (xevent->xclient.format == 32) && + (xevent->xclient.data.l[0] == videodata->WM_DELETE_WINDOW)) { #ifdef DEBUG_XEVENTS printf("window %p: WM_DELETE_WINDOW\n", data); @@ -1151,9 +1144,9 @@ 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)) { + 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); @@ -1167,7 +1160,7 @@ X11_DispatchEvent(_THIS) /* Do we need to refresh ourselves? */ case Expose:{ #ifdef DEBUG_XEVENTS - printf("window %p: Expose (count = %d)\n", data, xevent.xexpose.count); + printf("window %p: Expose (count = %d)\n", data, xevent->xexpose.count); #endif SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_EXPOSED, 0, 0); } @@ -1177,10 +1170,10 @@ 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", data, 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); + SDL_SendMouseMotion(data->window, 0, 0, xevent->xmotion.x, xevent->xmotion.y); } } break; @@ -1188,15 +1181,15 @@ 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); + printf("window %p: ButtonPress (X11 button = %d)\n", data, xevent->xbutton.button); #endif - if (X11_IsWheelEvent(display,&xevent,&xticks, &yticks)) { + if (X11_IsWheelEvent(display,xevent,&xticks, &yticks)) { SDL_SendMouseWheel(data->window, 0, (float) xticks, (float) yticks, SDL_MOUSEWHEEL_NORMAL); } else { SDL_bool ignore_click = SDL_FALSE; - int button = xevent.xbutton.button; + int button = xevent->xbutton.button; if(button == Button1) { - if (ProcessHitTest(_this, data, &xevent)) { + if (ProcessHitTest(_this, data, xevent)) { SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_HIT_TEST, 0, 0); break; /* don't pass this event on to app. */ } @@ -1217,18 +1210,18 @@ X11_DispatchEvent(_THIS) SDL_SendMouseButton(data->window, 0, SDL_PRESSED, button); } } - X11_UpdateUserTime(data, xevent.xbutton.time); + X11_UpdateUserTime(data, xevent->xbutton.time); } break; case ButtonRelease:{ - int button = xevent.xbutton.button; + int button = xevent->xbutton.button; /* The X server sends a Release event for each Press for wheels. Ignore them. */ int xticks = 0, yticks = 0; #ifdef DEBUG_XEVENTS - printf("window %p: ButtonRelease (X11 button = %d)\n", data, xevent.xbutton.button); + printf("window %p: ButtonRelease (X11 button = %d)\n", data, xevent->xbutton.button); #endif - if (!X11_IsWheelEvent(display, &xevent, &xticks, &yticks)) { + if (!X11_IsWheelEvent(display, xevent, &xticks, &yticks)) { if (button > 7) { /* see explanation at case ButtonPress */ button -= (8-SDL_BUTTON_X1); @@ -1245,13 +1238,13 @@ X11_DispatchEvent(_THIS) Atom real_type; unsigned long items_read, items_left; - char *name = X11_XGetAtomName(display, xevent.xproperty.atom); + char *name = X11_XGetAtomName(display, xevent->xproperty.atom); if (name) { - printf("window %p: PropertyNotify: %s %s time=%lu\n", data, name, (xevent.xproperty.state == PropertyDelete) ? "deleted" : "changed", xevent.xproperty.time); + printf("window %p: PropertyNotify: %s %s time=%lu\n", data, name, (xevent->xproperty.state == PropertyDelete) ? "deleted" : "changed", xevent->xproperty.time); X11_XFree(name); } - status = X11_XGetWindowProperty(display, data->xwindow, xevent.xproperty.atom, 0L, 8192L, False, AnyPropertyType, &real_type, &real_format, &items_read, &items_left, &propdata); + status = X11_XGetWindowProperty(display, data->xwindow, xevent->xproperty.atom, 0L, 8192L, False, AnyPropertyType, &real_type, &real_format, &items_read, &items_left, &propdata); if (status == Success && items_read > 0) { if (real_type == XA_INTEGER) { int *values = (int *)propdata; @@ -1323,16 +1316,16 @@ X11_DispatchEvent(_THIS) 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; + data->user_time = xevent->xproperty.time; } - if (xevent.xproperty.atom == data->videodata->_NET_WM_STATE) { + 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 without ever mapping / unmapping them, so we handle that here, because they use the NETWM protocol to notify us of changes. */ - const Uint32 flags = X11_GetNetWMState(_this, xevent.xproperty.window); + const Uint32 flags = X11_GetNetWMState(_this, xevent->xproperty.window); const Uint32 changed = flags ^ data->window->flags; if ((changed & SDL_WINDOW_HIDDEN) || (changed & SDL_WINDOW_FULLSCREEN)) { @@ -1350,7 +1343,7 @@ X11_DispatchEvent(_THIS) SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_RESTORED, 0, 0); } } - } else if (xevent.xproperty.atom == videodata->XKLAVIER_STATE) { + } else if (xevent->xproperty.atom == videodata->XKLAVIER_STATE) { /* Hack for Ubuntu 12.04 (etc) that doesn't send MappingNotify events when the keyboard layout changes (for example, changing from English to French on the menubar's keyboard @@ -1359,7 +1352,7 @@ X11_DispatchEvent(_THIS) right approach, but it seems to work. */ X11_UpdateKeymap(_this); SDL_SendKeymapChangedEvent(); - } else if (xevent.xproperty.atom == videodata->_NET_FRAME_EXTENTS) { + } else if (xevent->xproperty.atom == videodata->_NET_FRAME_EXTENTS) { Atom type; int format; unsigned long nitems, bytes_after; @@ -1382,10 +1375,10 @@ X11_DispatchEvent(_THIS) break; case SelectionNotify: { - Atom target = xevent.xselection.target; + Atom target = xevent->xselection.target; #ifdef DEBUG_XEVENTS printf("window %p: SelectionNotify (requestor = %ld, target = %ld)\n", data, - xevent.xselection.requestor, xevent.xselection.target); + xevent->xselection.requestor, xevent->xselection.target); #endif if (target == data->xdnd_req) { /* read data */ @@ -1433,7 +1426,7 @@ X11_DispatchEvent(_THIS) default:{ #ifdef DEBUG_XEVENTS - printf("window %p: Unhandled event %d\n", data, xevent.type); + printf("window %p: Unhandled event %d\n", data, xevent->type); #endif } break; @@ -1482,10 +1475,79 @@ X11_Pending(Display * display) return (0); } +void +X11_SendWakeupEvent(_THIS, SDL_Window *window) +{ + SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; + Display *req_display = data->request_display; + Window xwindow = ((SDL_WindowData *) window->driverdata)->xwindow; + XClientMessageEvent event; + + memset(&event, 0, sizeof(XClientMessageEvent)); + event.type = ClientMessage; + event.display = req_display; + event.send_event = True; + event.message_type = data->_SDL_WAKEUP; + event.format = 8; + + X11_XSendEvent(req_display, xwindow, False, NoEventMask, (XEvent *) &event); + /* XSendEvent returns a status and it could be BadValue or BadWindow. If an + error happens it is an SDL's internal error and there is nothing we can do here. */ + X11_XFlush(req_display); +} + +int +X11_WaitEventTimeout(_THIS, int timeout) +{ + SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata; + Display *display; + XEvent xevent; + + if (!videodata) { + return 0; + } + display = videodata->display; + + SDL_zero(xevent); + + if (timeout == 0) { + if (X11_Pending(display)) { + X11_XNextEvent(display, &xevent); + } else { + return 0; + } + } else if (timeout > 0) { + int display_fd = ConnectionNumber(display); + fd_set readset; + struct timeval tv_timeout; + FD_ZERO(&readset); + FD_SET(display_fd, &readset); + tv_timeout.tv_sec = (timeout / 1000); + tv_timeout.tv_usec = (timeout % 1000) * 1000; + if (select(display_fd + 1, &readset, NULL, NULL, &tv_timeout) > 0) { + X11_XNextEvent(display, &xevent); + } else { + return 0; + } + } else { + X11_XNextEvent(display, &xevent); + } + + X11_DispatchEvent(_this, &xevent); + +#ifdef SDL_USE_IME + if(SDL_GetEventState(SDL_TEXTINPUT) == SDL_ENABLE){ + SDL_IME_PumpEvents(); + } +#endif + return 1; +} + void X11_PumpEvents(_THIS) { SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; + XEvent xevent; if (data->last_mode_change_deadline) { if (SDL_TICKS_PASSED(SDL_GetTicks(), data->last_mode_change_deadline)) { @@ -1508,9 +1570,12 @@ X11_PumpEvents(_THIS) } } + SDL_zero(xevent); + /* Keep processing pending events */ while (X11_Pending(data->display)) { - X11_DispatchEvent(_this); + X11_XNextEvent(data->display, &xevent); + X11_DispatchEvent(_this, &xevent); } #ifdef SDL_USE_IME diff --git a/externals/SDL/src/video/x11/SDL_x11events.h b/externals/SDL/src/video/x11/SDL_x11events.h index 6f386e7c6..34899d458 100755 --- a/externals/SDL/src/video/x11/SDL_x11events.h +++ b/externals/SDL/src/video/x11/SDL_x11events.h @@ -24,6 +24,8 @@ #define SDL_x11events_h_ extern void X11_PumpEvents(_THIS); +extern int X11_WaitEventTimeout(_THIS, int timeout); +extern void X11_SendWakeupEvent(_THIS, SDL_Window *window); extern void X11_SuspendScreenSaver(_THIS); #endif /* SDL_x11events_h_ */ diff --git a/externals/SDL/src/video/x11/SDL_x11modes.c b/externals/SDL/src/video/x11/SDL_x11modes.c index f35e34b94..e14c90e83 100755 --- a/externals/SDL/src/video/x11/SDL_x11modes.c +++ b/externals/SDL/src/video/x11/SDL_x11modes.c @@ -345,6 +345,29 @@ SetXRandRDisplayName(Display *dpy, Atom EDID, char *name, const size_t namelen, #endif } +static int +GetXftDPI(Display* dpy) +{ + char* xdefault_resource; + int xft_dpi, err; + + xdefault_resource = X11_XGetDefault(dpy, "Xft", "dpi"); + + if(!xdefault_resource) { + return 0; + } + + /* + * It's possible for SDL_atoi to call strtol, if it fails due to a + * overflow or an underflow, it will return LONG_MAX or LONG_MIN and set + * errno to ERANGE. So we need to check for this so we dont get crazy dpi + * values + */ + xft_dpi = SDL_atoi(xdefault_resource); + err = errno; + + return err == ERANGE ? 0 : xft_dpi; +} static int X11_InitModes_XRandR(_THIS) @@ -417,6 +440,7 @@ X11_InitModes_XRandR(_THIS) RRMode modeID; RRCrtc output_crtc; XRRCrtcInfo *crtc; + int xft_dpi = 0; /* The primary output _should_ always be sorted first, but just in case... */ if ((looking_for_primary && (res->outputs[output] != primary)) || @@ -471,6 +495,14 @@ X11_InitModes_XRandR(_THIS) displaydata->hdpi = display_mm_width ? (((float) mode.w) * 25.4f / display_mm_width) : 0.0f; displaydata->vdpi = display_mm_height ? (((float) mode.h) * 25.4f / display_mm_height) : 0.0f; displaydata->ddpi = SDL_ComputeDiagonalDPI(mode.w, mode.h, ((float) display_mm_width) / 25.4f,((float) display_mm_height) / 25.4f); + + /* if xft dpi is available we will use this over xrandr */ + xft_dpi = GetXftDPI(dpy); + if(xft_dpi > 0) { + displaydata->hdpi = (float)xft_dpi; + displaydata->vdpi = (float)xft_dpi; + } + displaydata->scanline_pad = scanline_pad; displaydata->x = display_x; displaydata->y = display_y; diff --git a/externals/SDL/src/video/x11/SDL_x11sym.h b/externals/SDL/src/video/x11/SDL_x11sym.h index a550dc2e9..6433b9310 100755 --- a/externals/SDL/src/video/x11/SDL_x11sym.h +++ b/externals/SDL/src/video/x11/SDL_x11sym.h @@ -138,6 +138,7 @@ SDL_X11_SYM(int,XWarpPointer,(Display* a,Window b,Window c,int d,int e,unsigned SDL_X11_SYM(int,XWindowEvent,(Display* a,Window b,long c,XEvent* d),(a,b,c,d),return) SDL_X11_SYM(Status,XWithdrawWindow,(Display* a,Window b,int c),(a,b,c),return) SDL_X11_SYM(VisualID,XVisualIDFromVisual,(Visual* a),(a),return) +SDL_X11_SYM(char*,XGetDefault,(Display* a,char* b, char* c),(a,b,c),return) #if SDL_VIDEO_DRIVER_X11_CONST_PARAM_XEXTADDDISPLAY SDL_X11_SYM(XExtDisplayInfo*,XextAddDisplay,(XExtensionInfo* a,Display* b,_Xconst char* c,XExtensionHooks* d,int e,XPointer f),(a,b,c,d,e,f),return) #else @@ -276,6 +277,8 @@ SDL_X11_MODULE(XINPUT2) SDL_X11_SYM(XIDeviceInfo*,XIQueryDevice,(Display *a,int b,int *c),(a,b,c),return) SDL_X11_SYM(void,XIFreeDeviceInfo,(XIDeviceInfo *a),(a),) SDL_X11_SYM(int,XISelectEvents,(Display *a,Window b,XIEventMask *c,int d),(a,b,c,d),return) +SDL_X11_SYM(int,XIGrabTouchBegin,(Display *a,int b,Window c,int d,XIEventMask *e,int f,XIGrabModifiers *g),(a,b,c,d,e,f,g),return) +SDL_X11_SYM(int,XIUngrabTouchBegin, (Display *a,int b,Window c, int d,XIGrabModifiers *e),(a, b, c, d, e),return) SDL_X11_SYM(Status,XIQueryVersion,(Display *a,int *b,int *c),(a,b,c),return) SDL_X11_SYM(XIEventMask*,XIGetSelectedEvents,(Display *a,Window b,int *c),(a,b,c),return) #endif diff --git a/externals/SDL/src/video/x11/SDL_x11video.c b/externals/SDL/src/video/x11/SDL_x11video.c index fa543adef..e8b969311 100755 --- a/externals/SDL/src/video/x11/SDL_x11video.c +++ b/externals/SDL/src/video/x11/SDL_x11video.c @@ -105,7 +105,13 @@ X11_DeleteDevice(SDL_VideoDevice * device) X11_XSetErrorHandler(orig_x11_errhandler); X11_XCloseDisplay(data->display); } + if (data->request_display) { + X11_XCloseDisplay(data->request_display); + } SDL_free(data->windowlist); + if (device->wakeup_lock) { + SDL_DestroyMutex(device->wakeup_lock); + } SDL_free(device->driverdata); SDL_free(device); @@ -178,10 +184,22 @@ X11_CreateDevice(int devindex) return NULL; } device->driverdata = data; + device->wakeup_lock = SDL_CreateMutex(); data->global_mouse_changed = SDL_TRUE; data->display = x11_display; + data->request_display = X11_XOpenDisplay(display); + if (data->request_display == NULL) { + X11_XCloseDisplay(data->display); + SDL_free(device->driverdata); + SDL_free(device); + SDL_X11_UnloadSymbols(); + return NULL; + } + + device->wakeup_lock = SDL_CreateMutex(); + #ifdef X11_DEBUG X11_XSynchronize(data->display, True); #endif @@ -201,6 +219,8 @@ X11_CreateDevice(int devindex) device->SetDisplayMode = X11_SetDisplayMode; device->SuspendScreenSaver = X11_SuspendScreenSaver; device->PumpEvents = X11_PumpEvents; + device->WaitEventTimeout = X11_WaitEventTimeout; + device->SendWakeupEvent = X11_SendWakeupEvent; device->CreateSDLWindow = X11_CreateWindow; device->CreateSDLWindowFrom = X11_CreateWindowFrom; @@ -234,6 +254,7 @@ X11_CreateDevice(int devindex) device->GetWindowWMInfo = X11_GetWindowWMInfo; device->SetWindowHitTest = X11_SetWindowHitTest; device->AcceptDragAndDrop = X11_AcceptDragAndDrop; + device->FlashWindow = X11_FlashWindow; device->shape_driver.CreateShaper = X11_CreateShaper; device->shape_driver.SetWindowShape = X11_SetWindowShape; @@ -403,6 +424,7 @@ X11_VideoInit(_THIS) GET_ATOM(_NET_WM_USER_TIME); GET_ATOM(_NET_ACTIVE_WINDOW); GET_ATOM(_NET_FRAME_EXTENTS); + GET_ATOM(_SDL_WAKEUP); GET_ATOM(UTF8_STRING); GET_ATOM(PRIMARY); GET_ATOM(XdndEnter); diff --git a/externals/SDL/src/video/x11/SDL_x11video.h b/externals/SDL/src/video/x11/SDL_x11video.h index 11f7e9d84..7281e1130 100755 --- a/externals/SDL/src/video/x11/SDL_x11video.h +++ b/externals/SDL/src/video/x11/SDL_x11video.h @@ -75,6 +75,7 @@ typedef struct SDL_VideoData { Display *display; + Display *request_display; char *classname; pid_t pid; XIM im; @@ -111,6 +112,7 @@ typedef struct SDL_VideoData Atom _NET_WM_USER_TIME; Atom _NET_ACTIVE_WINDOW; Atom _NET_FRAME_EXTENTS; + Atom _SDL_WAKEUP; Atom UTF8_STRING; Atom PRIMARY; Atom XdndEnter; diff --git a/externals/SDL/src/video/x11/SDL_x11window.c b/externals/SDL/src/video/x11/SDL_x11window.c index 82e48d2b5..c4cdfc358 100755 --- a/externals/SDL/src/video/x11/SDL_x11window.c +++ b/externals/SDL/src/video/x11/SDL_x11window.c @@ -372,6 +372,7 @@ X11_CreateWindow(_THIS, SDL_Window * window) SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata; + const SDL_bool force_override_redirect = SDL_GetHintBoolean(SDL_HINT_X11_FORCE_OVERRIDE_REDIRECT, SDL_FALSE); SDL_WindowData *windowdata; Display *display = data->display; int screen = displaydata->screen; @@ -444,7 +445,7 @@ X11_CreateWindow(_THIS, SDL_Window * window) depth = displaydata->depth; } - xattr.override_redirect = ((window->flags & SDL_WINDOW_TOOLTIP) || (window->flags & SDL_WINDOW_POPUP_MENU)) ? True : False; + xattr.override_redirect = ((window->flags & SDL_WINDOW_TOOLTIP) || (window->flags & SDL_WINDOW_POPUP_MENU) || force_override_redirect) ? True : False; xattr.backing_store = NotUseful; xattr.background_pixmap = None; xattr.border_pixel = 0; @@ -725,38 +726,24 @@ X11_SetWindowTitle(_THIS, SDL_Window * window) { SDL_WindowData *data = (SDL_WindowData *) window->driverdata; Display *display = data->videodata->display; - XTextProperty titleprop; Status status; const char *title = window->title ? window->title : ""; - char *title_locale = NULL; -#ifdef X_HAVE_UTF8_STRING + Atom UTF8_STRING = data->videodata->UTF8_STRING; Atom _NET_WM_NAME = data->videodata->_NET_WM_NAME; -#endif - title_locale = SDL_iconv_utf8_locale(title); - if (!title_locale) { - SDL_OutOfMemory(); - return; - } + status = X11_XChangeProperty(display, data->xwindow, _NET_WM_NAME, UTF8_STRING, 8, 0, (const unsigned char *) title, strlen(title)); - status = X11_XStringListToTextProperty(&title_locale, 1, &titleprop); - SDL_free(title_locale); - if (status) { - X11_XSetTextProperty(display, data->xwindow, &titleprop, XA_WM_NAME); - X11_XFree(titleprop.value); - } -#ifdef X_HAVE_UTF8_STRING - if (SDL_X11_HAVE_UTF8) { - status = X11_Xutf8TextListToTextProperty(display, (char **) &title, 1, - XUTF8StringStyle, &titleprop); - if (status == Success) { - X11_XSetTextProperty(display, data->xwindow, &titleprop, - _NET_WM_NAME); - X11_XFree(titleprop.value); + if (status != Success) { + char *x11_error = NULL; + char x11_error_locale[256]; + if (X11_XGetErrorText(display, status, x11_error_locale, sizeof(x11_error_locale)) == Success) + { + x11_error = SDL_iconv_string("UTF-8", "", x11_error_locale, SDL_strlen(x11_error_locale)+1); + SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "Error when setting X11 window title to %s: %s\n", title, x11_error); + SDL_free(x11_error); } } -#endif X11_XFlush(display); } @@ -1637,6 +1624,8 @@ X11_SetWindowMouseGrab(_THIS, SDL_Window * window, SDL_bool grabbed) } } + X11_Xinput2GrabTouch(_this, window); + /* Raise the window if we grab the mouse */ X11_XRaiseWindow(display, data->xwindow); @@ -1646,6 +1635,8 @@ X11_SetWindowMouseGrab(_THIS, SDL_Window * window, SDL_bool grabbed) } } else { X11_XUngrabPointer(display, CurrentTime); + + X11_Xinput2UngrabTouch(_this, window); } X11_XSync(display, False); } @@ -1757,6 +1748,30 @@ X11_AcceptDragAndDrop(SDL_Window * window, SDL_bool accept) } } +int +X11_FlashWindow(_THIS, SDL_Window * window, Uint32 flash_count) +{ + SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_GetDisplayForWindow(window)->driverdata; + Display *display = data->videodata->display; + + Atom demands_attention = X11_XInternAtom(display, "_NET_WM_STATE_DEMANDS_ATTENTION", 1); + Atom wm_state = X11_XInternAtom(display, "_NET_WM_STATE", 1); + + XEvent snd_ntfy_ev = {ClientMessage}; + snd_ntfy_ev.xclient.window = data->xwindow; + snd_ntfy_ev.xclient.message_type = wm_state; + snd_ntfy_ev.xclient.format = 32; + snd_ntfy_ev.xclient.data.l[0] = 1; /* _NET_WM_STATE_ADD */ + snd_ntfy_ev.xclient.data.l[1] = demands_attention; + snd_ntfy_ev.xclient.data.l[2] = 0; + snd_ntfy_ev.xclient.data.l[3] = 1; /* normal application */ + snd_ntfy_ev.xclient.data.l[4] = 0; + X11_XSendEvent(display, RootWindow(display, displaydata->screen), False, SubstructureNotifyMask | SubstructureRedirectMask, &snd_ntfy_ev); + + return 0; +} + #endif /* SDL_VIDEO_DRIVER_X11 */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/externals/SDL/src/video/x11/SDL_x11window.h b/externals/SDL/src/video/x11/SDL_x11window.h index 98c150088..4e9764c43 100755 --- a/externals/SDL/src/video/x11/SDL_x11window.h +++ b/externals/SDL/src/video/x11/SDL_x11window.h @@ -107,6 +107,7 @@ extern SDL_bool X11_GetWindowWMInfo(_THIS, SDL_Window * window, struct SDL_SysWMinfo *info); extern int X11_SetWindowHitTest(SDL_Window *window, SDL_bool enabled); extern void X11_AcceptDragAndDrop(SDL_Window * window, SDL_bool accept); +extern int X11_FlashWindow(_THIS, SDL_Window * window, Uint32 flash_count); #endif /* SDL_x11window_h_ */ diff --git a/externals/SDL/src/video/x11/SDL_x11xinput2.c b/externals/SDL/src/video/x11/SDL_x11xinput2.c index 6634490e4..33685d80d 100755 --- a/externals/SDL/src/video/x11/SDL_x11xinput2.c +++ b/externals/SDL/src/video/x11/SDL_x11xinput2.c @@ -343,6 +343,50 @@ X11_Xinput2IsMultitouchSupported() #endif } +void +X11_Xinput2GrabTouch(_THIS, SDL_Window *window) +{ +#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH + SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + Display *display = data->videodata->display; + + unsigned char mask[4] = { 0, 0, 0, 0 }; + XIGrabModifiers mods; + XIEventMask eventmask; + + mods.modifiers = XIAnyModifier; + mods.status = 0; + + eventmask.deviceid = XIAllDevices; + eventmask.mask_len = sizeof(mask); + eventmask.mask = mask; + + XISetMask(eventmask.mask, XI_TouchBegin); + XISetMask(eventmask.mask, XI_TouchUpdate); + XISetMask(eventmask.mask, XI_TouchEnd); + XISetMask(eventmask.mask, XI_Motion); + + X11_XIGrabTouchBegin(display, XIAllDevices, data->xwindow, True, &eventmask, 1, &mods); +#endif +} + +void +X11_Xinput2UngrabTouch(_THIS, SDL_Window *window) +{ +#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH + SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + Display *display = data->videodata->display; + + XIGrabModifiers mods; + + mods.modifiers = XIAnyModifier; + mods.status = 0; + + X11_XIUngrabTouchBegin(display, XIAllDevices, data->xwindow, 1, &mods); +#endif +} + + #endif /* SDL_VIDEO_DRIVER_X11 */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/externals/SDL/src/video/x11/SDL_x11xinput2.h b/externals/SDL/src/video/x11/SDL_x11xinput2.h index 7fe4fb87a..5dd69266a 100755 --- a/externals/SDL/src/video/x11/SDL_x11xinput2.h +++ b/externals/SDL/src/video/x11/SDL_x11xinput2.h @@ -36,6 +36,8 @@ extern int X11_HandleXinput2Event(SDL_VideoData *videodata,XGenericEventCookie * extern int X11_Xinput2IsInitialized(void); extern int X11_Xinput2IsMultitouchSupported(void); extern void X11_Xinput2SelectTouch(_THIS, SDL_Window *window); +extern void X11_Xinput2GrabTouch(_THIS, SDL_Window *window); +extern void X11_Xinput2UngrabTouch(_THIS, SDL_Window *window); #endif /* SDL_x11xinput2_h_ */ diff --git a/externals/SDL/test/CMakeLists.txt b/externals/SDL/test/CMakeLists.txt index 970578505..2b0b92b0e 100755 --- a/externals/SDL/test/CMakeLists.txt +++ b/externals/SDL/test/CMakeLists.txt @@ -20,6 +20,7 @@ add_definitions(-DHAVE_OPENGL) endif() add_executable(checkkeys checkkeys.c) +add_executable(checkkeysthreads checkkeysthreads.c) add_executable(loopwave loopwave.c) add_executable(loopwavequeue loopwavequeue.c) add_executable(testresample testresample.c) diff --git a/externals/SDL/test/Makefile.in b/externals/SDL/test/Makefile.in index 6cf97ed2c..be907ae37 100755 --- a/externals/SDL/test/Makefile.in +++ b/externals/SDL/test/Makefile.in @@ -9,6 +9,7 @@ LIBS = @LIBS@ TARGETS = \ checkkeys$(EXE) \ + checkkeysthreads$(EXE) \ controllermap$(EXE) \ loopwave$(EXE) \ loopwavequeue$(EXE) \ @@ -83,6 +84,9 @@ Makefile: $(srcdir)/Makefile.in checkkeys$(EXE): $(srcdir)/checkkeys.c $(CC) -o $@ $^ $(CFLAGS) $(LIBS) +checkkeysthreads$(EXE): $(srcdir)/checkkeysthreads.c + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) + loopwave$(EXE): $(srcdir)/loopwave.c $(CC) -o $@ $^ $(CFLAGS) $(LIBS) diff --git a/externals/SDL/test/Makefile.os2 b/externals/SDL/test/Makefile.os2 index b85c52ceb..fe5ff6d6d 100755 --- a/externals/SDL/test/Makefile.os2 +++ b/externals/SDL/test/Makefile.os2 @@ -11,6 +11,7 @@ TARGETS = testatomic.exe testdisplayinfo.exe testbounds.exe testdraw2.exe & testshader.exe testshape.exe testsprite2.exe testspriteminimal.exe & teststreaming.exe testthread.exe testtimer.exe testver.exe & testviewport.exe testwm2.exe torturethread.exe checkkeys.exe & + checkkeysthreads.exe & controllermap.exe testhaptic.exe testqsort.exe testresample.exe & testaudioinfo.exe testaudiocapture.exe loopwave.exe loopwavequeue.exe & testyuv.exe testgl2.exe testvulkan.exe testnative.exe testautomation.exe diff --git a/externals/SDL/test/checkkeysthreads.c b/externals/SDL/test/checkkeysthreads.c new file mode 100755 index 000000000..4019a80a3 --- /dev/null +++ b/externals/SDL/test/checkkeysthreads.c @@ -0,0 +1,275 @@ +/* + Copyright (C) 1997-2021 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. +*/ + +/* Simple program: Loop, watching keystrokes + Note that you need to call SDL_PollEvent() or SDL_WaitEvent() to + pump the event loop and catch keystrokes. +*/ + +#include +#include +#include + +#ifdef __EMSCRIPTEN__ +#include +#endif + +#include "SDL.h" + +int done; + +/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */ +static void +quit(int rc) +{ + SDL_Quit(); + exit(rc); +} + +static void +print_string(char **text, size_t *maxlen, const char *fmt, ...) +{ + int len; + va_list ap; + + va_start(ap, fmt); + len = SDL_vsnprintf(*text, *maxlen, fmt, ap); + if (len > 0) { + *text += len; + if ( ((size_t) len) < *maxlen ) { + *maxlen -= (size_t) len; + } else { + *maxlen = 0; + } + } + va_end(ap); +} + +static void +print_modifiers(char **text, size_t *maxlen) +{ + int mod; + print_string(text, maxlen, " modifiers:"); + mod = SDL_GetModState(); + if (!mod) { + print_string(text, maxlen, " (none)"); + return; + } + if (mod & KMOD_LSHIFT) + print_string(text, maxlen, " LSHIFT"); + if (mod & KMOD_RSHIFT) + print_string(text, maxlen, " RSHIFT"); + if (mod & KMOD_LCTRL) + print_string(text, maxlen, " LCTRL"); + if (mod & KMOD_RCTRL) + print_string(text, maxlen, " RCTRL"); + if (mod & KMOD_LALT) + print_string(text, maxlen, " LALT"); + if (mod & KMOD_RALT) + print_string(text, maxlen, " RALT"); + if (mod & KMOD_LGUI) + print_string(text, maxlen, " LGUI"); + if (mod & KMOD_RGUI) + print_string(text, maxlen, " RGUI"); + if (mod & KMOD_NUM) + print_string(text, maxlen, " NUM"); + if (mod & KMOD_CAPS) + print_string(text, maxlen, " CAPS"); + if (mod & KMOD_MODE) + print_string(text, maxlen, " MODE"); +} + +static void +PrintModifierState() +{ + char message[512]; + char *spot; + size_t left; + + spot = message; + left = sizeof(message); + + print_modifiers(&spot, &left); + SDL_Log("Initial state:%s\n", message); +} + +static void +PrintKey(SDL_Keysym * sym, SDL_bool pressed, SDL_bool repeat) +{ + char message[512]; + char *spot; + size_t left; + + spot = message; + left = sizeof(message); + + /* Print the keycode, name and state */ + if (sym->sym) { + print_string(&spot, &left, + "Key %s: scancode %d = %s, keycode 0x%08X = %s ", + pressed ? "pressed " : "released", + sym->scancode, + SDL_GetScancodeName(sym->scancode), + sym->sym, SDL_GetKeyName(sym->sym)); + } else { + print_string(&spot, &left, + "Unknown Key (scancode %d = %s) %s ", + sym->scancode, + SDL_GetScancodeName(sym->scancode), + pressed ? "pressed " : "released"); + } + print_modifiers(&spot, &left); + if (repeat) { + print_string(&spot, &left, " (repeat)"); + } + SDL_Log("%s\n", message); + fflush(stderr); +} + +static void +PrintText(char *eventtype, char *text) +{ + char *spot, expanded[1024]; + + expanded[0] = '\0'; + for ( spot = text; *spot; ++spot ) + { + size_t length = SDL_strlen(expanded); + SDL_snprintf(expanded + length, sizeof(expanded) - length, "\\x%.2x", (unsigned char)*spot); + } + SDL_Log("%s Text (%s): \"%s%s\"\n", eventtype, expanded, *text == '"' ? "\\" : "", text); +} + +void +loop() +{ + SDL_Event event; + /* Check for events */ + /*SDL_WaitEvent(&event); emscripten does not like waiting*/ + + fprintf(stderr, "starting loop\n"); fflush(stderr); + // while (SDL_PollEvent(&event)) { + while (!done && SDL_WaitEvent(&event)) { + fprintf(stderr, "got event type: %d\n", event.type); fflush(stderr); + switch (event.type) { + case SDL_KEYDOWN: + case SDL_KEYUP: + PrintKey(&event.key.keysym, (event.key.state == SDL_PRESSED) ? SDL_TRUE : SDL_FALSE, (event.key.repeat) ? SDL_TRUE : SDL_FALSE); + break; + case SDL_TEXTEDITING: + PrintText("EDIT", event.text.text); + break; + case SDL_TEXTINPUT: + PrintText("INPUT", event.text.text); + break; + case SDL_MOUSEBUTTONDOWN: + /* Left button quits the app, other buttons toggles text input */ + fprintf(stderr, "mouse button down button: %d (LEFT=%d)\n", event.button.button, SDL_BUTTON_LEFT); fflush(stderr); + if (event.button.button == SDL_BUTTON_LEFT) { + done = 1; + } else { + if (SDL_IsTextInputActive()) { + SDL_Log("Stopping text input\n"); + SDL_StopTextInput(); + } else { + SDL_Log("Starting text input\n"); + SDL_StartTextInput(); + } + } + break; + case SDL_QUIT: + done = 1; + break; + default: + break; + } + fprintf(stderr, "waiting new event\n"); fflush(stderr); + } + fprintf(stderr, "exiting event loop\n"); fflush(stderr); +#ifdef __EMSCRIPTEN__ + if (done) { + emscripten_cancel_main_loop(); + } +#endif +} + +/* Very simple thread - counts 0 to 9 delaying 50ms between increments */ +static int SDLCALL ping_thread(void *ptr) +{ + int cnt; + SDL_Event sdlevent; + memset(&sdlevent, 0 , sizeof(SDL_Event)); + for (cnt = 0; cnt < 10; ++cnt) { + fprintf(stderr, "sending event (%d/%d) from thread.\n", cnt + 1, 10); fflush(stderr); + sdlevent.type = SDL_KEYDOWN; + sdlevent.key.keysym.sym = SDLK_1; + SDL_PushEvent(&sdlevent); + SDL_Delay(1000 + rand() % 1000); + } + return cnt; +} + +int +main(int argc, char *argv[]) +{ + SDL_Window *window; + SDL_Thread *thread; + + /* Enable standard application logging */ + SDL_LogSetPriority(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO); + + /* Initialize SDL */ + if (SDL_Init(SDL_INIT_VIDEO) < 0) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't initialize SDL: %s\n", SDL_GetError()); + return (1); + } + + /* Set 640x480 video mode */ + window = SDL_CreateWindow("CheckKeys Test", + SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + 640, 480, 0); + if (!window) { + SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create 640x480 window: %s\n", + SDL_GetError()); + quit(2); + } + +#if __IPHONEOS__ + /* Creating the context creates the view, which we need to show keyboard */ + SDL_GL_CreateContext(window); +#endif + + SDL_StartTextInput(); + + /* Print initial modifier state */ + SDL_PumpEvents(); + PrintModifierState(); + + /* Watch keystrokes */ + done = 0; + + thread = SDL_CreateThread(ping_thread, "PingThread", (void *)NULL); + +#ifdef __EMSCRIPTEN__ + emscripten_set_main_loop(loop, 0, 1); +#else + while (!done) { + loop(); + } +#endif + + SDL_WaitThread(thread, NULL); + SDL_Quit(); + return (0); +} + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/externals/SDL/test/testgamecontroller.c b/externals/SDL/test/testgamecontroller.c index 34e9001de..d48f92f76 100755 --- a/externals/SDL/test/testgamecontroller.c +++ b/externals/SDL/test/testgamecontroller.c @@ -346,7 +346,11 @@ loop(void *arg) if (SDL_GameControllerGetButton(gamecontroller, (SDL_GameControllerButton)i) == SDL_PRESSED) { SDL_bool on_front = (i < SDL_CONTROLLER_BUTTON_PADDLE1 || i > SDL_CONTROLLER_BUTTON_PADDLE4); if (on_front == showing_front) { - const SDL_Rect dst = { button_positions[i].x, button_positions[i].y, 50, 50 }; + SDL_Rect dst; + dst.x = button_positions[i].x; + dst.y = button_positions[i].y; + dst.w = 50; + dst.h = 50; SDL_RenderCopyEx(screen, button, NULL, &dst, 0, NULL, SDL_FLIP_NONE); } } @@ -357,12 +361,20 @@ loop(void *arg) const Sint16 deadzone = 8000; /* !!! FIXME: real deadzone */ const Sint16 value = SDL_GameControllerGetAxis(gamecontroller, (SDL_GameControllerAxis)(i)); 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_Rect dst; + dst.x = axis_positions[i].x; + dst.y = axis_positions[i].y; + dst.w = 50; + dst.h = 50; 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_Rect dst; + dst.x = axis_positions[i].x; + dst.y = axis_positions[i].y; + dst.w = 50; + dst.h = 50; SDL_RenderCopyEx(screen, axis, NULL, &dst, angle, NULL, SDL_FLIP_NONE); } } diff --git a/externals/SDL/test/testjoystick.c b/externals/SDL/test/testjoystick.c index e05403f95..e0ab2708d 100755 --- a/externals/SDL/test/testjoystick.c +++ b/externals/SDL/test/testjoystick.c @@ -92,7 +92,11 @@ PrintJoystick(SDL_Joystick *joystick) static void DrawRect(SDL_Renderer *r, const int x, const int y, const int w, const int h) { - const SDL_Rect area = { x, y, w, h }; + SDL_Rect area; + area.x = x; + area.y = y; + area.w = w; + area.h = h; SDL_RenderFillRect(r, &area); } diff --git a/externals/SDL/test/testwm2.c b/externals/SDL/test/testwm2.c index d84928358..1dc66350d 100755 --- a/externals/SDL/test/testwm2.c +++ b/externals/SDL/test/testwm2.c @@ -105,7 +105,12 @@ loop() for (i = 0; i < state->num_windows; ++i) { SDL_Renderer *renderer = state->renderers[i]; if (renderer != NULL) { + SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); SDL_RenderClear(renderer); + + SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255); + SDLTest_CommonDrawWindowInfo(renderer, state->windows[i]); + SDL_RenderPresent(renderer); } } diff --git a/externals/SDL/wayland-protocols/xdg-activation-v1.xml b/externals/SDL/wayland-protocols/xdg-activation-v1.xml new file mode 100755 index 000000000..d87e63374 --- /dev/null +++ b/externals/SDL/wayland-protocols/xdg-activation-v1.xml @@ -0,0 +1,186 @@ + + + + + Copyright © 2020 Aleix Pol Gonzalez <aleixpol@kde.org> + Copyright © 2020 Carlos Garnacho <carlosg@gnome.org> + + 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 (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, + 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. + + + + The way for a client to pass focus to another toplevel is as follows. + + The client that intends to activate another toplevel uses the + xdg_activation_v1.get_activation_token request to get an activation token. + This token is then passed to the client to be activated through a separate + band of communication. The client to be activated will then pass the token + it received to the xdg_activation_v1.activate request. The compositor can + then use this token to decide how to react to the activation request. + + The token the activating client gets may be ineffective either already at + the time it receives it, for example if it was not focused, for focus + stealing prevention. The activating client will have no way to discover + the validity of the token, and may still forward it to the to be activated + client. + + The created activation token may optionally get information attached to it + that can be used by the compositor to identify the application that we + intend to activate. This can for example be used to display a visual hint + about what application is being started. + + Warning! The protocol described in this file is currently in the testing + phase. Backward compatible changes may be added together with the + corresponding interface version bump. Backward incompatible changes can + only be done by creating a new major version of the extension. + + + + + A global interface used for informing the compositor about applications + being activated or started, or for applications to request to be + activated. + + + + + Notify the compositor that the xdg_activation object will no longer be + used. + + The child objects created via this interface are unaffected and should + be destroyed separately. + + + + + + Creates an xdg_activation_token_v1 object that will provide + the initiating client with a unique token for this activation. This + token should be offered to the clients to be activated. + + + + + + + + Requests surface activation. It's up to the compositor to display + this information as desired, for example by placing the surface above + the rest. + + The compositor may know who requested this by checking the activation + token and might decide not to follow through with the activation if it's + considered unwanted. + + Compositors can ignore unknown presentation tokens when an invalid + token is passed. + + + + + + + + + An object for setting up a token and receiving a token handle that can + be passed as an activation token to another client. + + The object is created using the xdg_activation_v1.get_activation_token + request. This object should then be populated with the app_id, surface + and serial information and committed. The compositor shall then issue a + done event with the token. In case the request's parameters are invalid, + the compositor will provide an invalid token. + + + + + + + + + Provides information about the seat and serial event that requested the + token. + + Must be sent before commit. This information is optional. + + + + + + + + The requesting client can specify an app_id to associate the token + being created with it. + + Must be sent before commit. This information is optional. + + + + + + + The requesting client can specify a surface to associate the token + being created with it. + + Must be triggered before commit. This information is optional. + + + + + + + Requests an activation token based on the different parameters that + have been offered through set_serial, set_surface and set_app_id. + + + + + + The 'done' event contains the unique token of this activation request + and notifies that the provider is done. + + Applications will typically receive the token through the + XDG_ACTIVATION_TOKEN environment variable as set by its launcher, and + should unset the environment variable right after this request, in + order to avoid propagating it to child processes. + + Applications implementing the D-Bus interface org.freedesktop.Application + should get their token under XDG_ACTIVATION_TOKEN on their platform_data. + + Presentation tokens may be transferred across clients through means not + described in this protocol. + + + + + + + Notify the compositor that the xdg_activation_token_v1 object will no + longer be used. + + + + diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp index 9ae384f01..8bd70abc7 100755 --- a/src/common/host_memory.cpp +++ b/src/common/host_memory.cpp @@ -449,21 +449,52 @@ private: int fd{-1}; // memfd file descriptor, -1 is the error value of memfd_create }; -#else // ^^^ Linux ^^^ +#else // ^^^ Linux ^^^ vvv Generic vvv -#error Please implement the host memory for your platform +class HostMemory::Impl { +public: + explicit Impl(size_t /*backing_size */, size_t /* virtual_size */) { + // This is just a place holder. + // Please implement fastmem in a propper way on your platform. + throw std::bad_alloc{}; + } -#endif + void Map(size_t virtual_offset, size_t host_offset, size_t length) {} + + void Unmap(size_t virtual_offset, size_t length) {} + + void Protect(size_t virtual_offset, size_t length, bool read, bool write) {} + + u8* backing_base{nullptr}; + u8* virtual_base{nullptr}; +}; + +#endif // ^^^ Generic ^^^ HostMemory::HostMemory(size_t backing_size_, size_t virtual_size_) - : backing_size(backing_size_), - virtual_size(virtual_size_), impl{std::make_unique( - AlignUp(backing_size, PageAlignment), - AlignUp(virtual_size, PageAlignment) + 3 * HugePageSize)}, - backing_base{impl->backing_base}, virtual_base{impl->virtual_base} { - virtual_base += 2 * HugePageSize - 1; - virtual_base -= reinterpret_cast(virtual_base) & (HugePageSize - 1); - virtual_base_offset = virtual_base - impl->virtual_base; + : backing_size(backing_size_), virtual_size(virtual_size_) { + try { + // Try to allocate a fastmem arena. + // The implementation will fail with std::bad_alloc on errors. + impl = std::make_unique(AlignUp(backing_size, PageAlignment), + AlignUp(virtual_size, PageAlignment) + + 3 * HugePageSize); + backing_base = impl->backing_base; + virtual_base = impl->virtual_base; + + if (virtual_base) { + virtual_base += 2 * HugePageSize - 1; + virtual_base -= reinterpret_cast(virtual_base) & (HugePageSize - 1); + virtual_base_offset = virtual_base - impl->virtual_base; + } + + } catch (const std::bad_alloc&) { + LOG_CRITICAL(HW_Memory, + "Fastmem unavailable, falling back to VirtualBuffer for memory allocation"); + fallback_buffer = std::make_unique>(backing_size); + backing_base = fallback_buffer->data(); + virtual_base = nullptr; + } } HostMemory::~HostMemory() = default; @@ -478,7 +509,7 @@ void HostMemory::Map(size_t virtual_offset, size_t host_offset, size_t length) { ASSERT(length % PageAlignment == 0); ASSERT(virtual_offset + length <= virtual_size); ASSERT(host_offset + length <= backing_size); - if (length == 0) { + if (length == 0 || !virtual_base || !impl) { return; } impl->Map(virtual_offset + virtual_base_offset, host_offset, length); @@ -488,7 +519,7 @@ void HostMemory::Unmap(size_t virtual_offset, size_t length) { ASSERT(virtual_offset % PageAlignment == 0); ASSERT(length % PageAlignment == 0); ASSERT(virtual_offset + length <= virtual_size); - if (length == 0) { + if (length == 0 || !virtual_base || !impl) { return; } impl->Unmap(virtual_offset + virtual_base_offset, length); @@ -498,7 +529,7 @@ void HostMemory::Protect(size_t virtual_offset, size_t length, bool read, bool w ASSERT(virtual_offset % PageAlignment == 0); ASSERT(length % PageAlignment == 0); ASSERT(virtual_offset + length <= virtual_size); - if (length == 0) { + if (length == 0 || !virtual_base || !impl) { return; } impl->Protect(virtual_offset + virtual_base_offset, length, read, write); diff --git a/src/common/host_memory.h b/src/common/host_memory.h index eaa7d18ab..9b8326d0f 100755 --- a/src/common/host_memory.h +++ b/src/common/host_memory.h @@ -6,6 +6,7 @@ #include #include "common/common_types.h" +#include "common/virtual_buffer.h" namespace Common { @@ -61,6 +62,9 @@ private: u8* backing_base{}; u8* virtual_base{}; size_t virtual_base_offset{}; + + // Fallback if fastmem is not supported on this platform + std::unique_ptr> fallback_buffer; }; } // namespace Common diff --git a/src/yuzu/configuration/configure_cpu.ui b/src/yuzu/configuration/configure_cpu.ui index 36152d93a..31ef9e3f5 100755 --- a/src/yuzu/configuration/configure_cpu.ui +++ b/src/yuzu/configuration/configure_cpu.ui @@ -131,7 +131,7 @@ - Disable adress space checks + Disable address space checks