diff options
author | DavidLudwig <dludwig@pobox.com> | 2012-11-04 09:46:59 -0500 |
---|---|---|
committer | DavidLudwig <dludwig@pobox.com> | 2012-11-04 09:46:59 -0500 |
commit | 3114de840703211dbf10dcc5bb8808d50a346c46 (patch) | |
tree | c55ef45fe8b54d969a589680739dd1b549a10cb2 | |
parent | 1f746f70019ac5a27648928fcff1ec14141a655d (diff) | |
parent | fd68d5fcceba81ff24b9888ae1ed6db3c7e42fea (diff) |
Merge with latest, official SDL code
66 files changed, 2624 insertions, 534 deletions
diff --git a/Makefile.in b/Makefile.in index d737a1c3e3..f452475657 100644 --- a/Makefile.in +++ b/Makefile.in @@ -60,6 +60,7 @@ HDRS = \ SDL_loadso.h \ SDL_log.h \ SDL_main.h \ + SDL_messagebox.h \ SDL_mouse.h \ SDL_mutex.h \ SDL_name.h \ diff --git a/README.Platforms b/README.Platforms index a766e0e30b..32fb0d0835 100644 --- a/README.Platforms +++ b/README.Platforms @@ -11,13 +11,12 @@ Windows 7 Mac OS X 10.4+ Linux 2.6+ iOS 3.1.3+ -Android 1.6+ +Android 2.1+ Unofficially supported platforms ================================ (code compiles, but not thoroughly tested) ================================ -Windows CE FreeBSD NetBSD OpenBSD diff --git a/README.android b/README.android index 2e02dc2d2e..30948f5dc9 100644 --- a/README.android +++ b/README.android @@ -39,18 +39,16 @@ src/main/android/SDL_android_main.cpp Instructions: 1. Copy the android-project directory wherever you want to keep your projects and rename it to the name of your project. -2. Move this SDL directory into the <project>/jni directory and then copy -SDL_config_android.h to SDL_config.h inside the include folder -3. Place your application source files in the <project>/jni/src directory -4. Edit <project>/jni/src/Android.mk to include your source files -5. Run 'ndk-build' (a script provided by the NDK). This compiles the C source +2. Move or symlink this SDL directory into the <project>/jni directory +3. Edit <project>/jni/src/Android.mk to include your source files +4. Run 'ndk-build' (a script provided by the NDK). This compiles the C source If you want to use the Eclipse IDE, skip to the Eclipse section below. -6. Edit <project>/local.properties to point to the Android SDK directory -7. Run 'ant debug' in android/project. This compiles the .java and eventually +5. Edit <project>/local.properties to point to the Android SDK directory +6. Run 'ant debug' in android/project. This compiles the .java and eventually creates a .apk with the native code embedded -8. 'ant install' will push the apk to the device or emulator (if connected) +7. 'ant install' will push the apk to the device or emulator (if connected) Here's an explanation of the files in the Android project, so you can customize them: @@ -74,6 +72,58 @@ android-project/ ================================================================================ + Customizing your application name +================================================================================ + +To customize your application name, edit AndroidManifest.xml and replace +"org.libsdl.app" with an identifier for your product package. + +Then create a Java class extending SDLActivity and place it in a directory +under src matching your package, e.g. + src/com/gamemaker/game/MyGame.java + +Here's an example of a minimal class file: +--- MyGame.java -------------------------- +package com.gamemaker.game; + +import org.libsdl.app.SDLActivity; +import android.os.*; + +/* + * A sample wrapper class that just calls SDLActivity + */ + +public class MyGame extends SDLActivity { + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + } + + protected void onDestroy() { + super.onDestroy(); + } +} +------------------------------------------ + +Then replace "SDLActivity" in AndroidManifest.xml with the name of your +class, .e.g. "MyGame" + +================================================================================ + Customizing your application icon +================================================================================ + +Conceptually changing your icon is just replacing the icon.png files in the +drawable directories under the res directory. + +The easiest way to create a set of icons for your project is to remove all +the existing icon.png files, and then use the Eclipse IDE to create a dummy +project. During the process of doing this Eclipse will prompt you to create +an icon. Then just copy the drawable directories it creates over to your +res directory. + +You may need to change the name of your icon in AndroidManifest.xml to match +the filename used by Eclipse. + +================================================================================ Pause / Resume behaviour ================================================================================ @@ -106,6 +156,16 @@ your thread automatically anyway (when you make an SDL call), but it'll never detach it. ================================================================================ + Using STL +================================================================================ + +You can use STL in your project by creating an Application.mk file in the jni +folder and adding the following line: +APP_STL := stlport_static + +For more information check out CPLUSPLUS-SUPPORT.html in the NDK documentation. + +================================================================================ Additional documentation ================================================================================ diff --git a/VisualC/SDL/SDL_VS2008.vcproj b/VisualC/SDL/SDL_VS2008.vcproj index 2ff9f0c8ad..3c06ac90b8 100644 --- a/VisualC/SDL/SDL_VS2008.vcproj +++ b/VisualC/SDL/SDL_VS2008.vcproj @@ -1217,6 +1217,14 @@ >
</File>
<File
+ RelativePath="..\..\src\video\windows\SDL_windowsmessagebox.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\src\video\windows\SDL_windowsmessagebox.h"
+ >
+ </File>
+ <File
RelativePath="..\..\src\video\windows\SDL_windowsmodes.c"
>
</File>
diff --git a/VisualC/SDL/SDL_VS2010.vcxproj b/VisualC/SDL/SDL_VS2010.vcxproj index 2bd02d825c..b3b7c88342 100644 --- a/VisualC/SDL/SDL_VS2010.vcxproj +++ b/VisualC/SDL/SDL_VS2010.vcxproj @@ -317,6 +317,7 @@ <ClInclude Include="..\..\src\video\windows\SDL_windowsevents.h" />
<ClInclude Include="..\..\src\video\windows\SDL_windowsframebuffer.h" />
<ClInclude Include="..\..\src\video\windows\SDL_windowskeyboard.h" />
+ <ClInclude Include="..\..\src\video\windows\SDL_windowsmessagebox.h" />
<ClInclude Include="..\..\src\video\windows\SDL_windowsmodes.h" />
<ClInclude Include="..\..\src\video\windows\SDL_windowsmouse.h" />
<ClInclude Include="..\..\src\video\windows\SDL_windowsopengl.h" />
@@ -432,6 +433,7 @@ <ClCompile Include="..\..\src\video\windows\SDL_windowsevents.c" />
<ClCompile Include="..\..\src\video\windows\SDL_windowsframebuffer.c" />
<ClCompile Include="..\..\src\video\windows\SDL_windowskeyboard.c" />
+ <ClCompile Include="..\..\src\video\windows\SDL_windowsmessagebox.c" />
<ClCompile Include="..\..\src\video\windows\SDL_windowsmodes.c" />
<ClCompile Include="..\..\src\video\windows\SDL_windowsmouse.c" />
<ClCompile Include="..\..\src\video\windows\SDL_windowsopengl.c" />
diff --git a/Xcode-iOS/SDL/SDL.xcodeproj/project.pbxproj b/Xcode-iOS/SDL/SDL.xcodeproj/project.pbxproj index bf99f20cf0..d074b1465e 100755 --- a/Xcode-iOS/SDL/SDL.xcodeproj/project.pbxproj +++ b/Xcode-iOS/SDL/SDL.xcodeproj/project.pbxproj @@ -156,6 +156,9 @@ AA7558C91595D55500BBD41B /* SDL_video.h in Headers */ = {isa = PBXBuildFile; fileRef = AA7558961595D55500BBD41B /* SDL_video.h */; }; AA7558CA1595D55500BBD41B /* SDL.h in Headers */ = {isa = PBXBuildFile; fileRef = AA7558971595D55500BBD41B /* SDL.h */; }; AA9781C91576A7FA00472542 /* libSDL2.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FD6526630DE8FCCB002AD96B /* libSDL2.a */; }; + AA9FF9511637C6E5000DF050 /* SDL_messagebox.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9FF9501637C6E5000DF050 /* SDL_messagebox.h */; }; + AABCC3941640643D00AB8930 /* SDL_uikitmessagebox.h in Headers */ = {isa = PBXBuildFile; fileRef = AABCC3921640643D00AB8930 /* SDL_uikitmessagebox.h */; }; + AABCC3951640643D00AB8930 /* SDL_uikitmessagebox.m in Sources */ = {isa = PBXBuildFile; fileRef = AABCC3931640643D00AB8930 /* SDL_uikitmessagebox.m */; }; FD3F4A760DEA620800C5B771 /* SDL_getenv.c in Sources */ = {isa = PBXBuildFile; fileRef = FD3F4A700DEA620800C5B771 /* SDL_getenv.c */; }; FD3F4A770DEA620800C5B771 /* SDL_iconv.c in Sources */ = {isa = PBXBuildFile; fileRef = FD3F4A710DEA620800C5B771 /* SDL_iconv.c */; }; FD3F4A780DEA620800C5B771 /* SDL_malloc.c in Sources */ = {isa = PBXBuildFile; fileRef = FD3F4A720DEA620800C5B771 /* SDL_malloc.c */; }; @@ -410,6 +413,9 @@ AA7558951595D55500BBD41B /* SDL_version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_version.h; sourceTree = "<group>"; }; AA7558961595D55500BBD41B /* SDL_video.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_video.h; sourceTree = "<group>"; }; AA7558971595D55500BBD41B /* SDL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL.h; sourceTree = "<group>"; }; + AA9FF9501637C6E5000DF050 /* SDL_messagebox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_messagebox.h; sourceTree = "<group>"; }; + AABCC3921640643D00AB8930 /* SDL_uikitmessagebox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_uikitmessagebox.h; sourceTree = "<group>"; }; + AABCC3931640643D00AB8930 /* SDL_uikitmessagebox.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_uikitmessagebox.m; sourceTree = "<group>"; }; FD0BBFEF0E3933DD00D833B1 /* SDL_uikitview.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_uikitview.h; sourceTree = "<group>"; }; FD3F4A700DEA620800C5B771 /* SDL_getenv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_getenv.c; sourceTree = "<group>"; }; FD3F4A710DEA620800C5B771 /* SDL_iconv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_iconv.c; sourceTree = "<group>"; }; @@ -853,6 +859,8 @@ FD689FCC0E26E9D400F90B21 /* SDL_uikitappdelegate.m */, FD689F0C0E26E5D900F90B21 /* SDL_uikitevents.h */, FD689F0D0E26E5D900F90B21 /* SDL_uikitevents.m */, + AABCC3921640643D00AB8930 /* SDL_uikitmessagebox.h */, + AABCC3931640643D00AB8930 /* SDL_uikitmessagebox.m */, AA126AD21617C5E6005ABC8F /* SDL_uikitmodes.h */, AA126AD31617C5E6005ABC8F /* SDL_uikitmodes.m */, FD689F0E0E26E5D900F90B21 /* SDL_uikitopengles.h */, @@ -894,13 +902,14 @@ children = ( AA7558651595D55500BBD41B /* begin_code.h */, AA7558661595D55500BBD41B /* close_code.h */, + AA7558971595D55500BBD41B /* SDL.h */, AA7558671595D55500BBD41B /* SDL_assert.h */, AA7558681595D55500BBD41B /* SDL_atomic.h */, AA7558691595D55500BBD41B /* SDL_audio.h */, AA75586A1595D55500BBD41B /* SDL_blendmode.h */, AA75586B1595D55500BBD41B /* SDL_clipboard.h */, - AA75586C1595D55500BBD41B /* SDL_config_iphoneos.h */, AA75586D1595D55500BBD41B /* SDL_config.h */, + AA75586C1595D55500BBD41B /* SDL_config_iphoneos.h */, AA75586E1595D55500BBD41B /* SDL_copying.h */, AA75586F1595D55500BBD41B /* SDL_cpuinfo.h */, AA7558701595D55500BBD41B /* SDL_endian.h */, @@ -916,6 +925,7 @@ AA75587A1595D55500BBD41B /* SDL_loadso.h */, AA75587B1595D55500BBD41B /* SDL_log.h */, AA75587C1595D55500BBD41B /* SDL_main.h */, + AA9FF9501637C6E5000DF050 /* SDL_messagebox.h */, AA75587D1595D55500BBD41B /* SDL_mouse.h */, AA75587E1595D55500BBD41B /* SDL_mutex.h */, AA75587F1595D55500BBD41B /* SDL_name.h */, @@ -942,7 +952,6 @@ AA7558941595D55500BBD41B /* SDL_types.h */, AA7558951595D55500BBD41B /* SDL_version.h */, AA7558961595D55500BBD41B /* SDL_video.h */, - AA7558971595D55500BBD41B /* SDL.h */, ); name = "Public Headers"; path = ../../include; @@ -1249,6 +1258,8 @@ AA7558CA1595D55500BBD41B /* SDL.h in Headers */, AA126AD41617C5E7005ABC8F /* SDL_uikitmodes.h in Headers */, AA704DD6162AA90A0076D1C1 /* SDL_dropevents_c.h in Headers */, + AA9FF9511637C6E5000DF050 /* SDL_messagebox.h in Headers */, + AABCC3941640643D00AB8930 /* SDL_uikitmessagebox.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1467,6 +1478,7 @@ AA628ADB159369E3005138DD /* SDL_rotate.c in Sources */, AA126AD51617C5E7005ABC8F /* SDL_uikitmodes.m in Sources */, AA704DD7162AA90A0076D1C1 /* SDL_dropevents.c in Sources */, + AABCC3951640643D00AB8930 /* SDL_uikitmessagebox.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Xcode/SDL/Info-Framework.plist b/Xcode/SDL/Info-Framework.plist index cb9748aed0..544baa6359 100644 --- a/Xcode/SDL/Info-Framework.plist +++ b/Xcode/SDL/Info-Framework.plist @@ -4,14 +4,12 @@ <dict> <key>CFBundleDevelopmentRegion</key> <string>English</string> - <key>CFBundleExecutable</key> - <string>SDL</string> <key>CFBundleGetInfoString</key> <string>http://www.libsdl.org</string> <key>CFBundleIconFile</key> <string></string> <key>CFBundleIdentifier</key> - <string>SDL</string> + <string>org.libsdl.SDL2</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundleName</key> @@ -19,10 +17,10 @@ <key>CFBundlePackageType</key> <string>FMWK</string> <key>CFBundleShortVersionString</key> - <string>1.3.0</string> + <string>2.0.0</string> <key>CFBundleSignature</key> <string>SDLX</string> <key>CFBundleVersion</key> - <string>1.3.0</string> + <string>2.0.0</string> </dict> </plist> diff --git a/Xcode/SDL/SDL.xcodeproj/project.pbxproj b/Xcode/SDL/SDL.xcodeproj/project.pbxproj index 1a28c3930c..604c77d481 100755 --- a/Xcode/SDL/SDL.xcodeproj/project.pbxproj +++ b/Xcode/SDL/SDL.xcodeproj/project.pbxproj @@ -539,6 +539,13 @@ AA75585D1595D4D800BBD41B /* SDL_video.h in Headers */ = {isa = PBXBuildFile; fileRef = AA7557F81595D4D800BBD41B /* SDL_video.h */; }; AA75585E1595D4D800BBD41B /* SDL.h in Headers */ = {isa = PBXBuildFile; fileRef = AA7557F91595D4D800BBD41B /* SDL.h */; settings = {ATTRIBUTES = (Public, ); }; }; AA75585F1595D4D800BBD41B /* SDL.h in Headers */ = {isa = PBXBuildFile; fileRef = AA7557F91595D4D800BBD41B /* SDL.h */; }; + AA9E4093163BE51E007A2AD0 /* SDL_x11messagebox.c in Sources */ = {isa = PBXBuildFile; fileRef = AA9E4092163BE51E007A2AD0 /* SDL_x11messagebox.c */; }; + AA9E4094163BE51E007A2AD0 /* SDL_x11messagebox.c in Sources */ = {isa = PBXBuildFile; fileRef = AA9E4092163BE51E007A2AD0 /* SDL_x11messagebox.c */; }; + AA9FF95A1637CBF9000DF050 /* SDL_messagebox.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9FF9591637CBF9000DF050 /* SDL_messagebox.h */; settings = {ATTRIBUTES = (Public, ); }; }; + AABCC38D164063D200AB8930 /* SDL_cocoamessagebox.h in Headers */ = {isa = PBXBuildFile; fileRef = AABCC38B164063D200AB8930 /* SDL_cocoamessagebox.h */; }; + AABCC38E164063D200AB8930 /* SDL_cocoamessagebox.h in Headers */ = {isa = PBXBuildFile; fileRef = AABCC38B164063D200AB8930 /* SDL_cocoamessagebox.h */; }; + AABCC38F164063D200AB8930 /* SDL_cocoamessagebox.m in Sources */ = {isa = PBXBuildFile; fileRef = AABCC38C164063D200AB8930 /* SDL_cocoamessagebox.m */; }; + AABCC390164063D200AB8930 /* SDL_cocoamessagebox.m in Sources */ = {isa = PBXBuildFile; fileRef = AABCC38C164063D200AB8930 /* SDL_cocoamessagebox.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -880,6 +887,10 @@ AA7557F71595D4D800BBD41B /* SDL_version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_version.h; sourceTree = "<group>"; }; AA7557F81595D4D800BBD41B /* SDL_video.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_video.h; sourceTree = "<group>"; }; AA7557F91595D4D800BBD41B /* SDL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL.h; sourceTree = "<group>"; }; + AA9E4092163BE51E007A2AD0 /* SDL_x11messagebox.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = SDL_x11messagebox.c; sourceTree = "<group>"; }; + AA9FF9591637CBF9000DF050 /* SDL_messagebox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_messagebox.h; sourceTree = "<group>"; }; + AABCC38B164063D200AB8930 /* SDL_cocoamessagebox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDL_cocoamessagebox.h; sourceTree = "<group>"; }; + AABCC38C164063D200AB8930 /* SDL_cocoamessagebox.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDL_cocoamessagebox.m; sourceTree = "<group>"; }; BECDF66B0761BA81005FE872 /* Info-Framework.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Info-Framework.plist"; sourceTree = "<group>"; }; BECDF66C0761BA81005FE872 /* SDL2.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SDL2.framework; sourceTree = BUILT_PRODUCTS_DIR; }; BECDF6B30761BA81005FE872 /* libSDL2.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libSDL2.a; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -1053,13 +1064,14 @@ children = ( AA7557C71595D4D800BBD41B /* begin_code.h */, AA7557C81595D4D800BBD41B /* close_code.h */, + AA7557F91595D4D800BBD41B /* SDL.h */, AA7557C91595D4D800BBD41B /* SDL_assert.h */, AA7557CA1595D4D800BBD41B /* SDL_atomic.h */, AA7557CB1595D4D800BBD41B /* SDL_audio.h */, AA7557CC1595D4D800BBD41B /* SDL_blendmode.h */, AA7557CD1595D4D800BBD41B /* SDL_clipboard.h */, - AA7557CE1595D4D800BBD41B /* SDL_config_macosx.h */, AA7557CF1595D4D800BBD41B /* SDL_config.h */, + AA7557CE1595D4D800BBD41B /* SDL_config_macosx.h */, AA7557D01595D4D800BBD41B /* SDL_copying.h */, AA7557D11595D4D800BBD41B /* SDL_cpuinfo.h */, AA7557D21595D4D800BBD41B /* SDL_endian.h */, @@ -1075,6 +1087,7 @@ AA7557DC1595D4D800BBD41B /* SDL_loadso.h */, AA7557DD1595D4D800BBD41B /* SDL_log.h */, AA7557DE1595D4D800BBD41B /* SDL_main.h */, + AA9FF9591637CBF9000DF050 /* SDL_messagebox.h */, AA7557DF1595D4D800BBD41B /* SDL_mouse.h */, AA7557E01595D4D800BBD41B /* SDL_mutex.h */, AA7557E11595D4D800BBD41B /* SDL_name.h */, @@ -1101,7 +1114,6 @@ AA7557F61595D4D800BBD41B /* SDL_types.h */, AA7557F71595D4D800BBD41B /* SDL_version.h */, AA7557F81595D4D800BBD41B /* SDL_video.h */, - AA7557F91595D4D800BBD41B /* SDL.h */, ); name = "Public Headers"; path = ../../include; @@ -1467,6 +1479,8 @@ 04BDFEC512E6671800899322 /* SDL_cocoaevents.m */, 04BDFEC612E6671800899322 /* SDL_cocoakeyboard.h */, 04BDFEC712E6671800899322 /* SDL_cocoakeyboard.m */, + AABCC38B164063D200AB8930 /* SDL_cocoamessagebox.h */, + AABCC38C164063D200AB8930 /* SDL_cocoamessagebox.m */, 04BDFEC812E6671800899322 /* SDL_cocoamodes.h */, 04BDFEC912E6671800899322 /* SDL_cocoamodes.m */, 04BDFECA12E6671800899322 /* SDL_cocoamouse.h */, @@ -1511,6 +1525,7 @@ 0442EC5912FE1C60004C9285 /* SDL_x11framebuffer.h */, 04BDFFC212E6671800899322 /* SDL_x11keyboard.c */, 04BDFFC312E6671800899322 /* SDL_x11keyboard.h */, + AA9E4092163BE51E007A2AD0 /* SDL_x11messagebox.c */, 04BDFFC412E6671800899322 /* SDL_x11modes.c */, 04BDFFC512E6671800899322 /* SDL_x11modes.h */, 04BDFFC612E6671800899322 /* SDL_x11mouse.c */, @@ -1670,6 +1685,7 @@ AA7558241595D4D800BBD41B /* SDL_loadso.h in Headers */, AA7558261595D4D800BBD41B /* SDL_log.h in Headers */, AA7558281595D4D800BBD41B /* SDL_main.h in Headers */, + AA9FF95A1637CBF9000DF050 /* SDL_messagebox.h in Headers */, AA75582A1595D4D800BBD41B /* SDL_mouse.h in Headers */, AA75582C1595D4D800BBD41B /* SDL_mutex.h in Headers */, AA75582E1595D4D800BBD41B /* SDL_name.h in Headers */, @@ -1782,6 +1798,7 @@ 566CDE8F148F0AC200C5A9BB /* SDL_dropevents_c.h in Headers */, AA628ACC159367B7005138DD /* SDL_rotate.h in Headers */, AA628AD3159367F2005138DD /* SDL_x11xinput2.h in Headers */, + AABCC38D164063D200AB8930 /* SDL_cocoamessagebox.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1924,6 +1941,7 @@ AA75585B1595D4D800BBD41B /* SDL_version.h in Headers */, AA75585D1595D4D800BBD41B /* SDL_video.h in Headers */, AA75585F1595D4D800BBD41B /* SDL.h in Headers */, + AABCC38E164063D200AB8930 /* SDL_cocoamessagebox.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2253,6 +2271,8 @@ 566CDE90148F0AC200C5A9BB /* SDL_dropevents.c in Sources */, AA628ACA159367B7005138DD /* SDL_rotate.c in Sources */, AA628AD1159367F2005138DD /* SDL_x11xinput2.c in Sources */, + AA9E4093163BE51E007A2AD0 /* SDL_x11messagebox.c in Sources */, + AABCC38F164063D200AB8930 /* SDL_cocoamessagebox.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2366,6 +2386,8 @@ 043567401303160F00BA5428 /* SDL_shaders_gl.c in Sources */, AA628ACB159367B7005138DD /* SDL_rotate.c in Sources */, AA628AD2159367F2005138DD /* SDL_x11xinput2.c in Sources */, + AA9E4094163BE51E007A2AD0 /* SDL_x11messagebox.c in Sources */, + AABCC390164063D200AB8930 /* SDL_cocoamessagebox.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2433,7 +2455,7 @@ FRAMEWORK_VERSION = A; HEADER_SEARCH_PATHS = /usr/X11R6/include; INFOPLIST_FILE = "Info-Framework.plist"; - INSTALL_PATH = "@rpath"; + INSTALL_PATH = "@executable_path/../Frameworks"; OTHER_LDFLAGS = "-liconv"; PRODUCT_NAME = SDL2; WRAPPER_EXTENSION = framework; @@ -2453,6 +2475,7 @@ GCC_SYMBOLS_PRIVATE_EXTERN = YES; HEADER_SEARCH_PATHS = /usr/X11R6/include; PRODUCT_NAME = SDL2; + SKIP_INSTALL = YES; }; name = Release; }; @@ -2493,7 +2516,7 @@ FRAMEWORK_VERSION = A; HEADER_SEARCH_PATHS = /usr/X11R6/include; INFOPLIST_FILE = "Info-Framework.plist"; - INSTALL_PATH = "@rpath"; + INSTALL_PATH = "@executable_path/../Frameworks"; OTHER_LDFLAGS = "-liconv"; PRODUCT_NAME = SDL2; WRAPPER_EXTENSION = framework; @@ -2513,6 +2536,7 @@ GCC_SYMBOLS_PRIVATE_EXTERN = YES; HEADER_SEARCH_PATHS = /usr/X11R6/include; PRODUCT_NAME = SDL2; + SKIP_INSTALL = YES; }; name = Debug; }; diff --git a/acinclude/libtool.m4 b/acinclude/libtool.m4 index 679e4d6d65..c444a5ed05 100644 --- a/acinclude/libtool.m4 +++ b/acinclude/libtool.m4 @@ -2364,13 +2364,15 @@ cygwin* | mingw* | pw32* | cegcc*) case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + #soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + soname_spec='`echo ${libname} | sed -e 's/^lib//'`${shared_ext}' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix - soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + #soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + soname_spec='`echo ${libname} | $SED -e 's/^lib//'`${shared_ext}' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' diff --git a/aclocal.m4 b/aclocal.m4 index b28ddf31cc..71c3d2be00 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -3061,13 +3061,15 @@ cygwin* | mingw* | pw32* | cegcc*) case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + #soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + soname_spec='`echo ${libname} | sed -e 's/^lib//'`${shared_ext}' m4_if([$1], [],[ sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix - soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + #soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + soname_spec='`echo ${libname} | $SED -e 's/^lib//'`${shared_ext}' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' diff --git a/android-project/AndroidManifest.xml b/android-project/AndroidManifest.xml index 8fbb3e6af3..e86194ddf5 100644 --- a/android-project/AndroidManifest.xml +++ b/android-project/AndroidManifest.xml @@ -1,12 +1,25 @@ <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" + <!-- Replace org.libsdl.app with the identifier of your game, e.g. + com.gamemaker.game + --> package="org.libsdl.app" android:versionCode="1" - android:versionName="1.0"> + android:versionName="1.0" + android:installLocation="auto"> - <uses-sdk android:minSdkVersion="5" /> + <!-- Create a Java class extending SDLActivity and place it in a + directory under src matching the package, e.g. + src/com/gamemaker/game/MyGame.java - <application android:label="@string/app_name" android:icon="@drawable/icon"> + then replace "SDLActivity" with the name of your class (e.g. "MyGame") + in the XML below. + + An example Java class can be found in README.android + --> + <application android:label="@string/app_name" + android:icon="@drawable/icon" + android:theme="@android:style/Theme.NoTitleBar.Fullscreen"> <activity android:name="SDLActivity" android:label="@string/app_name"> <intent-filter> @@ -15,4 +28,13 @@ </intent-filter> </activity> </application> + + <!-- Android 2.1 --> + <uses-sdk android:minSdkVersion="10" /> + + <!-- OpenGL ES 2.0 --> + <uses-feature android:glEsVersion="0x00020000" /> + + <!-- Allow writing to external storage --> + <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> </manifest> diff --git a/android-project/ant.properties b/android-project/ant.properties new file mode 100644 index 0000000000..b0971e891e --- /dev/null +++ b/android-project/ant.properties @@ -0,0 +1,17 @@ +# This file is used to override default values used by the Ant build system. +# +# This file must be checked into Version Control Systems, as it is +# integral to the build system of your project. + +# This file is only used by the Ant script. + +# You can use this to override default values such as +# 'source.dir' for the location of your java source folder and +# 'out.dir' for the location of your output folder. + +# You can also use it define how the release builds are signed by declaring +# the following properties: +# 'key.store' for the location of your keystore and +# 'key.alias' for the name of the key to use. +# The password will be asked during the build when you use the 'release' target. + diff --git a/android-project/build.xml b/android-project/build.xml index 37b3768076..9f19a077b1 100644 --- a/android-project/build.xml +++ b/android-project/build.xml @@ -1,67 +1,93 @@ <?xml version="1.0" encoding="UTF-8"?> -<project name="SDLApp" default="help"> +<!-- This should be changed to the name of your project --> +<project name="SDLActivity" default="help"> <!-- The local.properties file is created and updated by the 'android' tool. - It contains the path to the SDK. It should *NOT* be checked in in Version - Control Systems. --> + It contains the path to the SDK. It should *NOT* be checked into + Version Control Systems. --> <property file="local.properties" /> - <!-- The build.properties file can be created by you and is never touched - by the 'android' tool. This is the place to change some of the default property values - used by the Ant rules. + <!-- The ant.properties file can be created by you. It is only edited by the + 'android' tool to add properties to it. + This is the place to change some Ant specific build properties. Here are some properties you may want to change/update: - application.package - the name of your application package as defined in the manifest. Used by the - 'uninstall' rule. source.dir - the name of the source directory. Default is 'src'. + The name of the source directory. Default is 'src'. out.dir - the name of the output directory. Default is 'bin'. + The name of the output directory. Default is 'bin'. - Properties related to the SDK location or the project target should be updated - using the 'android' tool with the 'update' action. + For other overridable properties, look at the beginning of the rules + files in the SDK, at tools/ant/build.xml - This file is an integral part of the build system for your application and - should be checked in in Version Control Systems. + Properties related to the SDK location or the project target should + be updated using the 'android' tool with the 'update' action. + + This file is an integral part of the build system for your + application and should be checked into Version Control Systems. --> - <property file="build.properties" /> - - <!-- The default.properties file is created and updated by the 'android' tool, as well - as ADT. - This file is an integral part of the build system for your application and - should be checked in in Version Control Systems. --> - <property file="default.properties" /> - - <!-- Custom Android task to deal with the project target, and import the proper rules. - This requires ant 1.6.0 or above. --> - <path id="android.antlibs"> - <pathelement path="${sdk.dir}/tools/lib/anttasks.jar" /> - <pathelement path="${sdk.dir}/tools/lib/sdklib.jar" /> - <pathelement path="${sdk.dir}/tools/lib/androidprefs.jar" /> - <pathelement path="${sdk.dir}/tools/lib/apkbuilder.jar" /> - <pathelement path="${sdk.dir}/tools/lib/jarutils.jar" /> - </path> - - <taskdef name="setup" - classname="com.android.ant.SetupTask" - classpathref="android.antlibs" /> - - <!-- Execute the Android Setup task that will setup some properties specific to the target, - and import the build rules files. - - The rules file is imported from - <SDK>/platforms/<target_platform>/templates/android_rules.xml - - To customize some build steps for your project: - - copy the content of the main node <project> from android_rules.xml - - paste it in this build.xml below the <setup /> task. - - disable the import by changing the setup task below to <setup import="false" /> - - This will ensure that the properties are setup correctly but that your customized - build steps are used. + <property file="ant.properties" /> + + <!-- if sdk.dir was not set from one of the property file, then + get it from the ANDROID_HOME env var. + This must be done before we load project.properties since + the proguard config can use sdk.dir --> + <property environment="env" /> + <condition property="sdk.dir" value="${env.ANDROID_HOME}"> + <isset property="env.ANDROID_HOME" /> + </condition> + + <!-- The project.properties file is created and updated by the 'android' + tool, as well as ADT. + + This contains project specific properties such as project target, and library + dependencies. Lower level build properties are stored in ant.properties + (or in .classpath for Eclipse projects). + + This file is an integral part of the build system for your + application and should be checked into Version Control Systems. --> + <loadproperties srcFile="project.properties" /> + + <!-- quick check on sdk.dir --> + <fail + message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable." + unless="sdk.dir" + /> + + <!-- + Import per project custom build rules if present at the root of the project. + This is the place to put custom intermediary targets such as: + -pre-build + -pre-compile + -post-compile (This is typically used for code obfuscation. + Compiled code location: ${out.classes.absolute.dir} + If this is not done in place, override ${out.dex.input.absolute.dir}) + -post-package + -post-build + -pre-clean + --> + <import file="custom_rules.xml" optional="true" /> + + <!-- Import the actual build file. + + To customize existing targets, there are two options: + - Customize only one target: + - copy/paste the target into this file, *before* the + <import> task. + - customize it to your needs. + - Customize the whole content of build.xml + - copy/paste the content of the rules files (minus the top node) + into this file, replacing the <import> task. + - customize to your needs. + + *********************** + ****** IMPORTANT ****** + *********************** + In all cases you must update the value of version-tag below to read 'custom' instead of an integer, + in order to avoid having your file be overridden by tools such as "android update project" --> - <setup /> + <!-- version-tag: 1 --> + <import file="${sdk.dir}/tools/ant/build.xml" /> </project> diff --git a/android-project/default.properties b/android-project/default.properties index dbf05f24f2..9d135cb85f 100644 --- a/android-project/default.properties +++ b/android-project/default.properties @@ -8,4 +8,4 @@ # project structure. # Project target. -target=android-5 +target=android-7 diff --git a/android-project/jni/Application.mk b/android-project/jni/Application.mk new file mode 100644 index 0000000000..05cf0c31cb --- /dev/null +++ b/android-project/jni/Application.mk @@ -0,0 +1,4 @@ + +# Uncomment this if you're using STL in your project +# See CPLUSPLUS-SUPPORT.html in the NDK documentation for more information +# APP_STL := stlport_static diff --git a/android-project/local.properties b/android-project/local.properties index 2818bb8328..be9e6313df 100644 --- a/android-project/local.properties +++ b/android-project/local.properties @@ -7,4 +7,4 @@ # location of the SDK. This is only used by Ant # For customization when using a Version Control System, please read the # header note. -sdk.dir=/Users/hercules/eclipse/android-sdk-mac_86 +sdk.dir=/Users/slouken/android-sdk-macosx diff --git a/android-project/proguard-project.txt b/android-project/proguard-project.txt new file mode 100644 index 0000000000..f2fe1559a2 --- /dev/null +++ b/android-project/proguard-project.txt @@ -0,0 +1,20 @@ +# To enable ProGuard in your project, edit project.properties +# to define the proguard.config property as described in that file. +# +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in ${sdk.dir}/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the ProGuard +# include property in project.properties. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/android-project/project.properties b/android-project/project.properties new file mode 100644 index 0000000000..b7c2081d56 --- /dev/null +++ b/android-project/project.properties @@ -0,0 +1,14 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt + +# Project target. +target=android-10 diff --git a/android-project/src/org/libsdl/app/SDLActivity.java b/android-project/src/org/libsdl/app/SDLActivity.java index 1b60de2dd3..d5fda76abe 100644 --- a/android-project/src/org/libsdl/app/SDLActivity.java +++ b/android-project/src/org/libsdl/app/SDLActivity.java @@ -734,7 +734,7 @@ class DummyEdit extends View implements View.OnKeyListener { ic = new SDLInputConnection(this, true); outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI - | EditorInfo.IME_FLAG_NO_FULLSCREEN; + | 33554432 /* API 11: EditorInfo.IME_FLAG_NO_FULLSCREEN */; return ic; } @@ -10244,13 +10244,15 @@ cygwin* | mingw* | pw32* | cegcc*) case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + #soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + soname_spec='`echo ${libname} | sed -e 's/^lib//'`${shared_ext}' sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix - soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + #soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + soname_spec='`echo ${libname} | $SED -e 's/^lib//'`${shared_ext}' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' @@ -14919,12 +14921,14 @@ cygwin* | mingw* | pw32* | cegcc*) case $host_os in cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' - soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + #soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + soname_spec='`echo ${libname} | sed -e 's/^lib//'`${shared_ext}' ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix - soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + #soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + soname_spec='`echo ${libname} | $SED -e 's/^lib//'`${shared_ext}' ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' @@ -16684,7 +16688,7 @@ fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext fi - for ac_func in malloc calloc realloc free getenv setenv putenv unsetenv qsort abs bcopy memset memcpy memmove strlen strlcpy strlcat strdup _strrev _strupr _strlwr strchr strrchr strstr itoa _ltoa _uitoa _ultoa strtol strtoul _i64toa _ui64toa strtoll strtoull atoi atof strcmp strncmp _stricmp strcasecmp _strnicmp strncasecmp sscanf snprintf vsnprintf sigaction setjmp nanosleep sysconf sysctlbyname + for ac_func in malloc calloc realloc free getenv setenv putenv unsetenv qsort abs bcopy memset memcpy memmove strlen strlcpy strlcat strdup _strrev _strupr _strlwr strchr strrchr strstr itoa _ltoa _uitoa _ultoa strtol strtoul _i64toa _ui64toa strtoll strtoull atoi atof strcmp strncmp _stricmp strcasecmp _strnicmp strncasecmp sscanf snprintf vsnprintf fseeko fseeko64 sigaction setjmp nanosleep sysconf sysctlbyname do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" @@ -16930,6 +16934,7 @@ SOURCES="$SOURCES $srcdir/src/audio/*.c" SOURCES="$SOURCES $srcdir/src/cpuinfo/*.c" SOURCES="$SOURCES $srcdir/src/events/*.c" SOURCES="$SOURCES $srcdir/src/file/*.c" +SOURCES="$SOURCES $srcdir/src/libm/*.c" SOURCES="$SOURCES $srcdir/src/render/*.c" SOURCES="$SOURCES $srcdir/src/render/*/*.c" SOURCES="$SOURCES $srcdir/src/stdlib/*.c" diff --git a/configure.in b/configure.in index 19ecb79142..3b520d6448 100644 --- a/configure.in +++ b/configure.in @@ -237,7 +237,7 @@ if test x$enable_libc = xyes; then AC_DEFINE(HAVE_MPROTECT, 1, [ ]) ]), ) - AC_CHECK_FUNCS(malloc calloc realloc free getenv setenv putenv unsetenv qsort abs bcopy memset memcpy memmove strlen strlcpy strlcat strdup _strrev _strupr _strlwr strchr strrchr strstr itoa _ltoa _uitoa _ultoa strtol strtoul _i64toa _ui64toa strtoll strtoull atoi atof strcmp strncmp _stricmp strcasecmp _strnicmp strncasecmp sscanf snprintf vsnprintf sigaction setjmp nanosleep sysconf sysctlbyname) + AC_CHECK_FUNCS(malloc calloc realloc free getenv setenv putenv unsetenv qsort abs bcopy memset memcpy memmove strlen strlcpy strlcat strdup _strrev _strupr _strlwr strchr strrchr strstr itoa _ltoa _uitoa _ultoa strtol strtoul _i64toa _ui64toa strtoll strtoull atoi atof strcmp strncmp _stricmp strcasecmp _strnicmp strncasecmp sscanf snprintf vsnprintf fseeko fseeko64 sigaction setjmp nanosleep sysconf sysctlbyname) AC_CHECK_LIB(m, pow, [LIBS="$LIBS -lm"; EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lm"]) AC_CHECK_FUNCS(atan atan2 ceil copysign cos cosf fabs floor log pow scalbn sin sinf sqrt) @@ -297,6 +297,7 @@ SOURCES="$SOURCES $srcdir/src/audio/*.c" SOURCES="$SOURCES $srcdir/src/cpuinfo/*.c" SOURCES="$SOURCES $srcdir/src/events/*.c" SOURCES="$SOURCES $srcdir/src/file/*.c" +SOURCES="$SOURCES $srcdir/src/libm/*.c" SOURCES="$SOURCES $srcdir/src/render/*.c" SOURCES="$SOURCES $srcdir/src/render/*/*.c" SOURCES="$SOURCES $srcdir/src/stdlib/*.c" diff --git a/include/SDL.h b/include/SDL.h index aabbabaa3d..186ab8a18e 100644 --- a/include/SDL.h +++ b/include/SDL.h @@ -82,6 +82,7 @@ #include "SDL_hints.h" #include "SDL_loadso.h" #include "SDL_log.h" +#include "SDL_messagebox.h" #include "SDL_mutex.h" #include "SDL_power.h" #include "SDL_render.h" diff --git a/include/SDL_config.h b/include/SDL_config.h index db38b9a12a..19d0f1ddc4 100644 --- a/include/SDL_config.h +++ b/include/SDL_config.h @@ -1,6 +1,6 @@ /* Simple DirectMedia Layer - Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org> + Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages diff --git a/include/SDL_config.h.in b/include/SDL_config.h.in index be6b5cf477..0e271a83c8 100644 --- a/include/SDL_config.h.in +++ b/include/SDL_config.h.in @@ -139,6 +139,8 @@ #undef HAVE_SIN #undef HAVE_SINF #undef HAVE_SQRT +#undef HAVE_FSEEKO +#undef HAVE_FSEEKO64 #undef HAVE_SIGACTION #undef HAVE_SA_SIGACTION #undef HAVE_SETJMP diff --git a/include/SDL_config_windows.h b/include/SDL_config_windows.h index 5f7e89b6a8..e8d3ffb97e 100644 --- a/include/SDL_config_windows.h +++ b/include/SDL_config_windows.h @@ -142,14 +142,21 @@ typedef unsigned int uintptr_t; /* Enable various audio drivers */ #define SDL_AUDIO_DRIVER_DSOUND 1 +#ifndef __GNUC__ #define SDL_AUDIO_DRIVER_XAUDIO2 1 +#endif #define SDL_AUDIO_DRIVER_WINMM 1 #define SDL_AUDIO_DRIVER_DISK 1 #define SDL_AUDIO_DRIVER_DUMMY 1 /* Enable various input drivers */ #define SDL_JOYSTICK_DINPUT 1 +#ifdef __GNUC__ +/* There isn't a compatible dinput.h for mingw as far as I know */ +#define SDL_HAPTIC_DISABLED 1 +#else #define SDL_HAPTIC_DINPUT 1 +#endif /* Enable various shared object loading systems */ #define SDL_LOADSO_WINDOWS 1 diff --git a/include/SDL_events.h b/include/SDL_events.h index 39648af4d1..4eaf095638 100644 --- a/include/SDL_events.h +++ b/include/SDL_events.h @@ -336,7 +336,7 @@ typedef struct SDL_MultiGestureEvent SDL_TouchID touchId; /**< The touch device index */ float dTheta; float dDist; - float x; //currently 0...1. Change to screen coords? + float x; /* currently 0...1. Change to screen coords? */ float y; Uint16 numFingers; Uint16 padding; @@ -438,6 +438,15 @@ typedef union SDL_Event SDL_MultiGestureEvent mgesture; /**< Multi Finger Gesture data */ SDL_DollarGestureEvent dgesture; /**< Multi Finger Gesture data */ SDL_DropEvent drop; /**< Drag and drop event data */ + + /* This is necessary for ABI compatibility between Visual C++ and GCC + Visual C++ will respect the push pack pragma and use 52 bytes for + this structure, and GCC will use the alignment of the largest datatype + within the union, which is 8 bytes. + + So... we'll add padding to force the size to be 56 bytes for both. + */ + Uint8 padding[56]; } SDL_Event; diff --git a/include/SDL_log.h b/include/SDL_log.h index 9f7e8b4f02..c87e9dd07b 100644 --- a/include/SDL_log.h +++ b/include/SDL_log.h @@ -59,12 +59,14 @@ extern "C" { * \brief The predefined log categories * * By default the application category is enabled at the INFO level, - * and all other categories are enabled at the CRITICAL level. + * the assert category is enabled at the WARN level, and all other + * categories are enabled at the CRITICAL level. */ enum { SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_CATEGORY_ERROR, + SDL_LOG_CATEGORY_ASSERT, SDL_LOG_CATEGORY_SYSTEM, SDL_LOG_CATEGORY_AUDIO, SDL_LOG_CATEGORY_VIDEO, diff --git a/include/SDL_messagebox.h b/include/SDL_messagebox.h new file mode 100644 index 0000000000..724c72895f --- /dev/null +++ b/include/SDL_messagebox.h @@ -0,0 +1,147 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#ifndef _SDL_messagebox_h +#define _SDL_messagebox_h + +#include "SDL_stdinc.h" +#include "SDL_video.h" /* For SDL_Window */ + +#include "begin_code.h" +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +/** + * \brief SDL_MessageBox flags. If supported will display warning icon, etc. + */ +typedef enum +{ + SDL_MESSAGEBOX_ERROR = 0x00000010, /**< error dialog */ + SDL_MESSAGEBOX_WARNING = 0x00000020, /**< warning dialog */ + SDL_MESSAGEBOX_INFORMATION = 0x00000040, /**< informational dialog */ +} SDL_MessageBoxFlags; + +/** + * \brief Flags for SDL_MessageBoxButtonData. + */ +typedef enum +{ + SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT = 0x00000001, /**< Marks the default button when return is hit */ + SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT = 0x00000002, /**< Marks the default button when escape is hit */ +} SDL_MessageBoxButtonFlags; + +/** + * \brief Individual button data. + */ +typedef struct +{ + Uint32 flags; /**< ::SDL_MessageBoxButtonFlags */ + int buttonid; /**< User defined button id (value returned via SDL_MessageBox) */ + const char * text; /**< The UTF-8 button text */ +} SDL_MessageBoxButtonData; + +/** + * \brief RGB value used in a message box color scheme + */ +typedef struct +{ + Uint8 r, g, b; +} SDL_MessageBoxColor; + +typedef enum +{ + SDL_MESSAGEBOX_COLOR_BACKGROUND, + SDL_MESSAGEBOX_COLOR_TEXT, + SDL_MESSAGEBOX_COLOR_BUTTON_BORDER, + SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND, + SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED, + SDL_MESSAGEBOX_COLOR_MAX +} SDL_MessageBoxColorType; + +/** + * \brief A set of colors to use for message box dialogs + */ +typedef struct +{ + SDL_MessageBoxColor colors[SDL_MESSAGEBOX_COLOR_MAX]; +} SDL_MessageBoxColorScheme; + +/** + * \brief MessageBox structure containing title, text, window, etc. + */ +typedef struct +{ + Uint32 flags; /**< ::SDL_MessageBoxFlags */ + SDL_Window *window; /**< Parent window, can be NULL */ + const char *title; /**< UTF-8 title */ + const char *message; /**< UTF-8 message text */ + + int numbuttons; + const SDL_MessageBoxButtonData *buttons; + + const SDL_MessageBoxColorScheme *colorScheme; /**< ::SDL_MessageBoxColorScheme, can be NULL to use system settings */ +} SDL_MessageBoxData; + +/** + * \brief Create a modal message box. + * + * \param messagebox The SDL_MessageBox structure with title, text, etc. + * + * \return -1 on error, otherwise 0 and buttonid contains user id of button + * hit or -1 if dialog was closed. + * + * \note This function should be called on the thread that created the parent + * window, or on the main thread if the messagebox has no parent. It will + * block execution of that thread until the user clicks a button or + * closes the messagebox. + */ +extern DECLSPEC int SDLCALL SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid); + +/** + * \brief Create a simple modal message box + * + * \param flags ::SDL_MessageBoxFlags + * \param title UTF-8 title text + * \param message UTF-8 message text + * \param window The parent window, or NULL for no parent + * + * \return 0 on success, -1 on error + * + * \sa SDL_ShowMessageBox + */ +extern DECLSPEC int SDLCALL SDL_ShowSimpleMessageBox(Uint32 flags, const char *title, const char *message, SDL_Window *window); + + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif +#include "close_code.h" + +#endif /* _SDL_messagebox_h */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/include/SDL_rwops.h b/include/SDL_rwops.h index 87715f5bab..023baa68d0 100644 --- a/include/SDL_rwops.h +++ b/include/SDL_rwops.h @@ -46,13 +46,18 @@ extern "C" { typedef struct SDL_RWops { /** + * Return the size of the file in this rwops, or -1 if unknown + */ + Sint64 (SDLCALL * size) (struct SDL_RWops * context); + + /** * Seek to \c offset relative to \c whence, one of stdio's whence values: * RW_SEEK_SET, RW_SEEK_CUR, RW_SEEK_END * * \return the final offset in the data stream. */ - long (SDLCALL * seek) (struct SDL_RWops * context, long offset, - int whence); + Sint64 (SDLCALL * seek) (struct SDL_RWops * context, Sint64 offset, + int whence); /** * Read up to \c maxnum objects each of size \c size from the data @@ -60,8 +65,8 @@ typedef struct SDL_RWops * * \return the number of objects read, or 0 at error or end of file. */ - size_t(SDLCALL * read) (struct SDL_RWops * context, void *ptr, - size_t size, size_t maxnum); + size_t (SDLCALL * read) (struct SDL_RWops * context, void *ptr, + size_t size, size_t maxnum); /** * Write exactly \c num objects each of size \c size from the area @@ -69,8 +74,8 @@ typedef struct SDL_RWops * * \return the number of objects written, or 0 at error or end of file. */ - size_t(SDLCALL * write) (struct SDL_RWops * context, const void *ptr, - size_t size, size_t num); + size_t (SDLCALL * write) (struct SDL_RWops * context, const void *ptr, + size_t size, size_t num); /** * Close and free an allocated SDL_RWops structure. @@ -166,6 +171,7 @@ extern DECLSPEC void SDLCALL SDL_FreeRW(SDL_RWops * area); * Macros to easily read and write from an SDL_RWops structure. */ /*@{*/ +#define SDL_RWsize(ctx) (ctx)->size(ctx) #define SDL_RWseek(ctx, offset, whence) (ctx)->seek(ctx, offset, whence) #define SDL_RWtell(ctx) (ctx)->seek(ctx, 0, RW_SEEK_CUR) #define SDL_RWread(ctx, ptr, size, n) (ctx)->read(ctx, ptr, size, n) diff --git a/include/SDL_stdinc.h b/include/SDL_stdinc.h index b6e6992a4e..c753628d23 100644 --- a/include/SDL_stdinc.h +++ b/include/SDL_stdinc.h @@ -347,7 +347,7 @@ do { \ /* We can count on memcpy existing on Mac OS X and being well-tuned. */ #if defined(__MACOSX__) #define SDL_memcpy memcpy -#elif defined(__GNUC__) && defined(i386) +#elif defined(__GNUC__) && defined(i386) && !defined(__WIN32__) #define SDL_memcpy(dst, src, len) \ do { \ int u0, u1, u2; \ @@ -640,8 +640,10 @@ extern DECLSPEC int SDLCALL SDL_vsnprintf(char *text, size_t maxlen, #endif #ifndef HAVE_M_PI +#ifndef M_PI #define M_PI 3.14159265358979323846264338327950288 /* pi */ #endif +#endif #ifdef HAVE_ATAN #define SDL_atan atan @@ -755,8 +757,8 @@ extern DECLSPEC char *SDLCALL SDL_iconv_string(const char *tocode, const char *inbuf, size_t inbytesleft); #define SDL_iconv_utf8_locale(S) SDL_iconv_string("", "UTF-8", S, SDL_strlen(S)+1) -#define SDL_iconv_utf8_ucs2(S) (Uint16 *)SDL_iconv_string("UCS-2", "UTF-8", S, SDL_strlen(S)+1) -#define SDL_iconv_utf8_ucs4(S) (Uint32 *)SDL_iconv_string("UCS-4", "UTF-8", S, SDL_strlen(S)+1) +#define SDL_iconv_utf8_ucs2(S) (Uint16 *)SDL_iconv_string("UCS-2-INTERNAL", "UTF-8", S, SDL_strlen(S)+1) +#define SDL_iconv_utf8_ucs4(S) (Uint32 *)SDL_iconv_string("UCS-4-INTERNAL", "UTF-8", S, SDL_strlen(S)+1) /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/include/SDL_system.h b/include/SDL_system.h index 08dde6c407..6f0f6e610c 100644 --- a/include/SDL_system.h +++ b/include/SDL_system.h @@ -43,6 +43,7 @@ extern "C" { /* *INDENT-ON* */ #endif +/* Platform specific functions for iOS */ #if __IPHONEOS__ extern DECLSPEC int SDLCALL SDL_iPhoneSetAnimationCallback(SDL_Window * window, int interval, void (*callback)(void*), void *callbackParam); @@ -53,7 +54,43 @@ extern DECLSPEC void SDLCALL SDL_iPhoneSetEventPump(SDL_bool enabled); #define SDL_iPhoneKeyboardToggle SDL_ToggleScreenKeyboard #define SDL_iPhoneKeyboardIsShown SDL_IsScreenKeyboardShown -#endif +#endif /* __IPHONEOS__ */ + + +/* Platform specific functions for Android */ +#if __ANDROID__ + +/* Get the JNI environment for the current thread + This returns JNIEnv*, but the prototype is void* so we don't need jni.h + */ +extern DECLSPEC void * SDLCALL SDL_AndroidGetJNIEnv(); + +/* Get the SDL Activity object for the application + This returns jobject, but the prototype is void* so we don't need jni.h + */ +extern DECLSPEC void * SDLCALL SDL_AndroidGetActivity(); + +/* See the official Android developer guide for more information: + http://developer.android.com/guide/topics/data/data-storage.html +*/ +#define SDL_ANDROID_EXTERNAL_STORAGE_READ 0x01 +#define SDL_ANDROID_EXTERNAL_STORAGE_WRITE 0x02 + +/* Get the path used for internal storage for this application */ +extern DECLSPEC const char * SDLCALL SDL_AndroidGetInternalStoragePath(); + +/* Get the current state of external storage, a bitmask of these values: + SDL_ANDROID_EXTERNAL_STORAGE_READ + SDL_ANDROID_EXTERNAL_STORAGE_WRITE + If external storage is currently unavailable, this will return 0. +*/ +extern DECLSPEC int SDLCALL SDL_AndroidGetExternalStorageState(); + +/* Get the path used for external storage for this application */ +extern DECLSPEC const char * SDLCALL SDL_AndroidGetExternalStoragePath(); + +#endif /* __ANDROID__ */ + /* Ends C function definitions when using C++ */ #ifdef __cplusplus diff --git a/src/SDL_assert.c b/src/SDL_assert.c index 4760e03978..1d0fd05399 100644 --- a/src/SDL_assert.c +++ b/src/SDL_assert.c @@ -22,11 +22,13 @@ #include "SDL.h" #include "SDL_atomic.h" +#include "SDL_messagebox.h" +#include "SDL_video.h" #include "SDL_assert.h" #include "SDL_assert_c.h" #include "video/SDL_sysvideo.h" -#if defined(__WIN32__) || defined(__WINRT__) +#ifdef __WIN32__ #include "core/windows/SDL_windows.h" #ifndef WS_OVERLAPPEDWINDOW @@ -59,171 +61,12 @@ debug_print(const char *fmt, ...) __attribute__((format (printf, 1, 2))); static void debug_print(const char *fmt, ...) { -#if defined(__WIN32__) || defined(__WINRT__) - /* Format into a buffer for OutputDebugStringA(). */ - char buf[1024]; - char *startptr; - char *ptr; - LPTSTR tstr; - int len; - va_list ap; - va_start(ap, fmt); - len = (int) SDL_vsnprintf(buf, sizeof (buf), fmt, ap); - va_end(ap); - - /* Visual C's vsnprintf() may not null-terminate the buffer. */ - if ((len >= sizeof (buf)) || (len < 0)) { - buf[sizeof (buf) - 1] = '\0'; - } - - /* Write it, sorting out the Unix newlines... */ - startptr = buf; - for (ptr = startptr; *ptr; ptr++) { - if (*ptr == '\n') { - *ptr = '\0'; - tstr = WIN_UTF8ToString(startptr); - OutputDebugString(tstr); - SDL_free(tstr); - OutputDebugString(TEXT("\r\n")); - startptr = ptr+1; - } - } - - /* catch that last piece if it didn't have a newline... */ - if (startptr != ptr) { - tstr = WIN_UTF8ToString(startptr); - OutputDebugString(tstr); - SDL_free(tstr); - } -#else - /* Unix has it easy. Just dump it to stderr. */ va_list ap; va_start(ap, fmt); - vfprintf(stderr, fmt, ap); + SDL_LogMessageV(SDL_LOG_CATEGORY_ASSERT, SDL_LOG_PRIORITY_WARN, fmt, ap); va_end(ap); - fflush(stderr); -#endif -} - - -#ifdef __WIN32__ -static SDL_assert_state SDL_Windows_AssertChoice = SDL_ASSERTION_ABORT; -static const SDL_assert_data *SDL_Windows_AssertData = NULL; - -static LRESULT CALLBACK -SDL_Assertion_WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) - { - case WM_CREATE: - { - /* !!! FIXME: all this code stinks. */ - const SDL_assert_data *data = SDL_Windows_AssertData; - char buf[1024]; - LPTSTR tstr; - const int w = 100; - const int h = 25; - const int gap = 10; - int x = gap; - int y = 50; - int len; - int i; - static const struct { - LPCTSTR name; - SDL_assert_state state; - } buttons[] = { - {TEXT("Abort"), SDL_ASSERTION_ABORT }, - {TEXT("Break"), SDL_ASSERTION_BREAK }, - {TEXT("Retry"), SDL_ASSERTION_RETRY }, - {TEXT("Ignore"), SDL_ASSERTION_IGNORE }, - {TEXT("Always Ignore"), SDL_ASSERTION_ALWAYS_IGNORE }, - }; - - len = (int) SDL_snprintf(buf, sizeof (buf), - "Assertion failure at %s (%s:%d), triggered %u time%s:\r\n '%s'", - data->function, data->filename, data->linenum, - data->trigger_count, (data->trigger_count == 1) ? "" : "s", - data->condition); - if ((len < 0) || (len >= sizeof (buf))) { - buf[sizeof (buf) - 1] = '\0'; - } - - tstr = WIN_UTF8ToString(buf); - CreateWindow(TEXT("STATIC"), tstr, - WS_VISIBLE | WS_CHILD | SS_LEFT, - x, y, 550, 100, - hwnd, (HMENU) 1, NULL, NULL); - SDL_free(tstr); - y += 110; - - for (i = 0; i < (sizeof (buttons) / sizeof (buttons[0])); i++) { - CreateWindow(TEXT("BUTTON"), buttons[i].name, - WS_VISIBLE | WS_CHILD, - x, y, w, h, - hwnd, (HMENU) buttons[i].state, NULL, NULL); - x += w + gap; - } - break; - } - - case WM_COMMAND: - SDL_Windows_AssertChoice = ((SDL_assert_state) (LOWORD(wParam))); - SDL_Windows_AssertData = NULL; - break; - - case WM_DESTROY: - SDL_Windows_AssertData = NULL; - break; - } - - return DefWindowProc(hwnd, msg, wParam, lParam); -} - -static SDL_assert_state -SDL_PromptAssertion_windows(const SDL_assert_data *data) -{ - HINSTANCE hInstance = 0; /* !!! FIXME? */ - HWND hwnd; - MSG msg; - WNDCLASS wc = {0}; - - SDL_Windows_AssertChoice = SDL_ASSERTION_ABORT; - SDL_Windows_AssertData = data; - - wc.lpszClassName = TEXT("SDL_assert"); - wc.hInstance = hInstance ; - wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE); - wc.lpfnWndProc = SDL_Assertion_WndProc; - wc.hCursor = LoadCursor(0, IDC_ARROW); - - RegisterClass(&wc); - hwnd = CreateWindow(wc.lpszClassName, TEXT("SDL assertion failure"), - WS_OVERLAPPEDWINDOW | WS_VISIBLE, - 150, 150, 570, 260, 0, 0, hInstance, 0); - - while (GetMessage(&msg, NULL, 0, 0) && (SDL_Windows_AssertData != NULL)) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - - DestroyWindow(hwnd); - UnregisterClass(wc.lpszClassName, hInstance); - return SDL_Windows_AssertChoice; -} -#endif - - -#ifdef __WINRT__ - -static SDL_assert_state -SDL_PromptAssertion_windowsrt(const SDL_assert_data *data) -{ - /* TODO, WinRT: implement SDL_PromptAssertion_windowsrt */ - return SDL_ASSERTION_ABORT; } -#endif - static void SDL_AddAssertionToReport(SDL_assert_data *data) { @@ -266,10 +109,8 @@ static void SDL_GenerateAssertionReport(void) static void SDL_ExitProcess(int exitcode) { -#if defined(__WIN32__) +#ifdef __WIN32__ ExitProcess(exitcode); -#elif defined(__WINRT__) - exit(exitcode); #else _exit(exitcode); #endif @@ -288,20 +129,39 @@ SDL_PromptAssertion(const SDL_assert_data *data, void *userdata) const char *envr; SDL_assert_state state = SDL_ASSERTION_ABORT; SDL_Window *window; + SDL_MessageBoxData messagebox; + SDL_MessageBoxButtonData buttons[] = { + { 0, SDL_ASSERTION_RETRY, "Retry" }, + { 0, SDL_ASSERTION_BREAK, "Break" }, + { 0, SDL_ASSERTION_ABORT, "Abort" }, + { SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, + SDL_ASSERTION_IGNORE, "Ignore" }, + { SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, + SDL_ASSERTION_ALWAYS_IGNORE, "Always Ignore" } + }; + char *message; + int selected; (void) userdata; /* unused in default handler. */ - debug_print("\n\n" - "Assertion failure at %s (%s:%d), triggered %u time%s:\n" - " '%s'\n" - "\n", - data->function, data->filename, data->linenum, - data->trigger_count, (data->trigger_count == 1) ? "" : "s", - data->condition); + message = SDL_stack_alloc(char, SDL_MAX_LOG_MESSAGE); + if (!message) { + /* Uh oh, we're in real trouble now... */ + return SDL_ASSERTION_ABORT; + } + SDL_snprintf(message, SDL_MAX_LOG_MESSAGE, + "Assertion failure at %s (%s:%d), triggered %u %s:\r\n '%s'", + data->function, data->filename, data->linenum, + data->trigger_count, (data->trigger_count == 1) ? "time" : "times", + data->condition); + + debug_print("\n\n%s\n\n", message); /* let env. variable override, so unit tests won't block in a GUI. */ envr = SDL_getenv("SDL_ASSERT"); if (envr != NULL) { + SDL_stack_free(message); + if (SDL_strcmp(envr, "abort") == 0) { return SDL_ASSERTION_ABORT; } else if (SDL_strcmp(envr, "break") == 0) { @@ -325,57 +185,65 @@ SDL_PromptAssertion(const SDL_assert_data *data, void *userdata) } else { /* !!! FIXME: ungrab the input if we're not fullscreen? */ /* No need to mess with the window */ - window = 0; + window = NULL; } } - /* platform-specific UI... */ - -#if defined(__WIN32__) - state = SDL_PromptAssertion_windows(data); - -#elif defined(__WINRT__) - state = SDL_PromptAssertion_windowsrt(data); - -#elif defined __MACOSX__ && defined SDL_VIDEO_DRIVER_COCOA - /* This has to be done in an Objective-C (*.m) file, so we call out. */ - extern SDL_assert_state SDL_PromptAssertion_cocoa(const SDL_assert_data *); - state = SDL_PromptAssertion_cocoa(data); - -#else - /* this is a little hacky. */ - for ( ; ; ) { - char buf[32]; - fprintf(stderr, "Abort/Break/Retry/Ignore/AlwaysIgnore? [abriA] : "); - fflush(stderr); - if (fgets(buf, sizeof (buf), stdin) == NULL) { - break; + /* Show a messagebox if we can, otherwise fall back to stdio */ + SDL_zero(messagebox); + messagebox.flags = SDL_MESSAGEBOX_WARNING; + messagebox.window = window; + messagebox.title = "Assertion Failed"; + messagebox.message = message; + messagebox.numbuttons = SDL_arraysize(buttons); + messagebox.buttons = buttons; + + if (SDL_ShowMessageBox(&messagebox, &selected) == 0) { + if (selected == -1) { + state = SDL_ASSERTION_IGNORE; + } else { + state = (SDL_assert_state)selected; } + } +#ifdef HAVE_STDIO_H + else + { + /* this is a little hacky. */ + for ( ; ; ) { + char buf[32]; + fprintf(stderr, "Abort/Break/Retry/Ignore/AlwaysIgnore? [abriA] : "); + fflush(stderr); + if (fgets(buf, sizeof (buf), stdin) == NULL) { + break; + } - if (SDL_strcmp(buf, "a") == 0) { - state = SDL_ASSERTION_ABORT; - break; - } else if (SDL_strcmp(buf, "b") == 0) { - state = SDL_ASSERTION_BREAK; - break; - } else if (SDL_strcmp(buf, "r") == 0) { - state = SDL_ASSERTION_RETRY; - break; - } else if (SDL_strcmp(buf, "i") == 0) { - state = SDL_ASSERTION_IGNORE; - break; - } else if (SDL_strcmp(buf, "A") == 0) { - state = SDL_ASSERTION_ALWAYS_IGNORE; - break; + if (SDL_strcmp(buf, "a") == 0) { + state = SDL_ASSERTION_ABORT; + break; + } else if (SDL_strcmp(buf, "b") == 0) { + state = SDL_ASSERTION_BREAK; + break; + } else if (SDL_strcmp(buf, "r") == 0) { + state = SDL_ASSERTION_RETRY; + break; + } else if (SDL_strcmp(buf, "i") == 0) { + state = SDL_ASSERTION_IGNORE; + break; + } else if (SDL_strcmp(buf, "A") == 0) { + state = SDL_ASSERTION_ALWAYS_IGNORE; + break; + } } } -#endif +#endif /* HAVE_STDIO_H */ /* Re-enter fullscreen mode */ if (window) { SDL_RestoreWindow(window); } + SDL_stack_free(message); + return state; } diff --git a/src/SDL_log.c b/src/SDL_log.c index d7f99180d5..12392753f4 100644 --- a/src/SDL_log.c +++ b/src/SDL_log.c @@ -35,6 +35,7 @@ #endif #define DEFAULT_PRIORITY SDL_LOG_PRIORITY_CRITICAL +#define DEFAULT_ASSERT_PRIORITY SDL_LOG_PRIORITY_WARN #define DEFAULT_APPLICATION_PRIORITY SDL_LOG_PRIORITY_INFO typedef struct SDL_LogLevel @@ -50,8 +51,9 @@ static void SDL_LogOutput(void *userdata, const char *message); static SDL_LogLevel *SDL_loglevels; -static SDL_LogPriority SDL_application_priority = DEFAULT_APPLICATION_PRIORITY; static SDL_LogPriority SDL_default_priority = DEFAULT_PRIORITY; +static SDL_LogPriority SDL_assert_priority = DEFAULT_ASSERT_PRIORITY; +static SDL_LogPriority SDL_application_priority = DEFAULT_APPLICATION_PRIORITY; static SDL_LogOutputFunction SDL_log_function = SDL_LogOutput; static void *SDL_log_userdata = NULL; @@ -95,7 +97,9 @@ SDL_LogSetAllPriority(SDL_LogPriority priority) for (entry = SDL_loglevels; entry; entry = entry->next) { entry->priority = priority; } - SDL_application_priority = SDL_default_priority = priority; + SDL_default_priority = priority; + SDL_assert_priority = priority; + SDL_application_priority = priority; } void @@ -133,6 +137,8 @@ SDL_LogGetPriority(int category) if (category == SDL_LOG_CATEGORY_APPLICATION) { return SDL_application_priority; + } else if (category == SDL_LOG_CATEGORY_ASSERT) { + return SDL_assert_priority; } else { return SDL_default_priority; } @@ -149,8 +155,9 @@ SDL_LogResetPriorities(void) SDL_free(entry); } - SDL_application_priority = DEFAULT_APPLICATION_PRIORITY; SDL_default_priority = DEFAULT_PRIORITY; + SDL_assert_priority = DEFAULT_ASSERT_PRIORITY; + SDL_application_priority = DEFAULT_APPLICATION_PRIORITY; } void @@ -302,6 +309,19 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority, SDL_snprintf(tag, SDL_arraysize(tag), "SDL/%s", GetCategoryPrefix(category)); __android_log_write(SDL_android_priority[priority], tag, message); } +#elif defined(__APPLE__) + extern void SDL_NSLog(const char *text); + { + char *text; + + text = SDL_stack_alloc(char, SDL_MAX_LOG_MESSAGE); + if (text) { + SDL_snprintf(text, SDL_MAX_LOG_MESSAGE, "%s: %s", SDL_priority_prefixes[priority], message); + SDL_NSLog(text); + SDL_stack_free(text); + return; + } + } #endif #if HAVE_STDIO_H fprintf(stderr, "%s: %s\n", SDL_priority_prefixes[priority], message); diff --git a/src/audio/coreaudio/SDL_coreaudio.c b/src/audio/coreaudio/SDL_coreaudio.c index d6c12555ae..1747bb2cd8 100644 --- a/src/audio/coreaudio/SDL_coreaudio.c +++ b/src/audio/coreaudio/SDL_coreaudio.c @@ -340,9 +340,10 @@ COREAUDIO_CloseDevice(_THIS) scope, bus, &callback, sizeof(callback)); - /* !!! FIXME: how does iOS free this? */ #if MACOSX_COREAUDIO CloseComponent(this->hidden->audioUnit); + #else + AudioComponentInstanceDispose(this->hidden->audioUnit); #endif this->hidden->audioUnitOpened = 0; @@ -538,8 +539,16 @@ COREAUDIO_Init(SDL_AudioDriverImpl * impl) impl->DetectDevices = COREAUDIO_DetectDevices; #else impl->OnlyHasDefaultOutputDevice = 1; + + /* Set category to ambient sound so that other music continues playing. + You can change this at runtime in your own code if you need different + behavior. If this is common, we can add an SDL hint for this. + */ + AudioSessionInitialize(NULL, NULL, NULL, nil); + UInt32 category = kAudioSessionCategory_AmbientSound; + AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(UInt32), &category); #endif - + impl->ProvidesOwnCallbackThread = 1; return 1; /* this audio target is available. */ diff --git a/src/audio/coreaudio/SDL_coreaudio.h b/src/audio/coreaudio/SDL_coreaudio.h index 65941f584b..e6b47c8bc1 100644 --- a/src/audio/coreaudio/SDL_coreaudio.h +++ b/src/audio/coreaudio/SDL_coreaudio.h @@ -35,6 +35,8 @@ #if MAC_OS_X_VERSION_MAX_ALLOWED <= 1050 #include <AudioUnit/AUNTComponent.h> #endif +#else +#include <AudioToolbox/AudioToolbox.h> #endif #include <AudioUnit/AudioUnit.h> diff --git a/src/core/android/SDL_android.cpp b/src/core/android/SDL_android.cpp index b01735dc39..b7fe7c5c02 100644 --- a/src/core/android/SDL_android.cpp +++ b/src/core/android/SDL_android.cpp @@ -24,6 +24,7 @@ #ifdef __ANDROID__ +#include "SDL_system.h" #include "SDL_android.h" extern "C" { @@ -695,9 +696,14 @@ static int Android_JNI_FileClose(SDL_RWops* ctx, bool release) } -extern "C" long Android_JNI_FileSeek(SDL_RWops* ctx, long offset, int whence) +extern "C" Sint64 Android_JNI_FileSize(SDL_RWops* ctx) { - long newPosition; + return ctx->hidden.androidio.size; +} + +extern "C" Sint64 Android_JNI_FileSeek(SDL_RWops* ctx, Sint64 offset, int whence) +{ + Sint64 newPosition; switch (whence) { case RW_SEEK_SET: @@ -713,27 +719,27 @@ extern "C" long Android_JNI_FileSeek(SDL_RWops* ctx, long offset, int whence) SDL_SetError("Unknown value for 'whence'"); return -1; } + + /* Validate the new position */ if (newPosition < 0) { - newPosition = 0; + SDL_Error(SDL_EFSEEK); + return -1; } if (newPosition > ctx->hidden.androidio.size) { newPosition = ctx->hidden.androidio.size; } - long movement = newPosition - ctx->hidden.androidio.position; - jobject inputStream = (jobject)ctx->hidden.androidio.inputStreamRef; - + Sint64 movement = newPosition - ctx->hidden.androidio.position; if (movement > 0) { unsigned char buffer[1024]; // The easy case where we're seeking forwards while (movement > 0) { - long amount = (long) sizeof (buffer); + Sint64 amount = sizeof (buffer); if (amount > movement) { amount = movement; } size_t result = Android_JNI_FileRead(ctx, buffer, 1, amount); - if (result <= 0) { // Failed to read/skip the required amount, so fail return -1; @@ -741,6 +747,7 @@ extern "C" long Android_JNI_FileSeek(SDL_RWops* ctx, long offset, int whence) movement -= result; } + } else if (movement < 0) { // We can't seek backwards so we have to reopen the file and seek // forwards which obviously isn't very efficient @@ -749,8 +756,6 @@ extern "C" long Android_JNI_FileSeek(SDL_RWops* ctx, long offset, int whence) Android_JNI_FileSeek(ctx, newPosition, RW_SEEK_SET); } - ctx->hidden.androidio.position = newPosition; - return ctx->hidden.androidio.position; } @@ -963,8 +968,6 @@ extern "C" int Android_JNI_ShowTextInput(SDL_Rect *inputRect) /*extern "C" int Android_JNI_HideTextInput() { - - JNIEnv *env = Android_JNI_GetEnv(); if (!env) { return -1; @@ -978,6 +981,155 @@ extern "C" int Android_JNI_ShowTextInput(SDL_Rect *inputRect) return 0; }*/ +////////////////////////////////////////////////////////////////////////////// +// +// Functions exposed to SDL applications in SDL_system.h +// + +extern "C" void *SDL_AndroidGetJNIEnv() +{ + return Android_JNI_GetEnv(); +} + +extern "C" void *SDL_AndroidGetActivity() +{ + LocalReferenceHolder refs; + jmethodID mid; + + JNIEnv *env = Android_JNI_GetEnv(); + if (!refs.init(env)) { + return NULL; + } + + // return SDLActivity.getContext(); + mid = env->GetStaticMethodID(mActivityClass, + "getContext","()Landroid/content/Context;"); + return env->CallStaticObjectMethod(mActivityClass, mid); +} + +extern "C" const char * SDL_AndroidGetInternalStoragePath() +{ + static char *s_AndroidInternalFilesPath = NULL; + + if (!s_AndroidInternalFilesPath) { + LocalReferenceHolder refs; + jmethodID mid; + jobject context; + jobject fileObject; + jstring pathString; + const char *path; + + JNIEnv *env = Android_JNI_GetEnv(); + if (!refs.init(env)) { + return NULL; + } + + // context = SDLActivity.getContext(); + mid = env->GetStaticMethodID(mActivityClass, + "getContext","()Landroid/content/Context;"); + context = env->CallStaticObjectMethod(mActivityClass, mid); + + // fileObj = context.getFilesDir(); + mid = env->GetMethodID(env->GetObjectClass(context), + "getFilesDir", "()Ljava/io/File;"); + fileObject = env->CallObjectMethod(context, mid); + if (!fileObject) { + SDL_SetError("Couldn't get internal directory"); + return NULL; + } + + // path = fileObject.getAbsolutePath(); + mid = env->GetMethodID(env->GetObjectClass(fileObject), + "getAbsolutePath", "()Ljava/lang/String;"); + pathString = (jstring)env->CallObjectMethod(fileObject, mid); + + path = env->GetStringUTFChars(pathString, NULL); + s_AndroidInternalFilesPath = SDL_strdup(path); + env->ReleaseStringUTFChars(pathString, path); + } + return s_AndroidInternalFilesPath; +} + +extern "C" int SDL_AndroidGetExternalStorageState() +{ + LocalReferenceHolder refs; + jmethodID mid; + jclass cls; + jstring stateString; + const char *state; + int stateFlags; + + JNIEnv *env = Android_JNI_GetEnv(); + if (!refs.init(env)) { + return 0; + } + + cls = env->FindClass("android/os/Environment"); + mid = env->GetStaticMethodID(cls, + "getExternalStorageState", "()Ljava/lang/String;"); + stateString = (jstring)env->CallStaticObjectMethod(cls, mid); + + state = env->GetStringUTFChars(stateString, NULL); + + // Print an info message so people debugging know the storage state + __android_log_print(ANDROID_LOG_INFO, "SDL", "external storage state: %s", state); + + if (SDL_strcmp(state, "mounted") == 0) { + stateFlags = SDL_ANDROID_EXTERNAL_STORAGE_READ | + SDL_ANDROID_EXTERNAL_STORAGE_WRITE; + } else if (SDL_strcmp(state, "mounted_ro") == 0) { + stateFlags = SDL_ANDROID_EXTERNAL_STORAGE_READ; + } else { + stateFlags = 0; + } + env->ReleaseStringUTFChars(stateString, state); + + return stateFlags; +} + +extern "C" const char * SDL_AndroidGetExternalStoragePath() +{ + static char *s_AndroidExternalFilesPath = NULL; + + if (!s_AndroidExternalFilesPath) { + LocalReferenceHolder refs; + jmethodID mid; + jobject context; + jobject fileObject; + jstring pathString; + const char *path; + + JNIEnv *env = Android_JNI_GetEnv(); + if (!refs.init(env)) { + return NULL; + } + + // context = SDLActivity.getContext(); + mid = env->GetStaticMethodID(mActivityClass, + "getContext","()Landroid/content/Context;"); + context = env->CallStaticObjectMethod(mActivityClass, mid); + + // fileObj = context.getExternalFilesDir(); + mid = env->GetMethodID(env->GetObjectClass(context), + "getExternalFilesDir", "(Ljava/lang/String;)Ljava/io/File;"); + fileObject = env->CallObjectMethod(context, mid, NULL); + if (!fileObject) { + SDL_SetError("Couldn't get external directory"); + return NULL; + } + + // path = fileObject.getAbsolutePath(); + mid = env->GetMethodID(env->GetObjectClass(fileObject), + "getAbsolutePath", "()Ljava/lang/String;"); + pathString = (jstring)env->CallObjectMethod(fileObject, mid); + + path = env->GetStringUTFChars(pathString, NULL); + s_AndroidExternalFilesPath = SDL_strdup(path); + env->ReleaseStringUTFChars(pathString, path); + } + return s_AndroidExternalFilesPath; +} + #endif /* __ANDROID__ */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/core/android/SDL_android.h b/src/core/android/SDL_android.h index 637e465bc2..505e92b69a 100644 --- a/src/core/android/SDL_android.h +++ b/src/core/android/SDL_android.h @@ -45,7 +45,8 @@ extern void Android_JNI_CloseAudioDevice(); #include "SDL_rwops.h" int Android_JNI_FileOpen(SDL_RWops* ctx, const char* fileName, const char* mode); -long Android_JNI_FileSeek(SDL_RWops* ctx, long offset, int whence); +Sint64 Android_JNI_FileSize(SDL_RWops* ctx); +Sint64 Android_JNI_FileSeek(SDL_RWops* ctx, Sint64 offset, int whence); size_t Android_JNI_FileRead(SDL_RWops* ctx, void* buffer, size_t size, size_t maxnum); size_t Android_JNI_FileWrite(SDL_RWops* ctx, const void* buffer, size_t size, size_t num); int Android_JNI_FileClose(SDL_RWops* ctx); diff --git a/src/core/windows/SDL_windows.h b/src/core/windows/SDL_windows.h index 0c04866731..c7c6f9576a 100644 --- a/src/core/windows/SDL_windows.h +++ b/src/core/windows/SDL_windows.h @@ -37,8 +37,8 @@ /* Routines to convert from UTF8 to native Windows text */ #if UNICODE -#define WIN_StringToUTF8(S) SDL_iconv_string("UTF-8", "UCS-2", (char *)(S), (SDL_wcslen(S)+1)*sizeof(WCHAR)) -#define WIN_UTF8ToString(S) (WCHAR *)SDL_iconv_string("UCS-2", "UTF-8", (char *)(S), SDL_strlen(S)+1) +#define WIN_StringToUTF8(S) SDL_iconv_string("UTF-8", "UCS-2-INTERNAL", (char *)(S), (SDL_wcslen(S)+1)*sizeof(WCHAR)) +#define WIN_UTF8ToString(S) (WCHAR *)SDL_iconv_string("UCS-2-INTERNAL", "UTF-8", (char *)(S), SDL_strlen(S)+1) #else #define WIN_StringToUTF8(S) SDL_iconv_string("UTF-8", "ASCII", (char *)(S), (SDL_strlen(S)+1)) #define WIN_UTF8ToString(S) SDL_iconv_string("ASCII", "UTF-8", (char *)(S), SDL_strlen(S)+1) diff --git a/src/file/SDL_rwops.c b/src/file/SDL_rwops.c index 7a87c9d2a0..a4d76446fb 100644 --- a/src/file/SDL_rwops.c +++ b/src/file/SDL_rwops.c @@ -18,6 +18,8 @@ misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ +/* Need this so Linux systems define fseek64o, ftell64o and off64_t */ +#define _LARGEFILE64_SOURCE #include "SDL_config.h" /* This file provides a general interface for SDL to read and write @@ -121,11 +123,29 @@ windows_file_open(SDL_RWops * context, const char *filename, const char *mode) return 0; /* ok */ } -static long SDLCALL -windows_file_seek(SDL_RWops * context, long offset, int whence) +static Sint64 SDLCALL +windows_file_size(SDL_RWops * context) +{ + LARGE_INTEGER size; + + if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE) { + SDL_SetError("windows_file_size: invalid context/file not opened"); + return -1; + } + + if (!GetFileSizeEx(context->hidden.windowsio.h, &size)) { + WIN_SetError("windows_file_size"); + return -1; + } + + return size.QuadPart; +} + +static Sint64 SDLCALL +windows_file_seek(SDL_RWops * context, Sint64 offset, int whence) { DWORD windowswhence; - long file_pos; + LARGE_INTEGER windowsoffset; if (!context || context->hidden.windowsio.h == INVALID_HANDLE_VALUE) { SDL_SetError("windows_file_seek: invalid context/file not opened"); @@ -153,14 +173,12 @@ windows_file_seek(SDL_RWops * context, long offset, int whence) return -1; } - file_pos = - SetFilePointer(context->hidden.windowsio.h, offset, NULL, windowswhence); - - if (file_pos != INVALID_SET_FILE_POINTER) - return file_pos; /* success */ - - SDL_Error(SDL_EFSEEK); - return -1; /* error */ + windowsoffset.QuadPart = offset; + if (!SetFilePointerEx(context->hidden.windowsio.h, windowsoffset, &windowsoffset, windowswhence)) { + WIN_SetError("windows_file_seek"); + return -1; + } + return windowsoffset.QuadPart; } static size_t SDLCALL @@ -281,15 +299,39 @@ windows_file_close(SDL_RWops * context) /* Functions to read/write stdio file pointers */ -static long SDLCALL -stdio_seek(SDL_RWops * context, long offset, int whence) +static Sint64 SDLCALL +stdio_size(SDL_RWops * context) +{ + Sint64 pos, size; + + pos = SDL_RWseek(context, 0, RW_SEEK_CUR); + if (pos < 0) { + return -1; + } + size = SDL_RWseek(context, 0, RW_SEEK_END); + + SDL_RWseek(context, pos, RW_SEEK_SET); + return size; +} + +static Sint64 SDLCALL +stdio_seek(SDL_RWops * context, Sint64 offset, int whence) { +#ifdef HAVE_FSEEKO64 + if (fseeko64(context->hidden.stdio.fp, (off64_t)offset, whence) == 0) { + return ftello64(context->hidden.stdio.fp); + } +#elif defined(HAVE_FSEEKO) + if (fseeko(context->hidden.stdio.fp, (off_t)offset, whence) == 0) { + return ftello(context->hidden.stdio.fp); + } +#else if (fseek(context->hidden.stdio.fp, offset, whence) == 0) { return (ftell(context->hidden.stdio.fp)); - } else { - SDL_Error(SDL_EFSEEK); - return (-1); } +#endif + SDL_Error(SDL_EFSEEK); + return (-1); } static size_t SDLCALL @@ -336,8 +378,14 @@ stdio_close(SDL_RWops * context) /* Functions to read/write memory pointers */ -static long SDLCALL -mem_seek(SDL_RWops * context, long offset, int whence) +static Sint64 SDLCALL +mem_size(SDL_RWops * context) +{ + return (Sint64)(context->hidden.mem.stop - context->hidden.mem.base); +} + +static Sint64 SDLCALL +mem_seek(SDL_RWops * context, Sint64 offset, int whence) { Uint8 *newpos; @@ -362,7 +410,7 @@ mem_seek(SDL_RWops * context, long offset, int whence) newpos = context->hidden.mem.stop; } context->hidden.mem.here = newpos; - return (long)(context->hidden.mem.here - context->hidden.mem.base); + return (Sint64)(context->hidden.mem.here - context->hidden.mem.base); } static size_t SDLCALL @@ -427,6 +475,32 @@ SDL_RWFromFile(const char *file, const char *mode) return NULL; } #if defined(ANDROID) +#ifdef HAVE_STDIO_H + /* Try to open the file on the filesystem first */ + if (*file == '/') { + FILE *fp = fopen(file, mode); + if (fp) { + return SDL_RWFromFP(fp, 1); + } + } else { + /* Try opening it from internal storage if it's a relative path */ + char *path; + FILE *fp; + + path = SDL_stack_alloc(char, PATH_MAX); + if (path) { + SDL_snprintf(path, PATH_MAX, "%s/%s", + SDL_AndroidGetInternalStoragePath(), file); + fp = fopen(path, mode); + SDL_stack_free(path); + if (fp) { + return SDL_RWFromFP(fp, 1); + } + } + } +#endif /* HAVE_STDIO_H */ + + /* Try to open the file from the asset system */ rwops = SDL_AllocRW(); if (!rwops) return NULL; /* SDL_SetError already setup by SDL_AllocRW() */ @@ -434,6 +508,7 @@ SDL_RWFromFile(const char *file, const char *mode) SDL_FreeRW(rwops); return NULL; } + rwops->size = Android_JNI_FileSize; rwops->seek = Android_JNI_FileSeek; rwops->read = Android_JNI_FileRead; rwops->write = Android_JNI_FileWrite; @@ -447,6 +522,7 @@ SDL_RWFromFile(const char *file, const char *mode) SDL_FreeRW(rwops); return NULL; } + rwops->size = windows_file_size; rwops->seek = windows_file_seek; rwops->read = windows_file_read; rwops->write = windows_file_write; @@ -490,6 +566,7 @@ SDL_RWFromFP(FILE * fp, SDL_bool autoclose) rwops = SDL_AllocRW(); if (rwops != NULL) { + rwops->size = stdio_size; rwops->seek = stdio_seek; rwops->read = stdio_read; rwops->write = stdio_write; @@ -515,6 +592,7 @@ SDL_RWFromMem(void *mem, int size) rwops = SDL_AllocRW(); if (rwops != NULL) { + rwops->size = mem_size; rwops->seek = mem_seek; rwops->read = mem_read; rwops->write = mem_write; @@ -533,6 +611,7 @@ SDL_RWFromConstMem(const void *mem, int size) rwops = SDL_AllocRW(); if (rwops != NULL) { + rwops->size = mem_size; rwops->seek = mem_seek; rwops->read = mem_read; rwops->write = mem_writeconst; diff --git a/src/stdlib/SDL_iconv.c b/src/stdlib/SDL_iconv.c index e67be619bd..89a80a2c74 100644 --- a/src/stdlib/SDL_iconv.c +++ b/src/stdlib/SDL_iconv.c @@ -87,15 +87,21 @@ enum ENCODING_UTF32, /* Needs byte order marker */ ENCODING_UTF32BE, ENCODING_UTF32LE, - ENCODING_UCS2, /* Native byte order assumed */ - ENCODING_UCS4, /* Native byte order assumed */ + ENCODING_UCS2BE, + ENCODING_UCS2LE, + ENCODING_UCS4BE, + ENCODING_UCS4LE, }; #if SDL_BYTEORDER == SDL_BIG_ENDIAN #define ENCODING_UTF16NATIVE ENCODING_UTF16BE #define ENCODING_UTF32NATIVE ENCODING_UTF32BE +#define ENCODING_UCS2NATIVE ENCODING_UCS2BE +#define ENCODING_UCS4NATIVE ENCODING_UCS4BE #else #define ENCODING_UTF16NATIVE ENCODING_UTF16LE #define ENCODING_UTF32NATIVE ENCODING_UTF32LE +#define ENCODING_UCS2NATIVE ENCODING_UCS2LE +#define ENCODING_UCS4NATIVE ENCODING_UCS4LE #endif struct _SDL_iconv_t @@ -128,10 +134,16 @@ static struct { "UTF-32BE", ENCODING_UTF32BE }, { "UTF32LE", ENCODING_UTF32LE }, { "UTF-32LE", ENCODING_UTF32LE }, - { "UCS2", ENCODING_UCS2 }, - { "UCS-2", ENCODING_UCS2 }, - { "UCS4", ENCODING_UCS4 }, - { "UCS-4", ENCODING_UCS4 }, + { "UCS2", ENCODING_UCS2BE }, + { "UCS-2", ENCODING_UCS2BE }, + { "UCS-2LE", ENCODING_UCS2LE }, + { "UCS-2BE", ENCODING_UCS2BE }, + { "UCS-2-INTERNAL", ENCODING_UCS2NATIVE }, + { "UCS4", ENCODING_UCS4BE }, + { "UCS-4", ENCODING_UCS4BE }, + { "UCS-4LE", ENCODING_UCS4LE }, + { "UCS-4BE", ENCODING_UCS4BE }, + { "UCS-4-INTERNAL", ENCODING_UCS4NATIVE }, /* *INDENT-ON* */ }; @@ -518,6 +530,29 @@ SDL_iconv(SDL_iconv_t cd, (Uint32) (W2 & 0x3FF)) + 0x10000; } break; + case ENCODING_UCS2LE: + { + Uint8 *p = (Uint8 *) src; + if (srclen < 2) { + return SDL_ICONV_EINVAL; + } + ch = ((Uint32) p[1] << 8) | (Uint32) p[0]; + src += 2; + srclen -= 2; + } + break; + case ENCODING_UCS2BE: + { + Uint8 *p = (Uint8 *) src; + if (srclen < 2) { + return SDL_ICONV_EINVAL; + } + ch = ((Uint32) p[0] << 8) | (Uint32) p[1]; + src += 2; + srclen -= 2; + } + break; + case ENCODING_UCS4BE: case ENCODING_UTF32BE: { Uint8 *p = (Uint8 *) src; @@ -531,6 +566,7 @@ SDL_iconv(SDL_iconv_t cd, srclen -= 4; } break; + case ENCODING_UCS4LE: case ENCODING_UTF32LE: { Uint8 *p = (Uint8 *) src; @@ -544,28 +580,6 @@ SDL_iconv(SDL_iconv_t cd, srclen -= 4; } break; - case ENCODING_UCS2: - { - Uint16 *p = (Uint16 *) src; - if (srclen < 2) { - return SDL_ICONV_EINVAL; - } - ch = *p; - src += 2; - srclen -= 2; - } - break; - case ENCODING_UCS4: - { - Uint32 *p = (Uint32 *) src; - if (srclen < 4) { - return SDL_ICONV_EINVAL; - } - ch = *p; - src += 4; - srclen -= 4; - } - break; } /* Encode a character */ @@ -728,64 +742,74 @@ SDL_iconv(SDL_iconv_t cd, } } break; - case ENCODING_UTF32BE: + case ENCODING_UCS2BE: { Uint8 *p = (Uint8 *) dst; - if (ch > 0x10FFFF) { + if (ch > 0xFFFF) { ch = UNKNOWN_UNICODE; } - if (dstlen < 4) { + if (dstlen < 2) { return SDL_ICONV_E2BIG; } - p[0] = (Uint8) (ch >> 24); - p[1] = (Uint8) (ch >> 16); - p[2] = (Uint8) (ch >> 8); - p[3] = (Uint8) ch; - dst += 4; - dstlen -= 4; + p[0] = (Uint8) (ch >> 8); + p[1] = (Uint8) ch; + dst += 2; + dstlen -= 2; } break; - case ENCODING_UTF32LE: + case ENCODING_UCS2LE: { Uint8 *p = (Uint8 *) dst; - if (ch > 0x10FFFF) { + if (ch > 0xFFFF) { ch = UNKNOWN_UNICODE; } - if (dstlen < 4) { + if (dstlen < 2) { return SDL_ICONV_E2BIG; } - p[3] = (Uint8) (ch >> 24); - p[2] = (Uint8) (ch >> 16); p[1] = (Uint8) (ch >> 8); p[0] = (Uint8) ch; - dst += 4; - dstlen -= 4; + dst += 2; + dstlen -= 2; } break; - case ENCODING_UCS2: + case ENCODING_UTF32BE: + if (ch > 0x10FFFF) { + ch = UNKNOWN_UNICODE; + } + case ENCODING_UCS4BE: + if (ch > 0x7FFFFFFF) { + ch = UNKNOWN_UNICODE; + } { - Uint16 *p = (Uint16 *) dst; - if (ch > 0xFFFF) { - ch = UNKNOWN_UNICODE; - } - if (dstlen < 2) { + Uint8 *p = (Uint8 *) dst; + if (dstlen < 4) { return SDL_ICONV_E2BIG; } - *p = (Uint16) ch; - dst += 2; - dstlen -= 2; + p[0] = (Uint8) (ch >> 24); + p[1] = (Uint8) (ch >> 16); + p[2] = (Uint8) (ch >> 8); + p[3] = (Uint8) ch; + dst += 4; + dstlen -= 4; } break; - case ENCODING_UCS4: + case ENCODING_UTF32LE: + if (ch > 0x10FFFF) { + ch = UNKNOWN_UNICODE; + } + case ENCODING_UCS4LE: + if (ch > 0x7FFFFFFF) { + ch = UNKNOWN_UNICODE; + } { - Uint32 *p = (Uint32 *) dst; - if (ch > 0x7FFFFFFF) { - ch = UNKNOWN_UNICODE; - } + Uint8 *p = (Uint8 *) dst; if (dstlen < 4) { return SDL_ICONV_E2BIG; } - *p = ch; + p[3] = (Uint8) (ch >> 24); + p[2] = (Uint8) (ch >> 16); + p[1] = (Uint8) (ch >> 8); + p[0] = (Uint8) ch; dst += 4; dstlen -= 4; } diff --git a/src/thread/pthread/SDL_systhread.c b/src/thread/pthread/SDL_systhread.c index 9ffb611c5a..fa07fbfa64 100644 --- a/src/thread/pthread/SDL_systhread.c +++ b/src/thread/pthread/SDL_systhread.c @@ -28,12 +28,19 @@ #endif #include <signal.h> + #ifdef __LINUX__ #include <sys/time.h> #include <sys/resource.h> #include <sys/syscall.h> #include <unistd.h> -extern int pthread_setname_np (pthread_t __target_thread, __const char *__name) __THROW __nonnull ((2)); +#endif // __LINUX__ + +#if defined(__LINUX__) || defined(__MACOSX__) || defined(__IPHONEOS__) +#include <dlfcn.h> +#ifndef RTLD_DEFAULT +#define RTLD_DEFAULT NULL +#endif #endif #include "SDL_platform.h" @@ -44,6 +51,8 @@ extern int pthread_setname_np (pthread_t __target_thread, __const char *__name) #include "../../core/android/SDL_android.h" #endif +#include "SDL_assert.h" + /* List of signals to mask in the subthreads */ static const int sig_list[] = { SIGHUP, SIGINT, SIGQUIT, SIGPIPE, SIGALRM, SIGTERM, SIGCHLD, SIGWINCH, @@ -61,11 +70,31 @@ RunThread(void *data) return NULL; } +#if defined(__MACOSX__) || defined(__IPHONEOS__) +static SDL_bool checked_setname = SDL_FALSE; +static int (*ppthread_setname_np)(const char*) = NULL; +#elif defined(__LINUX__) +static SDL_bool checked_setname = SDL_FALSE; +static int (*ppthread_setname_np)(pthread_t, const char*) = NULL; +#endif int SDL_SYS_CreateThread(SDL_Thread * thread, void *args) { pthread_attr_t type; + /* do this here before any threads exist, so there's no race condition. */ + #if defined(__MACOSX__) || defined(__IPHONEOS__) || defined(__LINUX__) + if (!checked_setname) { + void *fn = dlsym(RTLD_DEFAULT, "pthread_setname_np"); + #if defined(__MACOSX__) || defined(__IPHONEOS__) + ppthread_setname_np = (int(*)(const char*)) fn; + #elif defined(__LINUX__) + ppthread_setname_np = (int(*)(pthread_t, const char*)) fn; + #endif + checked_setname = SDL_TRUE; + } + #endif + /* Set the thread attributes */ if (pthread_attr_init(&type) != 0) { SDL_SetError("Couldn't initialize pthread attributes"); @@ -89,14 +118,20 @@ SDL_SYS_SetupThread(const char *name) sigset_t mask; if (name != NULL) { -#if ( (__MACOSX__ && (MAC_OS_X_VERSION_MAX_ALLOWED >= 1060)) || \ - (__IPHONEOS__ && (__IPHONE_OS_VERSION_MAX_ALLOWED >= 30200)) ) - if (pthread_setname_np != NULL) { pthread_setname_np(name); } -#elif HAVE_PTHREAD_SETNAME_NP - pthread_setname_np(pthread_self(), name); -#elif HAVE_PTHREAD_SET_NAME_NP - pthread_set_name_np(pthread_self(), name); -#endif + #if defined(__MACOSX__) || defined(__IPHONEOS__) || defined(__LINUX__) + SDL_assert(checked_setname); + if (ppthread_setname_np != NULL) { + #if defined(__MACOSX__) || defined(__IPHONEOS__) + ppthread_setname_np(name); + #elif defined(__LINUX__) + ppthread_setname_np(pthread_self(), name); + #endif + } + #elif HAVE_PTHREAD_SETNAME_NP + pthread_setname_np(pthread_self(), name); + #elif HAVE_PTHREAD_SET_NAME_NP + pthread_set_name_np(pthread_self(), name); + #endif } /* Mask asynchronous signals for this thread */ diff --git a/src/video/SDL_sysvideo.h b/src/video/SDL_sysvideo.h index 056173cd54..051ec82bc1 100644 --- a/src/video/SDL_sysvideo.h +++ b/src/video/SDL_sysvideo.h @@ -23,6 +23,7 @@ #ifndef _SDL_sysvideo_h #define _SDL_sysvideo_h +#include "SDL_messagebox.h" #include "SDL_shape.h" /* The SDL video driver */ @@ -246,6 +247,9 @@ struct SDL_VideoDevice char * (*GetClipboardText) (_THIS); SDL_bool (*HasClipboardText) (_THIS); + /* MessageBox */ + int (*ShowMessageBox) (_THIS, const SDL_MessageBoxData *messageboxdata, int *buttonid); + /* * * */ /* Data common to all drivers */ SDL_bool suspend_screensaver; diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c index 6198a0cdbc..a353583b3a 100644 --- a/src/video/SDL_video.c +++ b/src/video/SDL_video.c @@ -1171,7 +1171,9 @@ SDL_CreateWindow(const char *title, int x, int y, int w, int h, Uint32 flags) SDL_SetError("No OpenGL support in video driver"); return NULL; } - SDL_GL_LoadLibrary(NULL); + if (SDL_GL_LoadLibrary(NULL) < 0) { + return NULL; + } } window = (SDL_Window *)SDL_calloc(1, sizeof(*window)); window->magic = &_this->window_magic; @@ -2842,4 +2844,79 @@ SDL_IsScreenKeyboardShown(SDL_Window *window) return SDL_FALSE; } +#if SDL_VIDEO_DRIVER_WINDOWS +#include "windows/SDL_windowsmessagebox.h" +#endif +#if SDL_VIDEO_DRIVER_COCOA +#include "cocoa/SDL_cocoamessagebox.h" +#endif +#if SDL_VIDEO_DRIVER_UIKIT +#include "uikit/SDL_uikitmessagebox.h" +#endif +#if SDL_VIDEO_DRIVER_X11 +#include "x11/SDL_x11messagebox.h" +#endif + +int +SDL_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid) +{ + int dummybutton; + + if (!buttonid) { + buttonid = &dummybutton; + } + if (_this && _this->ShowMessageBox) { + if (_this->ShowMessageBox(_this, messageboxdata, buttonid) == 0) { + return 0; + } + } + + /* It's completely fine to call this function before video is initialized */ +#if SDL_VIDEO_DRIVER_WINDOWS + if (WIN_ShowMessageBox(messageboxdata, buttonid) == 0) { + return 0; + } +#endif +#if SDL_VIDEO_DRIVER_COCOA + if (Cocoa_ShowMessageBox(messageboxdata, buttonid) == 0) { + return 0; + } +#endif +#if SDL_VIDEO_DRIVER_UIKIT + if (UIKit_ShowMessageBox(messageboxdata, buttonid) == 0) { + return 0; + } +#endif +#if SDL_VIDEO_DRIVER_X11 + if (X11_ShowMessageBox(messageboxdata, buttonid) == 0) { + return 0; + } +#endif + + SDL_SetError("No message system available"); + return -1; +} + +int +SDL_ShowSimpleMessageBox(Uint32 flags, const char *title, const char *message, SDL_Window *window) +{ + SDL_MessageBoxData data; + SDL_MessageBoxButtonData button; + + SDL_zero(data); + data.flags = flags; + data.title = title; + data.message = message; + data.numbuttons = 1; + data.buttons = &button; + data.window = window; + + SDL_zero(button); + button.flags |= SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT; + button.flags |= SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT; + button.text = "OK"; + + return SDL_ShowMessageBox(&data, NULL); +} + /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/cocoa/SDL_cocoaevents.m b/src/video/cocoa/SDL_cocoaevents.m index cf90d5dcb4..0c42828f15 100644 --- a/src/video/cocoa/SDL_cocoaevents.m +++ b/src/video/cocoa/SDL_cocoaevents.m @@ -156,6 +156,7 @@ CreateApplicationMenus(void) void Cocoa_RegisterApp(void) { + /* This can get called more than once! Be careful what you initialize! */ ProcessSerialNumber psn; NSAutoreleasePool *pool; diff --git a/src/video/cocoa/SDL_cocoamessagebox.h b/src/video/cocoa/SDL_cocoamessagebox.h new file mode 100644 index 0000000000..4d639060fe --- /dev/null +++ b/src/video/cocoa/SDL_cocoamessagebox.h @@ -0,0 +1,29 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_config.h" + +#if SDL_VIDEO_DRIVER_COCOA + +extern int Cocoa_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid); + +#endif /* SDL_VIDEO_DRIVER_COCOA */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/cocoa/SDL_cocoamessagebox.m b/src/video/cocoa/SDL_cocoamessagebox.m new file mode 100644 index 0000000000..7a30d5047f --- /dev/null +++ b/src/video/cocoa/SDL_cocoamessagebox.m @@ -0,0 +1,81 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_config.h" + +#if SDL_VIDEO_DRIVER_COCOA + +#if defined(__APPLE__) && defined(__POWERPC__) +#include <altivec.h> +#undef bool +#undef vector +#undef pixel +#endif + +#include "SDL_messagebox.h" +#include "SDL_cocoavideo.h" + + +/* Display a Cocoa message box */ +int +Cocoa_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid) +{ + Cocoa_RegisterApp(); + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + NSAlert* alert = [[NSAlert alloc] init]; + + if (messageboxdata->flags & SDL_MESSAGEBOX_ERROR) { + [alert setAlertStyle:NSCriticalAlertStyle]; + } else if (messageboxdata->flags & SDL_MESSAGEBOX_WARNING) { + [alert setAlertStyle:NSWarningAlertStyle]; + } else { + [alert setAlertStyle:NSInformationalAlertStyle]; + } + + [alert setMessageText:[[NSString alloc] initWithUTF8String:messageboxdata->title]]; + [alert setInformativeText:[[NSString alloc] initWithUTF8String:messageboxdata->message]]; + + const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons; + int i; + for (i = 0; i < messageboxdata->numbuttons; ++i) { + NSButton *button = [alert addButtonWithTitle:[[NSString alloc] initWithUTF8String:buttons[i].text]]; + if (buttons[i].flags & SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT) { + [button setKeyEquivalent:@"\r"]; + } else if (buttons[i].flags & SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT) { + [button setKeyEquivalent:@"\033"]; + } else { + [button setKeyEquivalent:@""]; + } + } + + NSInteger clicked = [alert runModal]; + clicked -= NSAlertFirstButtonReturn; + *buttonid = buttons[clicked].buttonid; + + [pool release]; + + return 0; +} + +#endif /* SDL_VIDEO_DRIVER_COCOA */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/cocoa/SDL_cocoavideo.m b/src/video/cocoa/SDL_cocoavideo.m index a38de1e093..4ada3b9858 100644 --- a/src/video/cocoa/SDL_cocoavideo.m +++ b/src/video/cocoa/SDL_cocoavideo.m @@ -26,6 +26,7 @@ #include <altivec.h> #undef bool #undef vector +#undef pixel #endif #include "SDL.h" @@ -218,6 +219,22 @@ Cocoa_CreateImage(SDL_Surface * surface) } /* + * Mac OS X log support. + * + * This doesn't really have aything to do with the interfaces of the SDL video + * subsystem, but we need to stuff this into an Objective-C source code file. + */ + +void SDL_NSLog(const char *text) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + NSLog(@"%@", [[NSString alloc] initWithUTF8String:text]); + + [pool release]; +} + +/* * Mac OS X assertion support. * * This doesn't really have aything to do with the interfaces of the SDL video diff --git a/src/video/uikit/SDL_uikitmessagebox.h b/src/video/uikit/SDL_uikitmessagebox.h new file mode 100644 index 0000000000..2fd3fc145f --- /dev/null +++ b/src/video/uikit/SDL_uikitmessagebox.h @@ -0,0 +1,29 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_config.h" + +#if SDL_VIDEO_DRIVER_UIKIT + +extern int UIKit_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid); + +#endif /* SDL_VIDEO_DRIVER_UIKIT */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/uikit/SDL_uikitmessagebox.m b/src/video/uikit/SDL_uikitmessagebox.m new file mode 100644 index 0000000000..6da90a1768 --- /dev/null +++ b/src/video/uikit/SDL_uikitmessagebox.m @@ -0,0 +1,101 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_config.h" + +#if SDL_VIDEO_DRIVER_UIKIT + +#include "SDL.h" +#include "SDL_uikitvideo.h" + + +/* Display a UIKit message box */ + + +@interface UIKit_UIAlertViewDelegate : NSObject <UIAlertViewDelegate> { +@private + int *clickedButtonIndex; +} + +- (id)initWithButtonIndex:(int *)_buttonIndex; +- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex; + +@end + +@implementation UIKit_UIAlertViewDelegate + +- (id)initWithButtonIndex:(int *)buttonIndex +{ + self = [self init]; + if (self == nil) { + return nil; + } + self->clickedButtonIndex = buttonIndex; + + return self; +} + +- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex; +{ + *clickedButtonIndex = buttonIndex; +} + +@end // UIKit_UIAlertViewDelegate + + +int +UIKit_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid) +{ + int clicked; + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + UIAlertView* alert = [[UIAlertView alloc] init]; + + alert.title = [[NSString alloc] initWithUTF8String:messageboxdata->title]; + alert.message = [[NSString alloc] initWithUTF8String:messageboxdata->message]; + alert.delegate = [[UIKit_UIAlertViewDelegate alloc] initWithButtonIndex:&clicked]; + + const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons; + int i; + for (i = 0; i < messageboxdata->numbuttons; ++i) { + [alert addButtonWithTitle:[[NSString alloc] initWithUTF8String:buttons[i].text]]; + } + + // Set up for showing the alert + clicked = messageboxdata->numbuttons; + + [alert show]; + + // Run the main event loop until the alert has finished + // Note that this needs to be done on the main thread + while (clicked == messageboxdata->numbuttons) { + [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; + } + *buttonid = messageboxdata->buttons[clicked].buttonid; + + [pool release]; + + return 0; +} + +#endif /* SDL_VIDEO_DRIVER_UIKIT */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/uikit/SDL_uikitvideo.m b/src/video/uikit/SDL_uikitvideo.m index 06b410cd9c..58f32787f5 100644 --- a/src/video/uikit/SDL_uikitvideo.m +++ b/src/video/uikit/SDL_uikitvideo.m @@ -129,6 +129,22 @@ UIKit_VideoQuit(_THIS) UIKit_QuitModes(_this); } +/* + * iOS log support. + * + * This doesn't really have aything to do with the interfaces of the SDL video + * subsystem, but we need to stuff this into an Objective-C source code file. + */ + +void SDL_NSLog(const char *text) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + NSLog(@"%@", [[NSString alloc] initWithUTF8String:text]); + + [pool release]; +} + #endif /* SDL_VIDEO_DRIVER_UIKIT */ /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/uikit/SDL_uikitview.h b/src/video/uikit/SDL_uikitview.h index 20e330745d..c60830ab1f 100644 --- a/src/video/uikit/SDL_uikitview.h +++ b/src/video/uikit/SDL_uikitview.h @@ -22,8 +22,9 @@ #import <UIKit/UIKit.h> #import "SDL_uikitviewcontroller.h" +#include "SDL_touch.h" + #define IPHONE_TOUCH_EFFICIENT_DANGEROUS -#define FIXED_MULTITOUCH #ifndef IPHONE_TOUCH_EFFICIENT_DANGEROUS #define MAX_SIMULTANEOUS_TOUCHES 5 @@ -35,12 +36,11 @@ @interface SDL_uikitview : UIView { #endif -#ifdef FIXED_MULTITOUCH - long touchId; + SDL_TouchID touchId; + SDL_FingerID leftFingerDown; #ifndef IPHONE_TOUCH_EFFICIENT_DANGEROUS UITouch *finger[MAX_SIMULTANEOUS_TOUCHES]; #endif -#endif #if SDL_IPHONE_KEYBOARD UITextField *textField; diff --git a/src/video/uikit/SDL_uikitview.m b/src/video/uikit/SDL_uikitview.m index 801acd7196..a54cc501d9 100644 --- a/src/video/uikit/SDL_uikitview.m +++ b/src/video/uikit/SDL_uikitview.m @@ -50,7 +50,6 @@ [self initializeKeyboard]; #endif -#ifdef FIXED_MULTITOUCH self.multipleTouchEnabled = YES; SDL_Touch touch; @@ -69,9 +68,7 @@ touch.pressure_max = 1; touch.native_pressureres = touch.pressure_max - touch.pressure_min; - touchId = SDL_AddTouch(&touch, "IPHONE SCREEN"); -#endif return self; @@ -102,25 +99,25 @@ NSEnumerator *enumerator = [touches objectEnumerator]; UITouch *touch = (UITouch*)[enumerator nextObject]; - if (touch) { - CGPoint locationInView = [self touchLocation:touch shouldNormalize:NO]; + while (touch) { + if (!leftFingerDown) { + CGPoint locationInView = [self touchLocation:touch shouldNormalize:NO]; - /* send moved event */ - SDL_SendMouseMotion(NULL, 0, locationInView.x, locationInView.y); + /* send moved event */ + SDL_SendMouseMotion(NULL, 0, locationInView.x, locationInView.y); - /* send mouse down event */ - SDL_SendMouseButton(NULL, SDL_PRESSED, SDL_BUTTON_LEFT); - } + /* send mouse down event */ + SDL_SendMouseButton(NULL, SDL_PRESSED, SDL_BUTTON_LEFT); -#ifdef FIXED_MULTITOUCH - while(touch) { - CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES]; + leftFingerDown = (SDL_FingerID)touch; + } + CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES]; #ifdef IPHONE_TOUCH_EFFICIENT_DANGEROUS - //FIXME: TODO: Using touch as the fingerId is potentially dangerous - //It is also much more efficient than storing the UITouch pointer - //and comparing it to the incoming event. - SDL_SendFingerDown(touchId, (long)touch, + // FIXME: TODO: Using touch as the fingerId is potentially dangerous + // It is also much more efficient than storing the UITouch pointer + // and comparing it to the incoming event. + SDL_SendFingerDown(touchId, (SDL_FingerID)touch, SDL_TRUE, locationInView.x, locationInView.y, 1); #else @@ -135,10 +132,8 @@ } } #endif - touch = (UITouch*)[enumerator nextObject]; } -#endif } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event @@ -146,15 +141,14 @@ NSEnumerator *enumerator = [touches objectEnumerator]; UITouch *touch = (UITouch*)[enumerator nextObject]; - if (touch) { - /* send mouse up */ - SDL_SendMouseButton(NULL, SDL_RELEASED, SDL_BUTTON_LEFT); - } - -#ifdef FIXED_MULTITOUCH while(touch) { - CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES]; + if ((SDL_FingerID)touch == leftFingerDown) { + /* send mouse up */ + SDL_SendMouseButton(NULL, SDL_RELEASED, SDL_BUTTON_LEFT); + leftFingerDown = 0; + } + CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES]; #ifdef IPHONE_TOUCH_EFFICIENT_DANGEROUS SDL_SendFingerDown(touchId, (long)touch, SDL_FALSE, locationInView.x, locationInView.y, @@ -171,10 +165,8 @@ } } #endif - touch = (UITouch*)[enumerator nextObject]; } -#endif } - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event @@ -192,17 +184,15 @@ NSEnumerator *enumerator = [touches objectEnumerator]; UITouch *touch = (UITouch*)[enumerator nextObject]; - if (touch) { - CGPoint locationInView = [self touchLocation:touch shouldNormalize:NO]; + while (touch) { + if ((SDL_FingerID)touch == leftFingerDown) { + CGPoint locationInView = [self touchLocation:touch shouldNormalize:NO]; - /* send moved event */ - SDL_SendMouseMotion(NULL, 0, locationInView.x, locationInView.y); - } + /* send moved event */ + SDL_SendMouseMotion(NULL, 0, locationInView.x, locationInView.y); + } -#ifdef FIXED_MULTITOUCH - while(touch) { CGPoint locationInView = [self touchLocation:touch shouldNormalize:YES]; - #ifdef IPHONE_TOUCH_EFFICIENT_DANGEROUS SDL_SendTouchMotion(touchId, (long)touch, SDL_FALSE, locationInView.x, locationInView.y, @@ -218,10 +208,8 @@ } } #endif - touch = (UITouch*)[enumerator nextObject]; } -#endif } /* diff --git a/src/video/windows/SDL_windowsmessagebox.c b/src/video/windows/SDL_windowsmessagebox.c new file mode 100644 index 0000000000..bb5eaaf245 --- /dev/null +++ b/src/video/windows/SDL_windowsmessagebox.c @@ -0,0 +1,282 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_config.h" + +#if SDL_VIDEO_DRIVER_WINDOWS + +#include "SDL.h" +#include "SDL_windowsvideo.h" + + +/* Display a Windows message box */ + +typedef struct +{ + LPDLGTEMPLATE lpDialog; + Uint8 *data; + size_t size; + size_t used; +} WIN_DialogData; + + +static INT_PTR MessageBoxDialogProc(HWND hDlg, UINT iMessage, WPARAM wParam, LPARAM lParam) +{ + switch ( iMessage ) { + case WM_COMMAND: + /* Return the ID of the button that was pushed */ + EndDialog(hDlg, LOWORD(wParam)); + return TRUE; + + default: + break; + } + return FALSE; +} + +static SDL_bool ExpandDialogSpace(WIN_DialogData *dialog, size_t space) +{ + size_t size = dialog->size; + + if (size == 0) { + size = space; + } else { + while ((dialog->used + space) > size) { + size *= 2; + } + } + if (size > dialog->size) { + void *data = SDL_realloc(dialog->data, size); + if (!data) { + SDL_OutOfMemory(); + return SDL_FALSE; + } + dialog->data = data; + dialog->size = size; + dialog->lpDialog = (LPDLGTEMPLATE)dialog->data; + } + return SDL_TRUE; +} + +static SDL_bool AlignDialogData(WIN_DialogData *dialog, size_t size) +{ + size_t padding = (dialog->used % size); + + if (!ExpandDialogSpace(dialog, padding)) { + return SDL_FALSE; + } + + dialog->used += padding; + + return SDL_TRUE; +} + +static SDL_bool AddDialogData(WIN_DialogData *dialog, const void *data, size_t size) +{ + if (!ExpandDialogSpace(dialog, size)) { + return SDL_FALSE; + } + + SDL_memcpy(dialog->data+dialog->used, data, size); + dialog->used += size; + + return SDL_TRUE; +} + +static SDL_bool AddDialogString(WIN_DialogData *dialog, const char *string) +{ + WCHAR *wstring; + WCHAR *p; + size_t count; + SDL_bool status; + + if (!string) { + string = ""; + } + + wstring = WIN_UTF8ToString(string); + if (!wstring) { + return SDL_FALSE; + } + + /* Find out how many characters we have, including null terminator */ + count = 0; + for (p = wstring; *p; ++p) { + ++count; + } + ++count; + + status = AddDialogData(dialog, wstring, count*sizeof(WCHAR)); + SDL_free(wstring); + return status; +} + +static SDL_bool AddDialogControl(WIN_DialogData *dialog, WORD type, DWORD style, DWORD exStyle, int x, int y, int w, int h, int id, const char *caption) +{ + DLGITEMTEMPLATE item; + WORD marker = 0xFFFF; + WORD extraData = 0; + + SDL_zero(item); + item.style = style; + item.dwExtendedStyle = exStyle; + item.x = x; + item.y = y; + item.cx = w; + item.cy = h; + item.id = id; + + if (!AlignDialogData(dialog, sizeof(DWORD))) { + return SDL_FALSE; + } + if (!AddDialogData(dialog, &item, sizeof(item))) { + return SDL_FALSE; + } + if (!AddDialogData(dialog, &marker, sizeof(marker))) { + return SDL_FALSE; + } + if (!AddDialogData(dialog, &type, sizeof(type))) { + return SDL_FALSE; + } + if (!AddDialogString(dialog, caption)) { + return SDL_FALSE; + } + if (!AddDialogData(dialog, &extraData, sizeof(extraData))) { + return SDL_FALSE; + } + ++dialog->lpDialog->cdit; + + return SDL_TRUE; +} + +static SDL_bool AddDialogStatic(WIN_DialogData *dialog, int x, int y, int w, int h, const char *text) +{ + DWORD style = WS_VISIBLE | WS_CHILD | SS_LEFT | SS_NOPREFIX; + return AddDialogControl(dialog, 0x0082, style, 0, x, y, w, h, -1, text); +} + +static SDL_bool AddDialogButton(WIN_DialogData *dialog, int x, int y, int w, int h, const char *text, int id, SDL_bool isDefault) +{ + DWORD style = WS_VISIBLE | WS_CHILD; + if (isDefault) { + style |= BS_DEFPUSHBUTTON; + } else { + style |= BS_PUSHBUTTON; + } + return AddDialogControl(dialog, 0x0080, style, 0, x, y, w, h, id, text); +} + +static void FreeDialogData(WIN_DialogData *dialog) +{ + if (dialog->data) { + SDL_free(dialog->data); + } + SDL_free(dialog); +} + +static WIN_DialogData *CreateDialogData(int w, int h, const char *caption) +{ + WIN_DialogData *dialog; + DLGTEMPLATE dialogTemplate; + + SDL_zero(dialogTemplate); + dialogTemplate.style = (WS_CAPTION | DS_CENTER); + dialogTemplate.x = 0; + dialogTemplate.y = 0; + dialogTemplate.cx = w; + dialogTemplate.cy = h; + + dialog = (WIN_DialogData *)SDL_calloc(1, sizeof(*dialog)); + if (!dialog) { + return NULL; + } + + if (!AddDialogData(dialog, &dialogTemplate, sizeof(dialogTemplate))) { + FreeDialogData(dialog); + return NULL; + } + + /* There is no menu or special class */ + if (!AddDialogString(dialog, "") || !AddDialogString(dialog, "")) { + FreeDialogData(dialog); + return NULL; + } + + if (!AddDialogString(dialog, caption)) { + FreeDialogData(dialog); + return NULL; + } + + return dialog; +} + +int +WIN_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid) +{ + WIN_DialogData *dialog; + int i, x, y, w, h, gap, which; + const SDL_MessageBoxButtonData *buttons = messageboxdata->buttons; + + /* FIXME: Need a better algorithm for laying out the message box */ + + dialog = CreateDialogData(570, 260, messageboxdata->title); + if (!dialog) { + return -1; + } + + w = 100; + h = 25; + gap = 10; + x = gap; + y = 50; + + if (!AddDialogStatic(dialog, x, y, 550, 100, messageboxdata->message)) { + FreeDialogData(dialog); + return -1; + } + + y += 110; + + for (i = 0; i < messageboxdata->numbuttons; ++i) { + SDL_bool isDefault; + + if (buttons[i].flags & SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT) { + isDefault = SDL_TRUE; + } else { + isDefault = SDL_FALSE; + } + if (!AddDialogButton(dialog, x, y, w, h, buttons[i].text, i, isDefault)) { + FreeDialogData(dialog); + return -1; + } + x += w + gap; + } + + /* FIXME: If we have a parent window, get the Instance and HWND for them */ + which = DialogBoxIndirect(NULL, dialog->lpDialog, NULL, (DLGPROC)MessageBoxDialogProc); + *buttonid = buttons[which].buttonid; + + FreeDialogData(dialog); + return 0; +} + +#endif /* SDL_VIDEO_DRIVER_WINDOWS */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/windows/SDL_windowsmessagebox.h b/src/video/windows/SDL_windowsmessagebox.h new file mode 100644 index 0000000000..29c3eb850a --- /dev/null +++ b/src/video/windows/SDL_windowsmessagebox.h @@ -0,0 +1,29 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_config.h" + +#if SDL_VIDEO_DRIVER_WINDOWS + +extern int WIN_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid); + +#endif /* SDL_VIDEO_DRIVER_WINDOWS */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index 26b1e00626..cfae4bcaac 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -386,10 +386,35 @@ X11_DispatchEvent(_THIS) /* Have we been requested to quit (or another client message?) */ case ClientMessage:{ - if ((xevent.xclient.format == 32) && + if ((xevent.xclient.message_type == videodata->WM_PROTOCOLS) && + (xevent.xclient.format == 32) && + (xevent.xclient.data.l[0] == videodata->_NET_WM_PING)) { + + SDL_DisplayData *dpydata; + Window root; + +#ifdef DEBUG_XEVENTS + printf("window %p: _NET_WM_PING\n", data); +#endif + + dpydata = (SDL_DisplayData *) + SDL_GetDisplayForWindow(data->window); + root = RootWindow(display, dpydata->screen); + xevent.xclient.window = root; + XSendEvent(display, root, False, SubstructureRedirectMask | SubstructureNotifyMask, &xevent); + break; + } + + else if ((xevent.xclient.message_type == videodata->WM_PROTOCOLS) && + (xevent.xclient.format == 32) && (xevent.xclient.data.l[0] == videodata->WM_DELETE_WINDOW)) { +#ifdef DEBUG_XEVENTS + printf("window %p: WM_DELETE_WINDOW\n", data); +#endif + SDL_SendWindowEvent(data->window, SDL_WINDOWEVENT_CLOSE, 0, 0); + break; } } break; diff --git a/src/video/x11/SDL_x11messagebox.c b/src/video/x11/SDL_x11messagebox.c new file mode 100644 index 0000000000..7b1956145a --- /dev/null +++ b/src/video/x11/SDL_x11messagebox.c @@ -0,0 +1,642 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ +#include "SDL_config.h" + +#if SDL_VIDEO_DRIVER_X11 + +#include "SDL.h" +#include "SDL_x11video.h" +#include "SDL_x11dyn.h" + +#define MAX_BUTTONS 8 /* Maximum number of buttons supported */ +#define MAX_TEXT_LINES 32 /* Maximum number of text lines supported */ +#define MIN_BUTTON_WIDTH 64 /* Minimum button width */ +#define MIN_DIALOG_WIDTH 200 /* Minimum dialog width */ +#define MIN_DIALOG_HEIGHT 100 /* Minimum dialog height */ + +static const char g_MessageBoxFont[] = "-*-*-medium-r-normal--0-120-*-*-p-0-iso8859-1"; + +static const SDL_MessageBoxColor g_default_colors[ SDL_MESSAGEBOX_COLOR_MAX ] = +{ + { 56, 54, 53 }, // SDL_MESSAGEBOX_COLOR_BACKGROUND, + { 209, 207, 205 }, // SDL_MESSAGEBOX_COLOR_TEXT, + { 140, 135, 129 }, // SDL_MESSAGEBOX_COLOR_BUTTON_BORDER, + { 105, 102, 99 }, // SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND, + { 205, 202, 53 }, // SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED, +}; + +#define SDL_MAKE_RGB( _r, _g, _b ) ( ( ( Uint32 )( _r ) << 16 ) | \ + ( ( Uint32 )( _g ) << 8 ) | \ + ( ( Uint32 )( _b ) ) ) + +typedef struct SDL_MessageBoxButtonDataX11 +{ + int x, y; /* Text position */ + int length; /* Text length */ + int text_width; /* Text width */ + + SDL_Rect rect; /* Rectangle for entire button */ + + const SDL_MessageBoxButtonData *buttondata; /* Button data from caller */ +} SDL_MessageBoxButtonDataX11; + +typedef struct TextLineData +{ + int width; /* Width of this text line */ + int length; /* String length of this text line */ + const char *text; /* Text for this line */ +} TextLineData; + +typedef struct SDL_MessageBoxDataX11 +{ + Font hfont; + Window window; + Display *display; + long event_mask; + Atom wm_protocols; + Atom wm_delete_message; + + int dialog_width; /* Dialog box width. */ + int dialog_height; /* Dialog box height. */ + + int xtext, ytext; /* Text position to start drawing at. */ + int numlines; /* Count of Text lines. */ + int text_height; /* Height for text lines. */ + TextLineData linedata[ MAX_TEXT_LINES ]; + + int *pbuttonid; /* Pointer to user return buttonid value. */ + + int button_press_index; /* Index into buttondata/buttonpos for button which is pressed (or -1). */ + int mouse_over_index; /* Index into buttondata/buttonpos for button mouse is over (or -1). */ + + int numbuttons; /* Count of buttons. */ + const SDL_MessageBoxButtonData *buttondata; + SDL_MessageBoxButtonDataX11 buttonpos[ MAX_BUTTONS ]; + + Uint32 color[ SDL_MESSAGEBOX_COLOR_MAX ]; + + const SDL_MessageBoxData *messageboxdata; +} SDL_MessageBoxDataX11; + +/* Maximum helper for ints. */ +static __inline__ int +IntMax( int a, int b ) +{ + return ( a > b ) ? a : b; +} + +/* Return width and height for a string. */ +static void +GetTextWidthHeight( XFontStruct *font_struct, const char *str, int nchars, int *pwidth, int *pheight ) +{ + XCharStruct text_structure; + int font_direction, font_ascent, font_descent; + + XTextExtents( font_struct, str, nchars, + &font_direction, &font_ascent, &font_descent, + &text_structure ); + + *pwidth = text_structure.width; + *pheight = text_structure.ascent + text_structure.descent; +} + +/* Return index of button if position x,y is contained therein. */ +static int +GetHitButtonIndex( SDL_MessageBoxDataX11 *data, int x, int y ) +{ + int i; + int numbuttons = data->numbuttons; + SDL_MessageBoxButtonDataX11 *buttonpos = data->buttonpos; + + for ( i = 0; i < numbuttons; i++ ) + { + SDL_Rect *rect = &buttonpos[ i ].rect; + + if ( ( x >= rect->x ) && + ( x <= ( rect->x + rect->w ) ) && + ( y >= rect->y ) && + ( y <= ( rect->y + rect->h ) ) ) + { + return i; + } + } + + return -1; +} + +/* Initialize SDL_MessageBoxData structure and Display, etc. */ +static int +X11_MessageBoxInit( SDL_MessageBoxDataX11 *data, const SDL_MessageBoxData * messageboxdata, int * pbuttonid ) +{ + int i; + int numbuttons = messageboxdata->numbuttons; + const SDL_MessageBoxButtonData *buttondata = messageboxdata->buttons; + const SDL_MessageBoxColor *colorhints; + + if ( numbuttons > MAX_BUTTONS ) { + SDL_SetError("Too many buttons (%d max allowed)", MAX_BUTTONS); + return -1; + } + + data->dialog_width = MIN_DIALOG_WIDTH; + data->dialog_height = MIN_DIALOG_HEIGHT; + data->messageboxdata = messageboxdata; + data->buttondata = buttondata; + data->numbuttons = numbuttons; + data->pbuttonid = pbuttonid; + + data->display = XOpenDisplay( NULL ); + if ( !data->display ) { + SDL_SetError("Couldn't open X11 display"); + return -1; + } + + data->hfont = XLoadFont( data->display, g_MessageBoxFont ); + if ( data->hfont == None ) { + SDL_SetError("Couldn't load font %s", g_MessageBoxFont); + return -1; + } + + if ( messageboxdata->colorScheme ) { + colorhints = messageboxdata->colorScheme->colors; + } else { + colorhints = g_default_colors; + } + + /* Convert our SDL_MessageBoxColor r,g,b values to packed RGB format. */ + for ( i = 0; i < SDL_MESSAGEBOX_COLOR_MAX; i++ ) { + data->color[ i ] = SDL_MAKE_RGB( colorhints[ i ].r, colorhints[ i ].g, colorhints[ i ].b ); + } + + return 0; +} + +/* Calculate and initialize text and button locations. */ +static int +X11_MessageBoxInitPositions( SDL_MessageBoxDataX11 *data ) +{ + int i; + int ybuttons; + int text_width_max = 0; + int button_text_height = 0; + int button_width = MIN_BUTTON_WIDTH; + const SDL_MessageBoxData *messageboxdata = data->messageboxdata; + + XFontStruct *fontinfo = XQueryFont( data->display, data->hfont ); + if ( !fontinfo ) { + SDL_SetError("Couldn't get font info"); + return -1; + } + + /* Go over text and break linefeeds into separate lines. */ + if ( messageboxdata->message && messageboxdata->message[ 0 ] ) + { + const char *text = messageboxdata->message; + TextLineData *plinedata = data->linedata; + + for ( i = 0; i < MAX_TEXT_LINES; i++, plinedata++ ) + { + int height; + char *lf = SDL_strchr( ( char * )text, '\n' ); + + data->numlines++; + + /* Only grab length up to lf if it exists and isn't the last line. */ + plinedata->length = ( lf && ( i < MAX_TEXT_LINES - 1 ) ) ? ( lf - text ) : SDL_strlen( text ); + plinedata->text = text; + + GetTextWidthHeight( fontinfo, text, plinedata->length, &plinedata->width, &height ); + + /* Text and widths are the largest we've ever seen. */ + data->text_height = IntMax( data->text_height, height ); + text_width_max = IntMax( text_width_max, plinedata->width ); + + text += plinedata->length + 1; + + /* Break if there are no more linefeeds. */ + if ( !lf ) + break; + } + + /* Bump up the text height slightly. */ + data->text_height += 2; + } + + /* Loop through all buttons and calculate the button widths and height. */ + for ( i = 0; i < data->numbuttons; i++ ) + { + int height; + + data->buttonpos[ i ].buttondata = &data->buttondata[ i ]; + data->buttonpos[ i ].length = SDL_strlen( data->buttondata[ i ].text ); + + GetTextWidthHeight( fontinfo, data->buttondata[ i ].text, SDL_strlen( data->buttondata[ i ].text ), + &data->buttonpos[ i ].text_width, &height ); + + button_width = IntMax( button_width, data->buttonpos[ i ].text_width ); + button_text_height = IntMax( button_text_height, height ); + } + + if ( data->numlines ) + { + /* x,y for this line of text. */ + data->xtext = data->text_height; + data->ytext = data->text_height + data->text_height; + + /* Bump button y down to bottom of text. */ + ybuttons = 3 * data->ytext / 2 + ( data->numlines - 1 ) * data->text_height; + + /* Bump the dialog box width and height up if needed. */ + data->dialog_width = IntMax( data->dialog_width, 2 * data->xtext + text_width_max ); + data->dialog_height = IntMax( data->dialog_height, ybuttons ); + } + else + { + /* Button y starts at height of button text. */ + ybuttons = button_text_height; + } + + if ( data->numbuttons ) + { + int x, y; + int width_of_buttons; + int button_spacing = button_text_height; + int button_height = 2 * button_text_height; + + /* Bump button width up a bit. */ + button_width += button_text_height; + + /* Get width of all buttons lined up. */ + width_of_buttons = data->numbuttons * button_width + ( data->numbuttons - 1 ) * button_spacing; + + /* Bump up dialog width and height if buttons are wider than text. */ + data->dialog_width = IntMax( data->dialog_width, width_of_buttons + 2 * button_spacing ); + data->dialog_height = IntMax( data->dialog_height, ybuttons + 2 * button_height ); + + /* Location for first button. */ + x = ( data->dialog_width - width_of_buttons ) / 2; + y = ybuttons + ( data->dialog_height - ybuttons - button_height ) / 2; + + for ( i = 0; i < data->numbuttons; i++ ) + { + /* Button coordinates. */ + data->buttonpos[ i ].rect.x = x; + data->buttonpos[ i ].rect.y = y; + data->buttonpos[ i ].rect.w = button_width; + data->buttonpos[ i ].rect.h = button_height; + + /* Button text coordinates. */ + data->buttonpos[ i ].x = x + ( button_width - data->buttonpos[ i ].text_width ) / 2; + data->buttonpos[ i ].y = y + ( button_height - button_text_height - 1 ) / 2 + button_text_height; + + /* Scoot over for next button. */ + x += button_width + button_spacing; + } + } + + XFreeFontInfo( NULL, fontinfo, 1 ); + return 0; +} + +/* Free SDL_MessageBoxData data. */ +static void +X11_MessageBoxShutdown( SDL_MessageBoxDataX11 *data ) +{ + if ( data->hfont != None ) + { + XUnloadFont( data->display, data->hfont ); + data->hfont = None; + } + + if ( data->display ) + { + if ( data->window != None ) + { + XUnmapWindow( data->display, data->window ); + XDestroyWindow( data->display, data->window ); + data->window = None; + } + + XCloseDisplay( data->display ); + data->display = NULL; + } +} + +/* Create and set up our X11 dialog box indow. */ +static int +X11_MessageBoxCreateWindow( SDL_MessageBoxDataX11 *data ) +{ + int x, y; + XSizeHints *sizehints; + XSetWindowAttributes wnd_attr; + Display *display = data->display; + SDL_WindowData *windowdata = NULL; + const SDL_MessageBoxData *messageboxdata = data->messageboxdata; + + if ( messageboxdata->window ) { + windowdata = (SDL_WindowData *)messageboxdata->window->driverdata; + } + + data->event_mask = ExposureMask | + ButtonPressMask | ButtonReleaseMask | KeyPressMask | KeyReleaseMask | + StructureNotifyMask | FocusChangeMask | PointerMotionMask; + wnd_attr.event_mask = data->event_mask; + + data->window = XCreateWindow( + display, DefaultRootWindow( display ), + 0, 0, + data->dialog_width, data->dialog_height, + 0, CopyFromParent, InputOutput, CopyFromParent, + CWEventMask, &wnd_attr ); + if ( data->window == None ) { + SDL_SetError("Couldn't create X window"); + return -1; + } + + if ( windowdata ) { + /* http://tronche.com/gui/x/icccm/sec-4.html#WM_TRANSIENT_FOR */ + XSetTransientForHint( display, data->window, windowdata->xwindow ); + } + + XStoreName( display, data->window, messageboxdata->title ); + + /* Allow the window to be deleted by the window manager */ + data->wm_protocols = XInternAtom( display, "WM_PROTOCOLS", False ); + data->wm_delete_message = XInternAtom( display, "WM_DELETE_WINDOW", False ); + XSetWMProtocols( display, data->window, &data->wm_delete_message, 1 ); + + if ( windowdata ) { + XWindowAttributes attrib; + Window dummy; + + XGetWindowAttributes(display, windowdata->xwindow, &attrib); + x = attrib.x + ( attrib.width - data->dialog_width ) / 2; + y = attrib.y + ( attrib.height - data->dialog_height ) / 3 ; + XTranslateCoordinates(display, windowdata->xwindow, DefaultRootWindow( display ), x, y, &x, &y, &dummy); + } else { + int screen = DefaultScreen( display ); + x = ( DisplayWidth( display, screen ) - data->dialog_width ) / 2; + y = ( DisplayHeight( display, screen ) - data->dialog_height ) / 3 ; + } + XMoveWindow( display, data->window, x, y ); + + sizehints = XAllocSizeHints(); + if ( sizehints ) { + sizehints->flags = USPosition | USSize | PMaxSize | PMinSize; + sizehints->x = x; + sizehints->y = y; + sizehints->width = data->dialog_width; + sizehints->height = data->dialog_height; + + sizehints->min_width = sizehints->max_width = data->dialog_width; + sizehints->min_height = sizehints->max_height = data->dialog_height; + + XSetWMNormalHints( display, data->window, sizehints ); + + XFree( sizehints ); + } + + XMapRaised( display, data->window ); + return 0; +} + +/* Draw our message box. */ +static void +X11_MessageBoxDraw( SDL_MessageBoxDataX11 *data, GC ctx ) +{ + int i; + Window window = data->window; + Display *display = data->display; + + XSetForeground( display, ctx, data->color[ SDL_MESSAGEBOX_COLOR_BACKGROUND ] ); + XFillRectangle( display, window, ctx, 0, 0, data->dialog_width, data->dialog_height ); + + XSetForeground( display, ctx, data->color[ SDL_MESSAGEBOX_COLOR_TEXT ] ); + for ( i = 0; i < data->numlines; i++ ) + { + TextLineData *plinedata = &data->linedata[ i ]; + + XDrawString( display, window, ctx, + data->xtext, data->ytext + i * data->text_height, + plinedata->text, plinedata->length ); + } + + for ( i = 0; i < data->numbuttons; i++ ) + { + SDL_MessageBoxButtonDataX11 *buttondatax11 = &data->buttonpos[ i ]; + const SDL_MessageBoxButtonData *buttondata = buttondatax11->buttondata; + int border = ( buttondata->flags & SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT ) ? 2 : 0; + int offset = ( ( data->mouse_over_index == i ) && ( data->button_press_index == data->mouse_over_index ) ) ? 1 : 0; + + XSetForeground( display, ctx, data->color[ SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND ] ); + XFillRectangle( display, window, ctx, + buttondatax11->rect.x - border, buttondatax11->rect.y - border, + buttondatax11->rect.w + 2 * border, buttondatax11->rect.h + 2 * border ); + + XSetForeground( display, ctx, data->color[ SDL_MESSAGEBOX_COLOR_BUTTON_BORDER ] ); + XDrawRectangle( display, window, ctx, + buttondatax11->rect.x, buttondatax11->rect.y, + buttondatax11->rect.w, buttondatax11->rect.h ); + + XSetForeground( display, ctx, ( data->mouse_over_index == i ) ? + data->color[ SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED ] : + data->color[ SDL_MESSAGEBOX_COLOR_TEXT ] ); + XDrawString( display, window, ctx, + buttondatax11->x + offset, buttondatax11->y + offset, + buttondata->text, buttondatax11->length ); + } +} + +/* Loop and handle message box event messages until something kills it. */ +static int +X11_MessageBoxLoop( SDL_MessageBoxDataX11 *data ) +{ + GC ctx; + XGCValues ctx_vals; + SDL_bool close_dialog = SDL_FALSE; + SDL_bool has_focus = SDL_TRUE; + KeySym last_key_pressed = XK_VoidSymbol; + + ctx_vals.font = data->hfont; + ctx_vals.foreground = data->color[ SDL_MESSAGEBOX_COLOR_BACKGROUND ]; + ctx_vals.background = data->color[ SDL_MESSAGEBOX_COLOR_BACKGROUND ]; + + ctx = XCreateGC( data->display, data->window, GCForeground | GCBackground | GCFont, &ctx_vals ); + if ( ctx == None ) { + SDL_SetError("Couldn't create graphics context"); + return -1; + } + + data->button_press_index = -1; /* Reset what button is currently depressed. */ + data->mouse_over_index = -1; /* Reset what button the mouse is over. */ + + while( !close_dialog ) { + XEvent e; + SDL_bool draw = SDL_TRUE; + + XWindowEvent( data->display, data->window, data->event_mask, &e ); + + /* If XFilterEvent returns True, then some input method has filtered the + event, and the client should discard the event. */ + if ( ( e.type != Expose ) && XFilterEvent( &e, None ) ) + continue; + + switch( e.type ) { + case Expose: + if ( e.xexpose.count > 0 ) { + draw = SDL_FALSE; + } + break; + + case FocusIn: + /* Got focus. */ + has_focus = SDL_TRUE; + break; + + case FocusOut: + /* lost focus. Reset button and mouse info. */ + has_focus = SDL_FALSE; + data->button_press_index = -1; + data->mouse_over_index = -1; + break; + + case MotionNotify: + if ( has_focus ) { + /* Mouse moved... */ + data->mouse_over_index = GetHitButtonIndex( data, e.xbutton.x, e.xbutton.y ); + } + break; + + case ClientMessage: + if ( e.xclient.message_type == data->wm_protocols && + e.xclient.format == 32 && + e.xclient.data.l[ 0 ] == data->wm_delete_message ) { + close_dialog = SDL_TRUE; + } + break; + + case KeyPress: + /* Store key press - we make sure in key release that we got both. */ + last_key_pressed = XLookupKeysym( &e.xkey, 0 ); + break; + + case KeyRelease: + { + Uint32 mask = 0; + KeySym key = XLookupKeysym( &e.xkey, 0 ); + + /* If this is a key release for something we didn't get the key down for, then bail. */ + if ( key != last_key_pressed ) + break; + + if ( key == XK_Escape ) + mask = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT; + else if ( ( key == XK_Return ) || ( key == XK_KP_Enter ) ) + mask = SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT; + + if ( mask ) { + int i; + + /* Look for first button with this mask set, and return it if found. */ + for ( i = 0; i < data->numbuttons; i++ ) { + SDL_MessageBoxButtonDataX11 *buttondatax11 = &data->buttonpos[ i ]; + + if ( buttondatax11->buttondata->flags & mask ) { + *data->pbuttonid = buttondatax11->buttondata->buttonid; + close_dialog = SDL_TRUE; + break; + } + } + } + break; + } + + case ButtonPress: + data->button_press_index = -1; + if ( e.xbutton.button == Button1 ) { + /* Find index of button they clicked on. */ + data->button_press_index = GetHitButtonIndex( data, e.xbutton.x, e.xbutton.y ); + } + break; + + case ButtonRelease: + /* If button is released over the same button that was clicked down on, then return it. */ + if ( ( e.xbutton.button == Button1 ) && ( data->button_press_index >= 0 ) ) { + int button = GetHitButtonIndex( data, e.xbutton.x, e.xbutton.y ); + + if ( data->button_press_index == button ) { + SDL_MessageBoxButtonDataX11 *buttondatax11 = &data->buttonpos[ button ]; + + *data->pbuttonid = buttondatax11->buttondata->buttonid; + close_dialog = SDL_TRUE; + } + } + data->button_press_index = -1; + break; + } + + if ( draw ) { + /* Draw our dialog box. */ + X11_MessageBoxDraw( data, ctx ); + } + } + + XFreeGC( data->display, ctx ); + return 0; +} + +/* Display an x11 message box. */ +int +X11_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid) +{ + int ret; + SDL_MessageBoxDataX11 data; + + SDL_memset( &data, 0, sizeof( data ) ); + + if ( !SDL_X11_LoadSymbols() ) + return -1; + + /* This code could get called from multiple threads maybe? */ + XInitThreads(); + + /* Initialize the return buttonid value to -1 (for error or dialogbox closed). */ + *buttonid = -1; + + /* Init and display the message box. */ + ret = X11_MessageBoxInit( &data, messageboxdata, buttonid ); + if ( ret != -1 ) { + ret = X11_MessageBoxInitPositions( &data ); + if ( ret != -1 ) { + ret = X11_MessageBoxCreateWindow( &data ); + if ( ret != -1 ) { + ret = X11_MessageBoxLoop( &data ); + } + } + } + + X11_MessageBoxShutdown( &data ); + return ret; +} + +#endif /* SDL_VIDEO_DRIVER_X11 */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/x11/SDL_x11messagebox.h b/src/video/x11/SDL_x11messagebox.h new file mode 100644 index 0000000000..6f01c1d1de --- /dev/null +++ b/src/video/x11/SDL_x11messagebox.h @@ -0,0 +1,28 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +#if SDL_VIDEO_DRIVER_X11 + +extern int X11_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonid); + +#endif /* SDL_VIDEO_DRIVER_X11 */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/x11/SDL_x11sym.h b/src/video/x11/SDL_x11sym.h index 9449849bd6..c7cc2a9662 100644 --- a/src/video/x11/SDL_x11sym.h +++ b/src/video/x11/SDL_x11sym.h @@ -43,13 +43,17 @@ SDL_X11_SYM(int,XDefineCursor,(Display* a,Window b,Cursor c),(a,b,c),return) SDL_X11_SYM(int,XDeleteProperty,(Display* a,Window b,Atom c),(a,b,c),return) SDL_X11_SYM(int,XDestroyWindow,(Display* a,Window b),(a,b),return) SDL_X11_SYM(int,XDisplayKeycodes,(Display* a,int* b,int* c),(a,b,c),return) +SDL_X11_SYM(int,XDrawRectangle,(Display* a,Drawable b,GC c,int d,int e,unsigned int f,unsigned int g),(a,b,c,d,e,f,g),return) SDL_X11_SYM(char*,XDisplayName,(_Xconst char* a),(a),return) +SDL_X11_SYM(int,XDrawString,(Display* a,Drawable b,GC c,int d,int e,_Xconst char* f,int g),(a,b,c,d,e,f,g),return) SDL_X11_SYM(int,XEventsQueued,(Display* a,int b),(a,b),return) +SDL_X11_SYM(int,XFillRectangle,(Display* a,Drawable b,GC c,int d,int e,unsigned int f,unsigned int g),(a,b,c,d,e,f,g),return) SDL_X11_SYM(Bool,XFilterEvent,(XEvent *event,Window w),(event,w),return) SDL_X11_SYM(int,XFlush,(Display* a),(a),return) SDL_X11_SYM(int,XFree,(void*a),(a),return) SDL_X11_SYM(int,XFreeCursor,(Display* a,Cursor b),(a,b),return) SDL_X11_SYM(int,XFreeGC,(Display* a,GC b),(a,b),return) +SDL_X11_SYM(int,XFreeFontInfo,(char** a,XFontStruct* b,int c),(a,b,c),return) SDL_X11_SYM(int,XFreeModifiermap,(XModifierKeymap* a),(a),return) SDL_X11_SYM(int,XFreePixmap,(Display* a,Pixmap b),(a,b),return) SDL_X11_SYM(char*,XGetAtomName,(Display *a,Atom b),(a,b),return) @@ -73,6 +77,7 @@ SDL_X11_SYM(char*,XKeysymToString,(KeySym a),(a),return) SDL_X11_SYM(int,XInstallColormap,(Display* a,Colormap b),(a,b),return) SDL_X11_SYM(Atom,XInternAtom,(Display* a,_Xconst char* b,Bool c),(a,b,c),return) SDL_X11_SYM(XPixmapFormatValues*,XListPixmapFormats,(Display* a,int* b),(a,b),return) +SDL_X11_SYM(Font,XLoadFont,(Display* a,_Xconst char* b),(a,b),return) SDL_X11_SYM(KeySym,XLookupKeysym,(XKeyEvent* a,int b),(a,b),return) SDL_X11_SYM(int,XLookupString,(XKeyEvent* a,char* b,int c,KeySym* d,XComposeStatus* e),(a,b,c,d,e),return) SDL_X11_SYM(int,XMapRaised,(Display* a,Window b),(a,b),return) @@ -85,6 +90,7 @@ SDL_X11_SYM(Status,XInitThreads,(void),(),return) SDL_X11_SYM(int,XPeekEvent,(Display* a,XEvent* b),(a,b),return) SDL_X11_SYM(int,XPending,(Display* a),(a),return) SDL_X11_SYM(int,XPutImage,(Display* a,Drawable b,GC c,XImage* d,int e,int f,int g,int h,unsigned int i,unsigned int j),(a,b,c,d,e,f,g,h,i,j),return) +SDL_X11_SYM(XFontStruct*,XQueryFont,(Display* a,XID b),(a,b),return) SDL_X11_SYM(int,XQueryKeymap,(Display* a,char *b),(a,b),return) SDL_X11_SYM(Bool,XQueryPointer,(Display* a,Window b,Window* c,Window* d,int* e,int* f,int* g,int* h,unsigned int* i),(a,b,c,d,e,f,g,h,i),return) SDL_X11_SYM(int,XRaiseWindow,(Display* a,Window b),(a,b),return) @@ -94,6 +100,7 @@ SDL_X11_SYM(int,XResizeWindow,(Display* a,Window b,unsigned int c,unsigned int d SDL_X11_SYM(int,XSelectInput,(Display* a,Window b,long c),(a,b,c),return) SDL_X11_SYM(Status,XSendEvent,(Display* a,Window b,Bool c,long d,XEvent* e),(a,b,c,d,e),return) SDL_X11_SYM(XErrorHandler,XSetErrorHandler,(XErrorHandler a),(a),return) +SDL_X11_SYM(int,XSetForeground,(Display* a,GC b,unsigned long c),(a,b,c),return) SDL_X11_SYM(XIOErrorHandler,XSetIOErrorHandler,(XIOErrorHandler a),(a),return) SDL_X11_SYM(int,XSetInputFocus,(Display *a,Window b,int c,Time d),(a,b,c,d),return) SDL_X11_SYM(int,XSetSelectionOwner,(Display* a,Atom b,Window c,Time d),(a,b,c,d),return) @@ -104,15 +111,20 @@ SDL_X11_SYM(void,XSetWMProperties,(Display* a,Window b,XTextProperty* c,XTextPro SDL_X11_SYM(void,XSetWMNormalHints,(Display* a,Window b,XSizeHints* c),(a,b,c),) SDL_X11_SYM(Status,XSetWMProtocols,(Display* a,Window b,Atom* c,int d),(a,b,c,d),return) SDL_X11_SYM(int,XStoreColors,(Display* a,Colormap b,XColor* c,int d),(a,b,c,d),return) +SDL_X11_SYM(int,XStoreName,(Display* a,Window b,_Xconst char* c),(a,b,c),return) SDL_X11_SYM(Status,XStringListToTextProperty,(char** a,int b,XTextProperty* c),(a,b,c),return) SDL_X11_SYM(int,XSync,(Display* a,Bool b),(a,b),return) +SDL_X11_SYM(int,XTextExtents,(XFontStruct* a,_Xconst char* b,int c,int* d,int* e,int* f,XCharStruct* g),(a,b,c,d,e,f,g),return) +SDL_X11_SYM(Bool,XTranslateCoordinates,(Display *a,Window b,Window c,int d,int e,int* f,int* g,Window* h),(a,b,c,d,e,f,g,h),return) SDL_X11_SYM(int,XUndefineCursor,(Display* a,Window b),(a,b),return) SDL_X11_SYM(int,XUngrabKeyboard,(Display* a,Time b),(a,b),return) SDL_X11_SYM(int,XUngrabPointer,(Display* a,Time b),(a,b),return) SDL_X11_SYM(int,XUngrabServer,(Display* a),(a),return) SDL_X11_SYM(int,XUninstallColormap,(Display* a,Colormap b),(a,b),return) +SDL_X11_SYM(int,XUnloadFont,(Display* a,Font b),(a,b),return) SDL_X11_SYM(int,XUnmapWindow,(Display* a,Window b),(a,b),return) SDL_X11_SYM(int,XWarpPointer,(Display* a,Window b,Window c,int d,int e,unsigned int f,unsigned int g,int h,int i),(a,b,c,d,e,f,g,h,i),return) +SDL_X11_SYM(int,XWindowEvent,(Display* a,Window b,long c,XEvent* d),(a,b,c,d),return) SDL_X11_SYM(VisualID,XVisualIDFromVisual,(Visual* a),(a),return) #if SDL_VIDEO_DRIVER_X11_CONST_PARAM_XEXTADDDISPLAY SDL_X11_SYM(XExtDisplayInfo*,XextAddDisplay,(XExtensionInfo* a,Display* b,_Xconst char* c,XExtensionHooks* d,int e,XPointer f),(a,b,c,d,e,f),return) diff --git a/src/video/x11/SDL_x11video.c b/src/video/x11/SDL_x11video.c index 122023832d..52a996a53b 100644 --- a/src/video/x11/SDL_x11video.c +++ b/src/video/x11/SDL_x11video.c @@ -370,6 +370,7 @@ X11_VideoInit(_THIS) /* Look up some useful Atoms */ #define GET_ATOM(X) data->X = XInternAtom(data->display, #X, False) + GET_ATOM(WM_PROTOCOLS); GET_ATOM(WM_DELETE_WINDOW); GET_ATOM(_NET_WM_STATE); GET_ATOM(_NET_WM_STATE_HIDDEN); @@ -382,6 +383,7 @@ X11_VideoInit(_THIS) GET_ATOM(_NET_WM_NAME); GET_ATOM(_NET_WM_ICON_NAME); GET_ATOM(_NET_WM_ICON); + GET_ATOM(_NET_WM_PING); GET_ATOM(UTF8_STRING); /* Detect the window manager */ diff --git a/src/video/x11/SDL_x11video.h b/src/video/x11/SDL_x11video.h index 94793fe66e..5c092048f0 100644 --- a/src/video/x11/SDL_x11video.h +++ b/src/video/x11/SDL_x11video.h @@ -80,6 +80,7 @@ typedef struct SDL_VideoData SDL_bool net_wm; /* Useful atoms */ + Atom WM_PROTOCOLS; Atom WM_DELETE_WINDOW; Atom _NET_WM_STATE; Atom _NET_WM_STATE_HIDDEN; @@ -92,6 +93,7 @@ typedef struct SDL_VideoData Atom _NET_WM_NAME; Atom _NET_WM_ICON_NAME; Atom _NET_WM_ICON; + Atom _NET_WM_PING; Atom UTF8_STRING; SDL_Scancode key_layout[256]; diff --git a/src/video/x11/SDL_x11window.c b/src/video/x11/SDL_x11window.c index ba4ecc24aa..2c883a573a 100644 --- a/src/video/x11/SDL_x11window.c +++ b/src/video/x11/SDL_x11window.c @@ -536,8 +536,14 @@ X11_CreateWindow(_THIS, SDL_Window * window) PropModeReplace, (unsigned char *)&_NET_WM_WINDOW_TYPE_NORMAL, 1); - /* Allow the window to be deleted by the window manager */ - XSetWMProtocols(display, w, &data->WM_DELETE_WINDOW, 1); + + { + Atom protocols[] = { + data->WM_DELETE_WINDOW, /* Allow window to be deleted by the WM */ + data->_NET_WM_PING, /* Respond so WM knows we're alive */ + }; + XSetWMProtocols(display, w, protocols, sizeof (protocols) / sizeof (protocols[0])); + } if (SetupWindowData(_this, window, w, SDL_TRUE) < 0) { XDestroyWindow(display, w); diff --git a/test/Makefile.in b/test/Makefile.in index cd4320e750..7e33d3edf1 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -47,6 +47,7 @@ TARGETS = \ testwm2$(EXE) \ torturethread$(EXE) \ testrendercopyex$(EXE) \ + testmessage$(EXE) \ all: Makefile $(TARGETS) @@ -54,142 +55,145 @@ Makefile: $(srcdir)/Makefile.in $(SHELL) config.status $@ checkkeys$(EXE): $(srcdir)/checkkeys.c - $(CC) -o $@ $? $(CFLAGS) $(LIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) loopwave$(EXE): $(srcdir)/loopwave.c - $(CC) -o $@ $? $(CFLAGS) $(LIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) testresample$(EXE): $(srcdir)/testresample.c - $(CC) -o $@ $? $(CFLAGS) $(LIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) testaudioinfo$(EXE): $(srcdir)/testaudioinfo.c - $(CC) -o $@ $? $(CFLAGS) $(LIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) testmultiaudio$(EXE): $(srcdir)/testmultiaudio.c - $(CC) -o $@ $? $(CFLAGS) $(LIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) testatomic$(EXE): $(srcdir)/testatomic.c - $(CC) -o $@ $? $(CFLAGS) $(LIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) testintersections$(EXE): $(srcdir)/testintersections.c $(srcdir)/common.c - $(CC) -o $@ $(srcdir)/testintersections.c $(srcdir)/common.c $(CFLAGS) $(LIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) testrelative$(EXE): $(srcdir)/testrelative.c $(srcdir)/common.c - $(CC) -o $@ $(srcdir)/testrelative.c $(srcdir)/common.c $(CFLAGS) $(LIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) testdraw2$(EXE): $(srcdir)/testdraw2.c $(srcdir)/common.c - $(CC) -o $@ $(srcdir)/testdraw2.c $(srcdir)/common.c $(CFLAGS) $(LIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) testerror$(EXE): $(srcdir)/testerror.c - $(CC) -o $@ $? $(CFLAGS) $(LIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) testfile$(EXE): $(srcdir)/testfile.c - $(CC) -o $@ $? $(CFLAGS) $(LIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) testgesture$(EXE): $(srcdir)/testgesture.c - $(CC) -o $@ $? $(CFLAGS) $(LIBS) @MATHLIB@ + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) @MATHLIB@ testgl2$(EXE): $(srcdir)/testgl2.c $(srcdir)/common.c - $(CC) -o $@ $(srcdir)/testgl2.c $(srcdir)/common.c $(CFLAGS) $(LIBS) @GLLIB@ @MATHLIB@ + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) @GLLIB@ @MATHLIB@ testgles$(EXE): $(srcdir)/testgles.c $(srcdir)/common.c - $(CC) -o $@ $(srcdir)/testgles.c $(srcdir)/common.c $(CFLAGS) $(LIBS) @GLLIB@ @MATHLIB@ + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) @GLLIB@ @MATHLIB@ testhaptic$(EXE): $(srcdir)/testhaptic.c - $(CC) -o $@ $? $(CFLAGS) $(LIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) testrumble$(EXE): $(srcdir)/testrumble.c - $(CC) -o $@ $? $(CFLAGS) $(LIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) testthread$(EXE): $(srcdir)/testthread.c - $(CC) -o $@ $? $(CFLAGS) $(LIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) testiconv$(EXE): $(srcdir)/testiconv.c - $(CC) -o $@ $? $(CFLAGS) $(LIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) testime$(EXE): $(srcdir)/testime.c $(srcdir)/common.c - $(CC) -o $@ $(srcdir)/testime.c $(srcdir)/common.c $(CFLAGS) $(LIBS) @SDL_TTF_LIB@ + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) @SDL_TTF_LIB@ testjoystick$(EXE): $(srcdir)/testjoystick.c $(srcdir)/common.c - $(CC) -o $@ $? $(CFLAGS) $(LIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) testkeys$(EXE): $(srcdir)/testkeys.c - $(CC) -o $@ $? $(CFLAGS) $(LIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) testloadso$(EXE): $(srcdir)/testloadso.c - $(CC) -o $@ $? $(CFLAGS) $(LIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) testlock$(EXE): $(srcdir)/testlock.c - $(CC) -o $@ $? $(CFLAGS) $(LIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) ifeq (@ISMACOSX@,true) testnative$(EXE): $(srcdir)/testnative.c \ $(srcdir)/testnativecocoa.m \ $(srcdir)/testnativew32.c \ $(srcdir)/testnativex11.c - $(CC) -o $@ $? $(CFLAGS) $(LIBS) -L/usr/X11/lib -lX11 -framework Cocoa + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) -L/usr/X11/lib -lX11 -framework Cocoa endif ifeq (@ISWINDOWS@,true) testnative$(EXE): $(srcdir)/testnative.c \ $(srcdir)/testnativew32.c - $(CC) -o $@ $? $(CFLAGS) $(LIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) endif ifeq (@ISUNIX@,true) testnative$(EXE): $(srcdir)/testnative.c \ $(srcdir)/testnativex11.c - $(CC) -o $@ $? $(CFLAGS) $(LIBS) -L/usr/X11/lib -lX11 + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) -L/usr/X11/lib -lX11 endif testoverlay2$(EXE): $(srcdir)/testoverlay2.c - $(CC) -o $@ $? $(CFLAGS) $(LIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) testplatform$(EXE): $(srcdir)/testplatform.c - $(CC) -o $@ $? $(CFLAGS) $(LIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) testpower$(EXE): $(srcdir)/testpower.c - $(CC) -o $@ $? $(CFLAGS) $(LIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) testrendertarget$(EXE): $(srcdir)/testrendertarget.c $(srcdir)/common.c - $(CC) -o $@ $(srcdir)/testrendertarget.c $(srcdir)/common.c $(CFLAGS) $(LIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) testscale$(EXE): $(srcdir)/testscale.c $(srcdir)/common.c - $(CC) -o $@ $(srcdir)/testscale.c $(srcdir)/common.c $(CFLAGS) $(LIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) testsem$(EXE): $(srcdir)/testsem.c - $(CC) -o $@ $? $(CFLAGS) $(LIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) testshader$(EXE): $(srcdir)/testshader.c - $(CC) -o $@ $(srcdir)/testshader.c $(CFLAGS) $(LIBS) @GLLIB@ @MATHLIB@ + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) @GLLIB@ @MATHLIB@ testshape$(EXE): $(srcdir)/testshape.c - $(CC) -o $@ $? -std=c99 $(CFLAGS) $(LIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) testsprite2$(EXE): $(srcdir)/testsprite2.c $(srcdir)/common.c - $(CC) -o $@ $(srcdir)/testsprite2.c $(srcdir)/common.c $(CFLAGS) $(LIBS) @MATHLIB@ + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) @MATHLIB@ testspriteminimal$(EXE): $(srcdir)/testspriteminimal.c - $(CC) -o $@ $? $(CFLAGS) $(LIBS) @MATHLIB@ + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) @MATHLIB@ teststreaming$(EXE): $(srcdir)/teststreaming.c - $(CC) -o $@ $? $(CFLAGS) $(LIBS) @MATHLIB@ + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) @MATHLIB@ testtimer$(EXE): $(srcdir)/testtimer.c - $(CC) -o $@ $? $(CFLAGS) $(LIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) testver$(EXE): $(srcdir)/testver.c - $(CC) -o $@ $? $(CFLAGS) $(LIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) testwm2$(EXE): $(srcdir)/testwm2.c $(srcdir)/common.c - $(CC) -o $@ $(srcdir)/testwm2.c $(srcdir)/common.c $(CFLAGS) $(LIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) torturethread$(EXE): $(srcdir)/torturethread.c - $(CC) -o $@ $? $(CFLAGS) $(LIBS) + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) testrendercopyex$(EXE): $(srcdir)/testrendercopyex.c $(srcdir)/common.c - $(CC) -o $@ $(srcdir)/testrendercopyex.c $(srcdir)/common.c $(CFLAGS) $(LIBS) @MATHLIB@ - + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) @MATHLIB@ + +testmessage$(EXE): $(srcdir)/testmessage.c + $(CC) -o $@ $^ $(CFLAGS) $(LIBS) + clean: rm -f $(TARGETS) diff --git a/test/common.c b/test/common.c index 8c4c1ee294..7af002caf4 100644 --- a/test/common.c +++ b/test/common.c @@ -1204,6 +1204,12 @@ CommonEvent(CommonState * state, SDL_Event * event, int *done) } } break; + case SDLK_1: + if (event->key.keysym.mod & KMOD_CTRL) { + SDL_Window *window = SDL_GetWindowFromID(event->key.windowID); + SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, "Test Message", "You're awesome!", window); + } + break; case SDLK_ESCAPE: *done = 1; break; diff --git a/test/configure b/test/configure index c5183f0970..41eb57c1a9 100755 --- a/test/configure +++ b/test/configure @@ -3865,39 +3865,52 @@ fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for SDL_ttf" >&5 -$as_echo_n "checking for SDL_ttf... " >&6; } -have_SDL_ttf=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for TTF_Init in -lSDL2_ttf" >&5 +$as_echo_n "checking for TTF_Init in -lSDL2_ttf... " >&6; } +if ${ac_cv_lib_SDL2_ttf_TTF_Init+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lSDL2_ttf $LIBS" cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ - #include "SDL_ttf.h" - +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char TTF_Init (); int main () { - - +return TTF_Init (); ; return 0; } _ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - -have_SDL_ttf=yes - +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_SDL2_ttf_TTF_Init=yes +else + ac_cv_lib_SDL2_ttf_TTF_Init=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_SDL2_ttf_TTF_Init" >&5 +$as_echo "$ac_cv_lib_SDL2_ttf_TTF_Init" >&6; } +if test "x$ac_cv_lib_SDL2_ttf_TTF_Init" = xyes; then : + have_SDL_ttf=yes fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $have_SDL_ttf" >&5 -$as_echo "$have_SDL_ttf" >&6; } if test x$have_SDL_ttf = xyes; then CFLAGS="$CFLAGS -DHAVE_SDL_TTF" - SDL_TTF_LIB="-lSDL_ttf" + SDL_TTF_LIB="-lSDL2_ttf" fi - ac_config_files="$ac_config_files Makefile" cat >confcache <<\_ACEOF diff --git a/test/configure.in b/test/configure.in index 6c53b93bf0..ec1d954f15 100644 --- a/test/configure.in +++ b/test/configure.in @@ -143,21 +143,11 @@ fi AC_SUBST(GLLIB) dnl Check for SDL_ttf -AC_MSG_CHECKING(for SDL_ttf) -have_SDL_ttf=no -AC_TRY_COMPILE([ - #include "SDL_ttf.h" -],[ -],[ -have_SDL_ttf=yes -]) -AC_MSG_RESULT($have_SDL_ttf) - +AC_CHECK_LIB(SDL2_ttf, TTF_Init, have_SDL_ttf=yes) if test x$have_SDL_ttf = xyes; then CFLAGS="$CFLAGS -DHAVE_SDL_TTF" - SDL_TTF_LIB="-lSDL_ttf" + SDL_TTF_LIB="-lSDL2_ttf" fi - AC_SUBST(SDL_TTF_LIB) dnl Finally create all the generated files diff --git a/test/testmessage.c b/test/testmessage.c new file mode 100644 index 0000000000..01db7475e7 --- /dev/null +++ b/test/testmessage.c @@ -0,0 +1,86 @@ +/* + Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org> + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely. +*/ + +/* Simple test of the SDL MessageBox API*/ + +#include <stdio.h> +#include <stdlib.h> +#include <signal.h> + +#include "SDL.h" +#include "SDL_thread.h" + +static int alive = 0; + +/* Call this instead of exit(), so we can clean up SDL: atexit() is evil. */ +static void +quit(int rc) +{ + SDL_Quit(); + exit(rc); +} + +int +main(int argc, char *argv[]) +{ + int success; + + /* Load the SDL library */ + if (SDL_Init(0) < 0) { + fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError()); + return (1); + } + + success = SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, + "Simple MessageBox", + "This is a simple error MessageBox", + NULL); + if (success == -1) { + printf("Error Presenting MessageBox: %s\n", SDL_GetError()); + quit(1); + } + + { + const SDL_MessageBoxButtonData buttons[] = { + { + SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, + 0, + "OK" + },{ + SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, + 1, + "Cancel" + }, + }; + + SDL_MessageBoxData data = { + SDL_MESSAGEBOX_INFORMATION, + NULL, // no parent window + "Custom MessageBox", + "This is a custom messagebox", + 2, + buttons, + NULL // Default color scheme + }; + + int button = -1; + success = SDL_ShowMessageBox(&data, &button); + if (success == -1) { + printf("Error Presenting MessageBox: %s\n", SDL_GetError()); + quit(2); + } + printf("Pressed button: %d, %s\n", button, button == 1 ? "Cancel" : "OK"); + } + + SDL_Quit(); + return (0); +} |