From 2fb789ce685fdc43a8c7273927cf79dddd6e7b40 Mon Sep 17 00:00:00 2001 From: rude Date: Sun, 9 Mar 2014 10:15:01 +0100 Subject: [PATCH] Upgrade to SDL2.0.2 (8393682d9d96d1516831a397290cb34ceb82129f). --- libs/SDL2/CMakeLists.txt | 7 +- libs/SDL2/README-macosx.txt | 6 +- libs/SDL2/README-windows.txt | 2 +- libs/SDL2/VisualC/SDL_VS2013.sln | 33 +- libs/SDL2/WhatsNew.txt | 24 +- libs/SDL2/cmake/sdlchecks.cmake | 6 +- libs/SDL2/configure | 20 +- libs/SDL2/configure.in | 16 +- libs/SDL2/include/SDL_events.h | 4 +- libs/SDL2/include/SDL_hints.h | 52 +- libs/SDL2/src/SDL.c | 9 +- libs/SDL2/src/audio/SDL_audiocvt.c | 54 +- libs/SDL2/src/cpuinfo/SDL_cpuinfo.c | 20 +- libs/SDL2/src/events/SDL_events.c | 17 +- libs/SDL2/src/events/SDL_gesture.c | 7 +- libs/SDL2/src/events/SDL_mouse.c | 5 +- .../filesystem/windows/SDL_sysfilesystem.c | 64 +- libs/SDL2/src/haptic/darwin/SDL_syshaptic.c | 5 +- libs/SDL2/src/haptic/linux/SDL_syshaptic.c | 4 +- libs/SDL2/src/haptic/windows/SDL_syshaptic.c | 22 +- libs/SDL2/src/joystick/SDL_gamecontroller.c | 2 + libs/SDL2/src/joystick/SDL_gamecontrollerdb.h | 3 +- .../src/joystick/android/SDL_sysjoystick.c | 6 +- .../src/joystick/darwin/SDL_sysjoystick.c | 1142 ++++++----------- .../src/joystick/darwin/SDL_sysjoystick_c.h | 45 +- .../src/joystick/windows/SDL_dxjoystick.c | 5 +- libs/SDL2/src/power/uikit/SDL_syspower.m | 4 +- libs/SDL2/src/render/SDL_render.c | 4 +- .../SDL2/src/render/direct3d/SDL_render_d3d.c | 24 +- libs/SDL2/src/render/opengl/SDL_render_gl.c | 22 +- .../src/render/opengles/SDL_render_gles.c | 25 +- .../src/render/opengles2/SDL_render_gles2.c | 24 +- libs/SDL2/src/stdlib/SDL_stdlib.c | 6 - libs/SDL2/src/test/SDL_test_common.c | 1 + libs/SDL2/src/timer/SDL_timer_c.h | 3 +- libs/SDL2/src/timer/dummy/SDL_systimer.c | 10 +- libs/SDL2/src/timer/haiku/SDL_systimer.c | 10 +- libs/SDL2/src/timer/psp/SDL_systimer.c | 11 +- libs/SDL2/src/timer/unix/SDL_systimer.c | 14 +- libs/SDL2/src/timer/windows/SDL_systimer.c | 28 +- libs/SDL2/src/video/SDL_video.c | 20 +- libs/SDL2/src/video/cocoa/SDL_cocoaevents.m | 38 +- libs/SDL2/src/video/cocoa/SDL_cocoamouse.h | 11 +- libs/SDL2/src/video/cocoa/SDL_cocoamouse.m | 124 +- libs/SDL2/src/video/cocoa/SDL_cocoaopengl.m | 85 +- libs/SDL2/src/video/cocoa/SDL_cocoavideo.h | 1 + libs/SDL2/src/video/cocoa/SDL_cocoavideo.m | 6 + libs/SDL2/src/video/cocoa/SDL_cocoawindow.h | 8 + libs/SDL2/src/video/cocoa/SDL_cocoawindow.m | 212 ++- libs/SDL2/src/video/mir/SDL_mirframebuffer.c | 6 +- .../src/video/uikit/SDL_uikitopenglview.m | 11 +- .../src/video/windows/SDL_windowsevents.c | 32 +- .../SDL2/src/video/windows/SDL_windowsmouse.c | 40 +- .../src/video/windows/SDL_windowsopengles.c | 2 - .../SDL2/src/video/windows/SDL_windowsvideo.c | 2 +- .../src/video/windows/SDL_windowswindow.c | 4 +- .../src/video/windows/SDL_windowswindow.h | 1 + libs/SDL2/src/video/windows/wmmsg.h | 82 +- libs/SDL2/src/video/x11/SDL_x11events.c | 24 +- libs/SDL2/src/video/x11/SDL_x11video.c | 77 ++ libs/SDL2/src/video/x11/SDL_x11video.h | 3 + libs/SDL2/src/video/x11/SDL_x11xinput2.c | 32 +- libs/SDL2/test/testgles2.c | 22 +- 63 files changed, 1450 insertions(+), 1159 deletions(-) diff --git a/libs/SDL2/CMakeLists.txt b/libs/SDL2/CMakeLists.txt index 075b7ab7..ab7783c9 100644 --- a/libs/SDL2/CMakeLists.txt +++ b/libs/SDL2/CMakeLists.txt @@ -235,8 +235,8 @@ set_option(RPATH "Use an rpath when linking SDL" ${UNIX_SYS}) set_option(CLOCK_GETTIME "Use clock_gettime() instead of gettimeofday()" OFF) set_option(INPUT_TSLIB "Use the Touchscreen library for input" ${UNIX_SYS}) set_option(VIDEO_X11 "Use X11 video driver" ${UNIX_SYS}) -set_option(VIDEO_WAYLAND "Use Wayland video driver" OFF) #${UNIX_SYS}) -set_option(VIDEO_MIR "Use Mir video driver" OFF) #${UNIX_SYS}) +set_option(VIDEO_WAYLAND "Use Wayland video driver" ${UNIX_SYS}) +set_option(VIDEO_MIR "Use Mir video driver" ${UNIX_SYS}) dep_option(X11_SHARED "Dynamically load X11 support" ON "VIDEO_X11" OFF) set(SDL_X11_OPTIONS Xcursor Xinerama XInput Xrandr Xscrnsaver XShape Xvm) foreach(_SUB ${SDL_X11_OPTIONS}) @@ -993,6 +993,7 @@ elseif(APPLE) if(SDL_FILESYSTEM) set(SDL_FILESYSTEM_COCOA 1) file(GLOB FILESYSTEM_SOURCES ${SDL2_SOURCE_DIR}/src/filesystem/cocoa/*.m) + set_source_files_properties(${FILESYSTEM_SOURCES} PROPERTIES LANGUAGE C) set(SOURCE_FILES ${SOURCE_FILES} ${FILESYSTEM_SOURCES}) set(HAVE_SDL_FILESYSTEM TRUE) endif() @@ -1261,7 +1262,7 @@ if(SDL_STATIC) set (BUILD_SHARED_LIBS FALSE) add_library(SDL2-static STATIC ${SOURCE_FILES}) set_target_properties(SDL2-static PROPERTIES OUTPUT_NAME "SDL2") - if(WINDOWS) + if(MSVC) set_target_properties(SDL2-static PROPERTIES LINK_FLAGS_RELEASE "/NODEFAULTLIB") set_target_properties(SDL2-static PROPERTIES LINK_FLAGS_DEBUG "/NODEFAULTLIB") set_target_properties(SDL2-static PROPERTIES STATIC_LIBRARY_FLAGS "/NODEFAULTLIB") diff --git a/libs/SDL2/README-macosx.txt b/libs/SDL2/README-macosx.txt index 4d9378fd..895b9d14 100644 --- a/libs/SDL2/README-macosx.txt +++ b/libs/SDL2/README-macosx.txt @@ -26,9 +26,9 @@ ABI compatibility on x86_64 architectures. For best compatibility you should compile your application the same way. A script which wraps gcc to make this easy is provided in test/gcc-fat.sh -Please note that building SDL requires at least the 10.7 SDK (even if you -target back to 10.5 systems). PowerPC support for Mac OS X has been officially -dropped as of SDL 2.0.2. +Please note that building SDL requires at least Xcode 4.6 and the 10.7 SDK +(even if you target back to 10.5 systems). PowerPC support for Mac OS X has +been officially dropped as of SDL 2.0.2. To use the library once it's built, you essential have two possibilities: use the traditional autoconf/automake/make method, or use Xcode. diff --git a/libs/SDL2/README-windows.txt b/libs/SDL2/README-windows.txt index f59b2661..7f9c4a35 100644 --- a/libs/SDL2/README-windows.txt +++ b/libs/SDL2/README-windows.txt @@ -32,7 +32,7 @@ d3dcompiler_* DLL at all (for details on this, see their documentation). However, by default SDL will try to preload the d3dcompiler_46.dll to comply with ANGLE's requirements. If you wish SDL to preload d3dcompiler_43.dll (to support Windows XP) or to skip this step at all, you can use the -SDL_VIDEO_WIN_D3DCOMPILER hint (see SDL_hints.h for more details). +SDL_HINT_VIDEO_WIN_D3DCOMPILER hint (see SDL_hints.h for more details). Known Bugs: diff --git a/libs/SDL2/VisualC/SDL_VS2013.sln b/libs/SDL2/VisualC/SDL_VS2013.sln index 82ac105d..3f84c4db 100644 --- a/libs/SDL2/VisualC/SDL_VS2013.sln +++ b/libs/SDL2/VisualC/SDL_VS2013.sln @@ -106,6 +106,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testjoystick", "tests\testj EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testgles2", "tests\testgles2\testgles2_VS2013.vcxproj", "{E5287C64-0646-4BFA-A772-1DB5A649F35E}" + ProjectSection(ProjectDependencies) = postProject + {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68} = {81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68} + {DA956FD3-E142-46F2-9DD5-C78BEBB56B7A} = {DA956FD3-E142-46F2-9DD5-C78BEBB56B7A} + {DA956FD3-E143-46F2-9FE5-C77BEBC56B1A} = {DA956FD3-E143-46F2-9FE5-C77BEBC56B1A} + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -137,62 +142,72 @@ Global {AAAD1CB5-7ADA-47AE-85A0-08A6EC48FAFB}.Debug|x64.Build.0 = Debug|x64 {AAAD1CB5-7ADA-47AE-85A0-08A6EC48FAFB}.Release|Win32.ActiveCfg = Release|Win32 {AAAD1CB5-7ADA-47AE-85A0-08A6EC48FAFB}.Release|Win32.Build.0 = Release|Win32 - {AAAD1CB5-7ADA-47AE-85A0-08A6EC48FAFB}.Release|x64.ActiveCfg = Release|Win32 + {AAAD1CB5-7ADA-47AE-85A0-08A6EC48FAFB}.Release|x64.ActiveCfg = Release|x64 + {AAAD1CB5-7ADA-47AE-85A0-08A6EC48FAFB}.Release|x64.Build.0 = Release|x64 {26932B24-EFC6-4E3A-B277-ED653DA37968}.Debug|Win32.ActiveCfg = Debug|Win32 {26932B24-EFC6-4E3A-B277-ED653DA37968}.Debug|Win32.Build.0 = Debug|Win32 {26932B24-EFC6-4E3A-B277-ED653DA37968}.Debug|x64.ActiveCfg = Debug|x64 {26932B24-EFC6-4E3A-B277-ED653DA37968}.Debug|x64.Build.0 = Debug|x64 {26932B24-EFC6-4E3A-B277-ED653DA37968}.Release|Win32.ActiveCfg = Release|Win32 {26932B24-EFC6-4E3A-B277-ED653DA37968}.Release|Win32.Build.0 = Release|Win32 - {26932B24-EFC6-4E3A-B277-ED653DA37968}.Release|x64.ActiveCfg = Release|Win32 + {26932B24-EFC6-4E3A-B277-ED653DA37968}.Release|x64.ActiveCfg = Release|x64 + {26932B24-EFC6-4E3A-B277-ED653DA37968}.Release|x64.Build.0 = Release|x64 {CAE4F1D0-314F-4B10-805B-0EFD670133A0}.Debug|Win32.ActiveCfg = Debug|Win32 {CAE4F1D0-314F-4B10-805B-0EFD670133A0}.Debug|Win32.Build.0 = Debug|Win32 {CAE4F1D0-314F-4B10-805B-0EFD670133A0}.Debug|x64.ActiveCfg = Debug|x64 {CAE4F1D0-314F-4B10-805B-0EFD670133A0}.Debug|x64.Build.0 = Debug|x64 {CAE4F1D0-314F-4B10-805B-0EFD670133A0}.Release|Win32.ActiveCfg = Release|Win32 {CAE4F1D0-314F-4B10-805B-0EFD670133A0}.Release|Win32.Build.0 = Release|Win32 - {CAE4F1D0-314F-4B10-805B-0EFD670133A0}.Release|x64.ActiveCfg = Release|Win32 + {CAE4F1D0-314F-4B10-805B-0EFD670133A0}.Release|x64.ActiveCfg = Release|x64 + {CAE4F1D0-314F-4B10-805B-0EFD670133A0}.Release|x64.Build.0 = Release|x64 {8B5CFB38-CCBA-40A8-AD7A-89C57B070884}.Debug|Win32.ActiveCfg = Debug|Win32 {8B5CFB38-CCBA-40A8-AD7A-89C57B070884}.Debug|Win32.Build.0 = Debug|Win32 {8B5CFB38-CCBA-40A8-AD7A-89C57B070884}.Debug|x64.ActiveCfg = Debug|x64 {8B5CFB38-CCBA-40A8-AD7A-89C57B070884}.Debug|x64.Build.0 = Debug|x64 {8B5CFB38-CCBA-40A8-AD7A-89C57B070884}.Release|Win32.ActiveCfg = Release|Win32 {8B5CFB38-CCBA-40A8-AD7A-89C57B070884}.Release|Win32.Build.0 = Release|Win32 - {8B5CFB38-CCBA-40A8-AD7A-89C57B070884}.Release|x64.ActiveCfg = Release|Win32 + {8B5CFB38-CCBA-40A8-AD7A-89C57B070884}.Release|x64.ActiveCfg = Release|x64 + {8B5CFB38-CCBA-40A8-AD7A-89C57B070884}.Release|x64.Build.0 = Release|x64 {26828762-C95D-4637-9CB1-7F0979523813}.Debug|Win32.ActiveCfg = Debug|Win32 {26828762-C95D-4637-9CB1-7F0979523813}.Debug|Win32.Build.0 = Debug|Win32 {26828762-C95D-4637-9CB1-7F0979523813}.Debug|x64.ActiveCfg = Debug|x64 {26828762-C95D-4637-9CB1-7F0979523813}.Debug|x64.Build.0 = Debug|x64 {26828762-C95D-4637-9CB1-7F0979523813}.Release|Win32.ActiveCfg = Release|Win32 {26828762-C95D-4637-9CB1-7F0979523813}.Release|Win32.Build.0 = Release|Win32 - {26828762-C95D-4637-9CB1-7F0979523813}.Release|x64.ActiveCfg = Release|Win32 + {26828762-C95D-4637-9CB1-7F0979523813}.Release|x64.ActiveCfg = Release|x64 + {26828762-C95D-4637-9CB1-7F0979523813}.Release|x64.Build.0 = Release|x64 {40FB7794-D3C3-4CFE-BCF4-A80C96635682}.Debug|Win32.ActiveCfg = Debug|Win32 {40FB7794-D3C3-4CFE-BCF4-A80C96635682}.Debug|Win32.Build.0 = Debug|Win32 {40FB7794-D3C3-4CFE-BCF4-A80C96635682}.Debug|x64.ActiveCfg = Debug|x64 {40FB7794-D3C3-4CFE-BCF4-A80C96635682}.Debug|x64.Build.0 = Debug|x64 {40FB7794-D3C3-4CFE-BCF4-A80C96635682}.Release|Win32.ActiveCfg = Release|Win32 {40FB7794-D3C3-4CFE-BCF4-A80C96635682}.Release|Win32.Build.0 = Release|Win32 - {40FB7794-D3C3-4CFE-BCF4-A80C96635682}.Release|x64.ActiveCfg = Release|Win32 + {40FB7794-D3C3-4CFE-BCF4-A80C96635682}.Release|x64.ActiveCfg = Release|x64 + {40FB7794-D3C3-4CFE-BCF4-A80C96635682}.Release|x64.Build.0 = Release|x64 {EDEA9D00-AF64-45DE-8F60-5957048F2F0F}.Debug|Win32.ActiveCfg = Debug|Win32 {EDEA9D00-AF64-45DE-8F60-5957048F2F0F}.Debug|Win32.Build.0 = Debug|Win32 {EDEA9D00-AF64-45DE-8F60-5957048F2F0F}.Debug|x64.ActiveCfg = Debug|x64 {EDEA9D00-AF64-45DE-8F60-5957048F2F0F}.Debug|x64.Build.0 = Debug|x64 {EDEA9D00-AF64-45DE-8F60-5957048F2F0F}.Release|Win32.ActiveCfg = Release|Win32 - {EDEA9D00-AF64-45DE-8F60-5957048F2F0F}.Release|x64.ActiveCfg = Release|Win32 + {EDEA9D00-AF64-45DE-8F60-5957048F2F0F}.Release|Win32.Build.0 = Release|Win32 + {EDEA9D00-AF64-45DE-8F60-5957048F2F0F}.Release|x64.ActiveCfg = Release|x64 + {EDEA9D00-AF64-45DE-8F60-5957048F2F0F}.Release|x64.Build.0 = Release|x64 {8682FE1E-0CF6-4EDD-9BB5-1733D8C8B4DF}.Debug|Win32.ActiveCfg = Debug|Win32 {8682FE1E-0CF6-4EDD-9BB5-1733D8C8B4DF}.Debug|Win32.Build.0 = Debug|Win32 {8682FE1E-0CF6-4EDD-9BB5-1733D8C8B4DF}.Debug|x64.ActiveCfg = Debug|x64 {8682FE1E-0CF6-4EDD-9BB5-1733D8C8B4DF}.Debug|x64.Build.0 = Debug|x64 {8682FE1E-0CF6-4EDD-9BB5-1733D8C8B4DF}.Release|Win32.ActiveCfg = Release|Win32 {8682FE1E-0CF6-4EDD-9BB5-1733D8C8B4DF}.Release|Win32.Build.0 = Release|Win32 - {8682FE1E-0CF6-4EDD-9BB5-1733D8C8B4DF}.Release|x64.ActiveCfg = Release|Win32 + {8682FE1E-0CF6-4EDD-9BB5-1733D8C8B4DF}.Release|x64.ActiveCfg = Release|x64 + {8682FE1E-0CF6-4EDD-9BB5-1733D8C8B4DF}.Release|x64.Build.0 = Release|x64 {C4E04D18-EF76-4B42-B4C2-16A1BACDC0A3}.Debug|Win32.ActiveCfg = Debug|Win32 {C4E04D18-EF76-4B42-B4C2-16A1BACDC0A3}.Debug|Win32.Build.0 = Debug|Win32 {C4E04D18-EF76-4B42-B4C2-16A1BACDC0A3}.Debug|x64.ActiveCfg = Debug|x64 {C4E04D18-EF76-4B42-B4C2-16A1BACDC0A3}.Debug|x64.Build.0 = Debug|x64 {C4E04D18-EF76-4B42-B4C2-16A1BACDC0A3}.Release|Win32.ActiveCfg = Release|Win32 {C4E04D18-EF76-4B42-B4C2-16A1BACDC0A3}.Release|Win32.Build.0 = Release|Win32 - {C4E04D18-EF76-4B42-B4C2-16A1BACDC0A3}.Release|x64.ActiveCfg = Release|Win32 + {C4E04D18-EF76-4B42-B4C2-16A1BACDC0A3}.Release|x64.ActiveCfg = Release|x64 + {C4E04D18-EF76-4B42-B4C2-16A1BACDC0A3}.Release|x64.Build.0 = Release|x64 {DA956FD3-E143-46F2-9FE5-C77BEBC56B1A}.Debug|Win32.ActiveCfg = Debug|Win32 {DA956FD3-E143-46F2-9FE5-C77BEBC56B1A}.Debug|Win32.Build.0 = Debug|Win32 {DA956FD3-E143-46F2-9FE5-C77BEBC56B1A}.Debug|x64.ActiveCfg = Debug|x64 diff --git a/libs/SDL2/WhatsNew.txt b/libs/SDL2/WhatsNew.txt index bb10895b..ae1ed18e 100644 --- a/libs/SDL2/WhatsNew.txt +++ b/libs/SDL2/WhatsNew.txt @@ -6,8 +6,8 @@ This is a list of major changes in SDL's version history. --------------------------------------------------------------------------- General: * Added SDL_GL_ResetAttributes() to reset OpenGL attributes to default values -* Added an API to load a database of Game Controller mappings from a file: - SDL_GameControllerAddMappingsFromFile +* Added an API to load a database of game controller mappings from a file: + SDL_GameControllerAddMappingsFromFile(), SDL_GameControllerAddMappingsFromRW() * Added game controller mappings for the PS4 and OUYA controllers * Added SDL_GetDefaultAssertionHandler() and SDL_GetAssertionHandler() * Added SDL_DetachThread() @@ -15,23 +15,33 @@ General: * Added SDL_vsscanf(), SDL_acos(), and SDL_asin() to the stdlib routines * EGL can now create/manage OpenGL and OpenGL ES 1.x/2.x contexts, and share them using SDL_GL_SHARE_WITH_CURRENT_CONTEXT +* Added a field "clicks" to the mouse button event which records whether the event is a single click, double click, etc. +* The screensaver is now disabled by default, and there is a hint SDL_HINT_VIDEO_ALLOW_SCREENSAVER that can change that behavior. +* Added a hint SDL_HINT_MOUSE_RELATIVE_MODE_WARP to specify whether mouse relative mode should be emulated using mouse warping. * testgl2 does not need to link with libGL anymore * Added testgles2 test program to demonstrate working with OpenGL ES 2.0 * Added controllermap test program to visually map a game controller - + Windows: * Support for OpenGL ES 2.x contexts using either WGL or EGL (natively via the driver or emulated through ANGLE) +* Added a hint SDL_HINT_VIDEO_WIN_D3DCOMPILER to specify which D3D shader compiler to use for OpenGL ES 2 support through ANGLE +* Added a hint SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT that is useful when creating multiple windows that should share the same OpenGL context. +* Added an event SDL_RENDER_TARGETS_RESET that is sent when D3D9 render targets are reset after the device has been restored. + +Mac OS X: +* Added a hint SDL_HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK to control whether Ctrl+click should be treated as a right click on Mac OS X. This is off by default. + +Linux: +* Fixed fullscreen and focused behavior when receiving NotifyGrab events +* Added experimental Wayland and Mir support, disabled by default Android: * Joystick support (minimum SDK version required to build SDL is now 12, the required runtime version remains at 10, but on such devices joystick support won't be available). * Hotplugging support for joysticks - -Linux: -* Fixed fullscreen and focused behavior when receiving NotifyGrab events -* Added experimental Wayland and Mir support, disabled by default +* Added a hint SDL_HINT_ACCELEROMETER_AS_JOYSTICK to control whether the accelerometer should be listed as a 3 axis joystick, which it will by default. --------------------------------------------------------------------------- diff --git a/libs/SDL2/cmake/sdlchecks.cmake b/libs/SDL2/cmake/sdlchecks.cmake index 15f06b05..2cd09e6f 100644 --- a/libs/SDL2/cmake/sdlchecks.cmake +++ b/libs/SDL2/cmake/sdlchecks.cmake @@ -556,9 +556,9 @@ endmacro(CheckWayland) # macro(CheckCOCOA) if(VIDEO_COCOA) - check_objc_source_compiles(" - #import - int main (int argc, char** argv) {}" HAVE_VIDEO_COCOA) + if(APPLE) # Apple always has Cocoa. + set(HAVE_VIDEO_COCOA TRUE) + endif(APPLE) if(HAVE_VIDEO_COCOA) file(GLOB COCOA_SOURCES ${SDL2_SOURCE_DIR}/src/video/cocoa/*.m) set_source_files_properties(${COCOA_SOURCES} PROPERTIES LANGUAGE C) diff --git a/libs/SDL2/configure b/libs/SDL2/configure index ccb585e2..dc614f79 100644 --- a/libs/SDL2/configure +++ b/libs/SDL2/configure @@ -18688,9 +18688,9 @@ CheckWayland() if test "${enable_video_wayland+set}" = set; then : enableval=$enable_video_wayland; else - enable_video_wayland=no + enable_video_wayland=yes fi - #yes) + # Check whether --enable-video-wayland-qt-touch was given. if test "${enable_video_wayland_qt_touch+set}" = set; then : @@ -18842,9 +18842,9 @@ CheckMir() if test "${enable_video_mir+set}" = set; then : enableval=$enable_video_mir; else - enable_video_mir=no + enable_video_mir=yes fi - #yes) + if test x$enable_video = xyes -a x$enable_video_mir = xyes; then # Extract the first word of "pkg-config", so it can be a program name with args. @@ -20173,11 +20173,6 @@ main () int event_type = XI_TouchBegin; XITouchClassInfo *t; -Status -XIAllowTouchEvents(Display *a,int b,unsigned int c,Window d,int f) -{ - return (Status)0; -} ; return 0; @@ -22808,7 +22803,12 @@ $as_echo "#define SDL_LOADSO_WINDOWS 1" >>confdefs.h have_loadso=yes fi # Set up the system libraries we need - EXTRA_LDFLAGS="$EXTRA_LDFLAGS -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lversion -luuid -XCClinker -static-libgcc" + if test -f /lib/w32api/libuuid.a; then + LIBUUID=/lib/w32api/libuuid.a + else + LIBUUID=-luuid + fi + EXTRA_LDFLAGS="$EXTRA_LDFLAGS -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lversion $LIBUUID -XCClinker -static-libgcc" # The Windows platform requires special setup VERSION_SOURCES="$srcdir/src/main/windows/*.rc" SDLMAIN_SOURCES="$srcdir/src/main/windows/*.c" diff --git a/libs/SDL2/configure.in b/libs/SDL2/configure.in index 3c7adcba..ee22e420 100644 --- a/libs/SDL2/configure.in +++ b/libs/SDL2/configure.in @@ -1164,7 +1164,7 @@ CheckWayland() { AC_ARG_ENABLE(video-wayland, AC_HELP_STRING([--enable-video-wayland], [use Wayland video driver [[default=yes]]]), - ,enable_video_wayland=no) #yes) + ,enable_video_wayland=yes) AC_ARG_ENABLE(video-wayland-qt-touch, AC_HELP_STRING([--enable-video-wayland-qt-touch], [QtWayland server support for Wayland video driver [[default=yes]]]), @@ -1246,7 +1246,7 @@ CheckMir() { AC_ARG_ENABLE(video-mir, AC_HELP_STRING([--enable-video-mir], [use Mir video driver [[default=yes]]]), - ,enable_video_mir=no) #yes) + ,enable_video_mir=yes) if test x$enable_video = xyes -a x$enable_video_mir = xyes; then AC_PATH_PROG(PKG_CONFIG, pkg-config, no) @@ -1555,11 +1555,6 @@ AC_HELP_STRING([--enable-video-x11-xinput], [enable X11 XInput extension for man ],[ int event_type = XI_TouchBegin; XITouchClassInfo *t; -Status -XIAllowTouchEvents(Display *a,int b,unsigned int c,Window d,int f) -{ - return (Status)0; -} ],[ have_xinput2_multitouch=yes AC_DEFINE(SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH) @@ -2860,7 +2855,12 @@ AC_HELP_STRING([--enable-render-d3d], [enable the Direct3D render driver [[defau have_loadso=yes fi # Set up the system libraries we need - EXTRA_LDFLAGS="$EXTRA_LDFLAGS -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lversion -luuid -XCClinker -static-libgcc" + if test -f /lib/w32api/libuuid.a; then + LIBUUID=/lib/w32api/libuuid.a + else + LIBUUID=-luuid + fi + EXTRA_LDFLAGS="$EXTRA_LDFLAGS -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lversion $LIBUUID -XCClinker -static-libgcc" # The Windows platform requires special setup VERSION_SOURCES="$srcdir/src/main/windows/*.rc" SDLMAIN_SOURCES="$srcdir/src/main/windows/*.c" diff --git a/libs/SDL2/include/SDL_events.h b/libs/SDL2/include/SDL_events.h index 0b848b94..fc5a145e 100644 --- a/libs/SDL2/include/SDL_events.h +++ b/libs/SDL2/include/SDL_events.h @@ -257,8 +257,8 @@ typedef struct SDL_MouseWheelEvent Uint32 timestamp; Uint32 windowID; /**< The window with mouse focus, if any */ Uint32 which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */ - Sint32 x; /**< The amount scrolled horizontally */ - Sint32 y; /**< The amount scrolled vertically */ + Sint32 x; /**< The amount scrolled horizontally, positive to the right and negative to the left */ + Sint32 y; /**< The amount scrolled vertically, positive away from the user and negative toward the user */ } SDL_MouseWheelEvent; /** diff --git a/libs/SDL2/include/SDL_hints.h b/libs/SDL2/include/SDL_hints.h index 0c0f88f6..a7c01620 100644 --- a/libs/SDL2/include/SDL_hints.h +++ b/libs/SDL2/include/SDL_hints.h @@ -128,6 +128,17 @@ extern "C" { */ #define SDL_HINT_RENDER_VSYNC "SDL_RENDER_VSYNC" +/** + * \brief A variable controlling whether the screensaver is enabled. + * + * This variable can be set to the following values: + * "0" - Disable screensaver + * "1" - Enable screensaver + * + * By default SDL will disable the screensaver. + */ +#define SDL_HINT_VIDEO_ALLOW_SCREENSAVER "SDL_VIDEO_ALLOW_SCREENSAVER" + /** * \brief A variable controlling whether the X11 VidMode extension should be used. * @@ -189,17 +200,6 @@ extern "C" { */ #define SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS "SDL_VIDEO_MINIMIZE_ON_FOCUS_LOSS" -/** - * \brief Set whether windows go fullscreen in their own spaces on Mac OS X - * - * This variable can be set to the following values: - * "0" - Fullscreen windows will use the classic fullscreen mode - * "1" - Fullscreen windows will use fullscreen spaces - * - * By default SDL will use the classic fullscreen mode. - */ -#define SDL_HINT_VIDEO_FULLSCREEN_SPACES "SDL_VIDEO_FULLSCREEN_SPACES" - /** * \brief A variable controlling whether the idle timer is disabled on iOS. * @@ -233,15 +233,15 @@ extern "C" { * "0" - List only real joysticks and accept input from them * "1" - List real joysticks along with the accelerometer as if it were a 3 axis joystick (the default). */ -#define SDL_HINT_ACCEL_AS_JOY "SDL_ACCEL_AS_JOY" +#define SDL_HINT_ACCELEROMETER_AS_JOYSTICK "SDL_ACCELEROMETER_AS_JOYSTICK" /** * \brief A variable that lets you disable the detection and use of Xinput gamepad devices * * The variable can be set to the following values: - * "0" - Disable XInput timer (only uses direct input) - * "1" - Enable XInput timer (the default) + * "0" - Disable XInput detection (only uses direct input) + * "1" - Enable XInput detection (the default) */ #define SDL_HINT_XINPUT_ENABLED "SDL_XINPUT_ENABLED" @@ -264,7 +264,7 @@ extern "C" { * "0" - Disable joystick & gamecontroller input events when the * application is in the background. * "1" - Enable joystick & gamecontroller input events when the - * application is in the backgroumd. + * application is in the background. * * The default value is "0". This hint may be set at any time. */ @@ -318,7 +318,7 @@ extern "C" { * SDL has EGL and OpenGL ES2 support on Windows via the ANGLE project. It * can use two different sets of binaries, those compiled by the user from source * or those provided by the Chrome browser. In the later case, these binaries require -* that SDL loads +* that SDL loads a DLL providing the shader compiler. * * This variable can be set to the following values: * "d3dcompiler_46.dll" - default, best for Vista or later. @@ -347,6 +347,26 @@ extern "C" { */ #define SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT "SDL_VIDEO_WINDOW_SHARE_PIXEL_FORMAT" +/** + * \brief A variable that dictates policy for fullscreen Spaces on Mac OS X. + * + * This hint only applies to Mac OS X. + * + * The variable can be set to the following values: + * "0" - Disable Spaces support (FULLSCREEN_DESKTOP won't use them and + * SDL_WINDOW_RESIZABLE windows won't offer the "fullscreen" + * button on their titlebars). + * "1" - Enable Spaces support (FULLSCREEN_DESKTOP will use them and + * SDL_WINDOW_RESIZABLE windows will offer the "fullscreen" + * button on their titlebars. + * + * The default value is "1". Spaces are disabled regardless of this hint if + * the OS isn't at least Mac OS X Lion (10.7). This hint must be set before + * any windows are created. + */ +#define SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES "SDL_VIDEO_MAC_FULLSCREEN_SPACES" + + /** * \brief An enumeration of hint priorities */ diff --git a/libs/SDL2/src/SDL.c b/libs/SDL2/src/SDL.c index 9a8da1ee..dacd0f7a 100644 --- a/libs/SDL2/src/SDL.c +++ b/libs/SDL2/src/SDL.c @@ -38,7 +38,8 @@ #if !SDL_TIMERS_DISABLED extern int SDL_TimerInit(void); extern void SDL_TimerQuit(void); -extern void SDL_InitTicks(void); +extern void SDL_TicksInit(void); +extern void SDL_TicksQuit(void); #endif #if SDL_VIDEO_DRIVER_WINDOWS extern int SDL_HelperWindowCreate(void); @@ -123,7 +124,7 @@ SDL_InitSubSystem(Uint32 flags) #endif #if !SDL_TIMERS_DISABLED - SDL_InitTicks(); + SDL_TicksInit(); #endif if ((flags & SDL_INIT_GAMECONTROLLER)) { @@ -355,6 +356,10 @@ SDL_Quit(void) #endif SDL_QuitSubSystem(SDL_INIT_EVERYTHING); +#if !SDL_TIMERS_DISABLED + SDL_TicksQuit(); +#endif + SDL_ClearHints(); SDL_AssertionsQuit(); SDL_LogResetPriorities(); diff --git a/libs/SDL2/src/audio/SDL_audiocvt.c b/libs/SDL2/src/audio/SDL_audiocvt.c index b167b94a..518735bf 100644 --- a/libs/SDL2/src/audio/SDL_audiocvt.c +++ b/libs/SDL2/src/audio/SDL_audiocvt.c @@ -39,7 +39,9 @@ SDL_ConvertMono(SDL_AudioCVT * cvt, SDL_AudioFormat format) #ifdef DEBUG_CONVERT fprintf(stderr, "Converting to mono\n"); #endif - switch (format & (SDL_AUDIO_MASK_SIGNED | SDL_AUDIO_MASK_BITSIZE)) { + switch (format & (SDL_AUDIO_MASK_SIGNED | + SDL_AUDIO_MASK_BITSIZE | + SDL_AUDIO_MASK_DATATYPE)) { case AUDIO_U8: { Uint8 *src, *dst; @@ -331,7 +333,9 @@ SDL_ConvertSurround(SDL_AudioCVT * cvt, SDL_AudioFormat format) fprintf(stderr, "Converting stereo to surround\n"); #endif - switch (format & (SDL_AUDIO_MASK_SIGNED | SDL_AUDIO_MASK_BITSIZE)) { + switch (format & (SDL_AUDIO_MASK_SIGNED | + SDL_AUDIO_MASK_BITSIZE | + SDL_AUDIO_MASK_DATATYPE)) { case AUDIO_U8: { Uint8 *src, *dst, lf, rf, ce; @@ -499,8 +503,8 @@ SDL_ConvertSurround(SDL_AudioCVT * cvt, SDL_AudioFormat format) case AUDIO_S32: { Sint32 lf, rf, ce; - const Uint32 *src = (const Uint32 *) cvt->buf + cvt->len_cvt; - Uint32 *dst = (Uint32 *) cvt->buf + cvt->len_cvt * 3; + const Uint32 *src = (const Uint32 *) (cvt->buf + cvt->len_cvt); + Uint32 *dst = (Uint32 *) (cvt->buf + cvt->len_cvt * 3); if (SDL_AUDIO_ISBIGENDIAN(format)) { for (i = cvt->len_cvt / 8; i; --i) { @@ -537,8 +541,8 @@ SDL_ConvertSurround(SDL_AudioCVT * cvt, SDL_AudioFormat format) case AUDIO_F32: { float lf, rf, ce; - const float *src = (const float *) cvt->buf + cvt->len_cvt; - float *dst = (float *) cvt->buf + cvt->len_cvt * 3; + const float *src = (const float *) (cvt->buf + cvt->len_cvt); + float *dst = (float *) (cvt->buf + cvt->len_cvt * 3); if (SDL_AUDIO_ISBIGENDIAN(format)) { for (i = cvt->len_cvt / 8; i; --i) { @@ -588,7 +592,9 @@ SDL_ConvertSurround_4(SDL_AudioCVT * cvt, SDL_AudioFormat format) fprintf(stderr, "Converting stereo to quad\n"); #endif - switch (format & (SDL_AUDIO_MASK_SIGNED | SDL_AUDIO_MASK_BITSIZE)) { + switch (format & (SDL_AUDIO_MASK_SIGNED | + SDL_AUDIO_MASK_BITSIZE | + SDL_AUDIO_MASK_DATATYPE)) { case AUDIO_U8: { Uint8 *src, *dst, lf, rf, ce; @@ -762,6 +768,40 @@ SDL_ConvertSurround_4(SDL_AudioCVT * cvt, SDL_AudioFormat format) } } break; + + case AUDIO_F32: + { + const float *src = (const float *) (cvt->buf + cvt->len_cvt); + float *dst = (float *) (cvt->buf + cvt->len_cvt * 2); + float lf, rf, ce; + + if (SDL_AUDIO_ISBIGENDIAN(format)) { + for (i = cvt->len_cvt / 8; i; --i) { + dst -= 4; + src -= 2; + lf = SDL_SwapFloatBE(src[0]); + rf = SDL_SwapFloatBE(src[1]); + ce = (lf / 2) + (rf / 2); + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = SDL_SwapFloatBE(lf - ce); + dst[3] = SDL_SwapFloatBE(rf - ce); + } + } else { + for (i = cvt->len_cvt / 8; i; --i) { + dst -= 4; + src -= 2; + lf = SDL_SwapFloatLE(src[0]); + rf = SDL_SwapFloatLE(src[1]); + ce = (lf / 2) + (rf / 2); + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = SDL_SwapFloatLE(lf - ce); + dst[3] = SDL_SwapFloatLE(rf - ce); + } + } + } + break; } cvt->len_cvt *= 2; if (cvt->filters[++cvt->filter_index]) { diff --git a/libs/SDL2/src/cpuinfo/SDL_cpuinfo.c b/libs/SDL2/src/cpuinfo/SDL_cpuinfo.c index 11acea57..6a529ae0 100644 --- a/libs/SDL2/src/cpuinfo/SDL_cpuinfo.c +++ b/libs/SDL2/src/cpuinfo/SDL_cpuinfo.c @@ -98,7 +98,7 @@ CPU_haveCPUID(void) ); #elif defined(__GNUC__) && defined(__x86_64__) /* Technically, if this is being compiled under __x86_64__ then it has -CPUid by definition. But it's nice to be able to prove it. :) */ + CPUid by definition. But it's nice to be able to prove it. :) */ __asm__ ( " pushfq # Get original EFLAGS \n" " popq %%rax \n" @@ -131,6 +131,8 @@ CPUid by definition. But it's nice to be able to prove it. :) */ mov has_CPUID,1 ; We have CPUID support done: } +#elif defined(_MSC_VER) && defined(_M_X64) + has_CPUID = 1; #elif defined(__sun) && defined(__i386) __asm ( " pushfl \n" @@ -191,7 +193,17 @@ done: __asm mov b, ebx \ __asm mov c, ecx \ __asm mov d, edx \ - } +} +#elif defined(_MSC_VER) && defined(_M_X64) +#define cpuid(func, a, b, c, d) \ +{ \ + int CPUInfo[4]; \ + __cpuid(CPUInfo, func); \ + a = CPUInfo[0]; \ + b = CPUInfo[1]; \ + c = CPUInfo[2]; \ + d = CPUInfo[3]; \ +} #else #define cpuid(func, a, b, c, d) \ a = b = c = d = 0 @@ -653,7 +665,7 @@ SDL_GetSystemRAM(void) #endif #ifdef HAVE_SYSCTLBYNAME if (SDL_SystemRAM <= 0) { -#ifdef __FreeBSD__ +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) #ifdef HW_REALMEM int mib[2] = {CTL_HW, HW_REALMEM}; #else @@ -662,7 +674,7 @@ SDL_GetSystemRAM(void) #endif /* HW_REALMEM */ #else int mib[2] = {CTL_HW, HW_MEMSIZE}; -#endif /* __FreeBSD__ */ +#endif /* __FreeBSD__ || __FreeBSD_kernel__ */ Uint64 memsize = 0; size_t len = sizeof(memsize); diff --git a/libs/SDL2/src/events/SDL_events.c b/libs/SDL2/src/events/SDL_events.c index 3944ade2..7a98c302 100644 --- a/libs/SDL2/src/events/SDL_events.c +++ b/libs/SDL2/src/events/SDL_events.c @@ -503,17 +503,28 @@ SDL_GetEventFilter(SDL_EventFilter * filter, void **userdata) void SDL_AddEventWatch(SDL_EventFilter filter, void *userdata) { - SDL_EventWatcher *watcher; + SDL_EventWatcher *watcher, *tail; watcher = (SDL_EventWatcher *)SDL_malloc(sizeof(*watcher)); if (!watcher) { /* Uh oh... */ return; } + + /* create the watcher */ watcher->callback = filter; watcher->userdata = userdata; - watcher->next = SDL_event_watchers; - SDL_event_watchers = watcher; + watcher->next = NULL; + + /* add the watcher to the end of the list */ + if (SDL_event_watchers) { + for (tail = SDL_event_watchers; tail->next; tail = tail->next) { + continue; + } + tail->next = watcher; + } else { + SDL_event_watchers = watcher; + } } /* FIXME: This is not thread-safe yet */ diff --git a/libs/SDL2/src/events/SDL_gesture.c b/libs/SDL2/src/events/SDL_gesture.c index a6ef5b5d..a47ab7d1 100644 --- a/libs/SDL2/src/events/SDL_gesture.c +++ b/libs/SDL2/src/events/SDL_gesture.c @@ -418,13 +418,8 @@ int SDL_GestureAddTouch(SDL_TouchID touchId) SDL_gestureTouch = gestureTouch; - SDL_gestureTouch[SDL_numGestureTouches].numDownFingers = 0; + SDL_zero(SDL_gestureTouch[SDL_numGestureTouches]); SDL_gestureTouch[SDL_numGestureTouches].id = touchId; - - SDL_gestureTouch[SDL_numGestureTouches].numDollarTemplates = 0; - - SDL_gestureTouch[SDL_numGestureTouches].recording = SDL_FALSE; - SDL_numGestureTouches++; return 0; } diff --git a/libs/SDL2/src/events/SDL_mouse.c b/libs/SDL2/src/events/SDL_mouse.c index 5e33cd5b..236b8c54 100644 --- a/libs/SDL2/src/events/SDL_mouse.c +++ b/libs/SDL2/src/events/SDL_mouse.c @@ -538,7 +538,10 @@ SDL_SetRelativeMouseMode(SDL_bool enabled) } else if (enabled && ShouldUseRelativeModeWarp(mouse)) { mouse->relative_mode_warp = SDL_TRUE; } else if (mouse->SetRelativeMouseMode(enabled) < 0) { - return -1; + if (enabled) { + // Fall back to warp mode if native relative mode failed + mouse->relative_mode_warp = SDL_TRUE; + } } mouse->relative_mode = enabled; diff --git a/libs/SDL2/src/filesystem/windows/SDL_sysfilesystem.c b/libs/SDL2/src/filesystem/windows/SDL_sysfilesystem.c index caa299ac..a15956f6 100644 --- a/libs/SDL2/src/filesystem/windows/SDL_sysfilesystem.c +++ b/libs/SDL2/src/filesystem/windows/SDL_sysfilesystem.c @@ -69,28 +69,70 @@ SDL_GetPrefPath(const char *org, const char *app) * NULL, &wszPath); */ - TCHAR path[MAX_PATH]; + WCHAR path[MAX_PATH]; char *utf8 = NULL; char *retval = NULL; + WCHAR* worg = NULL; + WCHAR* wapp = NULL; + size_t new_wpath_len = 0; + BOOL api_result = FALSE; - if (!SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, path))) { + if (!SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, path))) { WIN_SetError("Couldn't locate our prefpath"); return NULL; } - utf8 = WIN_StringToUTF8(path); - if (utf8) { - const size_t len = SDL_strlen(utf8) + SDL_strlen(org) + SDL_strlen(app) + 4; - retval = (char *) SDL_malloc(len); - if (!retval) { - SDL_free(utf8); - SDL_OutOfMemory(); + worg = WIN_UTF8ToString(org); + if (worg == NULL) { + SDL_OutOfMemory(); + return NULL; + } + + wapp = WIN_UTF8ToString(app); + if (wapp == NULL) { + SDL_free(worg); + SDL_OutOfMemory(); + return NULL; + } + + new_wpath_len = lstrlenW(worg) + lstrlenW(wapp) + lstrlenW(path) + 3; + + if ((new_wpath_len + 1) > MAX_PATH) { + SDL_free(worg); + SDL_free(wapp); + WIN_SetError("Path too long."); + return NULL; + } + + lstrcatW(path, L"\\"); + lstrcatW(path, worg); + SDL_free(worg); + + api_result = CreateDirectoryW(path, NULL); + if (api_result == FALSE) { + if (GetLastError() != ERROR_ALREADY_EXISTS) { + SDL_free(wapp); + WIN_SetError("Couldn't create a prefpath."); return NULL; } - SDL_snprintf(retval, len, "%s\\%s\\%s\\", utf8, org, app); - SDL_free(utf8); } + lstrcatW(path, L"\\"); + lstrcatW(path, wapp); + SDL_free(wapp); + + api_result = CreateDirectoryW(path, NULL); + if (api_result == FALSE) { + if (GetLastError() != ERROR_ALREADY_EXISTS) { + WIN_SetError("Couldn't create a prefpath."); + return NULL; + } + } + + lstrcatW(path, L"\\"); + + retval = WIN_StringToUTF8(path); + return retval; } diff --git a/libs/SDL2/src/haptic/darwin/SDL_syshaptic.c b/libs/SDL2/src/haptic/darwin/SDL_syshaptic.c index 4a62e350..14beb6c8 100644 --- a/libs/SDL2/src/haptic/darwin/SDL_syshaptic.c +++ b/libs/SDL2/src/haptic/darwin/SDL_syshaptic.c @@ -156,7 +156,7 @@ SDL_SYS_HapticInit(void) io_service_t device; if (numhaptics != -1) { - return SDL_Error("Haptic subsystem already initialized!"); + return SDL_SetError("Haptic subsystem already initialized!"); } numhaptics = 0; @@ -237,7 +237,7 @@ MacHaptic_MaybeAddDevice( io_object_t device ) } } - item = (SDL_hapticlist_item *)SDL_malloc( sizeof(SDL_hapticlist_item)); + item = (SDL_hapticlist_item *)SDL_calloc(1, sizeof(SDL_hapticlist_item)); if (item == NULL) { return SDL_SetError("Could not allocate haptic storage"); } @@ -248,7 +248,6 @@ MacHaptic_MaybeAddDevice( io_object_t device ) /* Set basic device data. */ HIDGetDeviceProduct(device, item->name); item->dev = device; - item->haptic = NULL; /* Set usage pages. */ hidProperties = 0; diff --git a/libs/SDL2/src/haptic/linux/SDL_syshaptic.c b/libs/SDL2/src/haptic/linux/SDL_syshaptic.c index 995001c9..281a9316 100644 --- a/libs/SDL2/src/haptic/linux/SDL_syshaptic.c +++ b/libs/SDL2/src/haptic/linux/SDL_syshaptic.c @@ -282,11 +282,11 @@ MaybeAddDevice(const char *path) return -1; } - item = (SDL_hapticlist_item *) SDL_malloc(sizeof (SDL_hapticlist_item)); + item = (SDL_hapticlist_item *) SDL_calloc(1, sizeof (SDL_hapticlist_item)); if (item == NULL) { return -1; } - SDL_zerop(item); + item->fname = SDL_strdup(path); if ( (item->fname == NULL) ) { SDL_free(item->fname); diff --git a/libs/SDL2/src/haptic/windows/SDL_syshaptic.c b/libs/SDL2/src/haptic/windows/SDL_syshaptic.c index 59f74566..a4b5e426 100644 --- a/libs/SDL2/src/haptic/windows/SDL_syshaptic.c +++ b/libs/SDL2/src/haptic/windows/SDL_syshaptic.c @@ -253,13 +253,11 @@ DirectInputHaptic_MaybeAddDevice(const DIDEVICEINSTANCE * pdidInstance) return -1; /* not a device we can use. */ } - item = (SDL_hapticlist_item *)SDL_malloc( sizeof(SDL_hapticlist_item)); + item = (SDL_hapticlist_item *)SDL_calloc(1, sizeof(SDL_hapticlist_item)); if (item == NULL) { return SDL_OutOfMemory(); } - SDL_zerop(item); - item->name = WIN_StringToUTF8(pdidInstance->tszProductName); if (!item->name) { SDL_free(item); @@ -941,20 +939,32 @@ SDL_SYS_HapticQuit(void) { SDL_hapticlist_item *item; SDL_hapticlist_item *next = NULL; + SDL_Haptic *hapticitem = NULL; - if (loaded_xinput) { - WIN_UnloadXInputDLL(); - loaded_xinput = SDL_FALSE; + extern SDL_Haptic *SDL_haptics; + for (hapticitem = SDL_haptics; hapticitem; hapticitem = hapticitem->next) { + if ((hapticitem->hwdata->bXInputHaptic) && (hapticitem->hwdata->thread)) { + /* we _have_ to stop the thread before we free the XInput DLL! */ + hapticitem->hwdata->stopThread = 1; + SDL_WaitThread(hapticitem->hwdata->thread, NULL); + hapticitem->hwdata->thread = NULL; + } } for (item = SDL_hapticlist; item; item = next) { /* Opened and not closed haptics are leaked, this is on purpose. * Close your haptic devices after usage. */ + /* !!! FIXME: (...is leaking on purpose a good idea?) */ next = item->next; SDL_free(item->name); SDL_free(item); } + if (loaded_xinput) { + WIN_UnloadXInputDLL(); + loaded_xinput = SDL_FALSE; + } + if (dinput != NULL) { IDirectInput8_Release(dinput); dinput = NULL; diff --git a/libs/SDL2/src/joystick/SDL_gamecontroller.c b/libs/SDL2/src/joystick/SDL_gamecontroller.c index a9fe3276..fc44bdb9 100644 --- a/libs/SDL2/src/joystick/SDL_gamecontroller.c +++ b/libs/SDL2/src/joystick/SDL_gamecontroller.c @@ -835,6 +835,7 @@ SDL_GameControllerLoadHints() char *pUserMappings = SDL_malloc( nchHints + 1 ); char *pTempMappings = pUserMappings; SDL_memcpy( pUserMappings, hint, nchHints ); + pUserMappings[nchHints] = '\0'; while ( pUserMappings ) { char *pchNewLine = NULL; @@ -1223,6 +1224,7 @@ SDL_GameControllerQuit(void) pControllerMap = s_pSupportedControllers; s_pSupportedControllers = s_pSupportedControllers->next; SDL_free( pControllerMap->name ); + SDL_free( pControllerMap->mapping ); SDL_free( pControllerMap ); } diff --git a/libs/SDL2/src/joystick/SDL_gamecontrollerdb.h b/libs/SDL2/src/joystick/SDL_gamecontrollerdb.h index 6c969d31..886d0180 100644 --- a/libs/SDL2/src/joystick/SDL_gamecontrollerdb.h +++ b/libs/SDL2/src/joystick/SDL_gamecontrollerdb.h @@ -49,7 +49,7 @@ static const char *s_ControllerMappings [] = "6d040000000000001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,", "6d0400000000000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* This includes F710 in DInput mode and the "Logitech Cordless RumblePad 2", at the very least. */ "4c050000000000006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,", - "4c05000000000000c405000000000000,PS4 Controller,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,lefttrigger:a3,rightshoulder:b5,righttrigger:a4,leftstick:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a5," + "4c05000000000000c405000000000000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", "5e040000000000008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,", #elif defined(__LINUX__) "0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,", @@ -59,6 +59,7 @@ static const char *s_ControllerMappings [] = "030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", "030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,", /* Guide button doesn't seem to be sent in DInput mode. */ "030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", +"050000003620000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,", "030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,", "030000004c050000c405000011010000,PS4 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,", "03000000de280000ff11000001000000,Valve Streaming Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,", diff --git a/libs/SDL2/src/joystick/android/SDL_sysjoystick.c b/libs/SDL2/src/joystick/android/SDL_sysjoystick.c index ce49fa93..422c5f5f 100644 --- a/libs/SDL2/src/joystick/android/SDL_sysjoystick.c +++ b/libs/SDL2/src/joystick/android/SDL_sysjoystick.c @@ -379,11 +379,11 @@ Android_RemoveJoystick(int device_id) int SDL_SYS_JoystickInit(void) { - const char *env; + const char *hint; SDL_SYS_JoystickDetect(); - env = SDL_GetHint(SDL_HINT_ACCEL_AS_JOY); - if (!env || SDL_atoi(env)) { + hint = SDL_GetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK); + if (!hint || SDL_atoi(hint)) { /* Default behavior, accelerometer as joystick */ Android_AddJoystick(ANDROID_ACCELEROMETER_DEVICE_ID, ANDROID_ACCELEROMETER_NAME, SDL_TRUE, 0, 3, 0, 0); } diff --git a/libs/SDL2/src/joystick/darwin/SDL_sysjoystick.c b/libs/SDL2/src/joystick/darwin/SDL_sysjoystick.c index 4be01623..bdface77 100644 --- a/libs/SDL2/src/joystick/darwin/SDL_sysjoystick.c +++ b/libs/SDL2/src/joystick/darwin/SDL_sysjoystick.c @@ -22,22 +22,7 @@ #ifdef SDL_JOYSTICK_IOKIT -/* SDL joystick driver for Darwin / Mac OS X, based on the IOKit HID API */ -/* Written 2001 by Max Horn */ - -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include /* for NewPtrClear, DisposePtr */ -#include /* For force feedback testing. */ #include @@ -53,75 +38,99 @@ #include "../../events/SDL_events_c.h" #endif +/* The base object of the HID Manager API */ +static IOHIDManagerRef hidman = NULL; /* Linked list of all available devices */ static recDevice *gpDeviceList = NULL; -/* OSX reference to the notification object that tells us about device insertion/removal */ -IONotificationPortRef notificationPort = 0; -/* if 1 then a device was added since the last update call */ + +/* if SDL_TRUE then a device was added since the last update call */ static SDL_bool s_bDeviceAdded = SDL_FALSE; static SDL_bool s_bDeviceRemoved = SDL_FALSE; /* static incrementing counter for new joystick devices seen on the system. Devices should start with index 0 */ static int s_joystick_instance_id = -1; + static void -HIDReportErrorNum(char *strError, long numError) +FreeElementList(recElement *pElement) { - SDL_SetError(strError); + while (pElement) { + recElement *pElementNext = pElement->pNext; + SDL_free(pElement); + pElement = pElementNext; + } } -static void HIDGetCollectionElements(CFMutableDictionaryRef deviceProperties, - recDevice * pDevice); +static recDevice * +FreeDevice(recDevice *removeDevice) +{ + recDevice *pDeviceNext = NULL; + if (removeDevice) { + /* save next device prior to disposing of this device */ + pDeviceNext = removeDevice->pNext; -/* returns current value for element, polling element - * will return 0 on error conditions which should be accounted for by application - */ + if ( gpDeviceList == removeDevice ) { + gpDeviceList = pDeviceNext; + } else { + recDevice *device = gpDeviceList; + while (device->pNext != removeDevice) { + device = device->pNext; + } + device->pNext = pDeviceNext; + } + removeDevice->pNext = NULL; + + /* free element lists */ + FreeElementList(removeDevice->firstAxis); + FreeElementList(removeDevice->firstButton); + FreeElementList(removeDevice->firstHat); + + SDL_free(removeDevice); + } + return pDeviceNext; +} static SInt32 -HIDGetElementValue(recDevice * pDevice, recElement * pElement) +GetHIDElementState(recDevice *pDevice, recElement *pElement) { - IOReturn result = kIOReturnSuccess; - IOHIDEventStruct hidEvent; - hidEvent.value = 0; + SInt32 value = 0; + + if (pDevice && pElement) { + IOHIDValueRef valueRef; + if (IOHIDDeviceGetValue(pDevice->deviceRef, pElement->elementRef, &valueRef) == kIOReturnSuccess) { + value = (SInt32) IOHIDValueGetIntegerValue(valueRef); - if (NULL != pDevice && NULL != pElement && NULL != pDevice->interface) { - result = - (*(pDevice->interface))->getElementValue(pDevice->interface, - pElement->cookie, - &hidEvent); - if (kIOReturnSuccess == result) { /* record min and max for auto calibration */ - if (hidEvent.value < pElement->minReport) - pElement->minReport = hidEvent.value; - if (hidEvent.value > pElement->maxReport) - pElement->maxReport = hidEvent.value; + if (value < pElement->minReport) { + pElement->minReport = value; + } + if (value > pElement->maxReport) { + pElement->maxReport = value; + } } } - /* auto user scale */ - return hidEvent.value; + return value; } static SInt32 -HIDScaledCalibratedValue(recDevice * pDevice, recElement * pElement, - long min, long max) +GetHIDScaledCalibratedState(recDevice * pDevice, recElement * pElement, SInt32 min, SInt32 max) { - float deviceScale = max - min; - float readScale = pElement->maxReport - pElement->minReport; - SInt32 value = HIDGetElementValue(pDevice, pElement); - if (readScale == 0) + const float deviceScale = max - min; + const float readScale = pElement->maxReport - pElement->minReport; + const SInt32 value = GetHIDElementState(pDevice, pElement); + if (readScale == 0) { return value; /* no scaling at all */ - else - return ((value - pElement->minReport) * deviceScale / readScale) + - min; + } + return ((value - pElement->minReport) * deviceScale / readScale) + min; } static void -HIDRemovalCallback(void *target, IOReturn result, void *refcon, void *sender) +JoystickDeviceWasRemovedCallback(void *ctx, IOReturn result, void *sender) { - recDevice *device = (recDevice *) refcon; + recDevice *device = (recDevice *) ctx; device->removed = 1; #if SDL_HAPTIC_IOKIT MacHaptic_MaybeRemoveDevice(device->ffservice); @@ -130,567 +139,259 @@ HIDRemovalCallback(void *target, IOReturn result, void *refcon, void *sender) } -/* Called by the io port notifier on removal of this device - */ -void JoystickDeviceWasRemovedCallback( void * refcon, io_service_t service, natural_t messageType, void * messageArgument ) -{ - if( messageType == kIOMessageServiceIsTerminated && refcon ) - { - recDevice *device = (recDevice *) refcon; - device->removed = 1; -#if SDL_HAPTIC_IOKIT - MacHaptic_MaybeRemoveDevice(device->ffservice); -#endif - s_bDeviceRemoved = SDL_TRUE; - } -} - - -/* Create and open an interface to device, required prior to extracting values or building queues. - * Note: application now owns the device and must close and release it prior to exiting - */ - -static IOReturn -HIDCreateOpenDeviceInterface(io_object_t hidDevice, recDevice * pDevice) -{ - IOReturn result = kIOReturnSuccess; - HRESULT plugInResult = S_OK; - SInt32 score = 0; - IOCFPlugInInterface **ppPlugInInterface = NULL; - - if (NULL == pDevice->interface) { - result = - IOCreatePlugInInterfaceForService(hidDevice, - kIOHIDDeviceUserClientTypeID, - kIOCFPlugInInterfaceID, - &ppPlugInInterface, &score); - if (kIOReturnSuccess == result) { - /* Call a method of the intermediate plug-in to create the device interface */ - plugInResult = - (*ppPlugInInterface)->QueryInterface(ppPlugInInterface, - CFUUIDGetUUIDBytes - (kIOHIDDeviceInterfaceID), - (void *) - &(pDevice->interface)); - if (S_OK != plugInResult) - HIDReportErrorNum - ("Couldn't query HID class device interface from plugInInterface", - plugInResult); - (*ppPlugInInterface)->Release(ppPlugInInterface); - } else - HIDReportErrorNum - ("Failed to create **plugInInterface via IOCreatePlugInInterfaceForService.", - result); - } - if (NULL != pDevice->interface) { - result = (*(pDevice->interface))->open(pDevice->interface, 0); - if (kIOReturnSuccess != result) - HIDReportErrorNum - ("Failed to open pDevice->interface via open.", result); - else - { - pDevice->portIterator = 0; - - /* It's okay if this fails, we have another detection method below */ - (*(pDevice->interface))->setRemovalCallback(pDevice->interface, - HIDRemovalCallback, - pDevice, pDevice); - - /* now connect notification for new devices */ - pDevice->notificationPort = IONotificationPortCreate(kIOMasterPortDefault); - - CFRunLoopAddSource(CFRunLoopGetCurrent(), - IONotificationPortGetRunLoopSource(pDevice->notificationPort), - kCFRunLoopDefaultMode); - - /* Register for notifications when a serial port is added to the system */ - result = IOServiceAddInterestNotification(pDevice->notificationPort, - hidDevice, - kIOGeneralInterest, - JoystickDeviceWasRemovedCallback, - pDevice, - &pDevice->portIterator); - if (kIOReturnSuccess != result) { - HIDReportErrorNum - ("Failed to register for removal callback.", result); - } - } - - } - return result; -} - -/* Closes and releases interface to device, should be done prior to exiting application - * Note: will have no affect if device or interface do not exist - * application will "own" the device if interface is not closed - * (device may have to be plug and re-plugged in different location to get it working again without a restart) - */ - -static IOReturn -HIDCloseReleaseInterface(recDevice * pDevice) -{ - IOReturn result = kIOReturnSuccess; - - if ((NULL != pDevice) && (NULL != pDevice->interface)) { - /* close the interface */ - result = (*(pDevice->interface))->close(pDevice->interface); - if (kIOReturnNotOpen == result) { - /* do nothing as device was not opened, thus can't be closed */ - } else if (kIOReturnSuccess != result) - HIDReportErrorNum("Failed to close IOHIDDeviceInterface.", - result); - /* release the interface */ - result = (*(pDevice->interface))->Release(pDevice->interface); - if (kIOReturnSuccess != result) - HIDReportErrorNum("Failed to release IOHIDDeviceInterface.", - result); - pDevice->interface = NULL; - - if ( pDevice->portIterator ) - { - IOObjectRelease( pDevice->portIterator ); - pDevice->portIterator = 0; - } - } - return result; -} - -/* extracts actual specific element information from each element CF dictionary entry */ +static void AddHIDElement(const void *value, void *parameter); +/* Call AddHIDElement() on all elements in an array of IOHIDElementRefs */ static void -HIDGetElementInfo(CFTypeRef refElement, recElement * pElement) +AddHIDElements(CFArrayRef array, recDevice *pDevice) { - long number; - CFTypeRef refType; - - refType = CFDictionaryGetValue(refElement, CFSTR(kIOHIDElementCookieKey)); - if (refType && CFNumberGetValue(refType, kCFNumberLongType, &number)) - pElement->cookie = (IOHIDElementCookie) number; - refType = CFDictionaryGetValue(refElement, CFSTR(kIOHIDElementMinKey)); - if (refType && CFNumberGetValue(refType, kCFNumberLongType, &number)) - pElement->minReport = pElement->min = number; - pElement->maxReport = pElement->min; - refType = CFDictionaryGetValue(refElement, CFSTR(kIOHIDElementMaxKey)); - if (refType && CFNumberGetValue(refType, kCFNumberLongType, &number)) - pElement->maxReport = pElement->max = number; -/* - TODO: maybe should handle the following stuff somehow? - - refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementScaledMinKey)); - if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) - pElement->scaledMin = number; - refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementScaledMaxKey)); - if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) - pElement->scaledMax = number; - refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementSizeKey)); - if (refType && CFNumberGetValue (refType, kCFNumberLongType, &number)) - pElement->size = number; - refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementIsRelativeKey)); - if (refType) - pElement->relative = CFBooleanGetValue (refType); - refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementIsWrappingKey)); - if (refType) - pElement->wrapping = CFBooleanGetValue (refType); - refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementIsNonLinearKey)); - if (refType) - pElement->nonLinear = CFBooleanGetValue (refType); - refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementHasPreferedStateKey)); - if (refType) - pElement->preferredState = CFBooleanGetValue (refType); - refType = CFDictionaryGetValue (refElement, CFSTR(kIOHIDElementHasNullStateKey)); - if (refType) - pElement->nullState = CFBooleanGetValue (refType); -*/ + const CFRange range = { 0, CFArrayGetCount(array) }; + CFArrayApplyFunction(array, range, AddHIDElement, pDevice); } -/* examines CF dictionary value in device element hierarchy to determine if it is element of interest or a collection of more elements - * if element of interest allocate storage, add to list and retrieve element specific info - * if collection then pass on to deconstruction collection into additional individual elements - */ +static SDL_bool +ElementAlreadyAdded(const IOHIDElementCookie cookie, const recElement *listitem) { + while (listitem) { + if (listitem->cookie == cookie) { + return SDL_TRUE; + } + listitem = listitem->pNext; + } + return SDL_FALSE; +} +/* See if we care about this HID element, and if so, note it in our recDevice. */ static void -HIDAddElement(CFTypeRef refElement, recDevice * pDevice) +AddHIDElement(const void *value, void *parameter) { - recElement *element = NULL; - recElement **headElement = NULL; - long elementType, usagePage, usage; - CFTypeRef refElementType = - CFDictionaryGetValue(refElement, CFSTR(kIOHIDElementTypeKey)); - CFTypeRef refUsagePage = - CFDictionaryGetValue(refElement, CFSTR(kIOHIDElementUsagePageKey)); - CFTypeRef refUsage = - CFDictionaryGetValue(refElement, CFSTR(kIOHIDElementUsageKey)); + recDevice *pDevice = (recDevice *) parameter; + IOHIDElementRef refElement = (IOHIDElementRef) value; + const CFTypeID elementTypeID = refElement ? CFGetTypeID(refElement) : 0; + if (refElement && (elementTypeID == IOHIDElementGetTypeID())) { + const IOHIDElementCookie cookie = IOHIDElementGetCookie(refElement); + const uint32_t usagePage = IOHIDElementGetUsagePage(refElement); + const uint32_t usage = IOHIDElementGetUsage(refElement); + recElement *element = NULL; + recElement **headElement = NULL; - if ((refElementType) - && - (CFNumberGetValue(refElementType, kCFNumberLongType, &elementType))) { /* look at types of interest */ - if ((elementType == kIOHIDElementTypeInput_Misc) - || (elementType == kIOHIDElementTypeInput_Button) - || (elementType == kIOHIDElementTypeInput_Axis)) { - if (refUsagePage - && CFNumberGetValue(refUsagePage, kCFNumberLongType, - &usagePage) && refUsage - && CFNumberGetValue(refUsage, kCFNumberLongType, &usage)) { + switch (IOHIDElementGetType(refElement)) { + case kIOHIDElementTypeInput_Misc: + case kIOHIDElementTypeInput_Button: + case kIOHIDElementTypeInput_Axis: { switch (usagePage) { /* only interested in kHIDPage_GenericDesktop and kHIDPage_Button */ - case kHIDPage_GenericDesktop: - { - switch (usage) { /* look at usage to determine function */ - case kHIDUsage_GD_X: - case kHIDUsage_GD_Y: - case kHIDUsage_GD_Z: - case kHIDUsage_GD_Rx: - case kHIDUsage_GD_Ry: - case kHIDUsage_GD_Rz: - case kHIDUsage_GD_Slider: - case kHIDUsage_GD_Dial: - case kHIDUsage_GD_Wheel: - element = (recElement *) - NewPtrClear(sizeof(recElement)); - if (element) { - pDevice->axes++; - headElement = &(pDevice->firstAxis); - } - break; - case kHIDUsage_GD_Hatswitch: - element = (recElement *) - NewPtrClear(sizeof(recElement)); - if (element) { - pDevice->hats++; - headElement = &(pDevice->firstHat); - } - break; + case kHIDPage_GenericDesktop: + switch (usage) { + case kHIDUsage_GD_X: + case kHIDUsage_GD_Y: + case kHIDUsage_GD_Z: + case kHIDUsage_GD_Rx: + case kHIDUsage_GD_Ry: + case kHIDUsage_GD_Rz: + case kHIDUsage_GD_Slider: + case kHIDUsage_GD_Dial: + case kHIDUsage_GD_Wheel: + if (!ElementAlreadyAdded(cookie, pDevice->firstAxis)) { + element = (recElement *) SDL_calloc(1, sizeof (recElement)); + if (element) { + pDevice->axes++; + headElement = &(pDevice->firstAxis); + } + } + break; + + case kHIDUsage_GD_Hatswitch: + if (!ElementAlreadyAdded(cookie, pDevice->firstHat)) { + element = (recElement *) SDL_calloc(1, sizeof (recElement)); + if (element) { + pDevice->hats++; + headElement = &(pDevice->firstHat); + } + } + break; } - } - break; - case kHIDPage_Simulation: - switch (usage) { - case kHIDUsage_Sim_Rudder: - case kHIDUsage_Sim_Throttle: - element = (recElement *) - NewPtrClear(sizeof(recElement)); + break; + + case kHIDPage_Simulation: + switch (usage) { + case kHIDUsage_Sim_Rudder: + case kHIDUsage_Sim_Throttle: + if (!ElementAlreadyAdded(cookie, pDevice->firstAxis)) { + element = (recElement *) SDL_calloc(1, sizeof (recElement)); + if (element) { + pDevice->axes++; + headElement = &(pDevice->firstAxis); + } + } + break; + + default: + break; + } + break; + + case kHIDPage_Button: + if (!ElementAlreadyAdded(cookie, pDevice->firstButton)) { + element = (recElement *) SDL_calloc(1, sizeof (recElement)); if (element) { - pDevice->axes++; - headElement = &(pDevice->firstAxis); + pDevice->buttons++; + headElement = &(pDevice->firstButton); } - break; + } + break; - default: - break; - } - break; - case kHIDPage_Button: - element = (recElement *) - NewPtrClear(sizeof(recElement)); - if (element) { - pDevice->buttons++; - headElement = &(pDevice->firstButton); - } - break; - default: - break; + default: + break; } } - } else if (kIOHIDElementTypeCollection == elementType) - HIDGetCollectionElements((CFMutableDictionaryRef) refElement, - pDevice); - } + break; - if (element && headElement) { /* add to list */ - recElement *elementPrevious = NULL; - recElement *elementCurrent = *headElement; - while (elementCurrent && usage >= elementCurrent->usage) { - elementPrevious = elementCurrent; - elementCurrent = elementCurrent->pNext; - } - if (elementPrevious) { - elementPrevious->pNext = element; - } else { - *headElement = element; - } - element->usagePage = usagePage; - element->usage = usage; - element->pNext = elementCurrent; - HIDGetElementInfo(refElement, element); - pDevice->elements++; - } -} - -/* collects information from each array member in device element list (each array member = element) */ - -static void -HIDGetElementsCFArrayHandler(const void *value, void *parameter) -{ - if (CFGetTypeID(value) == CFDictionaryGetTypeID()) - HIDAddElement((CFTypeRef) value, (recDevice *) parameter); -} - -/* handles retrieval of element information from arrays of elements in device IO registry information */ - -static void -HIDGetElements(CFTypeRef refElementCurrent, recDevice * pDevice) -{ - CFTypeID type = CFGetTypeID(refElementCurrent); - if (type == CFArrayGetTypeID()) { /* if element is an array */ - CFRange range = { 0, CFArrayGetCount(refElementCurrent) }; - /* CountElementsCFArrayHandler called for each array member */ - CFArrayApplyFunction(refElementCurrent, range, - HIDGetElementsCFArrayHandler, pDevice); - } -} - -/* handles extracting element information from element collection CF types - * used from top level element decoding and hierarchy deconstruction to flatten device element list - */ - -static void -HIDGetCollectionElements(CFMutableDictionaryRef deviceProperties, - recDevice * pDevice) -{ - CFTypeRef refElementTop = - CFDictionaryGetValue(deviceProperties, CFSTR(kIOHIDElementKey)); - if (refElementTop) - HIDGetElements(refElementTop, pDevice); -} - -/* use top level element usage page and usage to discern device usage page and usage setting appropriate vlaues in device record */ - -static void -HIDTopLevelElementHandler(const void *value, void *parameter) -{ - CFTypeRef refCF = 0; - if (CFGetTypeID(value) != CFDictionaryGetTypeID()) - return; - refCF = CFDictionaryGetValue(value, CFSTR(kIOHIDElementUsagePageKey)); - if (!CFNumberGetValue - (refCF, kCFNumberLongType, &((recDevice *) parameter)->usagePage)) - SDL_SetError("CFNumberGetValue error retrieving pDevice->usagePage."); - refCF = CFDictionaryGetValue(value, CFSTR(kIOHIDElementUsageKey)); - if (!CFNumberGetValue - (refCF, kCFNumberLongType, &((recDevice *) parameter)->usage)) - SDL_SetError("CFNumberGetValue error retrieving pDevice->usage."); -} - -/* extracts device info from CF dictionary records in IO registry */ - -static void -HIDGetDeviceInfo(io_object_t hidDevice, CFMutableDictionaryRef hidProperties, - recDevice * pDevice) -{ - CFMutableDictionaryRef usbProperties = 0; - io_registry_entry_t parent1, parent2; - - /* Mac OS X currently is not mirroring all USB properties to HID page so need to look at USB device page also - * get dictionary for USB properties: step up two levels and get CF dictionary for USB properties - */ - if ((KERN_SUCCESS == IORegistryEntryGetParentEntry(hidDevice, kIOServicePlane, &parent1)) - && (KERN_SUCCESS == IORegistryEntryGetParentEntry(parent1, kIOServicePlane, &parent2)) - && (KERN_SUCCESS == IORegistryEntryCreateCFProperties(parent2, &usbProperties, kCFAllocatorDefault, kNilOptions))) { - if (usbProperties) { - CFTypeRef refCF = 0; - /* get device info - * try hid dictionary first, if fail then go to usb dictionary - */ - - /* get product name */ - refCF = CFDictionaryGetValue(hidProperties, CFSTR(kIOHIDProductKey)); - if (!refCF) { - refCF = CFDictionaryGetValue(usbProperties, CFSTR("USB Product Name")); - } - if (refCF) { - if (!CFStringGetCString(refCF, pDevice->product, 256, CFStringGetSystemEncoding())) { - SDL_SetError("CFStringGetCString error retrieving pDevice->product."); + case kIOHIDElementTypeCollection: { + CFArrayRef array = IOHIDElementGetChildren(refElement); + if (array) { + AddHIDElements(array, pDevice); } } + break; - /* get usage page and usage */ - refCF = CFDictionaryGetValue(hidProperties, CFSTR(kIOHIDPrimaryUsagePageKey)); - if (refCF) { - if (!CFNumberGetValue (refCF, kCFNumberLongType, &pDevice->usagePage)) { - SDL_SetError("CFNumberGetValue error retrieving pDevice->usagePage."); - } - - refCF = CFDictionaryGetValue(hidProperties, CFSTR(kIOHIDPrimaryUsageKey)); - if (refCF) { - if (!CFNumberGetValue (refCF, kCFNumberLongType, &pDevice->usage)) { - SDL_SetError("CFNumberGetValue error retrieving pDevice->usage."); - } - } - } - - refCF = CFDictionaryGetValue(hidProperties, CFSTR(kIOHIDVendorIDKey)); - if (refCF) { - if (!CFNumberGetValue(refCF, kCFNumberLongType, &pDevice->guid.data[0])) { - SDL_SetError("CFNumberGetValue error retrieving pDevice->guid[0]"); - } - } - - refCF = CFDictionaryGetValue(hidProperties, CFSTR(kIOHIDProductIDKey)); - if (refCF) { - if (!CFNumberGetValue(refCF, kCFNumberLongType, &pDevice->guid.data[8])) { - SDL_SetError("CFNumberGetValue error retrieving pDevice->guid[8]"); - } - } - - /* Check to make sure we have a vendor and product ID - If we don't, use the same algorithm as the Linux code for Bluetooth devices */ - { - Uint32 *guid32 = (Uint32*)pDevice->guid.data; - if (!guid32[0] && !guid32[1]) { - const Uint16 BUS_BLUETOOTH = 0x05; - Uint16 *guid16 = (Uint16 *)guid32; - *guid16++ = BUS_BLUETOOTH; - *guid16++ = 0; - SDL_strlcpy((char*)guid16, pDevice->product, sizeof(pDevice->guid.data) - 4); - } - } - - /* If we don't have a vendor and product ID this is probably a Bluetooth device */ - - if (NULL == refCF) { /* get top level element HID usage page or usage */ - /* use top level element instead */ - CFTypeRef refCFTopElement = 0; - refCFTopElement = CFDictionaryGetValue(hidProperties, CFSTR(kIOHIDElementKey)); - { - /* refCFTopElement points to an array of element dictionaries */ - CFRange range = { 0, CFArrayGetCount(refCFTopElement) }; - CFArrayApplyFunction(refCFTopElement, range, HIDTopLevelElementHandler, pDevice); - } - } - - CFRelease(usbProperties); - } else { - SDL_SetError("IORegistryEntryCreateCFProperties failed to create usbProperties."); + default: + break; } - if (kIOReturnSuccess != IOObjectRelease(parent2)) { - SDL_SetError("IOObjectRelease error with parent2"); - } - if (kIOReturnSuccess != IOObjectRelease(parent1)) { - SDL_SetError("IOObjectRelease error with parent1"); - } - } -} - - -static recDevice * -HIDBuildDevice(io_object_t hidDevice) -{ - recDevice *pDevice = (recDevice *) NewPtrClear(sizeof(recDevice)); - if (pDevice) { - /* get dictionary for HID properties */ - CFMutableDictionaryRef hidProperties = 0; - kern_return_t result = - IORegistryEntryCreateCFProperties(hidDevice, &hidProperties, - kCFAllocatorDefault, - kNilOptions); - if ((result == KERN_SUCCESS) && hidProperties) { - /* create device interface */ - result = HIDCreateOpenDeviceInterface(hidDevice, pDevice); - if (kIOReturnSuccess == result) { - HIDGetDeviceInfo(hidDevice, hidProperties, pDevice); /* hidDevice used to find parents in registry tree */ - HIDGetCollectionElements(hidProperties, pDevice); + if (element && headElement) { /* add to list */ + recElement *elementPrevious = NULL; + recElement *elementCurrent = *headElement; + while (elementCurrent && usage >= elementCurrent->usage) { + elementPrevious = elementCurrent; + elementCurrent = elementCurrent->pNext; + } + if (elementPrevious) { + elementPrevious->pNext = element; } else { - DisposePtr((Ptr) pDevice); - pDevice = NULL; + *headElement = element; } - CFRelease(hidProperties); - } else { - DisposePtr((Ptr) pDevice); - pDevice = NULL; + + element->elementRef = refElement; + element->usagePage = usagePage; + element->usage = usage; + element->pNext = elementCurrent; + + element->minReport = element->min = (SInt32) IOHIDElementGetLogicalMin(refElement); + element->maxReport = element->max = (SInt32) IOHIDElementGetLogicalMax(refElement); + element->cookie = IOHIDElementGetCookie(refElement); + + pDevice->elements++; } } - return pDevice; } -/* disposes of the element list associated with a device and the memory associated with the list - */ +static SDL_bool +GetDeviceInfo(IOHIDDeviceRef hidDevice, recDevice *pDevice) +{ + Uint32 *guid32 = NULL; + CFTypeRef refCF = NULL; + CFArrayRef array = NULL; + + /* get usage page and usage */ + refCF = IOHIDDeviceGetProperty(hidDevice, CFSTR(kIOHIDPrimaryUsagePageKey)); + if (refCF) { + CFNumberGetValue(refCF, kCFNumberSInt32Type, &pDevice->usagePage); + } + if (pDevice->usagePage != kHIDPage_GenericDesktop) { + return SDL_FALSE; /* Filter device list to non-keyboard/mouse stuff */ + } + + refCF = IOHIDDeviceGetProperty(hidDevice, CFSTR(kIOHIDPrimaryUsageKey)); + if (refCF) { + CFNumberGetValue(refCF, kCFNumberSInt32Type, &pDevice->usage); + } + + if ((pDevice->usage != kHIDUsage_GD_Joystick && + pDevice->usage != kHIDUsage_GD_GamePad && + pDevice->usage != kHIDUsage_GD_MultiAxisController)) { + return SDL_FALSE; /* Filter device list to non-keyboard/mouse stuff */ + } + + pDevice->deviceRef = hidDevice; + + /* get device name */ + refCF = IOHIDDeviceGetProperty(hidDevice, CFSTR(kIOHIDProductKey)); + if (!refCF) { + /* Maybe we can't get "AwesomeJoystick2000", but we can get "Logitech"? */ + refCF = IOHIDDeviceGetProperty(hidDevice, CFSTR(kIOHIDManufacturerKey)); + } + if ((!refCF) || (!CFStringGetCString(refCF, pDevice->product, sizeof (pDevice->product), kCFStringEncodingUTF8))) { + SDL_strlcpy(pDevice->product, "Unidentified joystick", sizeof (pDevice->product)); + } + + refCF = IOHIDDeviceGetProperty(hidDevice, CFSTR(kIOHIDVendorIDKey)); + if (refCF) { + CFNumberGetValue(refCF, kCFNumberSInt32Type, &pDevice->guid.data[0]); + } + + refCF = IOHIDDeviceGetProperty(hidDevice, CFSTR(kIOHIDProductIDKey)); + if (refCF) { + CFNumberGetValue(refCF, kCFNumberSInt32Type, &pDevice->guid.data[8]); + } + + /* Check to make sure we have a vendor and product ID + If we don't, use the same algorithm as the Linux code for Bluetooth devices */ + guid32 = (Uint32*)pDevice->guid.data; + if (!guid32[0] && !guid32[1]) { + /* If we don't have a vendor and product ID this is probably a Bluetooth device */ + const Uint16 BUS_BLUETOOTH = 0x05; + Uint16 *guid16 = (Uint16 *)guid32; + *guid16++ = BUS_BLUETOOTH; + *guid16++ = 0; + SDL_strlcpy((char*)guid16, pDevice->product, sizeof(pDevice->guid.data) - 4); + } + + array = IOHIDDeviceCopyMatchingElements(hidDevice, NULL, kIOHIDOptionsTypeNone); + if (array) { + AddHIDElements(array, pDevice); + CFRelease(array); + } + + return SDL_TRUE; +} + static void -HIDDisposeElementList(recElement ** elementList) +JoystickDeviceWasAddedCallback(void *ctx, IOReturn res, void *sender, IOHIDDeviceRef ioHIDDeviceObject) { - recElement *pElement = *elementList; - while (pElement) { - recElement *pElementNext = pElement->pNext; - DisposePtr((Ptr) pElement); - pElement = pElementNext; + if (res != kIOReturnSuccess) { + return; } - *elementList = NULL; -} -/* disposes of a single device, closing and releaseing interface, freeing memory fro device and elements, setting device pointer to NULL - * all your device no longer belong to us... (i.e., you do not 'own' the device anymore) - */ + recDevice *device = (recDevice *) SDL_calloc(1, sizeof(recDevice)); -static recDevice * -HIDDisposeDevice(recDevice ** ppDevice) -{ - kern_return_t result = KERN_SUCCESS; - recDevice *pDeviceNext = NULL; - if (*ppDevice) { - /* save next device prior to disposing of this device */ - pDeviceNext = (*ppDevice)->pNext; - - /* free posible io_service_t */ - if ((*ppDevice)->ffservice) { - IOObjectRelease((*ppDevice)->ffservice); - (*ppDevice)->ffservice = 0; - } - - /* free element lists */ - HIDDisposeElementList(&(*ppDevice)->firstAxis); - HIDDisposeElementList(&(*ppDevice)->firstButton); - HIDDisposeElementList(&(*ppDevice)->firstHat); - - result = HIDCloseReleaseInterface(*ppDevice); /* function sanity checks interface value (now application does not own device) */ - if (kIOReturnSuccess != result) - HIDReportErrorNum - ("HIDCloseReleaseInterface failed when trying to dipose device.", - result); - DisposePtr((Ptr) * ppDevice); - *ppDevice = NULL; + if (!device) { + SDL_OutOfMemory(); + return; } - return pDeviceNext; -} - -/* Given an io_object_t from OSX adds a joystick device to our list if appropriate - */ -int -AddDeviceHelper( io_object_t ioHIDDeviceObject ) -{ - recDevice *device; - - /* build a device record */ - device = HIDBuildDevice(ioHIDDeviceObject); - if (!device) - return 0; - - /* Filter device list to non-keyboard/mouse stuff */ - if ((device->usagePage != kHIDPage_GenericDesktop) || - ((device->usage != kHIDUsage_GD_Joystick && - device->usage != kHIDUsage_GD_GamePad && - device->usage != kHIDUsage_GD_MultiAxisController))) { - - /* release memory for the device */ - HIDDisposeDevice(&device); - DisposePtr((Ptr) device); - return 0; + if (!GetDeviceInfo(ioHIDDeviceObject, device)) { + SDL_free(device); + return; /* not a device we care about, probably. */ } + /* Get notified when this device is disconnected. */ + IOHIDDeviceRegisterRemovalCallback(ioHIDDeviceObject, JoystickDeviceWasRemovedCallback, device); + IOHIDDeviceScheduleWithRunLoop(ioHIDDeviceObject, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); + /* Allocate an instance ID for this device */ device->instance_id = ++s_joystick_instance_id; - /* We have to do some storage of the io_service_t for - * SDL_HapticOpenFromJoystick */ - if (FFIsForceFeedback(ioHIDDeviceObject) == FF_OK) { - device->ffservice = ioHIDDeviceObject; + /* We have to do some storage of the io_service_t for SDL_HapticOpenFromJoystick */ + if (IOHIDDeviceGetService != NULL) { /* weak reference: available in 10.6 and later. */ + const io_service_t ioservice = IOHIDDeviceGetService(ioHIDDeviceObject); + if ((ioservice) && (FFIsForceFeedback(ioservice) == FF_OK)) { + device->ffservice = ioservice; #if SDL_HAPTIC_IOKIT - MacHaptic_MaybeAddDevice(ioHIDDeviceObject); + MacHaptic_MaybeAddDevice(ioservice); #endif - } else { - device->ffservice = 0; + } } device->send_open_event = 1; @@ -712,25 +413,93 @@ AddDeviceHelper( io_object_t ioHIDDeviceObject ) } curdevice->pNext = device; } +} - return 1; +static SDL_bool +ConfigHIDManager(CFArrayRef matchingArray) +{ + CFRunLoopRef runloop = CFRunLoopGetCurrent(); + + /* Run in a custom RunLoop mode just while initializing, + so we can detect sticks without messing with everything else. */ + CFStringRef tempRunLoopMode = CFSTR("SDLJoystickInit"); + + if (IOHIDManagerOpen(hidman, kIOHIDOptionsTypeNone) != kIOReturnSuccess) { + return SDL_FALSE; + } + + IOHIDManagerRegisterDeviceMatchingCallback(hidman, JoystickDeviceWasAddedCallback, NULL); + IOHIDManagerScheduleWithRunLoop(hidman, runloop, tempRunLoopMode); + IOHIDManagerSetDeviceMatchingMultiple(hidman, matchingArray); + + while (CFRunLoopRunInMode(tempRunLoopMode,0,TRUE)==kCFRunLoopRunHandledSource) { + /* no-op. Callback fires once per existing device. */ + } + + /* Put this in the normal RunLoop mode now, for future hotplug events. */ + IOHIDManagerUnscheduleFromRunLoop(hidman, runloop, tempRunLoopMode); + IOHIDManagerScheduleWithRunLoop(hidman, runloop, kCFRunLoopDefaultMode); + + return SDL_TRUE; /* good to go. */ } -/* Called by our IO port notifier on the master port when a HID device is inserted, we iterate - * and check for new joysticks - */ -void JoystickDeviceWasAddedCallback( void *refcon, io_iterator_t iterator ) +static CFDictionaryRef +CreateHIDDeviceMatchDictionary(const UInt32 page, const UInt32 usage, int *okay) { - io_object_t ioHIDDeviceObject = 0; + CFDictionaryRef retval = NULL; + CFNumberRef pageNumRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &page); + CFNumberRef usageNumRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &usage); + const void *keys[2] = { (void *) CFSTR(kIOHIDDeviceUsagePageKey), (void *) CFSTR(kIOHIDDeviceUsageKey) }; + const void *vals[2] = { (void *) pageNumRef, (void *) usageNumRef }; - while ( ( ioHIDDeviceObject = IOIteratorNext(iterator) ) ) - { - if ( ioHIDDeviceObject ) - { - AddDeviceHelper( ioHIDDeviceObject ); + if (pageNumRef && usageNumRef) { + retval = CFDictionaryCreate(kCFAllocatorDefault, keys, vals, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); + } + + if (pageNumRef) { + CFRelease(pageNumRef); + } + if (usageNumRef) { + CFRelease(usageNumRef); + } + + if (!retval) { + *okay = 0; + } + + return retval; +} + +static SDL_bool +CreateHIDManager(void) +{ + SDL_bool retval = SDL_FALSE; + int okay = 1; + const void *vals[] = { + (void *) CreateHIDDeviceMatchDictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick, &okay), + (void *) CreateHIDDeviceMatchDictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad, &okay), + (void *) CreateHIDDeviceMatchDictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_MultiAxisController, &okay), + }; + const size_t numElements = SDL_arraysize(vals); + CFArrayRef array = okay ? CFArrayCreate(kCFAllocatorDefault, vals, numElements, &kCFTypeArrayCallBacks) : NULL; + size_t i; + + for (i = 0; i < numElements; i++) { + if (vals[i]) { + CFRelease((CFTypeRef) vals[i]); } } + + if (array) { + hidman = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); + if (hidman != NULL) { + retval = ConfigHIDManager(array); + } + CFRelease(array); + } + + return retval; } @@ -742,82 +511,14 @@ void JoystickDeviceWasAddedCallback( void *refcon, io_iterator_t iterator ) int SDL_SYS_JoystickInit(void) { - IOReturn result = kIOReturnSuccess; - mach_port_t masterPort = 0; - io_iterator_t hidObjectIterator = 0; - CFMutableDictionaryRef hidMatchDictionary = NULL; - io_object_t ioHIDDeviceObject = 0; - io_iterator_t portIterator = 0; - if (gpDeviceList) { return SDL_SetError("Joystick: Device list already inited."); } - result = IOMasterPort(bootstrap_port, &masterPort); - if (kIOReturnSuccess != result) { - return SDL_SetError("Joystick: IOMasterPort error with bootstrap_port."); + if (!CreateHIDManager()) { + return SDL_SetError("Joystick: Couldn't initialize HID Manager"); } - /* Set up a matching dictionary to search I/O Registry by class name for all HID class devices. */ - hidMatchDictionary = IOServiceMatching(kIOHIDDeviceKey); - if (hidMatchDictionary) { - /* Add key for device type (joystick, in this case) to refine the matching dictionary. */ - - /* NOTE: we now perform this filtering later - UInt32 usagePage = kHIDPage_GenericDesktop; - UInt32 usage = kHIDUsage_GD_Joystick; - CFNumberRef refUsage = NULL, refUsagePage = NULL; - - refUsage = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &usage); - CFDictionarySetValue (hidMatchDictionary, CFSTR (kIOHIDPrimaryUsageKey), refUsage); - refUsagePage = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &usagePage); - CFDictionarySetValue (hidMatchDictionary, CFSTR (kIOHIDPrimaryUsagePageKey), refUsagePage); - */ - } else { - return SDL_SetError - ("Joystick: Failed to get HID CFMutableDictionaryRef via IOServiceMatching."); - } - - /* Now search I/O Registry for matching devices. */ - result = - IOServiceGetMatchingServices(masterPort, hidMatchDictionary, - &hidObjectIterator); - /* Check for errors */ - if (kIOReturnSuccess != result) { - return SDL_SetError("Joystick: Couldn't create a HID object iterator."); - } - if (!hidObjectIterator) { /* there are no joysticks */ - gpDeviceList = NULL; - return 0; - } - /* IOServiceGetMatchingServices consumes a reference to the dictionary, so we don't need to release the dictionary ref. */ - - /* build flat linked list of devices from device iterator */ - - gpDeviceList = NULL; - - while ((ioHIDDeviceObject = IOIteratorNext(hidObjectIterator))) { - AddDeviceHelper( ioHIDDeviceObject ); - } - result = IOObjectRelease(hidObjectIterator); /* release the iterator */ - - /* now connect notification for new devices */ - notificationPort = IONotificationPortCreate(masterPort); - hidMatchDictionary = IOServiceMatching(kIOHIDDeviceKey); - - CFRunLoopAddSource(CFRunLoopGetCurrent(), - IONotificationPortGetRunLoopSource(notificationPort), - kCFRunLoopDefaultMode); - - /* Register for notifications when a serial port is added to the system */ - result = IOServiceAddMatchingNotification(notificationPort, - kIOFirstMatchNotification, - hidMatchDictionary, - JoystickDeviceWasAddedCallback, - NULL, - &portIterator); - while (IOIteratorNext(portIterator)) {}; /* Run out the iterator or notifications won't start (you can also use it to iterate the available devices). */ - return SDL_SYS_NumJoysticks(); } @@ -828,10 +529,10 @@ SDL_SYS_NumJoysticks() recDevice *device = gpDeviceList; int nJoySticks = 0; - while ( device ) - { - if ( !device->removed ) + while (device) { + if (!device->removed) { nJoySticks++; + } device = device->pNext; } @@ -843,18 +544,16 @@ SDL_SYS_NumJoysticks() void SDL_SYS_JoystickDetect() { - if ( s_bDeviceAdded || s_bDeviceRemoved ) - { + if (s_bDeviceAdded || s_bDeviceRemoved) { recDevice *device = gpDeviceList; s_bDeviceAdded = SDL_FALSE; s_bDeviceRemoved = SDL_FALSE; int device_index = 0; /* send notifications */ - while ( device ) - { - if ( device->send_open_event ) - { + while (device) { + if (device->send_open_event) { device->send_open_event = 0; +/* !!! FIXME: why isn't there an SDL_PrivateJoyDeviceAdded()? */ #if !SDL_EVENTS_DISABLED SDL_Event event; event.type = SDL_JOYDEVICEADDED; @@ -870,43 +569,25 @@ SDL_SYS_JoystickDetect() } - if ( device->removed ) - { - recDevice *removeDevice = device; - if ( gpDeviceList == removeDevice ) - { - device = device->pNext; - gpDeviceList = device; - } - else - { - device = gpDeviceList; - while ( device->pNext != removeDevice ) - { - device = device->pNext; - } - - device->pNext = removeDevice->pNext; - } + if (device->removed) { + const int instance_id = device->instance_id; + device = FreeDevice(device); +/* !!! FIXME: why isn't there an SDL_PrivateJoyDeviceRemoved()? */ #if !SDL_EVENTS_DISABLED SDL_Event event; event.type = SDL_JOYDEVICEREMOVED; if (SDL_GetEventState(event.type) == SDL_ENABLE) { - event.jdevice.which = removeDevice->instance_id; + event.jdevice.which = instance_id; if ((SDL_EventOK == NULL) || (*SDL_EventOK) (SDL_EventOKParam, &event)) { SDL_PushEvent(&event); } } - - DisposePtr((Ptr) removeDevice); #endif /* !SDL_EVENTS_DISABLED */ - } - else - { + } else { device = device->pNext; device_index++; } @@ -926,8 +607,9 @@ SDL_SYS_JoystickNameForDeviceIndex(int device_index) { recDevice *device = gpDeviceList; - for (; device_index > 0; device_index--) + while (device_index-- > 0) { device = device->pNext; + } return device->product; } @@ -940,8 +622,9 @@ SDL_SYS_GetInstanceIdOfDeviceIndex(int device_index) recDevice *device = gpDeviceList; int index; - for (index = device_index; index > 0; index--) + for (index = device_index; index > 0; index--) { device = device->pNext; + } return device->instance_id; } @@ -957,8 +640,9 @@ SDL_SYS_JoystickOpen(SDL_Joystick * joystick, int device_index) recDevice *device = gpDeviceList; int index; - for (index = device_index; index > 0; index--) + for (index = device_index; index > 0; index--) { device = device->pNext; + } joystick->instance_id = device->instance_id; joystick->hwdata = device; @@ -979,11 +663,10 @@ SDL_SYS_JoystickAttached(SDL_Joystick * joystick) { recDevice *device = gpDeviceList; - while ( device ) - { - if ( joystick->instance_id == device->instance_id ) + while (device) { + if (joystick->instance_id == device->instance_id) { return SDL_TRUE; - + } device = device->pNext; } @@ -1003,53 +686,24 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick) SInt32 value, range; int i; - if ( !device ) + if (!device) { return; + } if (device->removed) { /* device was unplugged; ignore it. */ - recDevice *devicelist = gpDeviceList; joystick->closed = 1; joystick->uncentered = 1; - - if ( devicelist == device ) - { - gpDeviceList = device->pNext; - } - else - { - while ( devicelist->pNext != device ) - { - devicelist = devicelist->pNext; - } - - devicelist->pNext = device->pNext; - } - - DisposePtr((Ptr) device); joystick->hwdata = NULL; - -#if !SDL_EVENTS_DISABLED - SDL_Event event; - event.type = SDL_JOYDEVICEREMOVED; - - if (SDL_GetEventState(event.type) == SDL_ENABLE) { - event.jdevice.which = joystick->instance_id; - if ((SDL_EventOK == NULL) - || (*SDL_EventOK) (SDL_EventOKParam, &event)) { - SDL_PushEvent(&event); - } - } -#endif /* !SDL_EVENTS_DISABLED */ - return; } element = device->firstAxis; i = 0; while (element) { - value = HIDScaledCalibratedValue(device, element, -32768, 32767); - if (value != joystick->axes[i]) + value = GetHIDScaledCalibratedState(device, element, -32768, 32767); + if (value != joystick->axes[i]) { SDL_PrivateJoystickAxis(joystick, i, value); + } element = element->pNext; ++i; } @@ -1057,11 +711,13 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick) element = device->firstButton; i = 0; while (element) { - value = HIDGetElementValue(device, element); - if (value > 1) /* handle pressure-sensitive buttons */ + value = GetHIDElementState(device, element); + if (value > 1) { /* handle pressure-sensitive buttons */ value = 1; - if (value != joystick->buttons[i]) + } + if (value != joystick->buttons[i]) { SDL_PrivateJoystickButton(joystick, i, value); + } element = element->pNext; ++i; } @@ -1072,11 +728,12 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick) Uint8 pos = 0; range = (element->max - element->min + 1); - value = HIDGetElementValue(device, element) - element->min; - if (range == 4) /* 4 position hatswitch - scale up value */ + value = GetHIDElementState(device, element) - element->min; + if (range == 4) { /* 4 position hatswitch - scale up value */ value *= 2; - else if (range != 8) /* Neither a 4 nor 8 positions - fall back to default position (centered) */ + } else if (range != 8) { /* Neither a 4 nor 8 positions - fall back to default position (centered) */ value = -1; + } switch (value) { case 0: pos = SDL_HAT_UP; @@ -1110,13 +767,14 @@ SDL_SYS_JoystickUpdate(SDL_Joystick * joystick) pos = SDL_HAT_CENTERED; break; } - if (pos != joystick->hats[i]) + + if (pos != joystick->hats[i]) { SDL_PrivateJoystickHat(joystick, i, pos); + } + element = element->pNext; ++i; } - - return; } /* Function to close a joystick after use */ @@ -1130,14 +788,17 @@ SDL_SYS_JoystickClose(SDL_Joystick * joystick) void SDL_SYS_JoystickQuit(void) { - while (NULL != gpDeviceList) - gpDeviceList = HIDDisposeDevice(&gpDeviceList); - - if ( notificationPort ) - { - IONotificationPortDestroy( notificationPort ); - notificationPort = 0; + while (FreeDevice(gpDeviceList)) { + /* spin */ } + + if (hidman) { + IOHIDManagerClose(hidman, kIOHIDOptionsTypeNone); + CFRelease(hidman); + hidman = NULL; + } + + s_bDeviceAdded = s_bDeviceRemoved = SDL_FALSE; } @@ -1146,8 +807,9 @@ SDL_JoystickGUID SDL_SYS_JoystickGetDeviceGUID( int device_index ) recDevice *device = gpDeviceList; int index; - for (index = device_index; index > 0; index--) + for (index = device_index; index > 0; index--) { device = device->pNext; + } return device->guid; } diff --git a/libs/SDL2/src/joystick/darwin/SDL_sysjoystick_c.h b/libs/SDL2/src/joystick/darwin/SDL_sysjoystick_c.h index 6f3372f2..0a15ba18 100644 --- a/libs/SDL2/src/joystick/darwin/SDL_sysjoystick_c.h +++ b/libs/SDL2/src/joystick/darwin/SDL_sysjoystick_c.h @@ -22,34 +22,19 @@ #ifndef SDL_JOYSTICK_IOKIT_H - #include -#include -#include - struct recElement { - IOHIDElementCookie cookie; /* unique value which identifies element, will NOT change */ - long usagePage, usage; /* HID usage */ - long min; /* reported min value possible */ - long max; /* reported max value possible */ -#if 0 - /* TODO: maybe should handle the following stuff somehow? */ - - long scaledMin; /* reported scaled min value possible */ - long scaledMax; /* reported scaled max value possible */ - long size; /* size in bits of data return from element */ - Boolean relative; /* are reports relative to last report (deltas) */ - Boolean wrapping; /* does element wrap around (one value higher than max is min) */ - Boolean nonLinear; /* are the values reported non-linear relative to element movement */ - Boolean preferredState; /* does element have a preferred state (such as a button) */ - Boolean nullState; /* does element have null state */ -#endif /* 0 */ + IOHIDElementRef elementRef; + IOHIDElementCookie cookie; + uint32_t usagePage, usage; /* HID usage */ + SInt32 min; /* reported min value possible */ + SInt32 max; /* reported max value possible */ /* runtime variables used for auto-calibration */ - long minReport; /* min returned value */ - long maxReport; /* max returned value */ + SInt32 minReport; /* min returned value */ + SInt32 maxReport; /* max returned value */ struct recElement *pNext; /* next element in list */ }; @@ -57,19 +42,17 @@ typedef struct recElement recElement; struct joystick_hwdata { + IOHIDDeviceRef deviceRef; /* HIDManager device handle */ io_service_t ffservice; /* Interface for force feedback, 0 = no ff */ - IOHIDDeviceInterface **interface; /* interface to device, NULL = no interface */ - IONotificationPortRef notificationPort; /* port to be notified on joystick removal */ - io_iterator_t portIterator; /* iterator for removal callback */ char product[256]; /* name of product */ - long usage; /* usage page from IOUSBHID Parser.h which defines general usage */ - long usagePage; /* usage within above page from IOUSBHID Parser.h which defines specific usage */ + uint32_t usage; /* usage page from IOUSBHID Parser.h which defines general usage */ + uint32_t usagePage; /* usage within above page from IOUSBHID Parser.h which defines specific usage */ - long axes; /* number of axis (calculated, not reported by device) */ - long buttons; /* number of buttons (calculated, not reported by device) */ - long hats; /* number of hat switches (calculated, not reported by device) */ - long elements; /* number of total elements (should be total of above) (calculated, not reported by device) */ + int axes; /* number of axis (calculated, not reported by device) */ + int buttons; /* number of buttons (calculated, not reported by device) */ + int hats; /* number of hat switches (calculated, not reported by device) */ + int elements; /* number of total elements (should be total of above) (calculated, not reported by device) */ recElement *firstAxis; recElement *firstButton; diff --git a/libs/SDL2/src/joystick/windows/SDL_dxjoystick.c b/libs/SDL2/src/joystick/windows/SDL_dxjoystick.c index da96b606..3c009746 100644 --- a/libs/SDL2/src/joystick/windows/SDL_dxjoystick.c +++ b/libs/SDL2/src/joystick/windows/SDL_dxjoystick.c @@ -782,7 +782,7 @@ EnumXInputDevices(JoyStick_DeviceData **pContext) XINPUT_CAPABILITIES capabilities; if (XINPUTGETCAPABILITIES(userid, XINPUT_FLAG_GAMEPAD, &capabilities) == ERROR_SUCCESS) { /* Current version of XInput mistakenly returns 0 as the Type. Ignore it and ensure the subtype is a gamepad. */ - /* !!! FIXME: we might want to support steering wheels or guitars or whatever laster. */ + /* !!! FIXME: we might want to support steering wheels or guitars or whatever later. */ if (capabilities.SubType == XINPUT_DEVSUBTYPE_GAMEPAD) { AddXInputDevice(userid, pContext); } @@ -1448,6 +1448,7 @@ SDL_SYS_JoystickUpdate_XInput(SDL_Joystick * joystick) XINPUT_STATE_EX *pXInputState = &joystick->hwdata->XInputState[joystick->hwdata->currentXInputSlot]; XINPUT_STATE_EX *pXInputStatePrev = &joystick->hwdata->XInputState[joystick->hwdata->currentXInputSlot ^ 1]; + /* !!! FIXME: why isn't this just using SDL_PrivateJoystickAxis_Int()? */ SDL_PrivateJoystickAxis( joystick, 0, (Sint16)pXInputState->Gamepad.sThumbLX ); SDL_PrivateJoystickAxis( joystick, 1, (Sint16)(-SDL_max(-32767, pXInputState->Gamepad.sThumbLY)) ); SDL_PrivateJoystickAxis( joystick, 2, (Sint16)pXInputState->Gamepad.sThumbRX ); @@ -1455,6 +1456,7 @@ SDL_SYS_JoystickUpdate_XInput(SDL_Joystick * joystick) SDL_PrivateJoystickAxis( joystick, 4, (Sint16)(((int)pXInputState->Gamepad.bLeftTrigger*65535/255) - 32768)); SDL_PrivateJoystickAxis( joystick, 5, (Sint16)(((int)pXInputState->Gamepad.bRightTrigger*65535/255) - 32768)); + /* !!! FIXME: why isn't this just using SDL_PrivateJoystickButton_Int(), instead of keeping these two alternating state buffers? */ if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_DPAD_UP ) ) SDL_PrivateJoystickButton(joystick, 0, pXInputState->Gamepad.wButtons & XINPUT_GAMEPAD_DPAD_UP ? SDL_PRESSED : SDL_RELEASED ); if ( ButtonChanged( pXInputState->Gamepad.wButtons, pXInputStatePrev->Gamepad.wButtons, XINPUT_GAMEPAD_DPAD_DOWN ) ) @@ -1522,6 +1524,7 @@ TranslatePOV(DWORD value) /* SDL_PrivateJoystick* doesn't discard duplicate events, so we need to * do it. */ +/* !!! FIXME: SDL_PrivateJoystickAxis _does_ discard duplicate events now. Ditch this code. */ static int SDL_PrivateJoystickAxis_Int(SDL_Joystick * joystick, Uint8 axis, Sint16 value) { diff --git a/libs/SDL2/src/power/uikit/SDL_syspower.m b/libs/SDL2/src/power/uikit/SDL_syspower.m index e7cb9c23..60c42745 100644 --- a/libs/SDL2/src/power/uikit/SDL_syspower.m +++ b/libs/SDL2/src/power/uikit/SDL_syspower.m @@ -87,8 +87,8 @@ SDL_GetPowerInfo_UIKit(SDL_PowerState * state, int *seconds, int *percent) } const float level = [uidev batteryLevel]; - *percent = ( (level < 0.0f) ? -1 : (((int) (level + 0.5f)) * 100) ); - return SDL_TRUE; /* always the definitive answer on iPhoneOS. */ + *percent = ( (level < 0.0f) ? -1 : ((int) ((level * 100) + 0.5f)) ); + return SDL_TRUE; /* always the definitive answer on iOS. */ } #endif /* SDL_POWER_UIKIT */ diff --git a/libs/SDL2/src/render/SDL_render.c b/libs/SDL2/src/render/SDL_render.c index a9d04cc2..703594ae 100644 --- a/libs/SDL2/src/render/SDL_render.c +++ b/libs/SDL2/src/render/SDL_render.c @@ -1876,7 +1876,9 @@ int SDL_GL_UnbindTexture(SDL_Texture *texture) CHECK_TEXTURE_MAGIC(texture, -1); renderer = texture->renderer; - if (renderer && renderer->GL_UnbindTexture) { + if (texture->native) { + return SDL_GL_UnbindTexture(texture->native); + } else if (renderer && renderer->GL_UnbindTexture) { return renderer->GL_UnbindTexture(renderer, texture); } diff --git a/libs/SDL2/src/render/direct3d/SDL_render_d3d.c b/libs/SDL2/src/render/direct3d/SDL_render_d3d.c index 47675c7a..0caa8d26 100644 --- a/libs/SDL2/src/render/direct3d/SDL_render_d3d.c +++ b/libs/SDL2/src/render/direct3d/SDL_render_d3d.c @@ -217,6 +217,7 @@ static int D3D_UpdateTextureYUV(SDL_Renderer * renderer, SDL_Texture * texture, static int D3D_LockTexture(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * rect, void **pixels, int *pitch); static void D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture); +static int D3D_SetRenderTargetInternal(SDL_Renderer * renderer, SDL_Texture * texture); static int D3D_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture); static int D3D_UpdateViewport(SDL_Renderer * renderer); static int D3D_UpdateClipRect(SDL_Renderer * renderer); @@ -481,6 +482,10 @@ D3D_Reset(SDL_Renderer * renderer) IDirect3DSurface9_Release(data->defaultRenderTarget); data->defaultRenderTarget = NULL; } + if (data->currentRenderTarget != NULL) { + IDirect3DSurface9_Release(data->currentRenderTarget); + data->currentRenderTarget = NULL; + } /* Release application render targets */ for (texture = renderer->textures; texture; texture = texture->next) { @@ -508,6 +513,7 @@ D3D_Reset(SDL_Renderer * renderer) IDirect3DDevice9_GetRenderTarget(data->device, 0, &data->defaultRenderTarget); D3D_InitRenderState(data); + D3D_SetRenderTargetInternal(renderer, renderer->target); D3D_UpdateViewport(renderer); /* Let the application know that render targets were reset */ @@ -1003,6 +1009,12 @@ D3D_UpdateTextureInternal(IDirect3DTexture9 *texture, Uint32 format, SDL_bool fu if (length == pitch && length == locked.Pitch) { SDL_memcpy(dst, src, length*h); } else { + if (length > pitch) { + length = pitch; + } + if (length > locked.Pitch) { + length = locked.Pitch; + } for (row = 0; row < h; ++row) { SDL_memcpy(dst, src, length); src += pitch; @@ -1155,14 +1167,12 @@ D3D_UnlockTexture(SDL_Renderer * renderer, SDL_Texture * texture) } static int -D3D_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture) +D3D_SetRenderTargetInternal(SDL_Renderer * renderer, SDL_Texture * texture) { D3D_RenderData *data = (D3D_RenderData *) renderer->driverdata; D3D_TextureData *texturedata; HRESULT result; - D3D_ActivateRenderer(renderer); - /* Release the previous render target if it wasn't the default one */ if (data->currentRenderTarget != NULL) { IDirect3DSurface9_Release(data->currentRenderTarget); @@ -1192,6 +1202,14 @@ D3D_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture) return 0; } +static int +D3D_SetRenderTarget(SDL_Renderer * renderer, SDL_Texture * texture) +{ + D3D_ActivateRenderer(renderer); + + return D3D_SetRenderTargetInternal(renderer, texture); +} + static int D3D_UpdateViewport(SDL_Renderer * renderer) { diff --git a/libs/SDL2/src/render/opengl/SDL_render_gl.c b/libs/SDL2/src/render/opengl/SDL_render_gl.c index 17892768..c3465be7 100644 --- a/libs/SDL2/src/render/opengl/SDL_render_gl.c +++ b/libs/SDL2/src/render/opengl/SDL_render_gl.c @@ -32,6 +32,12 @@ #include #endif +/* To prevent unnecessary window recreation, + * these should match the defaults selected in SDL_GL_ResetAttributes + */ + +#define RENDERER_CONTEXT_MAJOR 2 +#define RENDERER_CONTEXT_MINOR 1 /* OpenGL renderer implementation */ @@ -381,11 +387,25 @@ GL_CreateRenderer(SDL_Window * window, Uint32 flags) const char *hint; GLint value; Uint32 window_flags; + int profile_mask, major, minor; + SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile_mask); + SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major); + SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor); + window_flags = SDL_GetWindowFlags(window); - if (!(window_flags & SDL_WINDOW_OPENGL)) { + if (!(window_flags & SDL_WINDOW_OPENGL) || + profile_mask == SDL_GL_CONTEXT_PROFILE_ES || major != RENDERER_CONTEXT_MAJOR || minor != RENDERER_CONTEXT_MINOR) { + + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, 0); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RENDERER_CONTEXT_MAJOR); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RENDERER_CONTEXT_MINOR); + if (SDL_RecreateWindow(window, window_flags | SDL_WINDOW_OPENGL) < 0) { /* Uh oh, better try to put it back... */ + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile_mask); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor); SDL_RecreateWindow(window, window_flags); return NULL; } diff --git a/libs/SDL2/src/render/opengles/SDL_render_gles.c b/libs/SDL2/src/render/opengles/SDL_render_gles.c index 27be42c6..899ca8f9 100644 --- a/libs/SDL2/src/render/opengles/SDL_render_gles.c +++ b/libs/SDL2/src/render/opengles/SDL_render_gles.c @@ -26,6 +26,13 @@ #include "SDL_opengles.h" #include "../SDL_sysrender.h" +/* To prevent unnecessary window recreation, + * these should match the defaults selected in SDL_GL_ResetAttributes + */ + +#define RENDERER_CONTEXT_MAJOR 1 +#define RENDERER_CONTEXT_MINOR 1 + #if defined(SDL_VIDEO_DRIVER_PANDORA) /* Empty function stub to get OpenGL ES 1.x support without */ @@ -279,15 +286,25 @@ GLES_CreateRenderer(SDL_Window * window, Uint32 flags) GLES_RenderData *data; GLint value; Uint32 windowFlags; + int profile_mask, major, minor; - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 1); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1); + SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile_mask); + SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major); + SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor); windowFlags = SDL_GetWindowFlags(window); - if (!(windowFlags & SDL_WINDOW_OPENGL)) { + if (!(windowFlags & SDL_WINDOW_OPENGL) || + profile_mask != SDL_GL_CONTEXT_PROFILE_ES || major != RENDERER_CONTEXT_MAJOR || minor != RENDERER_CONTEXT_MINOR) { + + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RENDERER_CONTEXT_MAJOR); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RENDERER_CONTEXT_MINOR); + if (SDL_RecreateWindow(window, windowFlags | SDL_WINDOW_OPENGL) < 0) { /* Uh oh, better try to put it back... */ + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile_mask); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor); SDL_RecreateWindow(window, windowFlags); return NULL; } diff --git a/libs/SDL2/src/render/opengles2/SDL_render_gles2.c b/libs/SDL2/src/render/opengles2/SDL_render_gles2.c index c0d1aeb0..f2fa8fa9 100644 --- a/libs/SDL2/src/render/opengles2/SDL_render_gles2.c +++ b/libs/SDL2/src/render/opengles2/SDL_render_gles2.c @@ -28,6 +28,12 @@ #include "../../video/SDL_blit.h" #include "SDL_shaders_gles2.h" +/* To prevent unnecessary window recreation, + * these should match the defaults selected in SDL_GL_ResetAttributes + */ +#define RENDERER_CONTEXT_MAJOR 2 +#define RENDERER_CONTEXT_MINOR 0 + /* Used to re-create the window with OpenGL ES capability */ extern int SDL_RecreateWindow(SDL_Window * window, Uint32 flags); @@ -1740,15 +1746,25 @@ GLES2_CreateRenderer(SDL_Window *window, Uint32 flags) Uint32 windowFlags; GLint window_framebuffer; GLint value; + int profile_mask, major, minor; - SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0); + SDL_GL_GetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, &profile_mask); + SDL_GL_GetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, &major); + SDL_GL_GetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, &minor); windowFlags = SDL_GetWindowFlags(window); - if (!(windowFlags & SDL_WINDOW_OPENGL)) { + if (!(windowFlags & SDL_WINDOW_OPENGL) || + profile_mask != SDL_GL_CONTEXT_PROFILE_ES || major != RENDERER_CONTEXT_MAJOR || minor != RENDERER_CONTEXT_MINOR) { + + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, RENDERER_CONTEXT_MAJOR); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, RENDERER_CONTEXT_MINOR); + if (SDL_RecreateWindow(window, windowFlags | SDL_WINDOW_OPENGL) < 0) { /* Uh oh, better try to put it back... */ + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, profile_mask); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, major); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, minor); SDL_RecreateWindow(window, windowFlags); return NULL; } diff --git a/libs/SDL2/src/stdlib/SDL_stdlib.c b/libs/SDL2/src/stdlib/SDL_stdlib.c index 1eb9a12d..7c2e0d57 100644 --- a/libs/SDL2/src/stdlib/SDL_stdlib.c +++ b/libs/SDL2/src/stdlib/SDL_stdlib.c @@ -278,12 +278,6 @@ void * memcpy ( void * destination, const void * source, size_t num ) #ifdef _M_IX86 -void -__declspec(naked) -_chkstk() -{ -} - /* Float to long */ void __declspec(naked) diff --git a/libs/SDL2/src/test/SDL_test_common.c b/libs/SDL2/src/test/SDL_test_common.c index c03da03a..9d41a194 100644 --- a/libs/SDL2/src/test/SDL_test_common.c +++ b/libs/SDL2/src/test/SDL_test_common.c @@ -1542,6 +1542,7 @@ SDLTest_CommonQuit(SDLTest_CommonState * state) SDL_AudioQuit(); } SDL_free(state); + SDL_Quit(); } /* vi: set ts=4 sw=4 expandtab: */ diff --git a/libs/SDL2/src/timer/SDL_timer_c.h b/libs/SDL2/src/timer/SDL_timer_c.h index 91646d99..8d563cff 100644 --- a/libs/SDL2/src/timer/SDL_timer_c.h +++ b/libs/SDL2/src/timer/SDL_timer_c.h @@ -26,7 +26,8 @@ #define ROUND_RESOLUTION(X) \ (((X+TIMER_RESOLUTION-1)/TIMER_RESOLUTION)*TIMER_RESOLUTION) -extern void SDL_InitTicks(void); +extern void SDL_TicksInit(void); +extern void SDL_TicksQuit(void); extern int SDL_TimerInit(void); extern void SDL_TimerQuit(void); diff --git a/libs/SDL2/src/timer/dummy/SDL_systimer.c b/libs/SDL2/src/timer/dummy/SDL_systimer.c index 0e2703fc..57899ae9 100644 --- a/libs/SDL2/src/timer/dummy/SDL_systimer.c +++ b/libs/SDL2/src/timer/dummy/SDL_systimer.c @@ -27,7 +27,7 @@ static SDL_bool ticks_started = SDL_FALSE; void -SDL_InitTicks(void) +SDL_TicksInit(void) { if (ticks_started) { return; @@ -35,11 +35,17 @@ SDL_InitTicks(void) ticks_started = SDL_TRUE; } +void +SDL_TicksQuit(void) +{ + ticks_started = SDL_FALSE; +} + Uint32 SDL_GetTicks(void) { if (!ticks_started) { - SDL_InitTicks(); + SDL_TicksInit(); } SDL_Unsupported(); diff --git a/libs/SDL2/src/timer/haiku/SDL_systimer.c b/libs/SDL2/src/timer/haiku/SDL_systimer.c index 1500f6b2..685f72a8 100644 --- a/libs/SDL2/src/timer/haiku/SDL_systimer.c +++ b/libs/SDL2/src/timer/haiku/SDL_systimer.c @@ -30,7 +30,7 @@ static bigtime_t start; static SDL_bool ticks_started = SDL_FALSE; void -SDL_InitTicks(void) +SDL_TicksInit(void) { if (ticks_started) { return; @@ -41,11 +41,17 @@ SDL_InitTicks(void) start = system_time(); } +void +SDL_TicksQuit(void) +{ + ticks_started = SDL_FALSE; +} + Uint32 SDL_GetTicks(void) { if (!ticks_started) { - SDL_InitTicks(); + SDL_TicksInit(); } return ((system_time() - start) / 1000); diff --git a/libs/SDL2/src/timer/psp/SDL_systimer.c b/libs/SDL2/src/timer/psp/SDL_systimer.c index 0f05a136..b706f449 100644 --- a/libs/SDL2/src/timer/psp/SDL_systimer.c +++ b/libs/SDL2/src/timer/psp/SDL_systimer.c @@ -31,7 +31,8 @@ static struct timeval start; static SDL_bool ticks_started = SDL_FALSE; -void SDL_InitTicks(void) +void +SDL_TicksInit(void) { if (ticks_started) { return; @@ -41,10 +42,16 @@ void SDL_InitTicks(void) gettimeofday(&start, NULL); } +void +SDL_TicksQuit(void) +{ + ticks_started = SDL_FALSE; +} + Uint32 SDL_GetTicks(void) { if (!ticks_started) { - SDL_InitTicks(); + SDL_TicksInit(); } struct timeval now; diff --git a/libs/SDL2/src/timer/unix/SDL_systimer.c b/libs/SDL2/src/timer/unix/SDL_systimer.c index 7c35bef5..0f4c7571 100644 --- a/libs/SDL2/src/timer/unix/SDL_systimer.c +++ b/libs/SDL2/src/timer/unix/SDL_systimer.c @@ -59,7 +59,7 @@ static struct timeval start_tv; static SDL_bool ticks_started = SDL_FALSE; void -SDL_InitTicks(void) +SDL_TicksInit(void) { if (ticks_started) { return; @@ -83,12 +83,18 @@ SDL_InitTicks(void) } } +void +SDL_TicksQuit(void) +{ + ticks_started = SDL_FALSE; +} + Uint32 SDL_GetTicks(void) { Uint32 ticks; if (!ticks_started) { - SDL_InitTicks(); + SDL_TicksInit(); } if (has_monotonic_time) { @@ -117,7 +123,7 @@ SDL_GetPerformanceCounter(void) { Uint64 ticks; if (!ticks_started) { - SDL_InitTicks(); + SDL_TicksInit(); } if (has_monotonic_time) { @@ -146,7 +152,7 @@ Uint64 SDL_GetPerformanceFrequency(void) { if (!ticks_started) { - SDL_InitTicks(); + SDL_TicksInit(); } if (has_monotonic_time) { diff --git a/libs/SDL2/src/timer/windows/SDL_systimer.c b/libs/SDL2/src/timer/windows/SDL_systimer.c index b1fe3017..186233a8 100644 --- a/libs/SDL2/src/timer/windows/SDL_systimer.c +++ b/libs/SDL2/src/timer/windows/SDL_systimer.c @@ -40,7 +40,6 @@ static BOOL hires_timer_available; static LARGE_INTEGER hires_start_ticks; /* The number of ticks per second of the high-resolution performance counter */ static LARGE_INTEGER hires_ticks_per_second; -#endif static void timeSetPeriod(UINT uPeriod) @@ -76,13 +75,15 @@ SDL_TimerResolutionChanged(void *userdata, const char *name, const char *oldValu } } +#endif /* !USE_GETTICKCOUNT */ + void -SDL_InitTicks(void) +SDL_TicksInit(void) { if (ticks_started) { return; } - ticks_started = TRUE; + ticks_started = SDL_TRUE; /* Set first ticks value */ #ifdef USE_GETTICKCOUNT @@ -98,11 +99,26 @@ SDL_InitTicks(void) hires_timer_available = FALSE; timeSetPeriod(1); /* use 1 ms timer precision */ start = timeGetTime(); + + SDL_AddHintCallback(SDL_HINT_TIMER_RESOLUTION, + SDL_TimerResolutionChanged, NULL); + } +#endif +} + +void +SDL_TicksQuit(void) +{ +#ifndef USE_GETTICKCOUNT + if (!hires_timer_available) { + SDL_DelHintCallback(SDL_HINT_TIMER_RESOLUTION, + SDL_TimerResolutionChanged, NULL); + + timeSetPeriod(0); } #endif - SDL_AddHintCallback(SDL_HINT_TIMER_RESOLUTION, - SDL_TimerResolutionChanged, NULL); + ticks_started = SDL_FALSE; } Uint32 @@ -114,7 +130,7 @@ SDL_GetTicks(void) #endif if (!ticks_started) { - SDL_InitTicks(); + SDL_TicksInit(); } #ifdef USE_GETTICKCOUNT diff --git a/libs/SDL2/src/video/SDL_video.c b/libs/SDL2/src/video/SDL_video.c index 338a4cc9..7426e2f4 100644 --- a/libs/SDL2/src/video/SDL_video.c +++ b/libs/SDL2/src/video/SDL_video.c @@ -421,8 +421,10 @@ int SDL_VideoInit(const char *driver_name) { SDL_VideoDevice *video; + const char *hint; int index; int i; + SDL_bool allow_screensaver; /* Check to make sure we don't overwrite '_this' */ if (_this != NULL) { @@ -430,7 +432,7 @@ SDL_VideoInit(const char *driver_name) } #if !SDL_TIMERS_DISABLED - SDL_InitTicks(); + SDL_TicksInit(); #endif /* Start the event loop */ @@ -504,6 +506,22 @@ SDL_VideoInit(const char *driver_name) _this->DestroyWindowFramebuffer = SDL_DestroyWindowTexture; } + /* Disable the screen saver by default. This is a change from <= 2.0.1, + but most things using SDL are games or media players; you wouldn't + want a screensaver to trigger if you're playing exclusively with a + joystick, or passively watching a movie. Things that use SDL but + function more like a normal desktop app should explicitly reenable the + screensaver. */ + hint = SDL_GetHint(SDL_HINT_VIDEO_ALLOW_SCREENSAVER); + if (hint) { + allow_screensaver = SDL_atoi(hint) ? SDL_TRUE : SDL_FALSE; + } else { + allow_screensaver = SDL_FALSE; + } + if (!allow_screensaver) { + SDL_DisableScreenSaver(); + } + /* If we don't use a screen keyboard, turn on text input by default, otherwise programs that expect to get text events without enabling UNICODE input won't get any events. diff --git a/libs/SDL2/src/video/cocoa/SDL_cocoaevents.m b/libs/SDL2/src/video/cocoa/SDL_cocoaevents.m index b3a6e93f..438385c3 100644 --- a/libs/SDL2/src/video/cocoa/SDL_cocoaevents.m +++ b/libs/SDL2/src/video/cocoa/SDL_cocoaevents.m @@ -36,6 +36,22 @@ #define UsrActivity 1 #endif +@interface SDLApplication : NSApplication + +- (void)terminate:(id)sender; + +@end + +@implementation SDLApplication + +// Override terminate to handle Quit and System Shutdown smoothly. +- (void)terminate:(id)sender +{ + SDL_SendQuit(); +} + +@end // SDLApplication + /* setAppleMenu disappeared from the headers in 10.4 */ @interface NSApplication(NSAppleMenu) - (void)setAppleMenu:(NSMenu *)menu; @@ -71,12 +87,6 @@ [super dealloc]; } -- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender -{ - SDL_SendQuit(); - return NSTerminateCancel; -} - - (void)focusSomeWindow:(NSNotification *)aNotification { /* HACK: Ignore the first call. The application gets a @@ -125,13 +135,12 @@ static SDLAppDelegate *appDelegate = nil; static NSString * GetApplicationName(void) { - NSDictionary *dict; - NSString *appName = 0; + NSString *appName; /* Determine the application name */ - dict = (NSDictionary *)CFBundleGetInfoDictionary(CFBundleGetMainBundle()); - if (dict) - appName = [dict objectForKey: @"CFBundleName"]; + appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"]; + if (!appName) + appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"]; if (![appName length]) appName = [[NSProcessInfo processInfo] processName]; @@ -256,13 +265,16 @@ Cocoa_RegisterApp(void) pool = [[NSAutoreleasePool alloc] init]; if (NSApp == nil) { - [NSApplication sharedApplication]; + [SDLApplication sharedApplication]; if ([NSApp mainMenu] == nil) { CreateApplicationMenus(); } [NSApp finishLaunching]; - NSDictionary *appDefaults = [NSDictionary dictionaryWithObject:@"NO" forKey:@"AppleMomentumScrollSupported"]; + NSDictionary *appDefaults = [[NSDictionary alloc] initWithObjectsAndKeys: + [NSNumber numberWithBool:NO], @"AppleMomentumScrollSupported", + [NSNumber numberWithBool:NO], @"ApplePressAndHoldEnabled", + nil]; [[NSUserDefaults standardUserDefaults] registerDefaults:appDefaults]; } diff --git a/libs/SDL2/src/video/cocoa/SDL_cocoamouse.h b/libs/SDL2/src/video/cocoa/SDL_cocoamouse.h index a0738eb9..336b8404 100644 --- a/libs/SDL2/src/video/cocoa/SDL_cocoamouse.h +++ b/libs/SDL2/src/video/cocoa/SDL_cocoamouse.h @@ -28,11 +28,18 @@ extern void Cocoa_InitMouse(_THIS); extern void Cocoa_HandleMouseEvent(_THIS, NSEvent * event); extern void Cocoa_HandleMouseWheel(SDL_Window *window, NSEvent * event); +extern void Cocoa_HandleMouseWarp(CGFloat x, CGFloat y); extern void Cocoa_QuitMouse(_THIS); typedef struct { - int deltaXOffset; - int deltaYOffset; + /* Wether we've seen a cursor warp since the last move event. */ + SDL_bool seenWarp; + /* What location our last cursor warp was to. */ + CGFloat lastWarpX; + CGFloat lastWarpY; + /* What location we last saw the cursor move to. */ + CGFloat lastMoveX; + CGFloat lastMoveY; void *tapdata; } SDL_MouseData; diff --git a/libs/SDL2/src/video/cocoa/SDL_cocoamouse.m b/libs/SDL2/src/video/cocoa/SDL_cocoamouse.m index 98b0e616..f5b54ed3 100644 --- a/libs/SDL2/src/video/cocoa/SDL_cocoamouse.m +++ b/libs/SDL2/src/video/cocoa/SDL_cocoamouse.m @@ -29,6 +29,14 @@ #include "../../events/SDL_mouse_c.h" +/* #define DEBUG_COCOAMOUSE */ + +#ifdef DEBUG_COCOAMOUSE +#define DLog(fmt, ...) printf("%s: " fmt "\n", __func__, ##__VA_ARGS__) +#else +#define DLog(...) do { } while (0) +#endif + @implementation NSCursor (InvisibleCursor) + (NSCursor *)invisibleCursor { @@ -203,18 +211,19 @@ Cocoa_ShowCursor(SDL_Cursor * cursor) static void Cocoa_WarpMouse(SDL_Window * window, int x, int y) { + SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + if ([data->listener isMoving]) + { + DLog("Postponing warp, window being moved."); + [data->listener setPendingMoveX:x + Y:y]; + return; + } + SDL_Mouse *mouse = SDL_GetMouse(); CGPoint point = CGPointMake(x + (float)window->x, y + (float)window->y); - { - /* This makes Cocoa_HandleMouseEvent ignore this delta in the next - * movement event. - */ - SDL_MouseData *driverdata = (SDL_MouseData*)mouse->driverdata; - NSPoint location = [NSEvent mouseLocation]; - driverdata->deltaXOffset = location.x - point.x; - driverdata->deltaYOffset = point.y - location.y; - } + Cocoa_HandleMouseWarp(point.x, point.y); /* According to the docs, this was deprecated in 10.6, but it's still * around. The substitute requires a CGEventSource, but I'm not entirely @@ -235,11 +244,28 @@ Cocoa_WarpMouse(SDL_Window * window, int x, int y) static int Cocoa_SetRelativeMouseMode(SDL_bool enabled) { - CGError result; + /* We will re-apply the relative mode when the window gets focus, if it + * doesn't have focus right now. + */ + SDL_Window *window = SDL_GetMouseFocus(); + if (!window) { + return 0; + } + /* We will re-apply the relative mode when the window finishes being moved, + * if it is being moved right now. + */ + SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + if ([data->listener isMoving]) { + return 0; + } + + CGError result; if (enabled) { + DLog("Turning on."); result = CGAssociateMouseAndMouseCursorPosition(NO); } else { + DLog("Turning off."); result = CGAssociateMouseAndMouseCursorPosition(YES); } if (result != kCGErrorSuccess) { @@ -265,25 +291,67 @@ Cocoa_InitMouse(_THIS) SDL_SetDefaultCursor(Cocoa_CreateDefaultCursor()); Cocoa_InitMouseEventTap(mouse->driverdata); + + SDL_MouseData *driverdata = (SDL_MouseData*)mouse->driverdata; + const NSPoint location = [NSEvent mouseLocation]; + driverdata->lastMoveX = location.x; + driverdata->lastMoveY = location.y; } void Cocoa_HandleMouseEvent(_THIS, NSEvent *event) { + switch ([event type]) + { + case NSMouseMoved: + case NSLeftMouseDragged: + case NSRightMouseDragged: + case NSOtherMouseDragged: + break; + + default: + /* Ignore any other events. */ + return; + } + SDL_Mouse *mouse = SDL_GetMouse(); - if (mouse->relative_mode && - ([event type] == NSMouseMoved || - [event type] == NSLeftMouseDragged || - [event type] == NSRightMouseDragged || - [event type] == NSOtherMouseDragged)) { - SDL_MouseData *driverdata = (SDL_MouseData*)mouse->driverdata; - float x = [event deltaX] + driverdata->deltaXOffset; - float y = [event deltaY] + driverdata->deltaYOffset; - driverdata->deltaXOffset = driverdata->deltaYOffset = 0; + SDL_MouseData *driverdata = (SDL_MouseData*)mouse->driverdata; + const SDL_bool seenWarp = driverdata->seenWarp; + driverdata->seenWarp = NO; - SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 1, (int)x, (int)y); + const NSPoint location = [NSEvent mouseLocation]; + const CGFloat lastMoveX = driverdata->lastMoveX; + const CGFloat lastMoveY = driverdata->lastMoveY; + driverdata->lastMoveX = location.x; + driverdata->lastMoveY = location.y; + DLog("Last seen mouse: (%g, %g)", location.x, location.y); + + /* Non-relative movement is handled in -[Cocoa_WindowListener mouseMoved:] */ + if (!mouse->relative_mode) { + return; } + + /* Ignore events that aren't inside the client area (i.e. title bar.) */ + if ([event window]) { + NSRect windowRect = [[[event window] contentView] frame]; + if (!NSPointInRect([event locationInWindow], windowRect)) { + return; + } + } + + float deltaX = [event deltaX]; + float deltaY = [event deltaY]; + + if (seenWarp) + { + deltaX += (lastMoveX - driverdata->lastWarpX); + deltaY += ((CGDisplayPixelsHigh(kCGDirectMainDisplay) - lastMoveY) - driverdata->lastWarpY); + + DLog("Motion was (%g, %g), offset to (%g, %g)", [event deltaX], [event deltaY], deltaX, deltaY); + } + + SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 1, (int)deltaX, (int)deltaY); } void @@ -291,7 +359,7 @@ Cocoa_HandleMouseWheel(SDL_Window *window, NSEvent *event) { SDL_Mouse *mouse = SDL_GetMouse(); - float x = [event deltaX]; + float x = -[event deltaX]; float y = [event deltaY]; if (x > 0) { @@ -307,6 +375,20 @@ Cocoa_HandleMouseWheel(SDL_Window *window, NSEvent *event) SDL_SendMouseWheel(window, mouse->mouseID, (int)x, (int)y); } +void +Cocoa_HandleMouseWarp(CGFloat x, CGFloat y) +{ + /* This makes Cocoa_HandleMouseEvent ignore the delta caused by the warp, + * since it gets included in the next movement event. + */ + SDL_MouseData *driverdata = (SDL_MouseData*)SDL_GetMouse()->driverdata; + driverdata->lastWarpX = x; + driverdata->lastWarpY = y; + driverdata->seenWarp = SDL_TRUE; + + DLog("(%g, %g)", x, y); +} + void Cocoa_QuitMouse(_THIS) { diff --git a/libs/SDL2/src/video/cocoa/SDL_cocoaopengl.m b/libs/SDL2/src/video/cocoa/SDL_cocoaopengl.m index 803b4ecd..cacb7551 100644 --- a/libs/SDL2/src/video/cocoa/SDL_cocoaopengl.m +++ b/libs/SDL2/src/video/cocoa/SDL_cocoaopengl.m @@ -35,17 +35,14 @@ #define DEFAULT_OPENGL "/System/Library/Frameworks/OpenGL.framework/Libraries/libGL.dylib" -#ifndef kCGLPFAOpenGLProfile -#define kCGLPFAOpenGLProfile 99 +#ifndef NSOpenGLPFAOpenGLProfile +#define NSOpenGLPFAOpenGLProfile 99 #endif -#ifndef kCGLOGLPVersion_Legacy -#define kCGLOGLPVersion_Legacy 0x1000 +#ifndef NSOpenGLProfileVersionLegacy +#define NSOpenGLProfileVersionLegacy 0x1000 #endif -#ifndef kCGLOGLPVersion_GL3_Core -#define kCGLOGLPVersion_GL3_Core 0x3200 -#endif -#ifndef kCGLOGLPVersion_GL4_Core -#define kCGLOGLPVersion_GL4_Core 0x4100 +#ifndef NSOpenGLProfileVersion3_2Core +#define NSOpenGLProfileVersion3_2Core 0x3200 #endif @implementation SDLOpenGLContext : NSOpenGLContext @@ -110,11 +107,19 @@ if ([self view] != [windowdata->nswindow contentView]) { [self setView:[windowdata->nswindow contentView]]; - [self scheduleUpdate]; + if (self == [NSOpenGLContext currentContext]) { + [self update]; + } else { + [self scheduleUpdate]; + } } } else { [self clearDrawable]; - [self scheduleUpdate]; + if (self == [NSOpenGLContext currentContext]) { + [self update]; + } else { + [self scheduleUpdate]; + } } } @@ -156,9 +161,8 @@ Cocoa_GL_UnloadLibrary(_THIS) SDL_GLContext Cocoa_GL_CreateContext(_THIS, SDL_Window * window) { - const int wantver = (_this->gl_config.major_version << 8) | - (_this->gl_config.minor_version); SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; + const GLubyte *(APIENTRY * glGetStringFunc)(GLenum) = NULL; NSAutoreleasePool *pool; SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window); SDL_DisplayData *displaydata = (SDL_DisplayData *)display->driverdata; @@ -167,16 +171,16 @@ Cocoa_GL_CreateContext(_THIS, SDL_Window * window) SDLOpenGLContext *context; NSOpenGLContext *share_context = nil; int i = 0; + const char *glversion; + int glversion_major; + int glversion_minor; if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) { SDL_SetError ("OpenGL ES is not supported on this platform"); return NULL; } - - /* Sadly, we'll have to update this as life progresses, since we need to - set an enum for context profiles, not a context version number */ - if (wantver > 0x0401) { - SDL_SetError ("OpenGL > 4.1 is not supported on this platform"); + if ((_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_CORE) && (data->osversion < 0x1070)) { + SDL_SetError ("OpenGL Core Profile is not supported on this platform version"); return NULL; } @@ -184,19 +188,11 @@ Cocoa_GL_CreateContext(_THIS, SDL_Window * window) /* specify a profile if we're on Lion (10.7) or later. */ if (data->osversion >= 0x1070) { - NSOpenGLPixelFormatAttribute profile = kCGLOGLPVersion_Legacy; + NSOpenGLPixelFormatAttribute profile = NSOpenGLProfileVersionLegacy; if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_CORE) { - if (wantver == 0x0302) { - profile = kCGLOGLPVersion_GL3_Core; - } else if ((wantver == 0x0401) && (data->osversion >= 0x1090)) { - profile = kCGLOGLPVersion_GL4_Core; - } else { - SDL_SetError("Requested GL version is not supported on this platform"); - [pool release]; - return NULL; - } + profile = NSOpenGLProfileVersion3_2Core; } - attr[i++] = kCGLPFAOpenGLProfile; + attr[i++] = NSOpenGLPFAOpenGLProfile; attr[i++] = profile; } @@ -276,9 +272,40 @@ Cocoa_GL_CreateContext(_THIS, SDL_Window * window) if ( Cocoa_GL_MakeCurrent(_this, window, context) < 0 ) { Cocoa_GL_DeleteContext(_this, context); + SDL_SetError ("Failed making OpenGL context current"); return NULL; } + glGetStringFunc = (const GLubyte *(APIENTRY *)(GLenum)) SDL_GL_GetProcAddress("glGetString"); + if (!glGetStringFunc) { + Cocoa_GL_DeleteContext(_this, context); + SDL_SetError ("Failed getting OpenGL glGetString entry point"); + return NULL; + } + + glversion = (const char *)glGetStringFunc(GL_VERSION); + if (glversion == NULL) { + Cocoa_GL_DeleteContext(_this, context); + SDL_SetError ("Failed getting OpenGL context version"); + return NULL; + } + + if (SDL_sscanf(glversion, "%d.%d", &glversion_major, &glversion_minor) != 2) { + Cocoa_GL_DeleteContext(_this, context); + SDL_SetError ("Failed parsing OpenGL context version"); + return NULL; + } + + if ((glversion_major < _this->gl_config.major_version) || + ((glversion_major == _this->gl_config.major_version) && (glversion_minor < _this->gl_config.minor_version))) { + Cocoa_GL_DeleteContext(_this, context); + SDL_SetError ("Failed creating OpenGL context at version requested"); + return NULL; + } + + _this->gl_config.major_version = glversion_major; + _this->gl_config.minor_version = glversion_minor; + return context; } diff --git a/libs/SDL2/src/video/cocoa/SDL_cocoavideo.h b/libs/SDL2/src/video/cocoa/SDL_cocoavideo.h index f5836bd8..f194e1f7 100644 --- a/libs/SDL2/src/video/cocoa/SDL_cocoavideo.h +++ b/libs/SDL2/src/video/cocoa/SDL_cocoavideo.h @@ -46,6 +46,7 @@ typedef struct SDL_VideoData { SInt32 osversion; + int allow_spaces; unsigned int modifierFlags; void *key_layout; SDLTranslatorResponder *fieldEdit; diff --git a/libs/SDL2/src/video/cocoa/SDL_cocoavideo.m b/libs/SDL2/src/video/cocoa/SDL_cocoavideo.m index 0ab015f2..6766b71b 100644 --- a/libs/SDL2/src/video/cocoa/SDL_cocoavideo.m +++ b/libs/SDL2/src/video/cocoa/SDL_cocoavideo.m @@ -148,9 +148,15 @@ VideoBootStrap COCOA_bootstrap = { int Cocoa_VideoInit(_THIS) { + SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; + Cocoa_InitModes(_this); Cocoa_InitKeyboard(_this); Cocoa_InitMouse(_this); + + const char *hint = SDL_GetHint(SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES); + data->allow_spaces = ( (data->osversion >= 0x1070) && (!hint || (*hint != '0')) ); + return 0; } diff --git a/libs/SDL2/src/video/cocoa/SDL_cocoawindow.h b/libs/SDL2/src/video/cocoa/SDL_cocoawindow.h index 65e0d4b3..a4ec07d7 100644 --- a/libs/SDL2/src/video/cocoa/SDL_cocoawindow.h +++ b/libs/SDL2/src/video/cocoa/SDL_cocoawindow.h @@ -43,6 +43,8 @@ typedef enum BOOL isFullscreenSpace; BOOL inFullscreenTransition; PendingWindowOperation pendingWindowOperation; + BOOL isMoving; + int pendingWindowWarpX, pendingWindowWarpY; } -(void) listen:(SDL_WindowData *) data; @@ -54,6 +56,10 @@ typedef enum -(void) addPendingWindowOperation:(PendingWindowOperation) operation; -(void) close; +-(BOOL) isMoving; +-(void) setPendingMoveX:(int)x Y:(int)y; +-(void) windowDidFinishMoving; + /* Window delegate functionality */ -(BOOL) windowShouldClose:(id) sender; -(void) windowDidExpose:(NSNotification *) aNotification; @@ -67,6 +73,7 @@ typedef enum -(void) windowDidEnterFullScreen:(NSNotification *) aNotification; -(void) windowWillExitFullScreen:(NSNotification *) aNotification; -(void) windowDidExitFullScreen:(NSNotification *) aNotification; +-(NSApplicationPresentationOptions)window:(NSWindow *)window willUseFullScreenPresentationOptions:(NSApplicationPresentationOptions)proposedOptions; /* Window event handling */ -(void) mouseDown:(NSEvent *) theEvent; @@ -105,6 +112,7 @@ struct SDL_WindowData NSWindow *nswindow; NSMutableArray *nscontexts; SDL_bool created; + SDL_bool inWindowMove; Cocoa_WindowListener *listener; struct SDL_VideoData *videodata; }; diff --git a/libs/SDL2/src/video/cocoa/SDL_cocoawindow.m b/libs/SDL2/src/video/cocoa/SDL_cocoawindow.m index 03ece7b9..1b58a678 100644 --- a/libs/SDL2/src/video/cocoa/SDL_cocoawindow.m +++ b/libs/SDL2/src/video/cocoa/SDL_cocoawindow.m @@ -38,6 +38,54 @@ #include "SDL_cocoashape.h" #include "SDL_cocoamouse.h" #include "SDL_cocoaopengl.h" +#include "SDL_assert.h" + +/* #define DEBUG_COCOAWINDOW */ + +#ifdef DEBUG_COCOAWINDOW +#define DLog(fmt, ...) printf("%s: " fmt "\n", __func__, ##__VA_ARGS__) +#else +#define DLog(...) do { } while (0) +#endif + + +@interface SDLWindow : NSWindow +/* These are needed for borderless/fullscreen windows */ +- (BOOL)canBecomeKeyWindow; +- (BOOL)canBecomeMainWindow; +- (void)sendEvent:(NSEvent *)event; +@end + +@implementation SDLWindow +- (BOOL)canBecomeKeyWindow +{ + return YES; +} + +- (BOOL)canBecomeMainWindow +{ + return YES; +} + +- (void)sendEvent:(NSEvent *)event +{ + [super sendEvent:event]; + + if ([event type] != NSLeftMouseUp) { + return; + } + + id delegate = [self delegate]; + if (![delegate isKindOfClass:[Cocoa_WindowListener class]]) { + return; + } + + if ([delegate isMoving]) { + [delegate windowDidFinishMoving]; + } +} +@end + static Uint32 s_moveHack; @@ -49,10 +97,15 @@ static void ConvertNSRect(NSRect *r) static void ScheduleContextUpdates(SDL_WindowData *data) { + NSOpenGLContext *currentContext = [NSOpenGLContext currentContext]; NSMutableArray *contexts = data->nscontexts; @synchronized (contexts) { for (SDLOpenGLContext *context in contexts) { - [context scheduleUpdate]; + if (context == currentContext) { + [context update]; + } else { + [context scheduleUpdate]; + } } } } @@ -125,6 +178,7 @@ SetWindowStyle(SDL_Window * window, unsigned int style) isFullscreenSpace = NO; inFullscreenTransition = NO; pendingWindowOperation = PENDING_OPERATION_NONE; + isMoving = NO; center = [NSNotificationCenter defaultCenter]; @@ -203,20 +257,18 @@ SetWindowStyle(SDL_Window * window, unsigned int style) } } --(BOOL) setFullscreenSpace:(BOOL) state; +-(BOOL) setFullscreenSpace:(BOOL) state { SDL_Window *window = _data->window; NSWindow *nswindow = _data->nswindow; + SDL_VideoData *videodata = ((SDL_WindowData *) window->driverdata)->videodata; - if (![nswindow respondsToSelector: @selector(collectionBehavior)]) { - return NO; - } - if ([nswindow collectionBehavior] != NSWindowCollectionBehaviorFullScreenPrimary) { - return NO; - } - - if (state == isFullscreenSpace) { - return YES; + if (!videodata->allow_spaces) { + return NO; /* Spaces are forcibly disabled. */ + } else if (state && ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) != SDL_WINDOW_FULLSCREEN_DESKTOP)) { + return NO; /* we only allow you to make a Space on FULLSCREEN_DESKTOP windows. */ + } else if (state == isFullscreenSpace) { + return YES; /* already there. */ } if (inFullscreenTransition) { @@ -229,13 +281,8 @@ SetWindowStyle(SDL_Window * window, unsigned int style) } inFullscreenTransition = YES; - /* Update the flags here so the state change is available immediately */ - if (state) { - window->flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; - } else { - window->flags &= ~SDL_WINDOW_FULLSCREEN_DESKTOP; - } - + /* you need to be FullScreenPrimary, or toggleFullScreen doesn't work. Unset it again in windowDidExitFullScreen. */ + [nswindow setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary]; [nswindow performSelectorOnMainThread: @selector(toggleFullScreen:) withObject:nswindow waitUntilDone:NO]; return YES; } @@ -310,6 +357,34 @@ SetWindowStyle(SDL_Window * window, unsigned int style) } } +- (BOOL)isMoving +{ + return isMoving; +} + +-(void) setPendingMoveX:(int)x Y:(int)y +{ + pendingWindowWarpX = x; + pendingWindowWarpY = y; +} + +- (void)windowDidFinishMoving +{ + if ([self isMoving]) + { + isMoving = NO; + + SDL_Mouse *mouse = SDL_GetMouse(); + if (pendingWindowWarpX >= 0 && pendingWindowWarpY >= 0) { + mouse->WarpMouse(_data->window, pendingWindowWarpX, pendingWindowWarpY); + pendingWindowWarpX = pendingWindowWarpY = -1; + } + if (mouse->relative_mode && SDL_GetMouseFocus() == _data->window) { + mouse->SetRelativeMouseMode(SDL_TRUE); + } + } +} + - (BOOL)windowShouldClose:(id)sender { SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_CLOSE, 0, 0); @@ -321,6 +396,14 @@ SetWindowStyle(SDL_Window * window, unsigned int style) SDL_SendWindowEvent(_data->window, SDL_WINDOWEVENT_EXPOSED, 0, 0); } +- (void)windowWillMove:(NSNotification *)aNotification +{ + if ([_data->nswindow isKindOfClass:[SDLWindow class]]) { + pendingWindowWarpX = pendingWindowWarpY = -1; + isMoving = YES; + } +} + - (void)windowDidMove:(NSNotification *)aNotification { int x, y; @@ -354,6 +437,11 @@ SetWindowStyle(SDL_Window * window, unsigned int style) - (void)windowDidResize:(NSNotification *)aNotification { + if (inFullscreenTransition) { + /* We'll take care of this at the end of the transition */ + return; + } + SDL_Window *window = _data->window; NSWindow *nswindow = _data->nswindow; int x, y, w, h; @@ -364,11 +452,6 @@ SetWindowStyle(SDL_Window * window, unsigned int style) w = (int)rect.size.width; h = (int)rect.size.height; - if (inFullscreenTransition) { - /* We'll take care of this at the end of the transition */ - return; - } - if (SDL_IsShapedWindow(window)) { Cocoa_ResizeWindowShape(window); } @@ -402,6 +485,9 @@ SetWindowStyle(SDL_Window * window, unsigned int style) { SDL_Window *window = _data->window; SDL_Mouse *mouse = SDL_GetMouse(); + if (mouse->relative_mode && ![self isMoving]) { + mouse->SetRelativeMouseMode(SDL_TRUE); + } /* We're going to get keyboard events, since we're key. */ SDL_SetKeyboardFocus(window); @@ -422,10 +508,19 @@ SetWindowStyle(SDL_Window * window, unsigned int style) /* Check to see if someone updated the clipboard */ Cocoa_CheckClipboardUpdate(_data->videodata); + + if ((isFullscreenSpace) && ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP)) { + [NSMenu setMenuBarVisible:NO]; + } } - (void)windowDidResignKey:(NSNotification *)aNotification { + SDL_Mouse *mouse = SDL_GetMouse(); + if (mouse->relative_mode) { + mouse->SetRelativeMouseMode(SDL_FALSE); + } + /* Some other window will get mouse events, since we're not key. */ if (SDL_GetMouseFocus() == _data->window) { SDL_SetMouseFocus(NULL); @@ -435,13 +530,16 @@ SetWindowStyle(SDL_Window * window, unsigned int style) if (SDL_GetKeyboardFocus() == _data->window) { SDL_SetKeyboardFocus(NULL); } + + if (isFullscreenSpace) { + [NSMenu setMenuBarVisible:YES]; + } } - (void)windowWillEnterFullScreen:(NSNotification *)aNotification { SDL_Window *window = _data->window; - window->flags |= SDL_WINDOW_FULLSCREEN_DESKTOP; SetWindowStyle(window, (NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask)); isFullscreenSpace = YES; @@ -458,6 +556,10 @@ SetWindowStyle(SDL_Window * window, unsigned int style) pendingWindowOperation = PENDING_OPERATION_NONE; [self setFullscreenSpace:NO]; } else { + if ((window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP) { + [NSMenu setMenuBarVisible:NO]; + } + pendingWindowOperation = PENDING_OPERATION_NONE; /* Force the size change event in case it was delivered earlier while the window was still animating into place. @@ -472,7 +574,6 @@ SetWindowStyle(SDL_Window * window, unsigned int style) { SDL_Window *window = _data->window; - window->flags &= ~SDL_WINDOW_FULLSCREEN_DESKTOP; SetWindowStyle(window, GetWindowStyle(window)); isFullscreenSpace = NO; @@ -493,6 +594,15 @@ SetWindowStyle(SDL_Window * window, unsigned int style) pendingWindowOperation = PENDING_OPERATION_NONE; [nswindow miniaturize:nil]; } else { + /* Adjust the fullscreen toggle button and readd menu now that we're here. */ + if (window->flags & SDL_WINDOW_RESIZABLE) { + /* resizable windows are Spaces-friendly: they get the "go fullscreen" toggle button on their titlebar. */ + [nswindow setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary]; + } else { + [nswindow setCollectionBehavior:NSWindowCollectionBehaviorManaged]; + } + [NSMenu setMenuBarVisible:YES]; + pendingWindowOperation = PENDING_OPERATION_NONE; /* Force the size change event in case it was delivered earlier while the window was still animating into place. @@ -503,6 +613,16 @@ SetWindowStyle(SDL_Window * window, unsigned int style) } } +-(NSApplicationPresentationOptions)window:(NSWindow *)window willUseFullScreenPresentationOptions:(NSApplicationPresentationOptions)proposedOptions +{ + if ((_data->window->flags & SDL_WINDOW_FULLSCREEN_DESKTOP) == SDL_WINDOW_FULLSCREEN_DESKTOP) { + return NSApplicationPresentationFullScreen | NSApplicationPresentationHideDock | NSApplicationPresentationHideMenuBar; + } else { + return proposedOptions; + } +} + + /* We'll respond to key events by doing nothing so we don't beep. * We could handle key messages here, but we lose some in the NSApp dispatch, * where they get converted to action messages, etc. @@ -619,8 +739,6 @@ SetWindowStyle(SDL_Window * window, unsigned int style) if (x < 0 || x >= window->w || y < 0 || y >= window->h) { if (window->flags & SDL_WINDOW_INPUT_GRABBED) { - CGPoint cgpoint; - if (x < 0) { x = 0; } else if (x >= window->w) { @@ -633,6 +751,8 @@ SetWindowStyle(SDL_Window * window, unsigned int style) } #if !SDL_MAC_NO_SANDBOX + CGPoint cgpoint; + /* When SDL_MAC_NO_SANDBOX is set, this is handled by * SDL_cocoamousetap.m. */ @@ -647,6 +767,8 @@ SetWindowStyle(SDL_Window * window, unsigned int style) CGSetLocalEventsSuppressionInterval(0.0); CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint); CGSetLocalEventsSuppressionInterval(0.25); + + Cocoa_HandleMouseWarp(cgpoint.x, cgpoint.y); #endif } } @@ -749,24 +871,6 @@ SetWindowStyle(SDL_Window * window, unsigned int style) @end -@interface SDLWindow : NSWindow -/* These are needed for borderless/fullscreen windows */ -- (BOOL)canBecomeKeyWindow; -- (BOOL)canBecomeMainWindow; -@end - -@implementation SDLWindow -- (BOOL)canBecomeKeyWindow -{ - return YES; -} - -- (BOOL)canBecomeMainWindow -{ - return YES; -} -@end - @interface SDLView : NSView /* The default implementation doesn't pass rightMouseDown to responder chain */ @@ -883,6 +987,7 @@ SetupWindowData(_THIS, SDL_Window * window, NSWindow *nswindow, SDL_bool created int Cocoa_CreateWindow(_THIS, SDL_Window * window) { + SDL_VideoData *videodata = (SDL_VideoData *) _this->driverdata; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSWindow *nswindow; SDL_VideoDisplay *display = SDL_GetDisplayForWindow(window); @@ -926,9 +1031,13 @@ Cocoa_CreateWindow(_THIS, SDL_Window * window) return -1; } [nswindow setBackgroundColor:[NSColor blackColor]]; - if ([nswindow respondsToSelector:@selector(setCollectionBehavior:)]) { - const char *hint = SDL_GetHint(SDL_HINT_VIDEO_FULLSCREEN_SPACES); - if (hint && SDL_atoi(hint) > 0) { + + if (videodata->allow_spaces) { + SDL_assert(videodata->osversion >= 0x1070); + SDL_assert([nswindow respondsToSelector:@selector(toggleFullScreen:)]); + /* we put FULLSCREEN_DESKTOP windows in their own Space, without a toggle button or menubar, later */ + if (window->flags & SDL_WINDOW_RESIZABLE) { + /* resizable windows are Spaces-friendly: they get the "go fullscreen" toggle button on their titlebar. */ [nswindow setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary]; } } @@ -1333,13 +1442,18 @@ void Cocoa_SetWindowGrab(_THIS, SDL_Window * window, SDL_bool grabbed) { /* Move the cursor to the nearest point in the window */ - if (grabbed) { + SDL_WindowData *data = (SDL_WindowData *) window->driverdata; + if (grabbed && data && ![data->listener isMoving]) { int x, y; CGPoint cgpoint; SDL_GetMouseState(&x, &y); cgpoint.x = window->x + x; cgpoint.y = window->y + y; + + Cocoa_HandleMouseWarp(cgpoint.x, cgpoint.y); + + DLog("Returning cursor to (%g, %g)", cgpoint.x, cgpoint.y); CGDisplayMoveCursorToPoint(kCGDirectMainDisplay, cgpoint); } diff --git a/libs/SDL2/src/video/mir/SDL_mirframebuffer.c b/libs/SDL2/src/video/mir/SDL_mirframebuffer.c index 22f290b9..f8b46649 100644 --- a/libs/SDL2/src/video/mir/SDL_mirframebuffer.c +++ b/libs/SDL2/src/video/mir/SDL_mirframebuffer.c @@ -91,11 +91,13 @@ MIR_UpdateWindowFramebuffer(_THIS, SDL_Window* window, MirGraphicsRegion region; int i, j, x, y, w, h, start; int bytes_per_pixel, bytes_per_row, s_stride, d_stride; + char* s_dest; + char* pixels; MIR_mir_surface_get_graphics_region(mir_window->surface, ®ion); - char* s_dest = region.vaddr; - char* pixels = (char*)window->surface->pixels; + s_dest = region.vaddr; + pixels = (char*)window->surface->pixels; s_stride = window->surface->pitch; d_stride = region.stride; diff --git a/libs/SDL2/src/video/uikit/SDL_uikitopenglview.m b/libs/SDL2/src/video/uikit/SDL_uikitopenglview.m index c6daa1e4..5c163c9a 100644 --- a/libs/SDL2/src/video/uikit/SDL_uikitopenglview.m +++ b/libs/SDL2/src/video/uikit/SDL_uikitopenglview.m @@ -56,6 +56,11 @@ const BOOL useDepthBuffer = (depthBits != 0); NSString *colorFormat = nil; + /* The EAGLRenderingAPI enum values currently map 1:1 to major GLES + versions, and this allows us to handle future OpenGL ES versions. + */ + EAGLRenderingAPI api = majorVersion; + if (rBits == 8 && gBits == 8 && bBits == 8) { /* if user specifically requests rbg888 or some color format higher than 16bpp */ colorFormat = kEAGLColorFormatRGBA8; @@ -71,11 +76,7 @@ eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool: retained], kEAGLDrawablePropertyRetainedBacking, colorFormat, kEAGLDrawablePropertyColorFormat, nil]; - if (majorVersion > 1) { - context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2 sharegroup:shareGroup]; - } else { - context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1 sharegroup:shareGroup]; - } + context = [[EAGLContext alloc] initWithAPI:api sharegroup:shareGroup]; if (!context || ![EAGLContext setCurrentContext:context]) { [self release]; SDL_SetError("OpenGL ES %d not supported", majorVersion); diff --git a/libs/SDL2/src/video/windows/SDL_windowsevents.c b/libs/SDL2/src/video/windows/SDL_windowsevents.c index dbd8e2e6..b4e51a0b 100644 --- a/libs/SDL2/src/video/windows/SDL_windowsevents.c +++ b/libs/SDL2/src/video/windows/SDL_windowsevents.c @@ -25,6 +25,7 @@ #include "SDL_windowsvideo.h" #include "SDL_windowsshape.h" #include "SDL_syswm.h" +#include "SDL_timer.h" #include "SDL_vkeys.h" #include "../../events/SDL_events_c.h" #include "../../events/SDL_touch_c.h" @@ -537,10 +538,10 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) /* Detect relevant keyboard shortcuts */ if (keyboardState[SDL_SCANCODE_LALT] == SDL_PRESSED || keyboardState[SDL_SCANCODE_RALT] == SDL_PRESSED ) { - /* ALT+F4: Close window */ - if (code == SDL_SCANCODE_F4) { - SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_CLOSE, 0, 0); - } + /* ALT+F4: Close window */ + if (code == SDL_SCANCODE_F4) { + SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_CLOSE, 0, 0); + } } if ( code != SDL_SCANCODE_UNKNOWN ) { @@ -569,6 +570,20 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) break; #endif /* WM_INPUTLANGCHANGE */ + case WM_NCLBUTTONDOWN: + { + data->in_title_click = SDL_TRUE; + WIN_UpdateClipCursor(data->window); + } + break; + + case WM_NCMOUSELEAVE: + { + data->in_title_click = SDL_FALSE; + WIN_UpdateClipCursor(data->window); + } + break; + case WM_ENTERSIZEMOVE: case WM_ENTERMENULOOP: { @@ -860,10 +875,17 @@ WIN_PumpEvents(_THIS) { const Uint8 *keystate; MSG msg; + DWORD start_ticks = GetTickCount(); + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { /* Always translate the message in case it's a non-SDL window (e.g. with Qt integration) */ TranslateMessage(&msg); - DispatchMessage(&msg); + DispatchMessage( &msg ); + + /* Make sure we don't busy loop here forever if there are lots of events coming in */ + if (SDL_TICKS_PASSED(msg.time, start_ticks)) { + break; + } } /* Windows loses a shift KEYUP event when you have both pressed at once and let go of one. diff --git a/libs/SDL2/src/video/windows/SDL_windowsmouse.c b/libs/SDL2/src/video/windows/SDL_windowsmouse.c index f7bcc10d..b49249db 100644 --- a/libs/SDL2/src/video/windows/SDL_windowsmouse.c +++ b/libs/SDL2/src/video/windows/SDL_windowsmouse.c @@ -183,9 +183,15 @@ WIN_ShowCursor(SDL_Cursor * cursor) static void WIN_WarpMouse(SDL_Window * window, int x, int y) { - HWND hwnd = ((SDL_WindowData *) window->driverdata)->hwnd; + SDL_WindowData *data = (SDL_WindowData *)window->driverdata; + HWND hwnd = data->hwnd; POINT pt; + /* Don't warp the mouse while we're doing a modal interaction */ + if (data->in_title_click || data->in_modal_loop) { + return; + } + pt.x = x; pt.y = y; ClientToScreen(hwnd, &pt); @@ -196,44 +202,20 @@ static int WIN_SetRelativeMouseMode(SDL_bool enabled) { RAWINPUTDEVICE rawMouse = { 0x01, 0x02, 0, NULL }; /* Mouse: UsagePage = 1, Usage = 2 */ - HWND hWnd; - hWnd = GetActiveWindow(); - rawMouse.hwndTarget = hWnd; - if(!enabled) { + if (!enabled) { rawMouse.dwFlags |= RIDEV_REMOVE; - rawMouse.hwndTarget = NULL; } - /* (Un)register raw input for mice */ if (RegisterRawInputDevices(&rawMouse, 1, sizeof(RAWINPUTDEVICE)) == FALSE) { - /* Only return an error when registering. If we unregister and fail, then - it's probably that we unregistered twice. That's OK. */ - if(enabled) { + /* Only return an error when registering. If we unregister and fail, + then it's probably that we unregistered twice. That's OK. */ + if (enabled) { return SDL_Unsupported(); } } - - if (enabled) { - LONG cx, cy; - RECT rect; - GetWindowRect(hWnd, &rect); - - cx = (rect.left + rect.right) / 2; - cy = (rect.top + rect.bottom) / 2; - - /* Make an absurdly small clip rect */ - rect.left = cx-1; - rect.right = cx+1; - rect.top = cy-1; - rect.bottom = cy+1; - - ClipCursor(&rect); - } else { - ClipCursor(NULL); - } return 0; } diff --git a/libs/SDL2/src/video/windows/SDL_windowsopengles.c b/libs/SDL2/src/video/windows/SDL_windowsopengles.c index 9cb5218a..a921ba8a 100644 --- a/libs/SDL2/src/video/windows/SDL_windowsopengles.c +++ b/libs/SDL2/src/video/windows/SDL_windowsopengles.c @@ -32,8 +32,6 @@ int WIN_GLES_LoadLibrary(_THIS, const char *path) { - SDL_VideoData *data = (SDL_VideoData *)_this->driverdata; - /* If the profile requested is not GL ES, switch over to WIN_GL functions */ if (_this->gl_config.profile_mask != SDL_GL_CONTEXT_PROFILE_ES) { #if SDL_VIDEO_OPENGL_WGL diff --git a/libs/SDL2/src/video/windows/SDL_windowsvideo.c b/libs/SDL2/src/video/windows/SDL_windowsvideo.c index dde26226..92ddcdfa 100644 --- a/libs/SDL2/src/video/windows/SDL_windowsvideo.c +++ b/libs/SDL2/src/video/windows/SDL_windowsvideo.c @@ -261,7 +261,7 @@ DXGI_LoadDLL( void **pDXGIDLL , IDXGIFactory **pDXGIFactory ) "CreateDXGIFactory"); if (CreateDXGI) { GUID dxgiGUID = {0x7b7166ec,0x21c7,0x44ae,{0xb2,0x1a,0xc9,0xae,0x32,0x1a,0xe3,0x69}}; - if( !SUCCEEDED( CreateDXGI( &dxgiGUID, pDXGIFactory ))) { + if( !SUCCEEDED( CreateDXGI( &dxgiGUID, (void**)pDXGIFactory ))) { *pDXGIFactory = NULL; } } diff --git a/libs/SDL2/src/video/windows/SDL_windowswindow.c b/libs/SDL2/src/video/windows/SDL_windowswindow.c index 7bf9e556..425b4da2 100644 --- a/libs/SDL2/src/video/windows/SDL_windowswindow.c +++ b/libs/SDL2/src/video/windows/SDL_windowswindow.c @@ -673,7 +673,7 @@ SDL_HelperWindowCreate(void) /* Register the class. */ SDL_HelperWindowClass = RegisterClass(&wce); - if (SDL_HelperWindowClass == 0) { + if (SDL_HelperWindowClass == 0 && GetLastError() != ERROR_CLASS_ALREADY_EXISTS) { return WIN_SetError("Unable to create Helper Window Class"); } @@ -746,7 +746,7 @@ WIN_UpdateClipCursor(SDL_Window *window) SDL_Mouse *mouse = SDL_GetMouse(); /* Don't clip the cursor while we're in the modal resize or move loop */ - if (data->in_modal_loop) { + if (data->in_title_click || data->in_modal_loop) { ClipCursor(NULL); return; } diff --git a/libs/SDL2/src/video/windows/SDL_windowswindow.h b/libs/SDL2/src/video/windows/SDL_windowswindow.h index 99ae4887..c4288874 100644 --- a/libs/SDL2/src/video/windows/SDL_windowswindow.h +++ b/libs/SDL2/src/video/windows/SDL_windowswindow.h @@ -38,6 +38,7 @@ typedef struct SDL_bool created; WPARAM mouse_button_flags; BOOL expected_resize; + SDL_bool in_title_click; SDL_bool in_modal_loop; struct SDL_VideoData *videodata; #if SDL_VIDEO_OPENGL_EGL diff --git a/libs/SDL2/src/video/windows/wmmsg.h b/libs/SDL2/src/video/windows/wmmsg.h index 2cc7a843..f4f0b092 100644 --- a/libs/SDL2/src/video/windows/wmmsg.h +++ b/libs/SDL2/src/video/windows/wmmsg.h @@ -257,7 +257,7 @@ char *wmtab[] = { "UNKNOWN (252)", "UNKNOWN (253)", "UNKNOWN (254)", - "UNKNOWN (255)", + "WM_INPUT", "WM_KEYDOWN", "WM_KEYUP", "WM_CHAR", @@ -570,30 +570,30 @@ char *wmtab[] = { "UNKNOWN (565)", "UNKNOWN (566)", "UNKNOWN (567)", - "UNKNOWN (568)", - "UNKNOWN (569)", - "UNKNOWN (570)", + "WM_POINTERDEVICECHANGE", + "WM_POINTERDEVICEINRANGE", + "WM_POINTERDEVICEOUTOFRANGE", "UNKNOWN (571)", "UNKNOWN (572)", "UNKNOWN (573)", "UNKNOWN (574)", "UNKNOWN (575)", "WM_TOUCH", - "UNKNOWN (577)", - "UNKNOWN (578)", - "UNKNOWN (579)", + "WM_NCPOINTERUPDATE", + "WM_NCPOINTERDOWN", + "WM_NCPOINTERUP", "UNKNOWN (580)", - "UNKNOWN (581)", - "UNKNOWN (582)", - "UNKNOWN (583)", - "UNKNOWN (584)", - "UNKNOWN (585)", - "UNKNOWN (586)", - "UNKNOWN (587)", - "UNKNOWN (588)", - "UNKNOWN (589)", - "UNKNOWN (590)", - "UNKNOWN (591)", + "WM_POINTERUPDATE", + "WM_POINTERDOWN", + "WM_POINTERUP", + "WM_POINTERENTER", + "WM_POINTERLEAVE", + "WM_POINTERACTIVATE", + "WM_POINTERCAPTURECHANGED", + "WM_TOUCHHITTESTING", + "WM_POINTERWHEEL", + "WM_POINTERHWHEEL", + "DM_POINTERHITTEST", "UNKNOWN (592)", "UNKNOWN (593)", "UNKNOWN (594)", @@ -643,14 +643,14 @@ char *wmtab[] = { "UNKNOWN (638)", "UNKNOWN (639)", "UNKNOWN (640)", - "UNKNOWN (641)", - "UNKNOWN (642)", - "UNKNOWN (643)", - "UNKNOWN (644)", - "UNKNOWN (645)", - "UNKNOWN (646)", + "WM_IME_SETCONTEXT", + "WM_IME_NOTIFY", + "WM_IME_CONTROL", + "WM_IME_COMPOSITIONFULL", + "WM_IME_SELECT", + "WM_IME_CHAR", "UNKNOWN (647)", - "UNKNOWN (648)", + "WM_IME_REQUEST", "UNKNOWN (649)", "UNKNOWN (650)", "UNKNOWN (651)", @@ -658,8 +658,8 @@ char *wmtab[] = { "UNKNOWN (653)", "UNKNOWN (654)", "UNKNOWN (655)", - "UNKNOWN (656)", - "UNKNOWN (657)", + "WM_IME_KEYDOWN", + "WM_IME_KEYUP", "UNKNOWN (658)", "UNKNOWN (659)", "UNKNOWN (660)", @@ -674,9 +674,9 @@ char *wmtab[] = { "UNKNOWN (669)", "UNKNOWN (670)", "UNKNOWN (671)", - "UNKNOWN (672)", + "WM_NCMOUSEHOVER", "WM_MOUSEHOVER", - "UNKNOWN (674)", + "WM_NCMOUSELEAVE", "WM_MOUSELEAVE", "UNKNOWN (676)", "UNKNOWN (677)", @@ -691,7 +691,7 @@ char *wmtab[] = { "UNKNOWN (686)", "UNKNOWN (687)", "UNKNOWN (688)", - "UNKNOWN (689)", + "WM_WTSSESSION_CHANGE", "UNKNOWN (690)", "UNKNOWN (691)", "UNKNOWN (692)", @@ -738,7 +738,7 @@ char *wmtab[] = { "UNKNOWN (733)", "UNKNOWN (734)", "UNKNOWN (735)", - "UNKNOWN (736)", + "WM_DPICHANGED", "UNKNOWN (737)", "UNKNOWN (738)", "UNKNOWN (739)", @@ -795,20 +795,20 @@ char *wmtab[] = { "UNKNOWN (790)", "WM_PRINT", "WM_PRINTCLIENT", - "UNKNOWN (793)", - "UNKNOWN (794)", + "WM_APPCOMMAND", + "WM_THEMECHANGED", "UNKNOWN (795)", "UNKNOWN (796)", - "UNKNOWN (797)", - "UNKNOWN (798)", - "UNKNOWN (799)", - "UNKNOWN (800)", - "UNKNOWN (801)", + "WM_CLIPBOARDUPDATE", + "WM_DWMCOMPOSITIONCHANGED", + "WM_DWMNCRENDERINGCHANGED", + "WM_DWMCOLORIZATIONCOLORCHANGED", + "WM_DWMWINDOWMAXIMIZEDCHANGE", "UNKNOWN (802)", - "UNKNOWN (803)", + "WM_DWMSENDICONICTHUMBNAIL", "UNKNOWN (804)", "UNKNOWN (805)", - "UNKNOWN (806)", + "WM_DWMSENDICONICLIVEPREVIEWBITMAP", "UNKNOWN (807)", "UNKNOWN (808)", "UNKNOWN (809)", @@ -833,7 +833,7 @@ char *wmtab[] = { "UNKNOWN (828)", "UNKNOWN (829)", "UNKNOWN (830)", - "UNKNOWN (831)", + "WM_GETTITLEBARINFOEX", "UNKNOWN (832)", "UNKNOWN (833)", "UNKNOWN (834)", diff --git a/libs/SDL2/src/video/x11/SDL_x11events.c b/libs/SDL2/src/video/x11/SDL_x11events.c index e99f91c5..ad3c59d6 100644 --- a/libs/SDL2/src/video/x11/SDL_x11events.c +++ b/libs/SDL2/src/video/x11/SDL_x11events.c @@ -28,7 +28,6 @@ #include #include /* For INT_MAX */ -#include "SDL_x11video.h" #include "SDL_x11video.h" #include "SDL_x11touch.h" #include "SDL_x11xinput2.h" @@ -993,11 +992,6 @@ X11_Pending(Display * display) return (0); } - -/* !!! FIXME: this should be exposed in a header, or something. */ -int SDL_GetNumTouch(void); -void SDL_dbus_screensaver_tickle(_THIS); - void X11_PumpEvents(_THIS) { @@ -1035,7 +1029,19 @@ X11_SuspendScreenSaver(_THIS) SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; int dummy; int major_version, minor_version; +#endif /* SDL_VIDEO_DRIVER_X11_XSCRNSAVER */ +#if SDL_USE_LIBDBUS + if (SDL_dbus_screensaver_inhibit(_this)) { + return; + } + + if (_this->suspend_screensaver) { + SDL_dbus_screensaver_tickle(_this); + } +#endif + +#if SDL_VIDEO_DRIVER_X11_XSCRNSAVER if (SDL_X11_HAVE_XSS) { /* X11_XScreenSaverSuspend was introduced in MIT-SCREEN-SAVER 1.1 */ if (!X11_XScreenSaverQueryExtension(data->display, &dummy, &dummy) || @@ -1049,12 +1055,6 @@ X11_SuspendScreenSaver(_THIS) X11_XResetScreenSaver(data->display); } #endif - -#if SDL_USE_LIBDBUS - if (_this->suspend_screensaver) { - SDL_dbus_screensaver_tickle(_this); - } -#endif } #endif /* SDL_VIDEO_DRIVER_X11 */ diff --git a/libs/SDL2/src/video/x11/SDL_x11video.c b/libs/SDL2/src/video/x11/SDL_x11video.c index 63cfa982..ca9faee3 100644 --- a/libs/SDL2/src/video/x11/SDL_x11video.c +++ b/libs/SDL2/src/video/x11/SDL_x11video.c @@ -45,6 +45,7 @@ #include "SDL_loadso.h" static const char *dbus_library = "libdbus-1.so.3"; static void *dbus_handle = NULL; +static unsigned int screensaver_cookie = 0; /* !!! FIXME: this is kinda ugly. */ static SDL_bool @@ -63,10 +64,13 @@ load_dbus_sym(const char *fn, void **addr) static DBusConnection *(*DBUS_dbus_bus_get_private)(DBusBusType, DBusError *) = NULL; static void (*DBUS_dbus_connection_set_exit_on_disconnect)(DBusConnection *, dbus_bool_t) = NULL; static dbus_bool_t (*DBUS_dbus_connection_send)(DBusConnection *, DBusMessage *, dbus_uint32_t *) = NULL; +static DBusMessage *(*DBUS_dbus_connection_send_with_reply_and_block)(DBusConnection *, DBusMessage *, int, DBusError *) = NULL; static void (*DBUS_dbus_connection_close)(DBusConnection *) = NULL; static void (*DBUS_dbus_connection_unref)(DBusConnection *) = NULL; static void (*DBUS_dbus_connection_flush)(DBusConnection *) = NULL; static DBusMessage *(*DBUS_dbus_message_new_method_call)(const char *, const char *, const char *, const char *) = NULL; +static dbus_bool_t (*DBUS_dbus_message_append_args)(DBusMessage *, int, ...) = NULL; +static dbus_bool_t (*DBUS_dbus_message_get_args)(DBusMessage *, DBusError *, int, ...) = NULL; static void (*DBUS_dbus_message_unref)(DBusMessage *) = NULL; static void (*DBUS_dbus_error_init)(DBusError *) = NULL; static dbus_bool_t (*DBUS_dbus_error_is_set)(const DBusError *) = NULL; @@ -82,9 +86,12 @@ load_dbus_syms(void) SDL_DBUS_SYM(dbus_bus_get_private); SDL_DBUS_SYM(dbus_connection_set_exit_on_disconnect); SDL_DBUS_SYM(dbus_connection_send); + SDL_DBUS_SYM(dbus_connection_send_with_reply_and_block); SDL_DBUS_SYM(dbus_connection_close); SDL_DBUS_SYM(dbus_connection_unref); SDL_DBUS_SYM(dbus_connection_flush); + SDL_DBUS_SYM(dbus_message_append_args); + SDL_DBUS_SYM(dbus_message_get_args); SDL_DBUS_SYM(dbus_message_new_method_call); SDL_DBUS_SYM(dbus_message_unref); SDL_DBUS_SYM(dbus_error_init); @@ -174,6 +181,76 @@ SDL_dbus_screensaver_tickle(_THIS) } } } + +SDL_bool +SDL_dbus_screensaver_inhibit(_THIS) +{ + const SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; + DBusConnection *conn = data->dbus; + + if (conn == NULL) + return SDL_FALSE; + + if (_this->suspend_screensaver && + screensaver_cookie != 0) + return SDL_TRUE; + if (!_this->suspend_screensaver && + screensaver_cookie == 0) + return SDL_TRUE; + + if (_this->suspend_screensaver) { + const char *app = "My SDL application"; + const char *reason = "Playing a game"; + + DBusMessage *msg = DBUS_dbus_message_new_method_call("org.freedesktop.ScreenSaver", + "/org/freedesktop/ScreenSaver", + "org.freedesktop.ScreenSaver", + "Inhibit"); + if (msg != NULL) { + DBUS_dbus_message_append_args (msg, + DBUS_TYPE_STRING, &app, + DBUS_TYPE_STRING, &reason, + DBUS_TYPE_INVALID); + } + + if (msg != NULL) { + DBusMessage *reply; + + reply = DBUS_dbus_connection_send_with_reply_and_block(conn, msg, 300, NULL); + if (reply) { + if (!DBUS_dbus_message_get_args(reply, NULL, + DBUS_TYPE_UINT32, &screensaver_cookie, + DBUS_TYPE_INVALID)) + screensaver_cookie = 0; + DBUS_dbus_message_unref(reply); + } + + DBUS_dbus_message_unref(msg); + } + + if (screensaver_cookie == 0) { + return SDL_FALSE; + } + return SDL_TRUE; + } else { + DBusMessage *msg = DBUS_dbus_message_new_method_call("org.freedesktop.ScreenSaver", + "/org/freedesktop/ScreenSaver", + "org.freedesktop.ScreenSaver", + "UnInhibit"); + DBUS_dbus_message_append_args (msg, + DBUS_TYPE_UINT32, &screensaver_cookie, + DBUS_TYPE_INVALID); + if (msg != NULL) { + if (DBUS_dbus_connection_send(conn, msg, NULL)) { + DBUS_dbus_connection_flush(conn); + } + DBUS_dbus_message_unref(msg); + } + + screensaver_cookie = 0; + return SDL_TRUE; + } +} #endif /* Initialization/Query functions */ diff --git a/libs/SDL2/src/video/x11/SDL_x11video.h b/libs/SDL2/src/video/x11/SDL_x11video.h index 68198bec..8ab88f72 100644 --- a/libs/SDL2/src/video/x11/SDL_x11video.h +++ b/libs/SDL2/src/video/x11/SDL_x11video.h @@ -121,6 +121,9 @@ typedef struct SDL_VideoData extern SDL_bool X11_UseDirectColorVisuals(void); +SDL_bool SDL_dbus_screensaver_inhibit(_THIS); +void SDL_dbus_screensaver_tickle(_THIS); + #endif /* _SDL_x11video_h */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/libs/SDL2/src/video/x11/SDL_x11xinput2.c b/libs/SDL2/src/video/x11/SDL_x11xinput2.c index 38c0dd32..7c149922 100644 --- a/libs/SDL2/src/video/x11/SDL_x11xinput2.c +++ b/libs/SDL2/src/video/x11/SDL_x11xinput2.c @@ -60,16 +60,18 @@ static void parse_valuators(const double *input_values,unsigned char *mask,int m } } -static SDL_bool -xinput2_version_okay(Display *display, const int major, const int minor) +static int +query_xinput2_version(Display *display, int major, int minor) { - int outmajor = major; - int outminor = minor; - if (X11_XIQueryVersion(display, &outmajor, &outminor) != Success) { - return SDL_FALSE; - } + /* We don't care if this fails, so long as it sets major/minor on it's way out the door. */ + X11_XIQueryVersion(display, &major, &minor); + return ((major * 1000) + minor); +} - return ( ((outmajor * 1000) + outminor) >= ((major * 1000) + minor) ); +static SDL_bool +xinput2_version_atleast(const int version, const int wantmajor, const int wantminor) +{ + return ( version >= ((wantmajor * 1000) + wantminor) ); } #endif /* SDL_VIDEO_DRIVER_X11_XINPUT2 */ @@ -79,9 +81,11 @@ X11_InitXinput2(_THIS) #if SDL_VIDEO_DRIVER_X11_XINPUT2 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; + int version = 0; XIEventMask eventmask; unsigned char mask[3] = { 0,0,0 }; int event, err; + /* * Initialize XInput 2 * According to http://who-t.blogspot.com/2009/05/xi2-recipes-part-1.html its better @@ -96,16 +100,16 @@ X11_InitXinput2(_THIS) return; /* X server does not have XInput at all */ } - if (!xinput2_version_okay(data->display, 2, 0)) { - return; /* X server does not support the version we want */ + /* We need at least 2.2 for Multitouch, 2.0 otherwise. */ + version = query_xinput2_version(data->display, 2, 2); + if (!xinput2_version_atleast(version, 2, 0)) { + return; /* X server does not support the version we want at all. */ } xinput2_initialized = 1; -#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH - if (xinput2_version_okay(data->display, 2, 2)) { /* Multitouch needs XInput 2.2 */ - xinput2_multitouch_supported = 1; - } +#if SDL_VIDEO_DRIVER_X11_XINPUT2_SUPPORTS_MULTITOUCH /* Multitouch needs XInput 2.2 */ + xinput2_multitouch_supported = xinput2_version_atleast(version, 2, 2); #endif /* Enable Raw motion events for this display */ diff --git a/libs/SDL2/test/testgles2.c b/libs/SDL2/test/testgles2.c index 6e99827b..ef9f38d6 100644 --- a/libs/SDL2/test/testgles2.c +++ b/libs/SDL2/test/testgles2.c @@ -629,7 +629,7 @@ main(int argc, char *argv[]) while (!done) { /* Check for events */ ++frames; - while (SDL_PollEvent(&event)) { + while (SDL_PollEvent(&event) && !done) { switch (event.type) { case SDL_WINDOWEVENT: switch (event.window.event) { @@ -654,16 +654,18 @@ main(int argc, char *argv[]) } SDLTest_CommonEvent(state, &event, &done); } - for (i = 0; i < state->num_windows; ++i) { - status = SDL_GL_MakeCurrent(state->windows[i], context[i]); - if (status) { - SDL_Log("SDL_GL_MakeCurrent(): %s\n", SDL_GetError()); + if (!done) { + for (i = 0; i < state->num_windows; ++i) { + status = SDL_GL_MakeCurrent(state->windows[i], context[i]); + if (status) { + SDL_Log("SDL_GL_MakeCurrent(): %s\n", SDL_GetError()); - /* Continue for next window */ - continue; - } - Render(state->window_w, state->window_h, &datas[i]); - SDL_GL_SwapWindow(state->windows[i]); + /* Continue for next window */ + continue; + } + Render(state->window_w, state->window_h, &datas[i]); + SDL_GL_SwapWindow(state->windows[i]); + } } }