├── .clang-format ├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── build ├── msvc │ ├── build.default.props │ ├── test │ │ ├── all.vcxproj │ │ ├── all.vcxproj.filters │ │ ├── window.vcxproj │ │ └── window.vcxproj.filters │ ├── window.sln │ └── window.vcxproj ├── ninja │ ├── android.py │ ├── clang.py │ ├── codesign.py │ ├── gcc.py │ ├── generator.py │ ├── msvc.py │ ├── platform.py │ ├── plist.py │ ├── syntax.py │ ├── toolchain.py │ ├── version.py │ ├── vslocate.py │ └── xcode.py ├── window.sublime-project └── xcode │ ├── ios │ ├── test.xcodeproj │ │ └── project.pbxproj │ └── window.xcodeproj │ │ └── project.pbxproj │ ├── osx │ ├── test.xcodeproj │ │ └── project.pbxproj │ └── window.xcodeproj │ │ └── project.pbxproj │ ├── window-ios.xcworkspace │ └── contents.xcworkspacedata │ └── window-osx.xcworkspace │ └── contents.xcworkspacedata ├── configure.py ├── doc ├── build.dox ├── event.dox ├── internal.dox ├── types.dox └── window.dox ├── test ├── all │ ├── android │ │ ├── AndroidManifest.xml │ │ ├── drawable-hdpi │ │ │ └── icon.png │ │ ├── drawable-ldpi │ │ │ └── icon.png │ │ ├── drawable-mdpi │ │ │ └── icon.png │ │ ├── drawable-xhdpi │ │ │ └── icon.png │ │ ├── drawable-xxhdpi │ │ │ └── icon.png │ │ ├── drawable-xxxhdpi │ │ │ └── icon.png │ │ ├── java │ │ │ └── com │ │ │ │ └── maniccoder │ │ │ │ └── window │ │ │ │ └── test │ │ │ │ └── TestActivity.java │ │ ├── layout │ │ │ └── main.xml │ │ └── values │ │ │ └── strings.xml │ ├── ios │ │ ├── Images.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ ├── Contents.json │ │ │ │ ├── icon_100.png │ │ │ │ ├── icon_114.png │ │ │ │ ├── icon_120.png │ │ │ │ ├── icon_144.png │ │ │ │ ├── icon_152.png │ │ │ │ ├── icon_180.png │ │ │ │ ├── icon_29-1.png │ │ │ │ ├── icon_29.png │ │ │ │ ├── icon_40.png │ │ │ │ ├── icon_50.png │ │ │ │ ├── icon_57.png │ │ │ │ ├── icon_58-1.png │ │ │ │ ├── icon_58.png │ │ │ │ ├── icon_72.png │ │ │ │ ├── icon_76.png │ │ │ │ ├── icon_80-1.png │ │ │ │ └── icon_80.png │ │ │ └── LaunchImage.launchimage │ │ │ │ ├── Contents.json │ │ │ │ ├── launch_1024_748.png │ │ │ │ ├── launch_1024_768.png │ │ │ │ ├── launch_1536_2008.png │ │ │ │ ├── launch_1536_2048.png │ │ │ │ ├── launch_2048_1496.png │ │ │ │ ├── launch_2048_1536.png │ │ │ │ ├── launch_320_480.png │ │ │ │ ├── launch_640_1136.png │ │ │ │ ├── launch_640_960.png │ │ │ │ ├── launch_768_1004.png │ │ │ │ └── launch_768_1024.png │ │ ├── test-all.plist │ │ ├── test-all.xib │ │ ├── viewcontroller.h │ │ └── viewcontroller.m │ ├── main.c │ └── tizen │ │ ├── res │ │ └── tizenapp.png │ │ └── tizen-manifest.xml └── window │ ├── macos │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── icon_1024.png │ │ │ ├── icon_128.png │ │ │ ├── icon_16.png │ │ │ ├── icon_256-1.png │ │ │ ├── icon_256.png │ │ │ ├── icon_32-1.png │ │ │ ├── icon_32.png │ │ │ ├── icon_512-1.png │ │ │ ├── icon_512.png │ │ │ └── icon_64.png │ ├── test-window.entitlements │ ├── test-window.plist │ └── test-window.xib │ └── main.c └── window ├── build.h ├── event.c ├── event.h ├── hashstrings.h ├── hashstrings.txt ├── internal.h ├── types.h ├── version.c ├── window.c ├── window.h ├── window_android.c ├── window_ios.m ├── window_linux.c ├── window_macos.m └── window_windows.c /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: Google 2 | AlignAfterOpenBracket: Align 3 | AlignConsecutiveAssignments: 'false' 4 | AlignConsecutiveDeclarations: 'false' 5 | AlignOperands: 'true' 6 | AlignTrailingComments: 'true' 7 | AllowAllParametersOfDeclarationOnNextLine: 'false' 8 | AllowShortBlocksOnASingleLine: 'false' 9 | AllowShortCaseLabelsOnASingleLine: 'false' 10 | AllowShortFunctionsOnASingleLine: None 11 | AllowShortIfStatementsOnASingleLine: 'false' 12 | AllowShortLoopsOnASingleLine: 'false' 13 | AlwaysBreakAfterDefinitionReturnType: TopLevel 14 | AlwaysBreakAfterReturnType: TopLevel 15 | AlwaysBreakBeforeMultilineStrings: 'true' 16 | AlwaysBreakTemplateDeclarations: 'true' 17 | BinPackArguments: 'true' 18 | BinPackParameters: 'true' 19 | BreakBeforeBinaryOperators: None 20 | BreakBeforeBraces: Attach 21 | BreakBeforeTernaryOperators: 'false' 22 | ColumnLimit: '120' 23 | ConstructorInitializerAllOnOneLineOrOnePerLine: 'false' 24 | DerivePointerAlignment: 'false' 25 | ExperimentalAutoDetectBinPacking: 'false' 26 | IndentCaseLabels: 'true' 27 | IndentWidth: '4' 28 | IndentWrappedFunctionNames: 'false' 29 | KeepEmptyLinesAtTheStartOfBlocks: 'false' 30 | MaxEmptyLinesToKeep: '1' 31 | NamespaceIndentation: None 32 | ObjCSpaceAfterProperty: 'true' 33 | ObjCSpaceBeforeProtocolList: 'true' 34 | PointerAlignment: Left 35 | SortIncludes: 'false' 36 | SpaceAfterCStyleCast: 'false' 37 | SpaceAfterTemplateKeyword: 'true' 38 | SpaceBeforeAssignmentOperators: 'true' 39 | SpaceBeforeParens: ControlStatements 40 | SpaceInEmptyParentheses: 'false' 41 | SpacesInAngles: 'false' 42 | SpacesInCStyleCastParentheses: 'false' 43 | SpacesInContainerLiterals: 'false' 44 | SpacesInParentheses: 'false' 45 | SpacesInSquareBrackets: 'false' 46 | TabWidth: '4' 47 | UseTab: ForIndentation 48 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Never mangle resource blob files 5 | *.blob -text 6 | 7 | # Custom for Visual Studio 8 | *.cs diff=csharp 9 | *.sln merge=union 10 | *.csproj merge=union 11 | *.vbproj merge=union 12 | *.fsproj merge=union 13 | *.dbproj merge=union 14 | 15 | # Standard to msysgit 16 | *.doc diff=astextplain 17 | *.DOC diff=astextplain 18 | *.docx diff=astextplain 19 | *.DOCX diff=astextplain 20 | *.dot diff=astextplain 21 | *.DOT diff=astextplain 22 | *.pdf diff=astextplain 23 | *.PDF diff=astextplain 24 | *.rtf diff=astextplain 25 | *.RTF diff=astextplain 26 | 27 | # Ignore build scripts in language stats 28 | build/* linguist-vendored 29 | configure.py linguist-vendored=true 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gitconfig 2 | *.pydevproject 3 | .project 4 | .metadata 5 | bin/ 6 | tmp/ 7 | *.tmp 8 | *.bak 9 | *.swp 10 | *~.nib 11 | local.properties 12 | .classpath 13 | .settings/ 14 | .loadpath 15 | .ninja* 16 | build.ninja 17 | 18 | # Generated version 19 | version.c 20 | 21 | # External tool builders 22 | .externalToolBuilders/ 23 | 24 | # Locally stored "Eclipse launch configurations" 25 | *.launch 26 | 27 | # CDT-specific 28 | .cproject 29 | 30 | # PDT-specific 31 | .buildpath 32 | 33 | #Android local build files 34 | build/android/assets 35 | build/android/libs 36 | 37 | #Xcode build 38 | build/xcode/foundation/build 39 | 40 | #Doxygen generated 41 | doc/html 42 | 43 | #Coverity scan 44 | cov-int/ 45 | cov-int.* 46 | 47 | ################# 48 | ## Visual Studio 49 | ################# 50 | 51 | ## Ignore Visual Studio temporary files, build results, and 52 | ## files generated by popular Visual Studio add-ons. 53 | 54 | # User-specific files 55 | *.suo 56 | *.user 57 | *.sln.docstates 58 | 59 | # Build results 60 | [Dd]ebug/ 61 | [Rr]elease/ 62 | [Pp]rofile/ 63 | [Dd]eploy/ 64 | *_i.c 65 | *_p.c 66 | *.ilk 67 | *.meta 68 | *.obj 69 | *.pch 70 | *.pchi 71 | *.pdb 72 | *.pgc 73 | *.pgd 74 | *.rsp 75 | *.sbr 76 | *.tlb 77 | *.tli 78 | *.tlh 79 | *.tmp 80 | *.vspscc 81 | .builds 82 | *.dotCover 83 | *.lastbuildstate 84 | *.unsuccessfulbuild 85 | *.opendb 86 | *.vc 87 | *.VC.db 88 | *.db-shm 89 | *.db-wal 90 | 91 | ## TODO: If you have NuGet Package Restore enabled, uncomment this 92 | #packages/ 93 | 94 | # Visual C++ cache files 95 | ipch/ 96 | *.aps 97 | *.ncb 98 | *.opensdf 99 | *.sdf 100 | 101 | # Visual Studio profiler 102 | *.psess 103 | *.vsp 104 | 105 | # ReSharper is a .NET coding add-in 106 | _ReSharper* 107 | 108 | # Installshield output folder 109 | [Ee]xpress 110 | 111 | # DocProject is a documentation generator add-in 112 | DocProject/buildhelp/ 113 | DocProject/Help/*.HxT 114 | DocProject/Help/*.HxC 115 | DocProject/Help/*.hhc 116 | DocProject/Help/*.hhk 117 | DocProject/Help/*.hhp 118 | DocProject/Help/Html2 119 | DocProject/Help/html 120 | 121 | # Click-Once directory 122 | publish 123 | 124 | # Others 125 | [Bb]in 126 | [Oo]bj 127 | sql 128 | TestResults 129 | *.Cache 130 | ClientBin 131 | stylecop.* 132 | ~$* 133 | *.dbmdl 134 | Generated_Code #added for RIA/Silverlight projects 135 | 136 | # Backup & report files from converting an old project file to a newer 137 | # Visual Studio version. Backup files are not needed, because we have git ;-) 138 | _UpgradeReport_Files/ 139 | Backup*/ 140 | UpgradeLog*.XML 141 | 142 | 143 | ############ 144 | ## Windows 145 | ############ 146 | 147 | # Windows image file caches 148 | Thumbs.db 149 | 150 | # Folder config file 151 | Desktop.ini 152 | 153 | 154 | ############# 155 | ## Python 156 | ############# 157 | 158 | *.py[co] 159 | 160 | # Packages 161 | *.egg 162 | *.egg-info 163 | dist 164 | eggs 165 | parts 166 | var 167 | sdist 168 | develop-eggs 169 | .installed.cfg 170 | 171 | # Installer logs 172 | pip-log.txt 173 | 174 | # Unit test / coverage reports 175 | .coverage 176 | .tox 177 | 178 | #Translations 179 | *.mo 180 | 181 | #Mr Developer 182 | .mr.developer.cfg 183 | 184 | # Mac crap 185 | .DS_Store 186 | 187 | 188 | ############### 189 | ## Generic 190 | ############### 191 | 192 | #Project builds 193 | lib/** 194 | bin/** 195 | dist/** 196 | libs/** 197 | 198 | #Log files 199 | *.log 200 | *.tlog 201 | 202 | #Scons build 203 | .sconsign.dblite 204 | build/scons/debug* 205 | build/scons/release* 206 | build/scons/profi* 207 | build/scons/deploy* 208 | 209 | #Backups 210 | *~ 211 | 212 | #Object files 213 | *.o 214 | 215 | #XCode 216 | xcuserdata 217 | *.xccheckout 218 | 219 | #SublimeText local workspace 220 | *.sublime-workspace 221 | 222 | #Never store keystores in version control! 223 | *.keystore 224 | 225 | #Do not store local build prefs 226 | build.json 227 | codesign.json 228 | coveralls.json 229 | coverallsreport.json 230 | codecov.json 231 | codecovreport.json 232 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | window_lib 2 | ========== 3 | 4 | Library for managing windows for cross platform UI applications 5 | -------------------------------------------------------------------------------- /build/msvc/build.default.props: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | x64 7 | 8 | 9 | Deploy 10 | x64 11 | 12 | 13 | Profile 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | $(Platform)\$(Configuration)\$(ProjectName)\ 23 | Unicode 24 | Sequential 25 | 26 | 27 | 28 | v143 29 | 30 | 31 | 32 | 33 | true 34 | false 35 | 36 | 37 | $(SolutionDir)..\..\bin\windows\debug\x86-64\ 38 | 39 | 40 | $(SolutionDir)..\..\lib\windows\debug\x86-64\ 41 | 42 | 43 | 44 | 45 | false 46 | true 47 | true 48 | 49 | 50 | $(SolutionDir)..\..\bin\windows\release\x86-64\ 51 | 52 | 53 | $(SolutionDir)..\..\lib\windows\release\x86-64\ 54 | 55 | 56 | 57 | 58 | false 59 | true 60 | true 61 | 62 | 63 | $(SolutionDir)..\..\bin\windows\deploy\x86-64\ 64 | 65 | 66 | $(SolutionDir)..\..\lib\windows\deploy\x86-64\ 67 | 68 | 69 | 70 | 71 | false 72 | true 73 | true 74 | 75 | 76 | $(SolutionDir)..\..\bin\windows\profile\x86-64\ 77 | 78 | 79 | $(SolutionDir)..\..\lib\windows\profile\x86-64\ 80 | 81 | 82 | 83 | 84 | false 85 | true 86 | true 87 | 88 | 89 | 90 | 91 | 92 | Level3 93 | $(ProjectDir)..\..;%(AdditionalIncludeDirectories) 94 | ProgramDatabase 95 | false 96 | false 97 | true 98 | true 99 | true 100 | false 101 | Default 102 | MultiThreaded 103 | false 104 | false 105 | AdvancedVectorExtensions2 106 | Fast 107 | false 108 | false 109 | false 110 | false 111 | false 112 | true 113 | SSE3 114 | true 115 | true 116 | true 117 | false 118 | stdc17 119 | 120 | 121 | Windows 122 | true 123 | 124 | 125 | 126 | 127 | opengl32.lib;gdi32.lib;iphlpapi.lib;ws2_32.lib;%(AdditionalDependencies) 128 | 129 | 130 | 131 | 132 | opengl32.lib;gdi32.lib;iphlpapi.lib;ws2_32.lib;%(AdditionalDependencies) 133 | 134 | 135 | 136 | 137 | BUILD_DEBUG=1;%(PreprocessorDefinitions) 138 | Disabled 139 | false 140 | false 141 | false 142 | 143 | 144 | $(SolutionDir)..\..\lib\windows;$(SolutionDir)..\..\lib\windows\debug\x86-64 145 | 146 | 147 | 148 | 149 | BUILD_RELEASE=1;%(PreprocessorDefinitions) 150 | ..\.. 151 | MaxSpeed 152 | AnySuitable 153 | Speed 154 | true 155 | true 156 | false 157 | 158 | 159 | true 160 | true 161 | $(SolutionDir)..\..\lib\windows;$(SolutionDir)..\..\lib\windows\release\x86-64 162 | 163 | 164 | 165 | 166 | $(ProjectDir)..\.. 167 | BUILD_DEPLOY=1;%(PreprocessorDefinitions) 168 | ..\.. 169 | Full 170 | AnySuitable 171 | Speed 172 | true 173 | true 174 | true 175 | 176 | 177 | true 178 | true 179 | $(SolutionDir)..\..\lib\windows;$(SolutionDir)..\..\lib\windows\deploy\x86-64 180 | 181 | 182 | 183 | 184 | $(ProjectDir)..\.. 185 | BUILD_PROFILE=1;%(PreprocessorDefinitions) 186 | Full 187 | AnySuitable 188 | Speed 189 | true 190 | true 191 | true 192 | 193 | 194 | true 195 | true 196 | $(SolutionDir)..\..\lib\windows;$(SolutionDir)..\..\lib\windows\profile\x86-64 197 | 198 | 199 | -------------------------------------------------------------------------------- /build/msvc/test/all.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /build/msvc/test/window.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /build/msvc/window.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.25920.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "window", "window.vcxproj", "{5F73E99D-7FB9-400D-B420-173D63D08A89}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "all", "test\all.vcxproj", "{9BE10365-AB0A-43E0-917E-F6A229F650A2}" 9 | ProjectSection(ProjectDependencies) = postProject 10 | {A8F2AD05-117D-4538-9A82-CB059525156D} = {A8F2AD05-117D-4538-9A82-CB059525156D} 11 | EndProjectSection 12 | EndProject 13 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{9A7F0B75-9BBA-4B08-929B-BDA9A1FCA7C7}" 14 | EndProject 15 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "window", "test\window.vcxproj", "{A8F2AD05-117D-4538-9A82-CB059525156D}" 16 | EndProject 17 | Global 18 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 19 | Debug|x64 = Debug|x64 20 | Debug|x86 = Debug|x86 21 | Deploy|x64 = Deploy|x64 22 | Deploy|x86 = Deploy|x86 23 | Profile|x64 = Profile|x64 24 | Profile|x86 = Profile|x86 25 | Release|x64 = Release|x64 26 | Release|x86 = Release|x86 27 | EndGlobalSection 28 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 29 | {5F73E99D-7FB9-400D-B420-173D63D08A89}.Debug|x64.ActiveCfg = Debug|x64 30 | {5F73E99D-7FB9-400D-B420-173D63D08A89}.Debug|x64.Build.0 = Debug|x64 31 | {5F73E99D-7FB9-400D-B420-173D63D08A89}.Debug|x86.ActiveCfg = Debug|Win32 32 | {5F73E99D-7FB9-400D-B420-173D63D08A89}.Debug|x86.Build.0 = Debug|Win32 33 | {5F73E99D-7FB9-400D-B420-173D63D08A89}.Deploy|x64.ActiveCfg = Deploy|x64 34 | {5F73E99D-7FB9-400D-B420-173D63D08A89}.Deploy|x64.Build.0 = Deploy|x64 35 | {5F73E99D-7FB9-400D-B420-173D63D08A89}.Deploy|x86.ActiveCfg = Deploy|Win32 36 | {5F73E99D-7FB9-400D-B420-173D63D08A89}.Deploy|x86.Build.0 = Deploy|Win32 37 | {5F73E99D-7FB9-400D-B420-173D63D08A89}.Profile|x64.ActiveCfg = Profile|x64 38 | {5F73E99D-7FB9-400D-B420-173D63D08A89}.Profile|x64.Build.0 = Profile|x64 39 | {5F73E99D-7FB9-400D-B420-173D63D08A89}.Profile|x86.ActiveCfg = Profile|Win32 40 | {5F73E99D-7FB9-400D-B420-173D63D08A89}.Profile|x86.Build.0 = Profile|Win32 41 | {5F73E99D-7FB9-400D-B420-173D63D08A89}.Release|x64.ActiveCfg = Release|x64 42 | {5F73E99D-7FB9-400D-B420-173D63D08A89}.Release|x64.Build.0 = Release|x64 43 | {5F73E99D-7FB9-400D-B420-173D63D08A89}.Release|x86.ActiveCfg = Release|Win32 44 | {5F73E99D-7FB9-400D-B420-173D63D08A89}.Release|x86.Build.0 = Release|Win32 45 | {9BE10365-AB0A-43E0-917E-F6A229F650A2}.Debug|x64.ActiveCfg = Debug|x64 46 | {9BE10365-AB0A-43E0-917E-F6A229F650A2}.Debug|x64.Build.0 = Debug|x64 47 | {9BE10365-AB0A-43E0-917E-F6A229F650A2}.Debug|x86.ActiveCfg = Debug|Win32 48 | {9BE10365-AB0A-43E0-917E-F6A229F650A2}.Debug|x86.Build.0 = Debug|Win32 49 | {9BE10365-AB0A-43E0-917E-F6A229F650A2}.Deploy|x64.ActiveCfg = Deploy|x64 50 | {9BE10365-AB0A-43E0-917E-F6A229F650A2}.Deploy|x64.Build.0 = Deploy|x64 51 | {9BE10365-AB0A-43E0-917E-F6A229F650A2}.Deploy|x86.ActiveCfg = Deploy|Win32 52 | {9BE10365-AB0A-43E0-917E-F6A229F650A2}.Deploy|x86.Build.0 = Deploy|Win32 53 | {9BE10365-AB0A-43E0-917E-F6A229F650A2}.Profile|x64.ActiveCfg = Profile|x64 54 | {9BE10365-AB0A-43E0-917E-F6A229F650A2}.Profile|x64.Build.0 = Profile|x64 55 | {9BE10365-AB0A-43E0-917E-F6A229F650A2}.Profile|x86.ActiveCfg = Profile|Win32 56 | {9BE10365-AB0A-43E0-917E-F6A229F650A2}.Profile|x86.Build.0 = Profile|Win32 57 | {9BE10365-AB0A-43E0-917E-F6A229F650A2}.Release|x64.ActiveCfg = Release|x64 58 | {9BE10365-AB0A-43E0-917E-F6A229F650A2}.Release|x64.Build.0 = Release|x64 59 | {9BE10365-AB0A-43E0-917E-F6A229F650A2}.Release|x86.ActiveCfg = Release|Win32 60 | {9BE10365-AB0A-43E0-917E-F6A229F650A2}.Release|x86.Build.0 = Release|Win32 61 | {A8F2AD05-117D-4538-9A82-CB059525156D}.Debug|x64.ActiveCfg = Debug|x64 62 | {A8F2AD05-117D-4538-9A82-CB059525156D}.Debug|x64.Build.0 = Debug|x64 63 | {A8F2AD05-117D-4538-9A82-CB059525156D}.Debug|x86.ActiveCfg = Debug|Win32 64 | {A8F2AD05-117D-4538-9A82-CB059525156D}.Debug|x86.Build.0 = Debug|Win32 65 | {A8F2AD05-117D-4538-9A82-CB059525156D}.Deploy|x64.ActiveCfg = Deploy|x64 66 | {A8F2AD05-117D-4538-9A82-CB059525156D}.Deploy|x64.Build.0 = Deploy|x64 67 | {A8F2AD05-117D-4538-9A82-CB059525156D}.Deploy|x86.ActiveCfg = Deploy|Win32 68 | {A8F2AD05-117D-4538-9A82-CB059525156D}.Deploy|x86.Build.0 = Deploy|Win32 69 | {A8F2AD05-117D-4538-9A82-CB059525156D}.Profile|x64.ActiveCfg = Profile|x64 70 | {A8F2AD05-117D-4538-9A82-CB059525156D}.Profile|x64.Build.0 = Profile|x64 71 | {A8F2AD05-117D-4538-9A82-CB059525156D}.Profile|x86.ActiveCfg = Profile|Win32 72 | {A8F2AD05-117D-4538-9A82-CB059525156D}.Profile|x86.Build.0 = Profile|Win32 73 | {A8F2AD05-117D-4538-9A82-CB059525156D}.Release|x64.ActiveCfg = Release|x64 74 | {A8F2AD05-117D-4538-9A82-CB059525156D}.Release|x64.Build.0 = Release|x64 75 | {A8F2AD05-117D-4538-9A82-CB059525156D}.Release|x86.ActiveCfg = Release|Win32 76 | {A8F2AD05-117D-4538-9A82-CB059525156D}.Release|x86.Build.0 = Release|Win32 77 | EndGlobalSection 78 | GlobalSection(SolutionProperties) = preSolution 79 | HideSolutionNode = FALSE 80 | EndGlobalSection 81 | GlobalSection(NestedProjects) = preSolution 82 | {9BE10365-AB0A-43E0-917E-F6A229F650A2} = {9A7F0B75-9BBA-4B08-929B-BDA9A1FCA7C7} 83 | {A8F2AD05-117D-4538-9A82-CB059525156D} = {9A7F0B75-9BBA-4B08-929B-BDA9A1FCA7C7} 84 | EndGlobalSection 85 | EndGlobal 86 | -------------------------------------------------------------------------------- /build/msvc/window.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Win32Proj 5 | window 6 | 10.0 7 | StaticLibrary 8 | {356236D9-2754-4025-9724-67E0FD8CBEC6} 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | $(ProjectDir)..\..\..\foundation;$(ProjectDir)..\..\..\foundation_lib;%(AdditionalIncludeDirectories) 54 | 55 | 56 | 57 | 58 | WINDOW_COMPILE=1;%(PreprocessorDefinitions) 59 | 60 | 61 | 62 | 63 | WINDOW_COMPILE=1;%(PreprocessorDefinitions) 64 | 65 | 66 | 67 | 68 | WINDOW_COMPILE=1;%(PreprocessorDefinitions) 69 | 70 | 71 | 72 | 73 | WINDOW_COMPILE=1;%(PreprocessorDefinitions) 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /build/ninja/android.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """Ninja toolchain abstraction for Android platform""" 4 | 5 | import os 6 | import subprocess 7 | 8 | import toolchain 9 | 10 | def make_target(toolchain, host, target): 11 | return Android(toolchain, host, target) 12 | 13 | class Android(object): 14 | def __init__(self, toolchain, host, target): 15 | self.host = host 16 | 17 | if host.is_windows(): 18 | self.exe_suffix = '.exe' 19 | else: 20 | self.exe_suffix = '' 21 | 22 | self.javaccmd = toolchain.mkdircmd('$outpath') + ' && $javac -d $outpath -classpath $outpath -sourcepath $sourcepath -target 1.5 -bootclasspath $androidjar -g -source 1.5 -Xlint:-options $in' 23 | self.dexcmd = '$dex --dex --output $out $in' 24 | self.aaptcmd = toolchain.cdcmd('$apkbuildpath') + ' && $aapt p -f -m -M AndroidManifest.xml -F $apk -I $androidjar -S res --debug-mode --no-crunch -J gen $aaptflags' 25 | self.aaptdeploycmd = toolchain.cdcmd('$apkbuildpath') + ' && $aapt c -S res -C bin/res && $aapt p -f -m -M AndroidManifest.xml -F $apk -I $androidjar -S bin/res -S res -J gen $aaptflags' 26 | self.aaptaddcmd = toolchain.cdcmd('$apkbuildpath') + ' && ' + toolchain.copycmd('$apksource', '$apk' ) + ' && $aapt a $apk $apkaddfiles' 27 | self.zipcmd = '$zip -r -9 $out $in $implicitin' 28 | self.zipaligncmd = '$zipalign -f 4 $in $out' 29 | self.codesigncmd = 'build/ninja/codesign.py --target $target --prefs codesign.json --zipfile $in --config $config --jarsigner $jarsigner $out' 30 | 31 | if host.is_windows(): 32 | self.codesigncmd = 'python ' + self.codesigncmd 33 | 34 | def initialize_toolchain(self): 35 | self.ndkpath = os.getenv('NDK_HOME', '') 36 | self.sdkpath = os.getenv('ANDROID_HOME', '') 37 | self.sysroot = '' 38 | self.platformversion = '21' 39 | self.gcc_toolchainversion = '4.9' 40 | self.javasdk = '' 41 | 42 | self.archname = dict() 43 | self.archname['x86'] = 'x86' 44 | self.archname['x86-64'] = 'x86_64' 45 | self.archname['arm6'] = 'arm' 46 | self.archname['arm7'] = 'arm' 47 | self.archname['arm64'] = 'arm64' 48 | self.archname['mips'] = 'mips' 49 | self.archname['mips64'] = 'mips64' 50 | 51 | self.archpath = dict() 52 | self.archpath['x86'] = 'x86' 53 | self.archpath['x86-64'] = 'x86-64' 54 | self.archpath['arm6'] = 'armeabi' 55 | self.archpath['arm7'] = 'armeabi-v7a' 56 | self.archpath['arm64'] = 'arm64-v8a' 57 | self.archpath['mips'] = 'mips' 58 | self.archpath['mips64'] = 'mips64' 59 | 60 | self.gcc_toolchainname = dict() 61 | self.gcc_toolchainname['x86'] = 'x86-' + self.gcc_toolchainversion 62 | self.gcc_toolchainname['x86-64'] = 'x86_64-' + self.gcc_toolchainversion 63 | self.gcc_toolchainname['arm6'] = 'arm-linux-androideabi-' + self.gcc_toolchainversion 64 | self.gcc_toolchainname['arm7'] = 'arm-linux-androideabi-' + self.gcc_toolchainversion 65 | self.gcc_toolchainname['arm64'] = 'aarch64-linux-android-' + self.gcc_toolchainversion 66 | self.gcc_toolchainname['mips'] = 'mipsel-linux-android-' + self.gcc_toolchainversion 67 | self.gcc_toolchainname['mips64'] = 'mips64el-linux-android-' + self.gcc_toolchainversion 68 | 69 | self.gcc_toolchainprefix = dict() 70 | self.gcc_toolchainprefix['x86'] = 'i686-linux-android-' 71 | self.gcc_toolchainprefix['x86-64'] = 'x86_64-linux-android-' 72 | self.gcc_toolchainprefix['arm6'] = 'arm-linux-androideabi-' 73 | self.gcc_toolchainprefix['arm7'] = 'arm-linux-androideabi-' 74 | self.gcc_toolchainprefix['arm64'] = 'aarch64-linux-android-' 75 | self.gcc_toolchainprefix['mips'] = 'mipsel-linux-android-' 76 | self.gcc_toolchainprefix['mips64'] = 'mips64el-linux-android-' 77 | 78 | if self.host.is_windows(): 79 | if os.getenv('PROCESSOR_ARCHITECTURE', 'AMD64').find('64') != -1: 80 | self.hostarchname = 'windows-x86_64' 81 | else: 82 | self.hostarchname = 'windows-x86' 83 | elif self.host.is_linux(): 84 | localarch = toolchain.check_output(['uname', '-m']) 85 | if localarch == 'x86_64': 86 | self.hostarchname = 'linux-x86_64' 87 | else: 88 | self.hostarchname = 'linux-x86' 89 | elif self.host.is_macos(): 90 | self.hostarchname = 'darwin-x86_64' 91 | 92 | def build_toolchain(self): 93 | buildtools_path = os.path.join(self.sdkpath, 'build-tools') 94 | buildtools_list = [item for item in os.listdir(buildtools_path) if os.path.isdir(os.path.join(buildtools_path, item))] 95 | buildtools_list.sort(key = lambda s: map(int, s.split('-')[0].split('.'))) 96 | 97 | self.buildtools_path = os.path.join(self.sdkpath, 'build-tools', buildtools_list[-1]) 98 | self.android_jar = os.path.join(self.sdkpath, 'platforms', 'android-' + self.platformversion, 'android.jar') 99 | 100 | self.javac = 'javac' 101 | self.jarsigner = 'jarsigner' 102 | if self.javasdk != '': 103 | self.javac = os.path.join(self.javasdk, 'bin', self.javac) 104 | self.jarsigner = os.path.join(self.javasdk, 'bin', self.jarsigner) 105 | if self.host.is_windows(): 106 | self.dex = os.path.join(self.buildtools_path, 'dx.bat') 107 | else: 108 | self.dex = os.path.join(self.buildtools_path, 'dx' + self.exe_suffix) 109 | if not os.path.isfile(self.dex): 110 | self.dex = os.path.join(self.sdkpath, 'tools', 'dx' + self.exe_suffix) 111 | self.aapt = os.path.join(self.buildtools_path, 'aapt' + self.exe_suffix) 112 | self.zipalign = os.path.join(self.buildtools_path, 'zipalign' + self.exe_suffix) 113 | if not os.path.isfile( self.zipalign ): 114 | self.zipalign = os.path.join(self.sdkpath, 'tools', 'zipalign' + self.exe_suffix) 115 | 116 | def parse_prefs(self, prefs): 117 | if 'android' in prefs: 118 | androidprefs = prefs['android'] 119 | if 'ndkpath' in androidprefs: 120 | self.ndkpath = os.path.expanduser(androidprefs['ndkpath']) 121 | if 'sdkpath' in androidprefs: 122 | self.sdkpath = os.path.expanduser(androidprefs['sdkpath']) 123 | if 'platformversion' in androidprefs: 124 | self.platformversion = androidprefs['platformversion'] 125 | if 'gccversion' in androidprefs: 126 | self.gcc_toolchainversion = androidprefs['gccversion'] 127 | if 'javasdk' in androidprefs: 128 | self.javasdk = androidprefs['javasdk'] 129 | 130 | def write_variables(self, writer): 131 | writer.variable('ndk', self.ndkpath) 132 | writer.variable('sdk', self.sdkpath) 133 | writer.variable('sysroot', self.sysroot) 134 | writer.variable('androidjar', self.android_jar ) 135 | writer.variable('apkbuildpath', '') 136 | writer.variable('apk', '') 137 | writer.variable('apksource', '') 138 | writer.variable('apkaddfiles', '') 139 | writer.variable('javac', self.javac) 140 | writer.variable('dex', self.dex) 141 | writer.variable('aapt', self.aapt) 142 | writer.variable('zipalign', self.zipalign) 143 | writer.variable('jarsigner', self.jarsigner) 144 | writer.variable('aaptflags', '') 145 | 146 | def write_rules(self, writer): 147 | writer.rule('aapt', command = self.aaptcmd, description = 'AAPT $out') 148 | writer.rule('aaptdeploy', command = self.aaptdeploycmd, description = 'AAPT $out') 149 | writer.rule('aaptadd', command = self.aaptaddcmd, description = 'AAPT $out') 150 | writer.rule('javac', command = self.javaccmd, description = 'JAVAC $in') 151 | writer.rule('dex', command = self.dexcmd, description = 'DEX $out') 152 | writer.rule('zip', command = self.zipcmd, description = 'ZIP $out') 153 | writer.rule('zipalign', command = self.zipaligncmd, description = 'ZIPALIGN $out') 154 | writer.rule('codesign', command = self.codesigncmd, description = 'CODESIGN $out') 155 | 156 | def make_sysroot_path(self, arch): 157 | return os.path.join(self.ndkpath, 'platforms', 'android-' + self.platformversion, 'arch-' + self.archname[arch]) 158 | 159 | def make_gcc_toolchain_path(self, arch): 160 | return os.path.join(self.ndkpath, 'toolchains', self.gcc_toolchainname[arch], 'prebuilt', self.hostarchname) 161 | 162 | def make_gcc_bin_path(self, arch): 163 | return os.path.join(self.make_gcc_toolchain_path(arch), 'bin', self.gcc_toolchainprefix[arch]) 164 | 165 | def archname(self): 166 | return self.archname 167 | 168 | def archpath(self): 169 | return self.archpath 170 | 171 | def hostarchname(self): 172 | return self.hostarchname 173 | 174 | def apk(self, toolchain, writer, module, archbins, javasources, outpath, binname, basepath, config, implicit_deps, resources): 175 | buildpath = os.path.join('$buildpath', config, 'apk', binname) 176 | baseapkname = binname + ".base.apk" 177 | unsignedapkname = binname + ".unsigned.apk" 178 | unalignedapkname = binname + ".unaligned.apk" 179 | apkname = binname + ".apk" 180 | apkfiles = [] 181 | libfiles = [] 182 | locallibs = [] 183 | resfiles = [] 184 | manifestfile = [] 185 | 186 | writer.comment('Make APK') 187 | for _, value in archbins.iteritems(): 188 | for archbin in value: 189 | archpair = os.path.split(archbin) 190 | libname = archpair[1] 191 | arch = os.path.split(archpair[0])[1] 192 | locallibpath = os.path.join('lib', self.archpath[arch], libname) 193 | archpath = os.path.join(buildpath, locallibpath) 194 | locallibs += [locallibpath + ' '] 195 | libfiles += toolchain.copy(writer, archbin, archpath) 196 | for resource in resources: 197 | filename = os.path.split(resource)[1] 198 | if filename == 'AndroidManifest.xml': 199 | manifestfile = toolchain.copy(writer, os.path.join(basepath, module, resource), os.path.join(buildpath, 'AndroidManifest.xml')) 200 | else: 201 | restype = os.path.split(os.path.split(resource)[0])[1] 202 | if restype == 'asset': 203 | pass #todo: implement 204 | else: 205 | resfiles += toolchain.copy(writer, os.path.join(basepath, module, resource), os.path.join(buildpath, 'res', restype, filename)) 206 | 207 | #Make directories 208 | gendir = toolchain.mkdir(writer, os.path.join(buildpath, 'gen')) 209 | bindir = toolchain.mkdir(writer, os.path.join(buildpath, 'bin')) 210 | binresdir = toolchain.mkdir(writer, os.path.join(buildpath, 'bin', 'res'), order_only = bindir) 211 | alldirs = gendir + bindir + binresdir 212 | 213 | aaptvars = [('apkbuildpath', buildpath), ('apk', baseapkname)] 214 | aaptout = os.path.join(buildpath, baseapkname) 215 | if config == 'deploy': 216 | baseapkfile = writer.build(aaptout, 'aaptdeploy', manifestfile, variables = aaptvars, implicit = manifestfile + resfiles, order_only = alldirs) 217 | else: 218 | baseapkfile = writer.build(aaptout, 'aapt', manifestfile, variables = aaptvars, implicit = manifestfile + resfiles, order_only = alldirs) 219 | 220 | #Compile java code 221 | javafiles = [] 222 | localjava = [] 223 | if javasources != []: 224 | #self.javaccmd = '$javac -d $outpath -classpath $outpath -sourcepath $sourcepath -target 1.5 -bootclasspath $androidjar -g -source 1.5 -Xlint:-options $in' 225 | #self.dexcmd = '$dex --dex --output $out $in' 226 | javasourcepath = '.' 227 | if self.host.is_windows(): 228 | javasourcepath += ';' 229 | else: 230 | javasourcepath += ':' 231 | javasourcepath += os.path.join(buildpath, 'gen') 232 | classpath = os.path.join(buildpath, 'classes') 233 | javavars = [('outpath', classpath), ('sourcepath', javasourcepath)] 234 | javaclasses = writer.build(classpath, 'javac', javasources, variables = javavars, implicit = baseapkfile) 235 | localjava += ['classes.dex'] 236 | javafiles += writer.build(os.path.join(buildpath, 'classes.dex'), 'dex', classpath) 237 | 238 | #Add native libraries and java classes to apk 239 | aaptvars = [('apkbuildpath', buildpath), ('apk', unsignedapkname), ('apksource', baseapkname), ('apkaddfiles', toolchain.paths_forward_slash(locallibs + localjava))] 240 | unsignedapkfile = writer.build(os.path.join(buildpath, unsignedapkname), 'aaptadd', baseapkfile, variables = aaptvars, implicit = libfiles + javafiles, order_only = alldirs) 241 | 242 | #Sign the APK 243 | codesignvars = [('config', config)] 244 | unalignedapkfile = writer.build(os.path.join(buildpath, unalignedapkname), 'codesign', unsignedapkfile, variables = codesignvars) 245 | 246 | #Run zipalign 247 | outfile = writer.build(os.path.join(outpath, config, apkname), 'zipalign', unalignedapkfile) 248 | return outfile 249 | -------------------------------------------------------------------------------- /build/ninja/codesign.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """Codesign utility""" 4 | 5 | import argparse 6 | import subprocess 7 | import os 8 | import time 9 | import shutil 10 | import json 11 | 12 | parser = argparse.ArgumentParser(description = 'Codesign utility for Ninja builds') 13 | parser.add_argument('file', type=str, 14 | help = 'Bundle/package to sign') 15 | parser.add_argument('--target', type=str, 16 | help = 'Target', 17 | choices = ['macos', 'ios', 'android'], 18 | default = '') 19 | parser.add_argument('--bundle', type=str, 20 | help = 'Bundle identifier (OSX/iOS)', 21 | default = '') 22 | parser.add_argument('--organisation', type=str, 23 | help = 'Organisation identifier (OSX/iOS)', 24 | default = '') 25 | parser.add_argument('--provisioning', type=str, 26 | help = 'Provisioning profile (OSX/iOS)', 27 | default = '') 28 | parser.add_argument('--builddir', type=str, 29 | help = 'Build directory (OSX/iOS)', 30 | default = '') 31 | parser.add_argument('--binname', type=str, 32 | help = 'Binary name (OSX/iOS)', 33 | default = '') 34 | parser.add_argument('--zipfile', type=str, 35 | help = 'Zip file (Android)', 36 | default = '') 37 | parser.add_argument('--tsacert', type=str, 38 | help = 'TSA cert (Android)', 39 | default = '') 40 | parser.add_argument('--tsa', type=str, 41 | help = 'TSA (Android)', 42 | default = '') 43 | parser.add_argument('--keystore', type=str, 44 | help = 'Keystore (Android)', 45 | default = '') 46 | parser.add_argument('--keystorepass', type=str, 47 | help = 'Keystore password (Android)', 48 | default = '') 49 | parser.add_argument('--keyalias', type=str, 50 | help = 'Key alias (Android)', 51 | default = '') 52 | parser.add_argument('--keypass', type=str, 53 | help = 'Key password (Android)', 54 | default = '') 55 | parser.add_argument('--jarsigner', type=str, 56 | help = 'JAR signer (Android)', 57 | default = 'jarsigner') 58 | parser.add_argument('--prefs', type=str, 59 | help = 'Preferences file', 60 | default = '') 61 | parser.add_argument('--config', type=str, 62 | help = 'Build configuration', 63 | default = '') 64 | parser.add_argument('--entitlements', type=str, 65 | help = 'Entitlements file', 66 | default = '') 67 | options = parser.parse_args() 68 | 69 | androidprefs = {} 70 | iosprefs = {} 71 | macosprefs = {} 72 | 73 | 74 | def parse_prefs( prefsfile ): 75 | global androidprefs 76 | global iosprefs 77 | global macosprefs 78 | if not os.path.isfile( prefsfile ): 79 | return 80 | file = open( prefsfile, 'r' ) 81 | prefs = json.load( file ) 82 | file.close() 83 | if 'android' in prefs: 84 | androidprefs = prefs['android'] 85 | if 'ios' in prefs: 86 | iosprefs = prefs['ios'] 87 | if 'macos' in prefs: 88 | macosprefs = prefs['macos'] 89 | 90 | 91 | def codesign_ios(): 92 | if not 'organisation' in iosprefs: 93 | iosprefs['organisation'] = options.organisation 94 | if not 'bundleidentifier' in iosprefs: 95 | iosprefs['bundleidentifier'] = options.bundle 96 | if not 'provisioning' in iosprefs: 97 | iosprefs['provisioning'] = options.provisioning 98 | 99 | sdkdir = subprocess.check_output( [ 'xcrun', '--sdk', 'iphoneos', '--show-sdk-path' ] ).decode().strip().splitlines()[-1] 100 | entitlements = os.path.join( sdkdir, 'Entitlements.plist' ) 101 | plistpath = os.path.join( options.builddir, 'Entitlements.xcent' ) 102 | 103 | platformpath = subprocess.check_output( [ 'xcrun', '--sdk', 'iphoneos', '--show-sdk-platform-path' ] ).decode().strip().splitlines()[-1] 104 | localpath = platformpath + "/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin" 105 | plutil = "PATH=" + localpath + " " + subprocess.check_output( [ 'xcrun', '--sdk', 'iphoneos', '-f', 'plutil' ] ).decode().strip().splitlines()[-1] 106 | 107 | shutil.copyfile( entitlements, plistpath ) 108 | os.system( plutil + ' -convert xml1 ' + plistpath ) 109 | 110 | f = open( plistpath, 'r' ) 111 | lines = [ line.strip( '\n\r' ) for line in f ] 112 | f.close() 113 | 114 | for i in range( 0, len( lines ) ): 115 | if lines[i].find( '$(AppIdentifierPrefix)' ) != -1: 116 | lines[i] = lines[i].replace( '$(AppIdentifierPrefix)', iosprefs['organisation'] + '.' ) 117 | if lines[i].find( '$(CFBundleIdentifier)' ) != -1: 118 | lines[i] = lines[i].replace( '$(CFBundleIdentifier)', iosprefs['bundleidentifier'] ) 119 | if lines[i].find( '$(binname)' ) != -1: 120 | lines[i] = lines[i].replace( '$(binname)', options.binname ) 121 | 122 | with open( plistpath, 'w' ) as plist_file: 123 | for line in lines: 124 | if options.config != 'deploy' and line == '': 125 | plist_file.write( '\tget-task-allow\n' ) 126 | plist_file.write( '\t\n' ) 127 | plist_file.write( line + '\n' ) 128 | plist_file.close() 129 | 130 | if os.path.isfile( os.path.join( options.file, '_CodeSignature', 'CodeResources' ) ): 131 | os.remove( os.path.join( options.file, '_CodeSignature', 'CodeResources' ) ) 132 | 133 | os.system( '/usr/bin/codesign --force --sign "' + iosprefs['signature'] + '" --entitlements ' + plistpath + ' ' + options.file ) 134 | 135 | if os.path.isfile( os.path.join( options.file, '_CodeSignature', 'CodeResources' ) ): 136 | os.utime( os.path.join( options.file, '_CodeSignature', 'CodeResources' ), None ) 137 | os.utime( os.path.join( options.file, '_CodeSignature' ), None ) 138 | os.utime( options.file, None ) 139 | 140 | 141 | def codesign_macos(): 142 | if not 'organisation' in macosprefs: 143 | macosprefs['organisation'] = options.organisation 144 | if not 'bundleidentifier' in macosprefs: 145 | macosprefs['bundleidentifier'] = options.bundle 146 | if not 'provisioning' in macosprefs: 147 | macosprefs['provisioning'] = options.provisioning 148 | if not 'entitlements' in macosprefs: 149 | macosprefs['entitlements'] = options.entitlements 150 | 151 | codesign_allocate = subprocess.check_output( [ 'xcrun', '--sdk', 'macosx', '-f', 'codesign_allocate' ] ).decode().strip().splitlines()[-1] 152 | sdkdir = subprocess.check_output( [ 'xcrun', '--sdk', 'macosx', '--show-sdk-path' ] ).decode().strip().splitlines()[-1] 153 | entitlements = os.path.join( sdkdir, 'Entitlements.plist' ) 154 | 155 | if os.path.isfile( os.path.join( options.file, 'Contents', '_CodeSignature', 'CodeResources' ) ): 156 | os.remove( os.path.join( options.file, 'Contents', '_CodeSignature', 'CodeResources' ) ) 157 | 158 | if 'signature' in macosprefs: 159 | command = 'export CODESIGN_ALLOCATE=' + codesign_allocate + '; /usr/bin/codesign --force --sign "' + macosprefs['signature'] + '" -o runtime ' 160 | if ('entitlements' in macosprefs) and (macosprefs['entitlements'] != '') and (macosprefs['entitlements'] != 'none'): 161 | command = command + '--entitlements ' + macosprefs['entitlements'] + ' --generate-entitlement-der ' 162 | command = command + options.file 163 | # print(command) 164 | os.system(command) 165 | 166 | if os.path.isfile( os.path.join( options.file, 'Contents', '_CodeSignature', 'CodeResources' ) ): 167 | os.utime( os.path.join( options.file, 'Contents', '_CodeSignature', 'CodeResources' ), None ) 168 | os.utime( os.path.join( options.file, 'Contents', '_CodeSignature' ), None ) 169 | os.utime( os.path.join( options.file, 'Contents' ), None ) 170 | os.utime( options.file, None ) 171 | 172 | 173 | def codesign_android(): 174 | if not 'tsacert' in androidprefs: 175 | androidprefs['tsacert'] = options.tsacert 176 | if not 'tsa' in androidprefs: 177 | androidprefs['tsa'] = options.tsa 178 | if not 'keystore' in androidprefs: 179 | androidprefs['keystore'] = options.keystore 180 | if not 'keystorepass' in androidprefs: 181 | androidprefs['keystorepass'] = options.keystorepass 182 | if not 'keyalias' in androidprefs: 183 | androidprefs['keyalias'] = options.keyalias 184 | if not 'keypass' in androidprefs: 185 | androidprefs['keypass'] = options.keypass 186 | if not 'jarsigner' in androidprefs: 187 | androidprefs['jarsigner'] = options.jarsigner 188 | 189 | timestamp = '' 190 | if androidprefs['tsacert'] != '': 191 | timestamp = '-tsacert ' + androidprefs['tsacert'] 192 | elif androidprefs['tsa'] != '': 193 | timestamp = '-tsa ' + androidprefs['tsa'] 194 | 195 | proxy = '' 196 | if 'proxy' in androidprefs and androidprefs['proxy'] != '' and androidprefs['proxy'] != 'None': 197 | proxy = androidprefs['proxy'] 198 | if proxy != '' and proxy != 'None': 199 | defstr = "-J-Dhttp.proxy" 200 | url = urlparse.urlparse(proxy) 201 | if url.scheme == 'https': 202 | defstr = "-J-Dhttps.proxy" 203 | host = url.netloc 204 | port = '' 205 | username = '' 206 | password = '' 207 | if '@' in host: 208 | username, host = host.split(':', 1) 209 | password, host = host.split('@', 1) 210 | if ':' in host: 211 | host, port = host.split(':', 1) 212 | proxy = defstr + "Host=" + host 213 | if port != '': 214 | proxy += " " + defstr + "Port=" + port 215 | if username != '': 216 | proxy += " " + defstr + "User=" + username 217 | if password != '': 218 | proxy += " " + defstr + "Password=" + password 219 | 220 | signcmd = androidprefs['jarsigner'] + ' ' + timestamp + ' -sigalg SHA1withRSA -digestalg SHA1 -keystore ' + androidprefs['keystore'] + ' -storepass ' + androidprefs['keystorepass'] + ' -keypass ' + androidprefs['keypass'] + ' -signedjar ' + options.file + ' ' + options.zipfile + ' ' + androidprefs['keyalias'] + ' ' + proxy 221 | os.system(signcmd) 222 | 223 | 224 | parse_prefs( options.prefs ) 225 | 226 | if options.target == 'ios': 227 | codesign_ios() 228 | elif options.target == 'macos': 229 | codesign_macos() 230 | elif options.target == 'android': 231 | codesign_android() 232 | -------------------------------------------------------------------------------- /build/ninja/generator.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """Ninja build generator""" 4 | 5 | import argparse 6 | import os 7 | import pipes 8 | import sys 9 | 10 | import platform 11 | import toolchain 12 | import syntax 13 | 14 | class Generator(object): 15 | def __init__(self, project, includepaths = [], dependlibs = [], libpaths = [], variables = None): 16 | parser = argparse.ArgumentParser(description = 'Ninja build generator') 17 | parser.add_argument('-t', '--target', 18 | help = 'Target platform', 19 | choices = platform.supported_platforms()) 20 | parser.add_argument('--host', 21 | help = 'Host platform', 22 | choices = platform.supported_platforms()) 23 | parser.add_argument('--toolchain', 24 | help = 'Toolchain to use', 25 | choices = toolchain.supported_toolchains()) 26 | parser.add_argument('-c', '--config', action = 'append', 27 | help = 'Build configuration', 28 | choices = ['debug', 'release', 'profile', 'deploy'], 29 | default = []) 30 | parser.add_argument('-a', '--arch', action = 'append', 31 | help = 'Add architecture', 32 | choices = toolchain.supported_architectures(), 33 | default = []) 34 | parser.add_argument('-i', '--includepath', action = 'append', 35 | help = 'Add include path', 36 | default = []) 37 | parser.add_argument('--monolithic', action='store_true', 38 | help = 'Build monolithic test suite', 39 | default = False) 40 | parser.add_argument('--coverage', action='store_true', 41 | help = 'Build with code coverage', 42 | default = False) 43 | parser.add_argument('--subninja', action='store', 44 | help = 'Build as subproject (exclude rules and pools) with the given subpath', 45 | default = '') 46 | parser.add_argument('--buildprefs', action='store', 47 | help = 'Read the given build preferences file', 48 | default = '') 49 | parser.add_argument('--updatebuild', action='store_true', 50 | help = 'Update submodule build scripts', 51 | default = '') 52 | parser.add_argument('--lto', action='store_true', 53 | help = 'Build with Link Time Optimization', 54 | default = False) 55 | options = parser.parse_args() 56 | 57 | self.project = project 58 | self.target = platform.Platform(options.target) 59 | self.host = platform.Platform(options.host) 60 | self.subninja = options.subninja 61 | archs = options.arch 62 | configs = options.config 63 | if includepaths is None: 64 | includepaths = [] 65 | if not options.includepath is None: 66 | includepaths += options.includepath 67 | 68 | buildfile = open('build.ninja', 'w') 69 | self.writer = syntax.Writer(buildfile) 70 | 71 | self.writer.variable('ninja_required_version', '1.3') 72 | self.writer.newline() 73 | 74 | self.writer.comment('configure.py arguments') 75 | self.writer.variable('configure_args', ' '.join(sys.argv[1:])) 76 | self.writer.newline() 77 | 78 | self.writer.comment('configure options') 79 | self.writer.variable('configure_target', self.target.platform) 80 | self.writer.variable('configure_host', self.host.platform) 81 | 82 | env_keys = set(['CC', 'AR', 'LINK', 'CFLAGS', 'ARFLAGS', 'LINKFLAGS']) 83 | configure_env = dict((key, os.environ[key]) for key in os.environ if key in env_keys) 84 | if configure_env: 85 | config_str = ' '.join([key + '=' + pipes.quote(configure_env[key]) for key in configure_env]) 86 | self.writer.variable('configure_env', config_str + '$ ') 87 | 88 | if variables is None: 89 | variables = {} 90 | if not isinstance(variables, dict): 91 | variables = dict(variables) 92 | 93 | if options.monolithic: 94 | variables['monolithic'] = True 95 | if options.coverage: 96 | variables['coverage'] = True 97 | if options.lto: 98 | variables['lto'] = True 99 | if self.subninja != '': 100 | variables['internal_deps'] = True 101 | 102 | self.toolchain = toolchain.make_toolchain(self.host, self.target, options.toolchain) 103 | self.toolchain.buildprefs = options.buildprefs 104 | self.toolchain.initialize(project, archs, configs, includepaths, dependlibs, libpaths, variables, self.subninja) 105 | 106 | self.writer.variable('configure_toolchain', self.toolchain.name()) 107 | self.writer.variable('configure_archs', archs) 108 | self.writer.variable('configure_configs', configs) 109 | self.writer.newline() 110 | 111 | self.toolchain.write_variables(self.writer) 112 | if self.subninja == '': 113 | self.toolchain.write_rules(self.writer) 114 | 115 | def target(self): 116 | return self.target 117 | 118 | def host(self): 119 | return self.host 120 | 121 | def toolchain(self): 122 | return self.toolchain 123 | 124 | def writer(self): 125 | return self.writer 126 | 127 | def is_subninja(self): 128 | return self.subninja != '' 129 | 130 | def lib(self, module, sources, libname = None, basepath = None, configs = None, includepaths = None, variables = None): 131 | return self.toolchain.lib(self.writer, module, sources, libname, basepath, configs, includepaths, variables) 132 | 133 | def sharedlib(self, module, sources, libname = None, basepath = None, configs = None, includepaths = None, libpaths = None, implicit_deps = None, dependlibs = None, libs = None, frameworks = None, variables = None): 134 | return self.toolchain.sharedlib(self.writer, module, sources, libname, basepath, configs, includepaths, libpaths, implicit_deps, dependlibs, libs, frameworks, variables) 135 | 136 | def bin(self, module, sources, binname, basepath = None, configs = None, includepaths = None, libpaths = None, implicit_deps = None, dependlibs = None, libs = None, frameworks = None, variables = None): 137 | return self.toolchain.bin(self.writer, module, sources, binname, basepath, configs, includepaths, libpaths, implicit_deps, dependlibs, libs, frameworks, variables) 138 | 139 | def app(self, module, sources, binname, basepath = None, configs = None, includepaths = None, libpaths = None, implicit_deps = None, dependlibs = None, libs = None, frameworks = None, variables = None, resources = None): 140 | return self.toolchain.app(self.writer, module, sources, binname, basepath, configs, includepaths, libpaths, implicit_deps, dependlibs, libs, frameworks, variables, resources) 141 | 142 | def test_includepaths(self): 143 | #TODO: This is ugly 144 | if self.project == "foundation": 145 | return ['test'] 146 | foundation_path = os.path.join('..', 'foundation_lib') 147 | if not os.path.isfile(os.path.join(foundation_path, 'foundation', 'foundation.h')): 148 | foundation_path = os.path.join('..', 'foundation') 149 | return ['test', os.path.join(foundation_path, 'test')] 150 | 151 | def test_monolithic(self): 152 | return self.toolchain.is_monolithic() 153 | -------------------------------------------------------------------------------- /build/ninja/platform.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """Ninja platform abstraction""" 4 | 5 | import sys 6 | 7 | def supported_platforms(): 8 | return [ 'windows', 'linux', 'macos', 'bsd', 'ios', 'android', 'raspberrypi', 'tizen', 'sunos', 'haiku' ] 9 | 10 | class Platform(object): 11 | def __init__(self, platform): 12 | self.platform = platform 13 | if self.platform is None: 14 | self.platform = sys.platform 15 | if self.platform.startswith('linux'): 16 | self.platform = 'linux' 17 | elif self.platform.startswith('darwin'): 18 | self.platform = 'macos' 19 | elif self.platform.startswith('macos'): 20 | self.platform = 'macos' 21 | elif self.platform.startswith('win'): 22 | self.platform = 'windows' 23 | elif 'bsd' in self.platform or self.platform.startswith('dragonfly'): 24 | self.platform = 'bsd' 25 | elif self.platform.startswith('ios'): 26 | self.platform = 'ios' 27 | elif self.platform.startswith('android'): 28 | self.platform = 'android' 29 | elif self.platform.startswith('raspberry'): 30 | self.platform = 'raspberrypi' 31 | elif self.platform.startswith('tizen'): 32 | self.platform = 'tizen' 33 | elif self.platform.startswith('sunos'): 34 | self.platform = 'sunos' 35 | elif self.platform.startswith('haiku'): 36 | self.platform = 'haiku' 37 | 38 | def platform(self): 39 | return self.platform 40 | 41 | def is_linux(self): 42 | return self.platform == 'linux' 43 | 44 | def is_windows(self): 45 | return self.platform == 'windows' 46 | 47 | def is_macos(self): 48 | return self.platform == 'macos' 49 | 50 | def is_bsd(self): 51 | return self.platform == 'bsd' 52 | 53 | def is_ios(self): 54 | return self.platform == 'ios' 55 | 56 | def is_android(self): 57 | return self.platform == 'android' 58 | 59 | def is_raspberrypi(self): 60 | return self.platform == 'raspberrypi' 61 | 62 | def is_tizen(self): 63 | return self.platform == 'tizen' 64 | 65 | def is_sunos(self): 66 | return self.platform == 'sunos' 67 | 68 | def is_haiku(self): 69 | return self.platform == 'haiku' 70 | 71 | def get(self): 72 | return self.platform 73 | -------------------------------------------------------------------------------- /build/ninja/plist.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """PList utility""" 4 | 5 | import argparse 6 | import os 7 | import subprocess 8 | import re 9 | import unicodedata 10 | 11 | def normalize_char(c): 12 | try: 13 | UNICODE_EXISTS = bool(type(unicode)) 14 | except NameError: 15 | unicode = lambda s: str(s) 16 | try: 17 | cname = unicodedata.name( unicode(c) ) 18 | cname = cname[:cname.index( ' WITH' )] 19 | return unicodedata.lookup( cname ) 20 | except ( ValueError, KeyError ): 21 | return c 22 | 23 | def normalize_string(s): 24 | return ''.join( normalize_char(c) for c in s ) 25 | 26 | def replace_var( str, var, val ): 27 | if str.find( '$(' + var + ')' ) != -1: 28 | return str.replace( '$(' + var + ')', val ) 29 | if str.find( '${' + var + '}' ) != -1: 30 | return str.replace( '${' + var + '}', val ) 31 | return str 32 | 33 | 34 | parser = argparse.ArgumentParser( description = 'PList utility for Ninja builds' ) 35 | parser.add_argument( 'files', 36 | metavar = 'file', type=open, nargs='+', 37 | help = 'Source plist file' ) 38 | parser.add_argument( '--exename', type=str, 39 | help = 'Executable name', 40 | default = [] ) 41 | parser.add_argument( '--prodname', type=str, 42 | help = 'Product name', 43 | default = [] ) 44 | parser.add_argument( '--bundle', type=str, 45 | help = 'Bundle identifier', 46 | default = [] ) 47 | parser.add_argument( '--output', type=str, 48 | help = 'Output path', 49 | default = [] ) 50 | parser.add_argument( '--target', type=str, 51 | help = 'Target OS', 52 | default = [] ) 53 | parser.add_argument( '--deploymenttarget', type=str, 54 | help = 'Target OS version', 55 | default = [] ) 56 | options = parser.parse_args() 57 | 58 | if not options.exename: 59 | options.exename = 'unknown' 60 | if not options.prodname: 61 | options.prodname = 'unknown' 62 | if not options.target: 63 | options.target = 'macos' 64 | if not options.deploymenttarget: 65 | if options.target == 'macos': 66 | options.deploymenttarget = '12.0' 67 | else: 68 | options.deploymenttarget = '10.0' 69 | 70 | buildversion = subprocess.check_output( [ 'sw_vers', '-buildVersion' ] ).decode().strip() 71 | 72 | #Merge input plists using first file as base 73 | lines = [] 74 | for f in options.files: 75 | _, extension = os.path.splitext(f.name) 76 | if extension != '.plist': 77 | continue 78 | if lines == []: 79 | lines += [ line.strip( '\n\r' ) for line in f ] 80 | else: 81 | mergelines = [ line.strip( '\n\r' ) for line in f ] 82 | for i in range( 0, len( mergelines ) ): 83 | if re.match( '^$', mergelines[i] ): 84 | break 85 | if re.match( '^$', mergelines[i] ): 86 | for j in range( 0, len( lines ) ): 87 | if re.match( '^$', lines[j] ): 88 | for k in range( i+1, len( mergelines ) ): 89 | if re.match( '^$', mergelines[k] ): 90 | break 91 | lines.insert( j+(k-(i+1)), mergelines[k] ) 92 | break 93 | break 94 | 95 | #Parse input plist to get package type and signature 96 | bundle_package_type = 'APPL' 97 | bundle_signature = '????' 98 | 99 | for i in range( 0, len( lines ) ): 100 | if 'CFBundlePackageType' in lines[i]: 101 | match = re.match( '^.*>(.*)<.*$', lines[i+1] ) 102 | if match: 103 | bundle_package_type = match.group(1) 104 | if 'CFBundleSignature' in lines[i]: 105 | match = re.match( '^.*>(.*)<.*$', lines[i+1] ) 106 | if match: 107 | bundle_signature = match.group(1) 108 | 109 | #Write package type and signature to PkgInfo in output path 110 | with open( os.path.join( os.path.dirname( options.output ), 'PkgInfo' ), 'w' ) as pkginfo_file: 111 | pkginfo_file.write( bundle_package_type + bundle_signature ) 112 | pkginfo_file.close() 113 | 114 | #insert os version 115 | for i in range( 0, len( lines ) ): 116 | if re.match( '^$', lines[i] ): 117 | lines.insert( i+1, '\tBuildMachineOSBuild' ) 118 | lines.insert( i+2, '\t' + buildversion + '' ) 119 | break 120 | 121 | #replace build variables name 122 | for i in range( 0, len( lines ) ): 123 | lines[i] = replace_var( lines[i], 'EXECUTABLE_NAME', options.exename ) 124 | lines[i] = replace_var( lines[i], 'PRODUCT_NAME', options.prodname ) 125 | lines[i] = replace_var( lines[i], 'PRODUCT_NAME:rfc1034identifier', normalize_string( options.exename ).lower() ) 126 | lines[i] = replace_var( lines[i], 'PRODUCT_NAME:c99extidentifier', normalize_string( options.exename ).lower().replace( '-', '_' ).replace( '.', '_' ) ) 127 | lines[i] = replace_var( lines[i], 'IOS_DEPLOYMENT_TARGET', options.deploymenttarget ) 128 | lines[i] = replace_var( lines[i], 'MACOSX_DEPLOYMENT_TARGET', options.deploymenttarget ) 129 | 130 | #replace bundle identifier if given 131 | if not options.bundle is None and options.bundle != '': 132 | for i in range( 0, len( lines ) ): 133 | if lines[i].find( 'CFBundleIdentifier' ) != -1: 134 | lines[i+1] = '\t' + normalize_string( options.bundle ) + '' 135 | break 136 | 137 | #add supported platform, minimum os version and requirements 138 | if options.target == 'ios': 139 | for i in range( 0, len( lines ) ): 140 | if 'CFBundleSignature' in lines[i]: 141 | lines.insert( i+2, '\tCFBundleSupportedPlatforms' ) 142 | lines.insert( i+3, '\t' ) 143 | lines.insert( i+4, '\t\tiPhoneOS' ) 144 | lines.insert( i+5, '\t' ) 145 | lines.insert( i+6, '\tMinimumOSVersion' ) 146 | lines.insert( i+7, '\t6.0' ) 147 | lines.insert( i+8, '\tUIDeviceFamily' ) 148 | lines.insert( i+9, '\t' ) 149 | lines.insert( i+10, '\t\t1' ) 150 | lines.insert( i+11, '\t\t2' ) 151 | lines.insert( i+12, '\t' ) 152 | break 153 | 154 | #add build info 155 | #DTCompiler 156 | #com.apple.compilers.llvm.clang.1_0 157 | #DTPlatformBuild 158 | #12B411 159 | #DTPlatformName 160 | #iphoneos 161 | #DTPlatformVersion 162 | #8.1 163 | #DTSDKBuild 164 | #12B411 165 | #DTSDKName 166 | #iphoneos8.1 167 | #DTXcode 168 | #0611 169 | #DTXcodeBuild 170 | #6A2008a 171 | 172 | #write final Info.plist in output path 173 | with open( options.output, 'w' ) as plist_file: 174 | for line in lines: 175 | #print lines[i] 176 | plist_file.write( line + '\n' ) 177 | plist_file.close() 178 | 179 | #run plutil -convert binary1 180 | sdk = 'iphoneos' 181 | platformpath = subprocess.check_output( [ 'xcrun', '--sdk', sdk, '--show-sdk-platform-path' ] ).decode().strip() 182 | localpath = platformpath + "/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin" 183 | plutil = "PATH=" + localpath + " " + subprocess.check_output( [ 'xcrun', '--sdk', sdk, '-f', 'plutil' ] ).decode().strip() 184 | plcommand = plutil + ' -convert binary1 ' + options.output 185 | os.system( plcommand ) 186 | -------------------------------------------------------------------------------- /build/ninja/syntax.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """Python module for generating .ninja files. 4 | 5 | Note that this is emphatically not a required piece of Ninja; it's 6 | just a helpful utility for build-file-generation systems that already 7 | use Python. 8 | """ 9 | 10 | import textwrap 11 | 12 | def escape_path(word): 13 | return word.replace('$ ', '$$ ').replace(' ', '$ ').replace(':', '$:') 14 | 15 | class Writer(object): 16 | def __init__(self, output, width=78): 17 | self.output = output 18 | self.width = width 19 | 20 | def newline(self): 21 | self.output.write('\n') 22 | 23 | def comment(self, text): 24 | for line in textwrap.wrap(text, self.width - 2): 25 | self.output.write('# ' + line + '\n') 26 | 27 | def variable(self, key, value, indent=0): 28 | if value is None: 29 | return 30 | if isinstance(value, list): 31 | value = ' '.join(filter(None, value)) # Filter out empty strings. 32 | self._line('%s = %s' % (key, value), indent) 33 | 34 | def pool(self, name, depth): 35 | self._line('pool %s' % name) 36 | self.variable('depth', depth, indent=1) 37 | 38 | def rule(self, name, command, description=None, depfile=None, 39 | generator=False, pool=None, restat=False, rspfile=None, 40 | rspfile_content=None, deps=None): 41 | self._line('rule %s' % name) 42 | self.variable('command', command, indent=1) 43 | if description: 44 | self.variable('description', description, indent=1) 45 | if depfile: 46 | self.variable('depfile', depfile, indent=1) 47 | if generator: 48 | self.variable('generator', '1', indent=1) 49 | if pool: 50 | self.variable('pool', pool, indent=1) 51 | if restat: 52 | self.variable('restat', '1', indent=1) 53 | if rspfile: 54 | self.variable('rspfile', rspfile, indent=1) 55 | if rspfile_content: 56 | self.variable('rspfile_content', rspfile_content, indent=1) 57 | if deps: 58 | self.variable('deps', deps, indent=1) 59 | 60 | def build(self, outputs, rule, inputs=None, implicit=None, order_only=None, 61 | variables=None): 62 | outputs = self._as_list(outputs) 63 | out_outputs = [escape_path(x) for x in outputs] 64 | all_inputs = [escape_path(x) for x in self._as_list(inputs)] 65 | 66 | if implicit: 67 | implicit = [escape_path(x) for x in self._as_list(implicit)] 68 | all_inputs.append('|') 69 | all_inputs.extend(implicit) 70 | if order_only: 71 | order_only = [escape_path(x) for x in self._as_list(order_only)] 72 | all_inputs.append('||') 73 | all_inputs.extend(order_only) 74 | 75 | self._line('build %s: %s' % (' '.join(out_outputs), 76 | ' '.join([rule] + all_inputs))) 77 | 78 | if variables: 79 | if isinstance(variables, dict): 80 | iterator = iter(variables.items()) 81 | else: 82 | iterator = iter(variables) 83 | 84 | for key, val in iterator: 85 | self.variable(key, val, indent=1) 86 | 87 | return outputs 88 | 89 | def include(self, path): 90 | self._line('include %s' % path) 91 | 92 | def subninja(self, path): 93 | self._line('subninja %s' % path) 94 | 95 | def default(self, paths): 96 | self._line('default %s' % ' '.join(self._as_list(paths))) 97 | 98 | def _count_dollars_before_index(self, s, i): 99 | """Returns the number of '$' characters right in front of s[i].""" 100 | dollar_count = 0 101 | dollar_index = i - 1 102 | while dollar_index > 0 and s[dollar_index] == '$': 103 | dollar_count += 1 104 | dollar_index -= 1 105 | return dollar_count 106 | 107 | def _line(self, text, indent=0): 108 | """Write 'text' word-wrapped at self.width characters.""" 109 | leading_space = ' ' * indent 110 | while len(leading_space) + len(text) > self.width: 111 | # The text is too wide; wrap if possible. 112 | 113 | # Find the rightmost space that would obey our width constraint and 114 | # that's not an escaped space. 115 | available_space = self.width - len(leading_space) - len(' $') 116 | space = available_space 117 | while True: 118 | space = text.rfind(' ', 0, space) 119 | if (space < 0 or 120 | self._count_dollars_before_index(text, space) % 2 == 0): 121 | break 122 | 123 | if space < 0: 124 | # No such space; just use the first unescaped space we can find. 125 | space = available_space - 1 126 | while True: 127 | space = text.find(' ', space + 1) 128 | if (space < 0 or 129 | self._count_dollars_before_index(text, space) % 2 == 0): 130 | break 131 | if space < 0: 132 | # Give up on breaking. 133 | break 134 | 135 | self.output.write(leading_space + text[0:space] + ' $\n') 136 | text = text[space+1:] 137 | 138 | # Subsequent lines are continuations, so indent them. 139 | leading_space = ' ' * (indent+2) 140 | 141 | self.output.write(leading_space + text + '\n') 142 | 143 | def _as_list(self, input): 144 | if input is None: 145 | return [] 146 | if isinstance(input, list): 147 | return input 148 | return [input] 149 | 150 | 151 | def escape(string): 152 | """Escape a string such that it can be embedded into a Ninja file without 153 | further interpretation.""" 154 | assert '\n' not in string, 'Ninja syntax does not allow newlines' 155 | # We only have one special metacharacter: '$'. 156 | return string.replace('$', '$$') 157 | -------------------------------------------------------------------------------- /build/ninja/version.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """Version utility""" 4 | 5 | import subprocess 6 | import os 7 | import sys 8 | 9 | def generate_version_string(libname): 10 | 11 | version_numbers = [] 12 | tokens = [] 13 | 14 | gitcmd = 'git' 15 | if sys.platform.startswith('win'): 16 | gitcmd = 'git.exe' 17 | try: 18 | git_version = subprocess.check_output( [ gitcmd, 'describe', '--tags', '--long' ], stderr = subprocess.STDOUT ).strip() 19 | tokens = git_version.decode().split( '-' ) 20 | version_numbers = tokens[0].split( '.' ) 21 | except Exception: 22 | pass 23 | 24 | version_major = "0" 25 | version_minor = "0" 26 | version_revision = "1" 27 | version_build = "0" 28 | version_scm = "0" 29 | 30 | if version_numbers and len( version_numbers ) > 2: 31 | version_major = version_numbers[0] 32 | version_minor = version_numbers[1] 33 | version_revision = version_numbers[2] 34 | 35 | if tokens and len( tokens ) > 2: 36 | version_build = tokens[1] 37 | version_scm = tokens[2][1:] 38 | 39 | module = "" 40 | if not libname == "foundation": 41 | module = "_module" 42 | 43 | source = """/* ****** AUTOMATICALLY GENERATED, DO NOT EDIT ****** 44 | This file is generated from the git describe command. 45 | Run the configure script to regenerate this file */ 46 | 47 | #include 48 | #include <""" + libname + "/" + libname + """.h> 49 | 50 | version_t 51 | """ + libname + module + """_version(void) { 52 | """ 53 | source += " return version_make(" + version_major + ", " + version_minor + ", " + version_revision + ", " + version_build + ", 0x" + version_scm + ");\n}\n" 54 | return source 55 | 56 | def read_version_string(input_path): 57 | try: 58 | file = open( os.path.join( input_path, 'version.c' ), "r" ) 59 | str = file.read() 60 | file.close() 61 | except IOError: 62 | str = "" 63 | return str 64 | 65 | def write_version_string(output_path, str): 66 | file = open( os.path.join( output_path, 'version.c' ), "w" ) 67 | file.write( str ) 68 | file.close 69 | 70 | def generate_version(libname, output_path): 71 | generated = generate_version_string(libname) 72 | if generated == None: 73 | return 74 | previous = read_version_string(output_path) 75 | 76 | if generated != previous: 77 | write_version_string(output_path, generated) 78 | 79 | if __name__ == "__main__": 80 | generate_version(sys.argv[1], sys.argv[2]) 81 | -------------------------------------------------------------------------------- /build/ninja/vslocate.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """Locate Visual Studio installations with Visual Studio Setup Configuration utility DLL""" 4 | 5 | import os 6 | import ctypes 7 | 8 | def get_vs_installations(): 9 | 10 | class ISetupInstanceVTable(ctypes.Structure): 11 | """Class matching VisualStudio Setup package ISetupInstance vtable""" 12 | pass 13 | 14 | class ISetupInstance(ctypes.Structure): 15 | """COM interface for ISetupInstance""" 16 | _fields_ = [('vtable', ctypes.POINTER(ISetupInstanceVTable))] 17 | 18 | class IEnumSetupInstancesVTable(ctypes.Structure): 19 | """Class matching VisualStudio Setup package IEnumSetupInstances vtable""" 20 | pass 21 | 22 | class IEnumSetupInstances(ctypes.Structure): 23 | """COM interface for IEnumSetupInstances""" 24 | _fields_ = [('vtable', ctypes.POINTER(IEnumSetupInstancesVTable))] 25 | 26 | class ISetupConfigurationVTable(ctypes.Structure): 27 | """Class matching VisualStudio Setup package ISetupConfiguration vtable""" 28 | pass 29 | 30 | class ISetupConfiguration(ctypes.Structure): 31 | """COM interface for ISetupConfiguration""" 32 | _fields_ = [('vtable', ctypes.POINTER(ISetupConfigurationVTable))] 33 | 34 | proto_get_installation_path = ctypes.WINFUNCTYPE( 35 | ctypes.c_int, 36 | ctypes.POINTER(ISetupInstance), 37 | ctypes.POINTER(ctypes.c_wchar_p)) 38 | 39 | proto_get_installation_version = ctypes.WINFUNCTYPE( 40 | ctypes.c_int, 41 | ctypes.POINTER(ISetupInstance), 42 | ctypes.POINTER(ctypes.c_wchar_p)) 43 | 44 | ISetupInstanceVTable._fields_ = ( 45 | ('QueryInterface', ctypes.c_void_p), 46 | ('AddRef', ctypes.c_void_p), 47 | ('Release', ctypes.c_void_p), 48 | ('GetInstanceId', ctypes.c_void_p), 49 | ('GetInstallDate', ctypes.c_void_p), 50 | ('GetInstallationName', ctypes.c_void_p), 51 | ('GetInstallationPath', proto_get_installation_path), 52 | ('GetInstallationVersion', proto_get_installation_version), 53 | ('GetDisplayName', ctypes.c_void_p), 54 | ('GetDescription', ctypes.c_void_p), 55 | ('ResolvePath', ctypes.c_void_p)) 56 | 57 | proto_next = ctypes.WINFUNCTYPE( 58 | ctypes.c_int, 59 | ctypes.POINTER(IEnumSetupInstances), 60 | ctypes.c_int, 61 | ctypes.POINTER(ctypes.POINTER(ISetupInstance)), 62 | ctypes.POINTER(ctypes.c_int)) 63 | 64 | IEnumSetupInstancesVTable._fields_ = ( 65 | ('QueryInterface', ctypes.c_void_p), 66 | ('AddRef', ctypes.c_void_p), 67 | ('Release', ctypes.c_void_p), 68 | ('Next', proto_next), 69 | ('Skip', ctypes.c_void_p), 70 | ('Reset', ctypes.c_void_p), 71 | ('Clone', ctypes.c_void_p)) 72 | 73 | proto_enum_instances = ctypes.WINFUNCTYPE( 74 | ctypes.c_int, 75 | ctypes.POINTER(ISetupConfiguration), 76 | ctypes.POINTER(ctypes.POINTER(IEnumSetupInstances))) 77 | 78 | ISetupConfigurationVTable._fields_ = ( 79 | ('QueryInterface', ctypes.c_void_p), 80 | ('AddRef', ctypes.c_void_p), 81 | ('Release', ctypes.c_void_p), 82 | ('EnumInstances', proto_enum_instances), 83 | ('GetInstanceForCurrentProcess', ctypes.c_void_p), 84 | ('GetInstanceForPath', ctypes.c_void_p)) 85 | 86 | proto_get_setup_configuration = ctypes.WINFUNCTYPE( 87 | ctypes.c_int, 88 | ctypes.POINTER(ctypes.POINTER(ISetupConfiguration)), 89 | ctypes.c_void_p) 90 | 91 | installations = [] 92 | dll = None 93 | 94 | dll_path = os.path.expandvars("$ProgramData\\Microsoft\\VisualStudio\\Setup\\x64\\Microsoft.VisualStudio.Setup.Configuration.Native.dll") 95 | try: 96 | dll = ctypes.WinDLL(dll_path) 97 | except OSError as e: 98 | #print("Failed to load Visual Studio setup configuration DLL: " + str(e)) 99 | return installations 100 | 101 | params_get_setup_configuration = (1, "configuration", 0), (1, "reserved", 0), 102 | 103 | get_setup_configuration = proto_get_setup_configuration(("GetSetupConfiguration", dll), params_get_setup_configuration) 104 | 105 | configuration = ctypes.POINTER(ISetupConfiguration)() 106 | reserved = ctypes.c_void_p(0) 107 | 108 | result = get_setup_configuration(ctypes.byref(configuration), reserved) 109 | if result != 0: 110 | #print("Failed to get setup configuration: " + str(result)) 111 | return installations 112 | 113 | enum_instances = configuration.contents.vtable.contents.EnumInstances 114 | 115 | enum_setup_instances = ctypes.POINTER(IEnumSetupInstances)() 116 | result = enum_instances(configuration, ctypes.byref(enum_setup_instances)) 117 | if result != 0: 118 | #print("Failed to enum setup instances: " + str(result)) 119 | return installations 120 | 121 | 122 | setup_instance = ctypes.POINTER(ISetupInstance)() 123 | fetched = ctypes.c_int(0) 124 | 125 | while True: 126 | next = enum_setup_instances.contents.vtable.contents.Next 127 | result = next(enum_setup_instances, 1, ctypes.byref(setup_instance), ctypes.byref(fetched)) 128 | if result == 1 or fetched == 0: 129 | break 130 | if result != 0: 131 | #print("Failed to get next setup instance: " + str(result)) 132 | break 133 | 134 | version = ctypes.c_wchar_p() 135 | path = ctypes.c_wchar_p() 136 | 137 | get_installation_version = setup_instance.contents.vtable.contents.GetInstallationVersion 138 | get_installation_path = setup_instance.contents.vtable.contents.GetInstallationPath 139 | 140 | result = get_installation_version(setup_instance, ctypes.byref(version)) 141 | if result != 0: 142 | #print("Failed to get setup instance version: " + str(result)) 143 | break 144 | 145 | result = get_installation_path(setup_instance, ctypes.byref(path)) 146 | if result != 0: 147 | #print("Failed to get setup instance version: " + str(result)) 148 | break 149 | 150 | installations.append((version.value, path.value)) 151 | 152 | return installations 153 | 154 | 155 | if __name__ == "__main__": 156 | 157 | installations = get_vs_installations() 158 | 159 | for version, path in installations: 160 | print(version + " " + path) 161 | -------------------------------------------------------------------------------- /build/ninja/xcode.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """Ninja toolchain abstraction for XCode toolchain""" 4 | 5 | import os 6 | import subprocess 7 | 8 | import toolchain 9 | import syntax 10 | 11 | def make_target(toolchain, host, target): 12 | return XCode(toolchain, host, target) 13 | 14 | class XCode(object): 15 | def __init__(self, toolchain, host, target): 16 | self.toolchain = toolchain 17 | self.host = host 18 | self.target = target 19 | 20 | def initialize_toolchain(self): 21 | self.organisation = '' 22 | self.bundleidentifier = '' 23 | self.provisioning = '' 24 | if self.target.is_macos(): 25 | self.deploymenttarget = '12.0' 26 | elif self.target.is_ios(): 27 | self.deploymenttarget = '15.0' 28 | 29 | def build_toolchain(self): 30 | if self.target.is_macos(): 31 | sdk = 'macosx' 32 | deploytarget = 'MACOSX_DEPLOYMENT_TARGET=' + self.deploymenttarget 33 | elif self.target.is_ios(): 34 | sdk = 'iphoneos' 35 | deploytarget = 'IPHONEOS_DEPLOYMENT_TARGET=' + self.deploymenttarget 36 | 37 | platformpath = toolchain.check_last_output(['xcrun', '--sdk', sdk, '--show-sdk-platform-path']) 38 | localpath = platformpath + "/Developer/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin" 39 | 40 | self.plist = "PATH=" + localpath + " " + toolchain.check_last_output(['xcrun', '--sdk', sdk, '-f', 'plutil']) 41 | self.xcassets = "PATH=" + localpath + " " + toolchain.check_last_output(['xcrun', '--sdk', sdk, '-f', 'actool']) 42 | self.xib = "PATH=" + localpath + " " + toolchain.check_last_output(['xcrun', '--sdk', sdk, '-f', 'ibtool']) 43 | self.dsymutil = "PATH=" + localpath + " " + toolchain.check_last_output(['xcrun', '--sdk', sdk, '-f', 'dsymutil']) 44 | 45 | self.plistcmd = 'build/ninja/plist.py --exename $exename --prodname $prodname --bundle $bundleidentifier --target $target --deploymenttarget $deploymenttarget --output $outpath $in' 46 | if self.target.is_macos(): 47 | self.xcassetscmd = 'mkdir -p $outpath && $xcassets --output-format human-readable-text --output-partial-info-plist $outplist' \ 48 | ' --app-icon AppIcon --launch-image LaunchImage --platform macosx --minimum-deployment-target ' + self.deploymenttarget + \ 49 | ' --target-device mac --compress-pngs --compile $outpath $in >/dev/null' 50 | self.xibcmd = '$xib --target-device mac --module $module --minimum-deployment-target ' + self.deploymenttarget + \ 51 | ' --output-partial-info-plist $outplist --auto-activate-custom-fonts' \ 52 | ' --output-format human-readable-text --compile $outpath $in' 53 | elif self.target.is_ios(): 54 | self.xcassetscmd = 'mkdir -p $outpath && $xcassets --output-format human-readable-text --output-partial-info-plist $outplist' \ 55 | ' --app-icon AppIcon --launch-image LaunchImage --platform iphoneos --minimum-deployment-target ' + self.deploymenttarget + \ 56 | ' --target-device iphone --target-device ipad --compress-pngs --compile $outpath $in >/dev/null' 57 | self.xibcmd = '$xib --target-device iphone --target-device ipad --module $module --minimum-deployment-target ' + self.deploymenttarget + \ 58 | ' --output-partial-info-plist $outplist --auto-activate-custom-fonts' \ 59 | ' --output-format human-readable-text --compile $outpath $in &> /dev/null ' 60 | self.dsymutilcmd = '$dsymutil $in -o $outpath' 61 | self.codesigncmd = 'build/ninja/codesign.py --target $target --prefs codesign.json --builddir $builddir --binname $binname --config $config --entitlements $entitlements $outpath' 62 | 63 | def parse_default_variables(self, variables): 64 | if not variables: 65 | return 66 | if isinstance(variables, dict): 67 | iterator = iter(variables.items()) 68 | else: 69 | iterator = iter(variables) 70 | for key, val in iterator: 71 | if key == 'deploymenttarget': 72 | self.deploymenttarget = val 73 | if key == 'organisation': 74 | self.organisation = val 75 | if key == 'bundleidentifier': 76 | self.bundleidentifier = val 77 | if key == 'provisioning': 78 | self.provisioning = val 79 | 80 | def parse_prefs(self, prefs): 81 | if self.target.is_ios() and 'ios' in prefs: 82 | iosprefs = prefs['ios'] 83 | if 'deploymenttarget' in iosprefs: 84 | self.deploymenttarget = iosprefs['deploymenttarget'] 85 | if 'organisation' in iosprefs: 86 | self.organisation = iosprefs['organisation'] 87 | if 'bundleidentifier' in iosprefs: 88 | self.bundleidentifier = iosprefs['bundleidentifier'] 89 | if 'provisioning' in iosprefs: 90 | self.provisioning = iosprefs['provisioning'] 91 | elif self.target.is_macos() and 'macos' in prefs: 92 | macosprefs = prefs['macos'] 93 | if 'deploymenttarget' in macosprefs: 94 | self.deploymenttarget = macosprefs['deploymenttarget'] 95 | if 'organisation' in macosprefs: 96 | self.organisation = macosprefs['organisation'] 97 | if 'bundleidentifier' in macosprefs: 98 | self.bundleidentifier = macosprefs['bundleidentifier'] 99 | if 'provisioning' in macosprefs: 100 | self.provisioning = macosprefs['provisioning'] 101 | 102 | def write_variables(self, writer): 103 | writer.variable('plist', self.plist) 104 | writer.variable('xcassets', self.xcassets) 105 | writer.variable('xib', self.xib) 106 | writer.variable('dsymutil', self.dsymutil) 107 | writer.variable('bundleidentifier', syntax.escape(self.bundleidentifier)) 108 | writer.variable('deploymenttarget', self.deploymenttarget) 109 | writer.variable('entitlements', 'none') 110 | 111 | def write_rules(self, writer): 112 | writer.rule('dsymutil', command = self.dsymutilcmd, description = 'DSYMUTIL $outpath') 113 | writer.rule('plist', command = self.plistcmd, description = 'PLIST $outpath') 114 | writer.rule('xcassets', command = self.xcassetscmd, description = 'XCASSETS $outpath') 115 | writer.rule('xib', command = self.xibcmd, description = 'XIB $outpath') 116 | writer.rule('codesign', command = self.codesigncmd, description = 'CODESIGN $outpath') 117 | 118 | def make_bundleidentifier(self, binname): 119 | return self.bundleidentifier.replace('$(binname)', binname) 120 | 121 | def app(self, toolchain, writer, module, archbins, outpath, binname, basepath, config, implicit_deps, resources, codesign): 122 | #Outputs 123 | builtbin = [] 124 | builtres = [] 125 | builtsym = [] 126 | 127 | #Paths 128 | builddir = os.path.join('$buildpath', config, 'app', binname) 129 | configpath = os.path.join(outpath, config) 130 | apppath = os.path.join(configpath, binname + '.app') 131 | dsympath = os.path.join(outpath, config, binname + '.dSYM') 132 | 133 | #Extract debug symbols from universal binary 134 | dsymcontentpath = os.path.join(dsympath, 'Contents') 135 | builtsym = writer.build([os.path.join(dsymcontentpath, 'Resources', 'DWARF', binname), os.path.join(dsymcontentpath, 'Resources', 'DWARF' ), os.path.join(dsymcontentpath, 'Resources'), os.path.join(dsymcontentpath, 'Info.plist'), dsymcontentpath, dsympath], 'dsymutil', archbins[config], variables = [('outpath', dsympath)]) 136 | 137 | #Copy final universal binary 138 | if self.target.is_ios(): 139 | builtbin = toolchain.copy(writer, archbins[config], os.path.join(apppath, toolchain.binprefix + binname + toolchain.binext)) 140 | else: 141 | builtbin = toolchain.copy(writer, archbins[config], os.path.join(apppath, 'Contents', 'MacOS', toolchain.binprefix + binname + toolchain.binext)) 142 | 143 | #Build resources 144 | if resources: 145 | has_resources = False 146 | 147 | #Lists of input plists and partial plist files produced by resources 148 | plists = [] 149 | assetsplists = [] 150 | xibplists = [] 151 | entitlements = [] 152 | 153 | #All resource output files 154 | outfiles = [] 155 | 156 | #First build everything except plist inputs 157 | for resource in resources: 158 | if resource.endswith('.xcassets'): 159 | if self.target.is_macos(): 160 | assetsvars = [('outpath', os.path.join(os.getcwd(), apppath, 'Contents', 'Resources'))] 161 | else: 162 | assetsvars = [('outpath', apppath)] 163 | outplist = os.path.join(os.getcwd(), builddir, os.path.splitext(os.path.basename(resource))[0] + '-xcassets.plist') 164 | assetsvars += [('outplist', outplist)] 165 | outfiles = [outplist] 166 | if self.target.is_macos(): 167 | outfiles += [os.path.join(os.getcwd(), apppath, 'Contents', 'Resources', 'AppIcon.icns')] 168 | elif self.target.is_ios(): 169 | pass #TODO: Need to list all icon and launch image files here 170 | assetsplists += writer.build(outfiles, 'xcassets', os.path.join(os.getcwd(), basepath, module, resource), variables = assetsvars) 171 | has_resources = True 172 | elif resource.endswith('.xib'): 173 | xibmodule = binname.replace('-', '_').replace('.', '_') 174 | if self.target.is_macos(): 175 | nibpath = os.path.join(apppath, 'Contents', 'Resources', os.path.splitext(os.path.basename(resource))[0] + '.nib') 176 | else: 177 | nibpath = os.path.join(apppath, os.path.splitext(os.path.basename(resource))[0] + '.nib') 178 | plistpath = os.path.join(builddir, os.path.splitext(os.path.basename(resource))[0] + '-xib.plist') 179 | xibplists += [plistpath] 180 | outfiles = [] 181 | if self.target.is_ios(): 182 | outfiles += [os.path.join(nibpath, 'objects.nib'), os.path.join(nibpath, 'objects-8.0+.nib'), os.path.join(nibpath, 'runtime.nib')] 183 | outfiles += [nibpath, plistpath] 184 | builtres += writer.build(outfiles, 'xib', os.path.join(os.getcwd(), basepath, module, resource), variables = [('outpath', nibpath), ('outplist', plistpath), ('module', xibmodule)]) 185 | has_resources = True 186 | elif resource.endswith('.plist'): 187 | plists += [os.path.join(os.getcwd(), basepath, module, resource)] 188 | elif resource.endswith('.entitlements'): 189 | entitlements += [os.path.join(os.getcwd(), basepath, module, resource)] 190 | 191 | #Extra output files/directories 192 | outfiles = [] 193 | if has_resources and self.target.is_macos(): 194 | outfiles += [os.path.join(apppath, 'Contents', 'Resources')] 195 | 196 | #Now build input plists appending partial plists created by previous resources 197 | if self.target.is_macos(): 198 | plistpath = os.path.join(apppath, 'Contents', 'Info.plist') 199 | pkginfopath = os.path.join(apppath, 'Contents', 'PkgInfo') 200 | else: 201 | plistpath = os.path.join(apppath, 'Info.plist') 202 | pkginfopath = os.path.join(apppath, 'PkgInfo') 203 | plistvars = [('exename', binname), ('prodname', binname), ('outpath', plistpath)] 204 | bundleidentifier = self.make_bundleidentifier(binname) 205 | if bundleidentifier != '': 206 | plistvars += [('bundleidentifier', bundleidentifier)] 207 | outfiles += [plistpath, pkginfopath] 208 | builtres += writer.build(outfiles, 'plist', plists + assetsplists + xibplists, implicit = [os.path.join( 'build', 'ninja', 'plist.py')], variables = plistvars) 209 | 210 | #Do code signing (might modify binary, but does not matter, nothing should have final binary as input anyway) 211 | if codesign: 212 | codesignvars = [('builddir', builddir), ('binname', binname), ('outpath', apppath), ('config', config)] 213 | if self.target.is_ios(): 214 | if self.provisioning != '': 215 | codesignvars += [('provisioning', self.provisioning)] 216 | writer.build([os.path.join(apppath, '_CodeSignature', 'CodeResources'), os.path.join(apppath, '_CodeSignature'), apppath], 'codesign', builtbin, implicit = builtres + [os.path.join('build', 'ninja', 'codesign.py')], variables = codesignvars) 217 | elif self.target.is_macos(): 218 | if self.provisioning != '': 219 | codesignvars += [('provisioning', self.provisioning)] 220 | if len(entitlements) > 0: 221 | codesignvars += [('entitlements', entitlements[0])] 222 | writer.build([os.path.join(apppath, 'Contents', '_CodeSignature', 'CodeResources'), os.path.join(apppath, 'Contents', '_CodeSignature'), os.path.join(apppath, 'Contents'), apppath], 'codesign', builtbin, implicit = builtres + [os.path.join('build', 'ninja', 'codesign.py')], variables = codesignvars) 223 | 224 | return builtbin + builtsym + builtres 225 | -------------------------------------------------------------------------------- /build/window.sublime-project: -------------------------------------------------------------------------------- 1 | { 2 | "folders": 3 | [ 4 | { 5 | "follow_symlinks": true, 6 | "path": "../window" 7 | }, 8 | { 9 | "follow_symlinks": true, 10 | "path": "../test" 11 | }, 12 | { 13 | "follow_symlinks": true, 14 | "path": "../tools" 15 | }, 16 | { 17 | "follow_symlinks": true, 18 | "path": "../doc" 19 | } 20 | ], 21 | "build_systems": 22 | [ 23 | { 24 | "name": "Ninja", 25 | "shell_cmd": "ninja", 26 | "working_dir": "${project_path:${folder:${file_path}}}/..", 27 | } 28 | ], 29 | "translate_tabs_to_spaces": false, 30 | "use_tab_stops": true, 31 | "trim_trailing_white_space_on_save": true, 32 | "settings": 33 | { 34 | "AStyleFormatter": 35 | { 36 | "options_default": 37 | { 38 | "style" : "attach", 39 | "pad-oper": true, 40 | "indent-switches" : false, 41 | "indent-cases" : true, 42 | "unpad-paren": true, 43 | "break-closing-brackets": true, 44 | "align-pointer": "type", 45 | "max-code-length": 100, 46 | "max-instatement-indent": 60, 47 | "break-after-logical": true 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /build/xcode/window-ios.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /build/xcode/window-osx.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /configure.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """Ninja build configurator for window library""" 4 | 5 | import sys 6 | import os 7 | 8 | sys.path.insert(0, os.path.join('build', 'ninja')) 9 | 10 | import generator 11 | 12 | dependlibs = ['window', 'foundation'] 13 | 14 | generator = generator.Generator(project = 'window', dependlibs = dependlibs, variables = [('bundleidentifier', 'com.maniccoder.window.$(binname)')]) 15 | target = generator.target 16 | writer = generator.writer 17 | toolchain = generator.toolchain 18 | 19 | window_lib = generator.lib(module = 'window', sources = [ 20 | 'event.c', 'version.c', 'window.c', 'window_android.c', 'window_ios.m', 'window_linux.c', 'window_macos.m', 'window_windows.c']) 21 | 22 | #No test cases if we're a submodule 23 | if generator.is_subninja(): 24 | sys.exit() 25 | 26 | includepaths = generator.test_includepaths() 27 | 28 | gllibs = [] 29 | glframeworks = [] 30 | if target.is_macos(): 31 | glframeworks = ['QuartzCore'] 32 | elif target.is_ios(): 33 | glframeworks = ['QuartzCore'] 34 | if target.is_windows(): 35 | gllibs = ['gdi32'] 36 | if target.is_linux(): 37 | gllibs = ['GL', 'Xext', 'X11'] 38 | print("GLlibs: " + str(gllibs)) 39 | 40 | test_cases = [ 41 | 'window' 42 | ] 43 | if toolchain.is_monolithic() or target.is_ios() or target.is_android() or target.is_tizen(): 44 | #Build one fat binary with all test cases 45 | test_resources = [] 46 | test_extrasources = [] 47 | test_cases += ['all'] 48 | if target.is_ios(): 49 | test_resources = [os.path.join( 'all', 'ios', item) for item in ['test-all.plist', 'Images.xcassets', 'test-all.xib']] 50 | test_extrasources = [os.path.join('all', 'ios', 'viewcontroller.m')] 51 | elif target.is_android(): 52 | test_resources = [os.path.join('all', 'android', item) for item in [ 53 | 'AndroidManifest.xml', os.path.join('layout', 'main.xml'), os.path.join('values', 'strings.xml'), 54 | os.path.join('drawable-ldpi', 'icon.png'), os.path.join('drawable-mdpi', 'icon.png'), os.path.join('drawable-hdpi', 'icon.png'), 55 | os.path.join('drawable-xhdpi', 'icon.png'), os.path.join('drawable-xxhdpi', 'icon.png'), os.path.join('drawable-xxxhdpi', 'icon.png') 56 | ]] 57 | test_extrasources = [os.path.join('all', 'android', 'java', 'com', 'maniccoder', 'window', 'test', item) for item in [ 58 | 'TestActivity.java' 59 | ]] 60 | elif target.is_tizen(): 61 | test_resources = [os.path.join('all', 'tizen', item) for item in [ 62 | 'tizen-manifest.xml', os.path.join( 'res', 'tizenapp.png') 63 | ]] 64 | if target.is_macos() or target.is_ios() or target.is_android() or target.is_tizen(): 65 | generator.app(module = '', sources = [os.path.join(module, 'main.c') for module in test_cases] + test_extrasources, binname = 'test-all', basepath = 'test', implicit_deps = [window_lib], libs = ['test'] + dependlibs + gllibs, frameworks = glframeworks, resources = test_resources, includepaths = includepaths) 66 | else: 67 | generator.bin(module = '', sources = [os.path.join(module, 'main.c') for module in test_cases] + test_extrasources, binname = 'test-all', basepath = 'test', implicit_deps = [window_lib], libs = ['test'] + dependlibs + gllibs, frameworks = glframeworks, resources = test_resources, includepaths = includepaths) 68 | else: 69 | #Build one binary per test case 70 | generator.bin(module = 'all', sources = ['main.c'], binname = 'test-all', basepath = 'test', implicit_deps = [window_lib], libs = dependlibs + gllibs, includepaths = includepaths) 71 | for test in test_cases: 72 | if target.is_macos(): 73 | test_resources = [os.path.join('macos', item) for item in ['test-' + test + '.plist', 'test-' + test + '.entitlements', 'Images.xcassets', 'test-' + test + '.xib']] 74 | generator.app(module = test, sources = ['main.c'], binname = 'test-' + test, basepath = 'test', implicit_deps = [window_lib], libs = ['test'] + dependlibs + gllibs, frameworks = glframeworks, resources = test_resources, includepaths = includepaths) 75 | else: 76 | generator.bin(module = test, sources = ['main.c'], binname = 'test-' + test, basepath = 'test', implicit_deps = [window_lib], libs = ['test'] + dependlibs + gllibs, frameworks = glframeworks, includepaths = includepaths) 77 | -------------------------------------------------------------------------------- /doc/build.dox: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | 4 | \file build.h 5 | \brief Build setup 6 | \details Build setup 7 | 8 | 9 | \def WINDOW_EXTERN 10 | \brief Declare extern symbol 11 | \details Declare an extern symbol 12 | 13 | \def WINDOW_API 14 | \brief API entry point 15 | \details Declare an API entry point 16 | 17 | */ 18 | -------------------------------------------------------------------------------- /doc/event.dox: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | 4 | \file types.h 5 | \brief Window events 6 | \details Window events 7 | 8 | 9 | \fn void window_event_process( void ) 10 | \brief Process window events 11 | \details Process window events. You should call this once every loop iteration in your main loop 12 | 13 | \fn event_stream_t* window_event_stream( void ) 14 | \brief Get window event stream 15 | \details Get window event stream 16 | \return Window event stream 17 | 18 | \fn void window_event_handle_foundation( event_t* event ) 19 | \brief Process foundation events 20 | \details Send a foundation system event to the window library to handle. You should ideally let the window system listen to all foundation events for full functionality. 21 | \param event Foundation event 22 | 23 | */ 24 | -------------------------------------------------------------------------------- /doc/internal.dox: -------------------------------------------------------------------------------- 1 | 2 | /!* 3 | 4 | \file internal.h 5 | \brief Internal functions and data types 6 | \details Internal functions and data types not intended for external access as these definitions could change at any point. 7 | 8 | 9 | \fn int _window_event_initialize( void ) 10 | \brief Initialize window events 11 | \details Initialize window event system. 12 | \return Status code, 0 if success, <0 if error 13 | 14 | \fn void _window_event_shutdown( void ) 15 | \brief Shutdown window events 16 | \details Shutdown window event system and free any used resources. 17 | 18 | \fn void _window_class_reference( void ) 19 | \brief Symbol reference helper 20 | \details Helper function to make sure all window system symbols and classes are properly referenced and not removed by linker. 21 | 22 | \fn void _window_native_initialize( void ) 23 | \brief Initialize native bindings 24 | \details Initialize any bindings to native windowing system. 25 | 26 | \fn void _window_native_shutdown( void ) 27 | \brief Initialize native bindings 28 | \details Initialize any bindings to native windowing system. 29 | 30 | 31 | \var _window_app_started 32 | \brief Start flag 33 | \details Flag indicating that application has properly started and window system is available. 34 | 35 | \var _window_app_paused 36 | \brief Pause flag 37 | \details Flag indicating that application is paused (not visible in background) 38 | 39 | 40 | */ 41 | -------------------------------------------------------------------------------- /doc/types.dox: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | 4 | \file types.h 5 | \brief Window types 6 | \details Window types. 7 | 8 | 9 | \var WINDOW_ADAPTER_DEFAULT 10 | \brief Default adapter ID 11 | \details Default adapter ID. 12 | 13 | \typedef window_t 14 | \brief Window data 15 | \details Window type with all platform specific data. 16 | 17 | \var window_t::adapter 18 | \brief Adapter the window is displayed on 19 | \details Adapter the window is displayed on. Also used when maximizing or going fullscreen to determine which adapter to use. 20 | 21 | \var window_t::hwnd 22 | \brief Window handle 23 | \details Window handle. 24 | 25 | \var window_t::hinstance 26 | \brief Application instance handle 27 | \details Application instance handle. 28 | 29 | \var window_t::created 30 | \brief Creation flag 31 | \brief Flag indicating if window was created by window library or supplied externally. 32 | 33 | \var window_t::cursor_lock 34 | \brief Cursor lock flag 35 | \details Flag indicating the cursor is locked to a position. 36 | 37 | \var window_t::cursor_pos 38 | \brief Cursor lock position 39 | \details Position the cursor should be locked to. 40 | 41 | \var window_t::wstyle 42 | \brief Window style 43 | \details Window style. 44 | 45 | \var window_t::nswindow 46 | \brief Window 47 | \details Window (type NSWindow*). 48 | 49 | \var window_t::uiwindow 50 | \brief Window 51 | \details Window (type UIWindow*). 52 | 53 | \var window_t::tag 54 | \brief Window tag 55 | \details Tag used to identify window association during startup. 56 | 57 | \var window_t::display 58 | \brief Display 59 | \details Display where window is located. 60 | 61 | \var window_t::screen 62 | \brief Screen 63 | \details Screen where window is located. 64 | 65 | \var window_t::visual 66 | \brief Visual information 67 | \details Visual information for window. 68 | 69 | \var window_t::drawable 70 | \brief Window drawable 71 | \details Window drawable. 72 | 73 | \var window_t::atom 74 | \brief Window destroy atom 75 | \details Window destroy atom. 76 | 77 | \var window_t::xim 78 | \brief Window input 79 | \details Window input. 80 | 81 | \var window_t::xic 82 | \brief Window input 83 | \details Window input. 84 | 85 | \var window_t::focus 86 | \brief Focus flag 87 | \details Flag indicating if window has focus or not. 88 | 89 | \var window_t::visible 90 | \brief Visible flag 91 | \details Flag indicating if window is visible or not. 92 | 93 | \var window_t::size 94 | \brief Window size 95 | \details Window size. 96 | 97 | \var window_t::native 98 | \brief Native handle 99 | \brief Window native handle. 100 | 101 | \class WindowView 102 | \brief Window view type 103 | \details This class wraps the CAEAGLLayer from CoreAnimation into a convenient NSView/UIView subclass. 104 | The view content is basically an AGL/EAGL surface you render your OpenGL content onto. 105 | Note that setting the view non-opaque will only work if the AGL/EAGL surface has an alpha channel. 106 | 107 | 108 | \class WindowViewController 109 | \brief Window controller 110 | \details Convenience window view controller for a single WindowView view. On iOS it can also optionally 111 | hide the status bar. 112 | 113 | 114 | \var window_draw_fn 115 | \brief Window draw callback 116 | \details Window draw callback. 117 | \param window Window to draw 118 | 119 | */ 120 | -------------------------------------------------------------------------------- /doc/window.dox: -------------------------------------------------------------------------------- 1 | 2 | /*! 3 | 4 | \file window.h 5 | \brief Window handling 6 | \details Window handling functions. Wrapper for window library headers and main entry/exit points. 7 | 8 | 9 | \fn int window_module_initialize( void ) 10 | \brief Initialize window library 11 | \details Main entry point. Call this to bootstrap the window library and initialize all functionality. 12 | \return 0 if initialization successful, <0 if error 13 | 14 | \fn void window_module_shutdown( void ) 15 | \brief Shutdown window library 16 | \details Main exit point. Call this to cleanup the window library and terminate all functionality. 17 | 18 | \fn bool window_module_is_initialized( void ) 19 | \brief Query if initialized 20 | \details Query if window library is initialized properly 21 | \return true if initialized, false if not 22 | 23 | \fn version_t window_module_version( void ) 24 | \brief Get library version 25 | \details Get the window library version 26 | \return Window library version 27 | 28 | \fn void window_finalize( window_t* window ) 29 | \brief Finalize window object 30 | \details Finalize window object and destroy window if created by the window library. 31 | \param window Window 32 | 33 | \fn void window_deallocate( window_t* window ) 34 | \brief Deallocate and destroy window 35 | \details Deallocate window object and destroy window if created by the window library. 36 | \param window Window 37 | 38 | \fn unsigned int window_adapter( window_t* window ) 39 | \brief Get window adapter 40 | \details Get the adapter ID the window is associated with. 41 | \param window Window 42 | \return Adapter ID 43 | 44 | \fn void window_maximize( window_t* window ) 45 | \brief Maximize window 46 | \details Maximize window. 47 | \param window Window 48 | 49 | \fn void window_minimize( window_t* window ) 50 | \brief Minimize window 51 | \details Minimize window. 52 | \param window Window 53 | 54 | \fn void window_restore( window_t* window ) 55 | \brief Restore window 56 | \details Restore window to the view state prior to minimization. 57 | \param window Window 58 | 59 | \fn void window_resize( window_t* window, unsigned int width, unsigned int height ) 60 | \brief Resize window 61 | \details Resize window. 62 | \param window Window 63 | \param widht New width 64 | \param height New height 65 | 66 | \fn void window_move( window_t* window, int x, int y ) 67 | \brief Move window 68 | \details Move window. 69 | \param window Window 70 | \param x New x coordinate 71 | \param y New y coordinate 72 | 73 | \fn bool window_is_open( window_t* window ) 74 | \brief Query if open 75 | \details Query if window is open 76 | \param window Window 77 | \return true if window is open, false if not 78 | 79 | \fn bool window_is_visible( window_t* window ) 80 | \brief Query if visible 81 | \details Query if window is visible. 82 | \param window Window 83 | \return true if visible, false if not 84 | 85 | \fn bool window_is_maximized( window_t* window ) 86 | \brief Query if maximized 87 | \details Query if window is maximized. 88 | \param window Window 89 | \return true if maximized, false if not 90 | 91 | \fn bool window_is_minimized( window_t* window ) 92 | \brief Query if minimized 93 | \details Query if window is minimized. 94 | \param window Window 95 | \return true if minimized, false if not 96 | 97 | \fn bool window_has_focus( window_t* window ) 98 | \brief Query if focused 99 | \details Query if window has focus. 100 | \param window Window 101 | \return true if focused, false if not 102 | 103 | \fn void window_show_cursor( window_t* window, bool show, bool lock ) 104 | \brief Show cursor 105 | \details Show cursor when inside the window and optionally lock it in place to prevent it from leaving the window. 106 | \param window Window 107 | \param show Show flag, show the cursor if true, hide if false 108 | \param lock Lock flag, lock the cursor at the center of the window if true, release if false 109 | 110 | \fn void window_set_cursor_pos( window_t* window, int x, int y ) 111 | \brief Move cursor 112 | \details Move the cursor to the specified position inside the window. 113 | \param window Window 114 | \param x X coordinate in window coordinate system 115 | \param y Y coordinate in window coordinate system 116 | 117 | \fn bool window_is_cursor_locked( window_t* window ) 118 | \brief Query if cursor locked 119 | \details Query if the cursor is locked inside the window. 120 | \param window Window 121 | \return true if cursor is locked inside the window, false if not 122 | 123 | \fn void window_set_title( window_t* window, const char* title ) 124 | \brief Set window title 125 | \details Set window title bar name. 126 | \param window Window 127 | \param title New window title 128 | 129 | \fn int window_width( window_t* window ) 130 | \brief Get content width 131 | \details Get width of window content area. 132 | \param window Window 133 | \return Width of window, 0 if invalid or not open window 134 | 135 | \fn int window_height( window_t* window ) 136 | \brief Get content height 137 | \details Get Height of window content area. 138 | \param window Window 139 | \return Height of window, 0 if invalid or not open window 140 | 141 | \fn int window_position_x( window_t* window ) 142 | \brief Get x position 143 | \details Get x coordinate of window position in windowing system units. 144 | \param window Window 145 | \return Window x position 146 | 147 | \fn int window_position_y( window_t* window ) 148 | \brief Get y position 149 | \details Get y coordinate of window position in windowing system units. 150 | \param window Window 151 | \return Window y position 152 | 153 | \fn void window_fit_to_screen( window_t* window ) 154 | \brief Constrain window to screen 155 | \details Constrain the window size and position to be fully visible on the current screen/adapter, 156 | while maintaining the current aspect ratio of the window in the process. 157 | \param window Window 158 | 159 | \fn window_t* window_create( unsigned int adapter, const char* title, unsigned int width, unsigned int height, unsigned int flags ) 160 | \brief Create new window (Windows/Linux only) 161 | \details Create a new window with the given properties (Windows/Linux only). 162 | \param adapter Adapter ID (use WINDOW_ADAPTER_DEFAULT for default) 163 | \param title Window title 164 | \param width Width 165 | \param height Height 166 | \param flags Creations flags controlling menus, appearance and visibility (see WINDOW_FLAG_* defines) 167 | \return Window 168 | 169 | \fn window_t* window_allocate_from_hwnd( void* hwnd ) 170 | \brief Allocate window from native handle (Windows only) 171 | \details Allocate a window object using a native window handle for a pre-created window (Windows only). 172 | \param hwnd Window handle 173 | \return Window 174 | 175 | \fn void* window_hwnd( window_t* window ) 176 | \brief Get window handle (Windows only) 177 | \details Get window handle (Windows only). 178 | \param window Window 179 | \return Native window handle, null if window is not open or invalid 180 | 181 | \fn void* window_hinstance( window_t* window ) 182 | \brief Get application instance (Windows only) 183 | \details Get application instance that created the given window (Windows only). 184 | \param window Window 185 | \return Application instance handle, null if window is not open or invalid 186 | 187 | \fn void* window_hdc( window_t* window ) 188 | \brief Get device context (Windows only) 189 | \details Get a device context for the given window (Windows only). You must call window_release_hdc to release the context once all operations have been completed. 190 | \param window Window 191 | \return Device context, null if window is not open or invalid 192 | 193 | \fn void window_release_hdc( void* hwnd, void* hdc ) 194 | \brief Release device context (Windows only) 195 | \details Release a device context previously obtained from a call to window_hdc (Windows only). 196 | \param hwnd Native window handle 197 | \param hdc Device context 198 | 199 | \fn unsigned int window_screen_width( unsigned int adapter ) 200 | \brief Get screen width (Windows only) 201 | \details Get screen width in pixels of the given adapter (Windows only). 202 | \param adapter Adapter ID 203 | \return Screen width in pixels 204 | 205 | \fn unsigned int window_screen_height( unsigned int adapter ) 206 | \brief Get screen height (Windows only) 207 | \details Get screen height in pixels of the given adapter (Windows only). 208 | \param adapter 209 | \return Screen height in pixels 210 | 211 | \fn window_t* window_allocate_from_nswindow( void* nswindow ) 212 | \brief Allocate window from native window (MacOSX only) 213 | \details Allocate a window object using a native window (MacOSX only). 214 | \param nswindow Window (NSWindow*) 215 | \return Window 216 | 217 | \fn void* window_content_view( window_t* window ) 218 | \brief Get content view (MacOSX only) 219 | \details Get content view (MacOSX only). 220 | \param window Window 221 | \return Content view (NSView*), null if invalid window or not open 222 | 223 | \fn void* window_display( window_t* window ) 224 | \brief Get window display (Linux only) 225 | \details Get the display where the given window is located (Linux only). 226 | \param window Window 227 | \return Display (Display*), null if invalid window or not open 228 | 229 | \fn int window_screen( window_t* window ) 230 | \brief Get window screen (Linux only) 231 | \details get the screen where the given window is located (Linux only). 232 | \param window Window 233 | \return Screen index, -1 if invalid window or not open 234 | 235 | \fn int window_drawable( window_t* window ) 236 | \brief Get window drawable (Linux only) 237 | \details Get drawable for the given window (Linux only). 238 | \param window Window 239 | \return Drawable, 0 if invalid window or not open 240 | 241 | \fn void* window_visual( window_t* window ) 242 | \brief Get window visual (Linux only) 243 | \details Get visual for the given window (Linux only). 244 | \param window Window 245 | \return Visual (Visual*), null if invalid window or not open 246 | 247 | \fn window_t* window_allocate_from_uiwindow( void* uiwindow ) 248 | \brief Allocate window from native window (iOS only) 249 | \details Allocate a window object using a native window (iOS only). 250 | \param uiwindow Window (UIWindow*) 251 | \return Window 252 | 253 | \fn void* window_view( window_t* window, unsigned int tag ) 254 | \brief Get content view (iOS only) 255 | \details Get content view (iOS only). 256 | \param window Window 257 | \param tag View tag 258 | \return Content view with the given tag (UIView*), null if invalid window/tag or not open 259 | 260 | \fn void* window_layer( window_t* window, void* view ) 261 | \brief Get view EAGL layer (iOS only) 262 | \details Get the EAGL layer for the given view (iOS only). 263 | \param window Window 264 | \param view View 265 | \return EAGL layer (CAEAGLLayer*), null if invalid window/view or not open 266 | 267 | \fn int window_view_width( window_t* window, void* view ) 268 | \brief Get view width (iOS only) 269 | \details Get view width in pixels (iOS only). 270 | \param window Window 271 | \param view View 272 | \return View width in pixels 273 | 274 | \fn int window_view_height( window_t* window, void* view ) 275 | \brief Get view height (iOS only) 276 | \details Get view height in pixels (iOS only). 277 | \param window Window 278 | \param view View 279 | \return View height in pixels 280 | 281 | \fn void window_add_displaylink( window_t* window, window_draw_fn drawfn ) 282 | \brief Add display link (iOS only) 283 | \details Add display link for draw callbacks (iOS only). 284 | \param window Window 285 | \param drawfn Draw function to call on display link updates 286 | 287 | \fn void window_show_keyboard( window_t* window ) 288 | \brief Show software keyboard (iOS/Android only) 289 | \details Show the software keyboard (iOS/Android only). 290 | \param window Window 291 | 292 | \fn void window_hide_keyboard( window_t* window ) 293 | \brief Hide software keyboard (iOS/Android only) 294 | \details Hide the software keyboard (iOS/Android only). 295 | \param window Window 296 | 297 | \fn window_t* window_allocate_from_native( void* window ) 298 | \brief Allocate from native window (Android only) 299 | \details Allocate a window object using a native window (Android only). 300 | \param window Native window 301 | \return Window 302 | 303 | \fn void* window_native( window_t* window ) 304 | \brief Get native window (Android only) 305 | \details Get native window (Android only). 306 | \param window Window 307 | \return Native window, null if invalid window or not open 308 | 309 | \fn void* window_display( window_t* window ) 310 | \brief Get display (Android only) 311 | \details Get display window is located on (Android only). 312 | \param window Window 313 | \return Display, null if invalid window or not open 314 | 315 | */ 316 | -------------------------------------------------------------------------------- /test/all/android/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | 19 | 20 | 21 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /test/all/android/drawable-hdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/android/drawable-hdpi/icon.png -------------------------------------------------------------------------------- /test/all/android/drawable-ldpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/android/drawable-ldpi/icon.png -------------------------------------------------------------------------------- /test/all/android/drawable-mdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/android/drawable-mdpi/icon.png -------------------------------------------------------------------------------- /test/all/android/drawable-xhdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/android/drawable-xhdpi/icon.png -------------------------------------------------------------------------------- /test/all/android/drawable-xxhdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/android/drawable-xxhdpi/icon.png -------------------------------------------------------------------------------- /test/all/android/drawable-xxxhdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/android/drawable-xxxhdpi/icon.png -------------------------------------------------------------------------------- /test/all/android/java/com/maniccoder/window/test/TestActivity.java: -------------------------------------------------------------------------------- 1 | package com.maniccoder.window.test; 2 | 3 | import android.os.Bundle; 4 | import android.app.NativeActivity; 5 | import android.graphics.Color; 6 | import android.graphics.Point; 7 | import android.widget.TextView; 8 | import android.util.Log; 9 | import android.widget.LinearLayout; 10 | import android.widget.PopupWindow; 11 | import android.view.Gravity; 12 | import android.view.Display; 13 | import android.view.ViewGroup; 14 | import android.view.ViewGroup.LayoutParams; 15 | import android.view.ViewGroup.MarginLayoutParams; 16 | 17 | public class TestActivity extends NativeActivity 18 | { 19 | private TextView textView; 20 | private boolean displayedTextView = false; 21 | 22 | @Override 23 | public void onWindowFocusChanged( boolean hasFocus ) 24 | { 25 | super.onWindowFocusChanged( hasFocus ); 26 | 27 | if( !displayedTextView && hasFocus ) 28 | { 29 | displayedTextView = true; 30 | 31 | setContentView( R.layout.main ); 32 | 33 | textView = (TextView)findViewById( R.id.logtext ); 34 | textView.setText( "" ); 35 | ((ViewGroup)textView.getParent()).removeView(textView); 36 | 37 | final TestActivity activity = this; 38 | 39 | runOnUiThread( new Runnable() { 40 | 41 | @Override 42 | public void run() 43 | { 44 | PopupWindow popup = new PopupWindow( activity ); 45 | 46 | Display display = getWindowManager().getDefaultDisplay(); 47 | Point size = new Point(); 48 | display.getSize( size ); 49 | 50 | popup.setWidth( size.x ); 51 | popup.setHeight( size.y ); 52 | popup.setWindowLayoutMode( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT ); 53 | popup.setClippingEnabled( false ); 54 | 55 | MarginLayoutParams params = new MarginLayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT ); 56 | params.setMargins(0, 0, 0, 0); 57 | 58 | LinearLayout layout = new LinearLayout( activity ); 59 | layout.setOrientation( LinearLayout.VERTICAL ); 60 | layout.addView( activity.textView, params ); 61 | 62 | popup.setContentView( layout ); 63 | 64 | final ViewGroup viewGroup = (ViewGroup)((ViewGroup)activity.findViewById( android.R.id.content )).getChildAt(0); 65 | 66 | popup.showAtLocation( viewGroup, Gravity.TOP, 0, 0 ); 67 | popup.update(); 68 | } 69 | } ); 70 | } 71 | } 72 | 73 | public void appendLog( final String msg ) 74 | { 75 | runOnUiThread( new Runnable() { 76 | @Override 77 | public void run() 78 | { 79 | if( textView != null ) 80 | textView.append( msg ); 81 | } 82 | } ); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /test/all/android/layout/main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /test/all/android/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Window Test Suite 4 | 5 | -------------------------------------------------------------------------------- /test/all/ios/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "29x29", 5 | "idiom" : "iphone", 6 | "filename" : "icon_29.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "29x29", 11 | "idiom" : "iphone", 12 | "filename" : "icon_58.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "40x40", 17 | "idiom" : "iphone", 18 | "filename" : "icon_80-1.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "57x57", 23 | "idiom" : "iphone", 24 | "filename" : "icon_57.png", 25 | "scale" : "1x" 26 | }, 27 | { 28 | "size" : "57x57", 29 | "idiom" : "iphone", 30 | "filename" : "icon_114.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "60x60", 35 | "idiom" : "iphone", 36 | "filename" : "icon_120.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "60x60", 41 | "idiom" : "iphone", 42 | "filename" : "icon_180.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "29x29", 47 | "idiom" : "ipad", 48 | "filename" : "icon_29-1.png", 49 | "scale" : "1x" 50 | }, 51 | { 52 | "size" : "29x29", 53 | "idiom" : "ipad", 54 | "filename" : "icon_58-1.png", 55 | "scale" : "2x" 56 | }, 57 | { 58 | "size" : "40x40", 59 | "idiom" : "ipad", 60 | "filename" : "icon_40.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "40x40", 65 | "idiom" : "ipad", 66 | "filename" : "icon_80.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "50x50", 71 | "idiom" : "ipad", 72 | "filename" : "icon_50.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "50x50", 77 | "idiom" : "ipad", 78 | "filename" : "icon_100.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "72x72", 83 | "idiom" : "ipad", 84 | "filename" : "icon_72.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "72x72", 89 | "idiom" : "ipad", 90 | "filename" : "icon_144.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "icon_76.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "icon_152.png", 103 | "scale" : "2x" 104 | } 105 | ], 106 | "info" : { 107 | "version" : 1, 108 | "author" : "xcode" 109 | } 110 | } -------------------------------------------------------------------------------- /test/all/ios/Images.xcassets/AppIcon.appiconset/icon_100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/ios/Images.xcassets/AppIcon.appiconset/icon_100.png -------------------------------------------------------------------------------- /test/all/ios/Images.xcassets/AppIcon.appiconset/icon_114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/ios/Images.xcassets/AppIcon.appiconset/icon_114.png -------------------------------------------------------------------------------- /test/all/ios/Images.xcassets/AppIcon.appiconset/icon_120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/ios/Images.xcassets/AppIcon.appiconset/icon_120.png -------------------------------------------------------------------------------- /test/all/ios/Images.xcassets/AppIcon.appiconset/icon_144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/ios/Images.xcassets/AppIcon.appiconset/icon_144.png -------------------------------------------------------------------------------- /test/all/ios/Images.xcassets/AppIcon.appiconset/icon_152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/ios/Images.xcassets/AppIcon.appiconset/icon_152.png -------------------------------------------------------------------------------- /test/all/ios/Images.xcassets/AppIcon.appiconset/icon_180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/ios/Images.xcassets/AppIcon.appiconset/icon_180.png -------------------------------------------------------------------------------- /test/all/ios/Images.xcassets/AppIcon.appiconset/icon_29-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/ios/Images.xcassets/AppIcon.appiconset/icon_29-1.png -------------------------------------------------------------------------------- /test/all/ios/Images.xcassets/AppIcon.appiconset/icon_29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/ios/Images.xcassets/AppIcon.appiconset/icon_29.png -------------------------------------------------------------------------------- /test/all/ios/Images.xcassets/AppIcon.appiconset/icon_40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/ios/Images.xcassets/AppIcon.appiconset/icon_40.png -------------------------------------------------------------------------------- /test/all/ios/Images.xcassets/AppIcon.appiconset/icon_50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/ios/Images.xcassets/AppIcon.appiconset/icon_50.png -------------------------------------------------------------------------------- /test/all/ios/Images.xcassets/AppIcon.appiconset/icon_57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/ios/Images.xcassets/AppIcon.appiconset/icon_57.png -------------------------------------------------------------------------------- /test/all/ios/Images.xcassets/AppIcon.appiconset/icon_58-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/ios/Images.xcassets/AppIcon.appiconset/icon_58-1.png -------------------------------------------------------------------------------- /test/all/ios/Images.xcassets/AppIcon.appiconset/icon_58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/ios/Images.xcassets/AppIcon.appiconset/icon_58.png -------------------------------------------------------------------------------- /test/all/ios/Images.xcassets/AppIcon.appiconset/icon_72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/ios/Images.xcassets/AppIcon.appiconset/icon_72.png -------------------------------------------------------------------------------- /test/all/ios/Images.xcassets/AppIcon.appiconset/icon_76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/ios/Images.xcassets/AppIcon.appiconset/icon_76.png -------------------------------------------------------------------------------- /test/all/ios/Images.xcassets/AppIcon.appiconset/icon_80-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/ios/Images.xcassets/AppIcon.appiconset/icon_80-1.png -------------------------------------------------------------------------------- /test/all/ios/Images.xcassets/AppIcon.appiconset/icon_80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/ios/Images.xcassets/AppIcon.appiconset/icon_80.png -------------------------------------------------------------------------------- /test/all/ios/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "filename" : "launch_640_960.png", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "extent" : "full-screen", 13 | "idiom" : "iphone", 14 | "subtype" : "retina4", 15 | "filename" : "launch_640_1136.png", 16 | "minimum-system-version" : "7.0", 17 | "orientation" : "portrait", 18 | "scale" : "2x" 19 | }, 20 | { 21 | "orientation" : "portrait", 22 | "idiom" : "ipad", 23 | "extent" : "full-screen", 24 | "minimum-system-version" : "7.0", 25 | "filename" : "launch_768_1024.png", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "orientation" : "landscape", 30 | "idiom" : "ipad", 31 | "extent" : "full-screen", 32 | "minimum-system-version" : "7.0", 33 | "filename" : "launch_1024_768.png", 34 | "scale" : "1x" 35 | }, 36 | { 37 | "orientation" : "portrait", 38 | "idiom" : "ipad", 39 | "extent" : "full-screen", 40 | "minimum-system-version" : "7.0", 41 | "filename" : "launch_1536_2048.png", 42 | "scale" : "2x" 43 | }, 44 | { 45 | "orientation" : "landscape", 46 | "idiom" : "ipad", 47 | "extent" : "full-screen", 48 | "minimum-system-version" : "7.0", 49 | "filename" : "launch_2048_1536.png", 50 | "scale" : "2x" 51 | }, 52 | { 53 | "orientation" : "portrait", 54 | "idiom" : "iphone", 55 | "extent" : "full-screen", 56 | "filename" : "launch_320_480.png", 57 | "scale" : "1x" 58 | }, 59 | { 60 | "orientation" : "portrait", 61 | "idiom" : "iphone", 62 | "extent" : "full-screen", 63 | "filename" : "launch_640_960.png", 64 | "scale" : "2x" 65 | }, 66 | { 67 | "orientation" : "portrait", 68 | "idiom" : "iphone", 69 | "extent" : "full-screen", 70 | "filename" : "launch_640_1136.png", 71 | "subtype" : "retina4", 72 | "scale" : "2x" 73 | }, 74 | { 75 | "orientation" : "portrait", 76 | "idiom" : "ipad", 77 | "extent" : "to-status-bar", 78 | "filename" : "launch_768_1004.png", 79 | "scale" : "1x" 80 | }, 81 | { 82 | "orientation" : "landscape", 83 | "idiom" : "ipad", 84 | "extent" : "to-status-bar", 85 | "filename" : "launch_1024_748.png", 86 | "scale" : "1x" 87 | }, 88 | { 89 | "orientation" : "portrait", 90 | "idiom" : "ipad", 91 | "extent" : "to-status-bar", 92 | "filename" : "launch_1536_2008.png", 93 | "scale" : "2x" 94 | }, 95 | { 96 | "orientation" : "landscape", 97 | "idiom" : "ipad", 98 | "extent" : "to-status-bar", 99 | "filename" : "launch_2048_1496.png", 100 | "scale" : "2x" 101 | } 102 | ], 103 | "info" : { 104 | "version" : 1, 105 | "author" : "xcode" 106 | } 107 | } -------------------------------------------------------------------------------- /test/all/ios/Images.xcassets/LaunchImage.launchimage/launch_1024_748.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/ios/Images.xcassets/LaunchImage.launchimage/launch_1024_748.png -------------------------------------------------------------------------------- /test/all/ios/Images.xcassets/LaunchImage.launchimage/launch_1024_768.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/ios/Images.xcassets/LaunchImage.launchimage/launch_1024_768.png -------------------------------------------------------------------------------- /test/all/ios/Images.xcassets/LaunchImage.launchimage/launch_1536_2008.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/ios/Images.xcassets/LaunchImage.launchimage/launch_1536_2008.png -------------------------------------------------------------------------------- /test/all/ios/Images.xcassets/LaunchImage.launchimage/launch_1536_2048.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/ios/Images.xcassets/LaunchImage.launchimage/launch_1536_2048.png -------------------------------------------------------------------------------- /test/all/ios/Images.xcassets/LaunchImage.launchimage/launch_2048_1496.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/ios/Images.xcassets/LaunchImage.launchimage/launch_2048_1496.png -------------------------------------------------------------------------------- /test/all/ios/Images.xcassets/LaunchImage.launchimage/launch_2048_1536.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/ios/Images.xcassets/LaunchImage.launchimage/launch_2048_1536.png -------------------------------------------------------------------------------- /test/all/ios/Images.xcassets/LaunchImage.launchimage/launch_320_480.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/ios/Images.xcassets/LaunchImage.launchimage/launch_320_480.png -------------------------------------------------------------------------------- /test/all/ios/Images.xcassets/LaunchImage.launchimage/launch_640_1136.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/ios/Images.xcassets/LaunchImage.launchimage/launch_640_1136.png -------------------------------------------------------------------------------- /test/all/ios/Images.xcassets/LaunchImage.launchimage/launch_640_960.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/ios/Images.xcassets/LaunchImage.launchimage/launch_640_960.png -------------------------------------------------------------------------------- /test/all/ios/Images.xcassets/LaunchImage.launchimage/launch_768_1004.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/ios/Images.xcassets/LaunchImage.launchimage/launch_768_1004.png -------------------------------------------------------------------------------- /test/all/ios/Images.xcassets/LaunchImage.launchimage/launch_768_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/ios/Images.xcassets/LaunchImage.launchimage/launch_768_1024.png -------------------------------------------------------------------------------- /test/all/ios/test-all.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.maniccoder.window.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | Foundation 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | TEST 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | NSMainNibFile 26 | test-all 27 | NSMainNibFile~ipad 28 | test-all 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UIStatusBarHidden 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | UIInterfaceOrientationPortraitUpsideDown 41 | 42 | UISupportedInterfaceOrientations~ipad 43 | 44 | UIInterfaceOrientationPortrait 45 | UIInterfaceOrientationPortraitUpsideDown 46 | UIInterfaceOrientationLandscapeLeft 47 | UIInterfaceOrientationLandscapeRight 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /test/all/ios/test-all.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /test/all/ios/viewcontroller.h: -------------------------------------------------------------------------------- 1 | /* viewcontroller.h - Foundation test launcher - Public Domain - 2013 Mattias Jansson 2 | * 3 | * This library provides a cross-platform foundation library in C11 providing basic support 4 | * data types and functions to write applications and games in a platform-independent fashion. 5 | * The latest source code is always available at 6 | * 7 | * https://github.com/mjansson/foundation_lib 8 | * 9 | * This library is put in the public domain; you can redistribute it and/or modify it without 10 | * any restrictions. 11 | */ 12 | 13 | #pragma once 14 | 15 | #include 16 | #include 17 | 18 | #ifdef __OBJC__ 19 | 20 | @interface ViewController : UIViewController { 21 | @public 22 | } 23 | @end 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /test/all/ios/viewcontroller.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/ios/viewcontroller.m -------------------------------------------------------------------------------- /test/all/tizen/res/tizenapp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/all/tizen/res/tizenapp.png -------------------------------------------------------------------------------- /test/all/tizen/tizen-manifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | tizenapp.png 6 | 7 | 8 | 9 | http://tizen.org/privilege/systemsettings 10 | 11 | 12 | -------------------------------------------------------------------------------- /test/window/macos/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "icon_16.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "icon_32-1.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "icon_32.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "icon_64.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "icon_128.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "icon_256-1.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "icon_256.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "icon_512-1.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "icon_512.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "icon_1024.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /test/window/macos/Images.xcassets/AppIcon.appiconset/icon_1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/window/macos/Images.xcassets/AppIcon.appiconset/icon_1024.png -------------------------------------------------------------------------------- /test/window/macos/Images.xcassets/AppIcon.appiconset/icon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/window/macos/Images.xcassets/AppIcon.appiconset/icon_128.png -------------------------------------------------------------------------------- /test/window/macos/Images.xcassets/AppIcon.appiconset/icon_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/window/macos/Images.xcassets/AppIcon.appiconset/icon_16.png -------------------------------------------------------------------------------- /test/window/macos/Images.xcassets/AppIcon.appiconset/icon_256-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/window/macos/Images.xcassets/AppIcon.appiconset/icon_256-1.png -------------------------------------------------------------------------------- /test/window/macos/Images.xcassets/AppIcon.appiconset/icon_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/window/macos/Images.xcassets/AppIcon.appiconset/icon_256.png -------------------------------------------------------------------------------- /test/window/macos/Images.xcassets/AppIcon.appiconset/icon_32-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/window/macos/Images.xcassets/AppIcon.appiconset/icon_32-1.png -------------------------------------------------------------------------------- /test/window/macos/Images.xcassets/AppIcon.appiconset/icon_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/window/macos/Images.xcassets/AppIcon.appiconset/icon_32.png -------------------------------------------------------------------------------- /test/window/macos/Images.xcassets/AppIcon.appiconset/icon_512-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/window/macos/Images.xcassets/AppIcon.appiconset/icon_512-1.png -------------------------------------------------------------------------------- /test/window/macos/Images.xcassets/AppIcon.appiconset/icon_512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/window/macos/Images.xcassets/AppIcon.appiconset/icon_512.png -------------------------------------------------------------------------------- /test/window/macos/Images.xcassets/AppIcon.appiconset/icon_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mjansson/window_lib/707d4cd123a95f8fdf660d80662a3fb2aa27ebe2/test/window/macos/Images.xcassets/AppIcon.appiconset/icon_64.png -------------------------------------------------------------------------------- /test/window/macos/test-window.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-only 8 | 9 | com.apple.security.get-task-allow 10 | 11 | com.apple.security.network.client 12 | 13 | com.apple.security.network.server 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /test/window/macos/test-window.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | com.maniccoder.window.test-window 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | TEST 21 | CFBundleVersion 22 | 1 23 | LSMinimumSystemVersion 24 | ${MACOSX_DEPLOYMENT_TARGET} 25 | NSHumanReadableCopyright 26 | 27 | NSMainNibFile 28 | test-window 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /test/window/macos/test-window.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /test/window/main.c: -------------------------------------------------------------------------------- 1 | /* main.c - Window test - Public Domain - 2013 Mattias Jansson 2 | * 3 | * This library provides a cross-platform window library in C11 providing basic support data types 4 | * and functions to create and manage windows in a platform-independent fashion. The latest source 5 | * code is always available at 6 | * 7 | * https://github.com/mjansson/window_lib 8 | * 9 | * This library is put in the public domain; you can redistribute it and/or modify it without any 10 | * restrictions. 11 | * 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | static application_t 20 | test_window_application(void) { 21 | application_t app; 22 | memset(&app, 0, sizeof(app)); 23 | app.name = string_const(STRING_CONST("Window tests")); 24 | app.short_name = string_const(STRING_CONST("test_window")); 25 | app.company = string_const(STRING_CONST("")); 26 | app.version = window_module_version(); 27 | app.exception_handler = test_exception_handler; 28 | return app; 29 | } 30 | 31 | static memory_system_t 32 | test_window_memory_system(void) { 33 | return memory_system_malloc(); 34 | } 35 | 36 | static foundation_config_t 37 | test_window_config(void) { 38 | foundation_config_t config; 39 | memset(&config, 0, sizeof(config)); 40 | return config; 41 | } 42 | 43 | static int 44 | test_window_initialize(void) { 45 | window_config_t config; 46 | memset(&config, 0, sizeof(config)); 47 | return window_module_initialize(config); 48 | } 49 | 50 | static void 51 | test_window_finalize(void) { 52 | window_module_finalize(); 53 | } 54 | 55 | static int got_create, got_destroy, got_show, got_hide, got_focus, got_unfocus, got_redraw, got_resize, got_other; 56 | 57 | static void 58 | on_test_fail(void) { 59 | window_message_quit(); 60 | } 61 | 62 | static void* 63 | createdestroy_thread(void* arg) { 64 | FOUNDATION_UNUSED(arg); 65 | thread_sleep(500); 66 | 67 | event_stream_t* stream = window_event_stream(); 68 | event_block_t* block = event_stream_process(stream); 69 | event_t* event = 0; 70 | while ((event = event_next(block, event))) { 71 | switch (event->id) { 72 | case WINDOWEVENT_CREATE: 73 | got_create++; 74 | break; 75 | case WINDOWEVENT_GOTFOCUS: 76 | got_focus++; 77 | break; 78 | case WINDOWEVENT_SHOW: 79 | got_show++; 80 | break; 81 | case WINDOWEVENT_REDRAW: 82 | got_redraw++; 83 | break; 84 | case WINDOWEVENT_RESIZE: 85 | got_resize++; 86 | break; 87 | case WINDOWEVENT_DESTROY: 88 | got_destroy++; 89 | break; 90 | case WINDOWEVENT_HIDE: 91 | got_hide++; 92 | break; 93 | case WINDOWEVENT_LOSTFOCUS: 94 | got_unfocus++; 95 | break; 96 | default: 97 | got_other++; 98 | break; 99 | } 100 | } 101 | 102 | EXPECT_INTEQ(got_create, 1); 103 | EXPECT_INTEQ(got_show, 1); 104 | EXPECT_INTEQ(got_focus, 1); 105 | EXPECT_INTGE(got_redraw, 1); 106 | 107 | window_message_quit(); 108 | 109 | return 0; 110 | } 111 | 112 | DECLARE_TEST(window, createdestroy) { 113 | window_t window; 114 | thread_t thread; 115 | 116 | test_set_fail_hook(on_test_fail); 117 | 118 | thread_sleep(100); 119 | 120 | #if FOUNDATION_PLATFORM_WINDOWS || FOUNDATION_PLATFORM_LINUX || FOUNDATION_PLATFORM_BSD 121 | window_create(&window, WINDOW_ADAPTER_DEFAULT, STRING_CONST("Window test"), 800, 600, 0); 122 | #elif FOUNDATION_PLATFORM_MACOS || FOUNDATION_PLATFORM_IOS 123 | window_initialize(&window, delegate_window()); 124 | #endif 125 | 126 | EXPECT_TRUE(window_is_open(&window)); 127 | 128 | got_create = got_destroy = got_show = got_hide = got_focus = got_unfocus = got_redraw = got_resize = got_other = 0; 129 | 130 | thread_initialize(&thread, createdestroy_thread, &window, STRING_CONST("createdestroy_thread"), 131 | THREAD_PRIORITY_NORMAL, 0); 132 | thread_start(&thread); 133 | 134 | EXPECT_EQ(window_message_loop(), 0); 135 | 136 | void* ret = thread_join(&thread); 137 | 138 | window_finalize(&window); 139 | thread_finalize(&thread); 140 | 141 | if (ret) 142 | return ret; 143 | 144 | got_create = got_destroy = got_show = got_hide = got_focus = got_unfocus = got_redraw = got_resize = got_other = 0; 145 | 146 | event_stream_t* stream = window_event_stream(); 147 | event_block_t* block = event_stream_process(stream); 148 | event_t* event = 0; 149 | while ((event = event_next(block, event))) { 150 | switch (event->id) { 151 | case WINDOWEVENT_CREATE: 152 | got_create++; 153 | break; 154 | case WINDOWEVENT_GOTFOCUS: 155 | got_focus++; 156 | break; 157 | case WINDOWEVENT_SHOW: 158 | got_show++; 159 | break; 160 | case WINDOWEVENT_REDRAW: 161 | got_redraw++; 162 | break; 163 | case WINDOWEVENT_RESIZE: 164 | got_resize++; 165 | break; 166 | case WINDOWEVENT_DESTROY: 167 | got_destroy++; 168 | break; 169 | case WINDOWEVENT_HIDE: 170 | got_hide++; 171 | break; 172 | case WINDOWEVENT_LOSTFOCUS: 173 | got_unfocus++; 174 | break; 175 | default: 176 | got_other++; 177 | break; 178 | } 179 | } 180 | 181 | #if FOUNDATION_PLATFORM_MACOS 182 | EXPECT_INTEQ(got_destroy, 0); // Does not destroy actual NS window 183 | #else 184 | EXPECT_INTEQ(got_destroy, 1); 185 | #endif 186 | EXPECT_INTLE(got_hide, 1); // Potential event 187 | EXPECT_INTLE(got_unfocus, 1); // Potential event 188 | 189 | EXPECT_FALSE(window_is_open(&window)); 190 | 191 | return 0; 192 | } 193 | 194 | static void* 195 | sizemove_thread(void* arg) { 196 | window_t* window = arg; 197 | 198 | thread_sleep(100); 199 | 200 | event_stream_t* stream = window_event_stream(); 201 | event_block_t* block = event_stream_process(stream); 202 | // Ignore initial batch of events in this test 203 | 204 | EXPECT_NE(window, 0); 205 | EXPECT_TRUE(window_is_open(window)); 206 | 207 | EXPECT_TRUE(window_is_visible(window)); 208 | EXPECT_TRUE(window_has_focus(window)); 209 | #if FOUNDATION_PLATFORM_IOS || FOUNDATION_PLATFORM_ANDROID 210 | EXPECT_TRUE(window_is_maximized(window)); 211 | #else 212 | // EXPECT_FALSE(window_is_maximized(window)); 213 | #endif 214 | 215 | block = event_stream_process(stream); 216 | event_t* event = 0; 217 | while ((event = event_next(block, event))) { 218 | } 219 | 220 | window_maximize(window); 221 | thread_sleep(1000); 222 | 223 | #if !(FOUNDATION_PLATFORM_IOS || FOUNDATION_PLATFORM_ANDROID) 224 | block = event_stream_process(stream); 225 | event = 0; 226 | got_resize = got_redraw = 0; 227 | got_other = 0; 228 | while ((event = event_next(block, event))) { 229 | switch (event->id) { 230 | case WINDOWEVENT_RESIZE: 231 | got_resize++; 232 | break; 233 | case WINDOWEVENT_REDRAW: 234 | got_redraw++; 235 | break; 236 | default: 237 | // log_warnf(HASH_TEST, WARNING_INVALID_VALUE, STRING_CONST("Got invalid window event: %d"), event->id); 238 | got_other++; 239 | break; 240 | } 241 | } 242 | EXPECT_INTEQ(got_resize, 1); 243 | EXPECT_INTEQ(got_redraw, 1); 244 | #endif 245 | 246 | EXPECT_TRUE(window_is_maximized(window)); 247 | EXPECT_TRUE(window_has_focus(window)); 248 | 249 | #if !FOUNDATION_PLATFORM_IOS && !FOUNDATION_PLATFORM_ANDROID 250 | window_restore(window); 251 | thread_sleep(1000); 252 | 253 | block = event_stream_process(stream); 254 | event = 0; 255 | got_resize = got_redraw = 0; 256 | got_other = 0; 257 | while ((event = event_next(block, event))) { 258 | switch (event->id) { 259 | case WINDOWEVENT_RESIZE: 260 | got_resize++; 261 | break; 262 | case WINDOWEVENT_REDRAW: 263 | got_redraw++; 264 | break; 265 | default: 266 | got_other++; 267 | break; 268 | } 269 | } 270 | EXPECT_INTEQ(got_resize, 1); 271 | EXPECT_INTEQ(got_redraw, 1); 272 | 273 | EXPECT_FALSE(window_is_maximized(window)); 274 | EXPECT_TRUE(window_has_focus(window)); 275 | #endif 276 | 277 | window_maximize(window); 278 | thread_sleep(1000); 279 | 280 | block = event_stream_process(stream); 281 | EXPECT_TRUE(window_is_maximized(window)); 282 | 283 | #if !FOUNDATION_PLATFORM_IOS && !FOUNDATION_PLATFORM_ANDROID 284 | window_resize(window, 150, 100); 285 | thread_sleep(1000); 286 | 287 | block = event_stream_process(stream); 288 | event = 0; 289 | got_resize = got_redraw = 0; 290 | got_other = 0; 291 | while ((event = event_next(block, event))) { 292 | switch (event->id) { 293 | case WINDOWEVENT_RESIZE: 294 | got_resize++; 295 | break; 296 | case WINDOWEVENT_REDRAW: 297 | got_redraw++; 298 | break; 299 | default: 300 | got_other++; 301 | break; 302 | } 303 | } 304 | // Can get two resize && redraw for restore and resize 305 | EXPECT_INTGE(got_resize, 1); 306 | EXPECT_INTLE(got_resize, 2); 307 | EXPECT_INTGE(got_redraw, 1); 308 | EXPECT_INTLE(got_redraw, 2); 309 | 310 | EXPECT_INTEQ(window_width(window), 150); 311 | EXPECT_INTEQ(window_height(window), 100); 312 | EXPECT_FALSE(window_is_maximized(window)); 313 | EXPECT_TRUE(window_has_focus(window)); 314 | 315 | window_move(window, 200, 300); 316 | thread_sleep(1000); 317 | 318 | int base_x = window_position_x(window); 319 | int base_y = window_position_y(window); 320 | window_move(window, 300, 500); 321 | thread_sleep(1000); 322 | 323 | block = event_stream_process(stream); 324 | 325 | EXPECT_INTEQ(window_position_x(window), base_x + 100); 326 | EXPECT_INTEQ(window_position_y(window), base_y + 200); 327 | EXPECT_FALSE(window_is_maximized(window)); 328 | EXPECT_TRUE(window_has_focus(window)); 329 | 330 | window_minimize(window); 331 | thread_sleep(1000); 332 | 333 | block = event_stream_process(stream); 334 | event = 0; 335 | got_resize = got_redraw = got_unfocus = 0; 336 | got_other = 0; 337 | while ((event = event_next(block, event))) { 338 | switch (event->id) { 339 | case WINDOWEVENT_RESIZE: 340 | got_resize++; 341 | break; 342 | case WINDOWEVENT_REDRAW: 343 | got_redraw++; 344 | break; 345 | case WINDOWEVENT_LOSTFOCUS: 346 | got_unfocus++; 347 | break; 348 | default: 349 | got_other++; 350 | break; 351 | } 352 | } 353 | EXPECT_INTEQ(got_resize, 0); 354 | EXPECT_INTEQ(got_redraw, 0); 355 | EXPECT_INTEQ(got_unfocus, 1); 356 | 357 | EXPECT_FALSE(window_is_maximized(window)); 358 | EXPECT_FALSE(window_has_focus(window)); 359 | 360 | window_restore(window); 361 | thread_sleep(1000); 362 | 363 | block = event_stream_process(stream); 364 | event = 0; 365 | got_resize = got_redraw = got_focus = 0; 366 | got_other = 0; 367 | while ((event = event_next(block, event))) { 368 | switch (event->id) { 369 | case WINDOWEVENT_RESIZE: 370 | got_resize++; 371 | break; 372 | case WINDOWEVENT_REDRAW: 373 | got_redraw++; 374 | break; 375 | case WINDOWEVENT_GOTFOCUS: 376 | got_focus++; 377 | break; 378 | default: 379 | got_other++; 380 | break; 381 | } 382 | } 383 | EXPECT_INTEQ(got_resize, 0); 384 | EXPECT_INTGE(got_redraw, 1); 385 | EXPECT_INTEQ(got_focus, 1); 386 | 387 | EXPECT_FALSE(window_is_maximized(window)); 388 | EXPECT_FALSE(window_is_minimized(window)); 389 | EXPECT_TRUE(window_has_focus(window)); 390 | 391 | window_minimize(window); 392 | thread_sleep(1000); 393 | 394 | EXPECT_FALSE(window_is_maximized(window)); 395 | EXPECT_TRUE(window_is_minimized(window)); 396 | #endif 397 | 398 | window_message_quit(); 399 | 400 | return 0; 401 | } 402 | 403 | DECLARE_TEST(window, sizemove) { 404 | window_t window; 405 | thread_t thread; 406 | 407 | test_set_fail_hook(on_test_fail); 408 | 409 | thread_sleep(100); 410 | 411 | #if FOUNDATION_PLATFORM_WINDOWS || FOUNDATION_PLATFORM_LINUX || FOUNDATION_PLATFORM_BSD 412 | window_create(&window, WINDOW_ADAPTER_DEFAULT, STRING_CONST("Window test"), 800, 600, 0); 413 | #elif FOUNDATION_PLATFORM_MACOS || FOUNDATION_PLATFORM_IOS 414 | window_initialize(&window, delegate_window()); 415 | #endif 416 | 417 | EXPECT_TRUE(window_is_open(&window)); 418 | 419 | got_create = got_destroy = got_show = got_hide = got_focus = got_unfocus = got_redraw = got_resize = got_other = 0; 420 | 421 | thread_initialize(&thread, sizemove_thread, &window, STRING_CONST("sizemove_thread"), THREAD_PRIORITY_NORMAL, 0); 422 | thread_start(&thread); 423 | 424 | EXPECT_EQ(window_message_loop(), 0); 425 | 426 | void* ret = thread_join(&thread); 427 | 428 | window_finalize(&window); 429 | thread_finalize(&thread); 430 | window_finalize(&window); 431 | 432 | EXPECT_FALSE(window_is_open(&window)); 433 | 434 | return ret; 435 | } 436 | 437 | static void 438 | test_window_declare(void) { 439 | ADD_TEST(window, createdestroy); 440 | ADD_TEST(window, sizemove); 441 | } 442 | 443 | static test_suite_t test_window_suite = {test_window_application, 444 | test_window_memory_system, 445 | test_window_config, 446 | test_window_declare, 447 | test_window_initialize, 448 | test_window_finalize, 449 | 0}; 450 | 451 | #if FOUNDATION_PLATFORM_ANDROID || FOUNDATION_PLATFORM_IOS 452 | 453 | int 454 | test_window_run(void); 455 | 456 | int 457 | test_window_run(void) { 458 | test_suite = test_window_suite; 459 | return test_run_all(); 460 | } 461 | 462 | #else 463 | 464 | test_suite_t 465 | test_suite_define(void); 466 | 467 | test_suite_t 468 | test_suite_define(void) { 469 | return test_window_suite; 470 | } 471 | 472 | #endif 473 | -------------------------------------------------------------------------------- /window/build.h: -------------------------------------------------------------------------------- 1 | /* build.h - Window library build setup - Public Domain - 2014 Mattias Jansson 2 | * 3 | * This library provides a cross-platform window library in C11 providing basic support data types 4 | * and functions to create and manage windows in a platform-independent fashion. The latest source 5 | * code is always available at 6 | * 7 | * https://github.com/mjansson/window_lib 8 | * 9 | * This library is put in the public domain; you can redistribute it and/or modify it without any 10 | * restrictions. 11 | * 12 | */ 13 | 14 | #pragma once 15 | 16 | #include 17 | 18 | #if defined(WINDOW_COMPILE) && WINDOW_COMPILE 19 | #ifdef __cplusplus 20 | #define WINDOW_EXTERN extern "C" 21 | #define WINDOW_API extern "C" 22 | #else 23 | #define WINDOW_EXTERN extern 24 | #define WINDOW_API extern 25 | #endif 26 | #else 27 | #ifdef __cplusplus 28 | #define WINDOW_EXTERN extern "C" 29 | #define WINDOW_API extern "C" 30 | #else 31 | #define WINDOW_EXTERN extern 32 | #define WINDOW_API extern 33 | #endif 34 | #endif 35 | -------------------------------------------------------------------------------- /window/event.c: -------------------------------------------------------------------------------- 1 | /* event.c - Window library events - Public Domain - 2014 Mattias Jansson 2 | * 3 | * This library provides a cross-platform window library in C11 providing basic support data types 4 | * and functions to create and manage windows in a platform-independent fashion. The latest source 5 | * code is always available at 6 | * 7 | * https://github.com/mjansson/window_lib 8 | * 9 | * This library is put in the public domain; you can redistribute it and/or modify it without any 10 | * restrictions. 11 | * 12 | */ 13 | 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #if FOUNDATION_PLATFORM_WINDOWS 23 | #include 24 | #endif 25 | 26 | tick_t window_event_token; 27 | 28 | static event_stream_t* window_stream = 0; 29 | 30 | bool window_app_started = false; 31 | bool window_app_paused = true; 32 | 33 | #if FOUNDATION_PLATFORM_LINUX 34 | static semaphore_t windows_lock; 35 | static window_t** windows; 36 | #endif 37 | 38 | int 39 | window_event_initialize(void) { 40 | window_stream = event_stream_allocate(1024); 41 | window_event_token = 1; 42 | #if FOUNDATION_PLATFORM_LINUX 43 | semaphore_initialize(&windows_lock, 1); 44 | windows = 0; 45 | #endif 46 | return 0; 47 | } 48 | 49 | void 50 | window_event_finalize(void) { 51 | #if FOUNDATION_PLATFORM_LINUX 52 | array_deallocate(windows); 53 | semaphore_finalize(&windows_lock); 54 | #endif 55 | event_stream_deallocate(window_stream); 56 | window_stream = nullptr; 57 | } 58 | 59 | void 60 | window_event_post(window_event_id id, window_t* window) { 61 | if (window_stream) 62 | event_post(window_stream, (int)id, 0, 0, &window, sizeof(window_t*)); 63 | } 64 | 65 | #if FOUNDATION_PLATFORM_WINDOWS 66 | 67 | void 68 | window_event_post_native(window_event_id id, window_t* window, void* hwnd, uintptr_t msg, uintptr_t wparam, 69 | uintptr_t lparam, void* buffer, size_t size) { 70 | if (window_stream) 71 | event_post_varg(window_stream, (int)id, 0, 0, &window, sizeof(window_t*), &hwnd, sizeof(void*), &msg, 72 | sizeof(uintptr_t), &wparam, sizeof(uintptr_t), &lparam, sizeof(uintptr_t), 73 | size ? buffer : nullptr, size, nullptr, nullptr); 74 | } 75 | 76 | #elif FOUNDATION_PLATFORM_LINUX 77 | 78 | void 79 | window_event_post_native(window_event_id id, window_t* window, void* xevent) { 80 | if (window_stream) 81 | event_post_varg(window_stream, (int)id, 0, 0, &window, sizeof(window_t*), xevent, sizeof(XEvent), nullptr, 82 | nullptr); 83 | } 84 | 85 | #endif 86 | 87 | const window_t* 88 | window_event_window(const event_t* event) { 89 | return *(const window_t* const*)&event->payload[0]; 90 | } 91 | 92 | event_stream_t* 93 | window_event_stream(void) { 94 | return window_stream; 95 | } 96 | 97 | void 98 | window_event_handle(event_t* event) { 99 | if (event->id == FOUNDATIONEVENT_START) { 100 | window_app_started = true; 101 | window_app_paused = false; 102 | } else if (event->id == FOUNDATIONEVENT_PAUSE) 103 | window_app_paused = true; 104 | else if (event->id == FOUNDATIONEVENT_RESUME) 105 | window_app_paused = false; 106 | } 107 | -------------------------------------------------------------------------------- /window/event.h: -------------------------------------------------------------------------------- 1 | /* event.h - Window library events - Public Domain - 2014 Mattias Jansson 2 | * 3 | * This library provides a cross-platform window library in C11 providing basic support data types 4 | * and functions to create and manage windows in a platform-independent fashion. The latest source 5 | * code is always available at 6 | * 7 | * https://github.com/mjansson/window_lib 8 | * 9 | * This library is put in the public domain; you can redistribute it and/or modify it without any 10 | * restrictions. 11 | * 12 | */ 13 | 14 | #pragma once 15 | 16 | #include 17 | #include 18 | 19 | #include 20 | 21 | WINDOW_API void 22 | window_event_post(window_event_id id, window_t* window); 23 | 24 | WINDOW_API event_stream_t* 25 | window_event_stream(void); 26 | 27 | /*! Handle foundation events. Do not pass in events from any other 28 | event namespace to this function. 29 | \param event Foundation event */ 30 | WINDOW_API void 31 | window_event_handle(event_t* event); 32 | 33 | /*! Get window related to the event 34 | \param event Window event 35 | \return Window */ 36 | WINDOW_API const window_t* 37 | window_event_window(const event_t* event); 38 | 39 | #if FOUNDATION_PLATFORM_WINDOWS 40 | 41 | WINDOW_API void 42 | window_event_post_native(window_event_id id, window_t* window, void* hwnd, uintptr_t msg, uintptr_t wparam, 43 | uintptr_t lparam, void* buffer, size_t size); 44 | 45 | #elif FOUNDATION_PLATFORM_LINUX 46 | 47 | WINDOW_API void 48 | window_event_post_native(window_event_id id, window_t* window, void* xevent); 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /window/hashstrings.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | /* ****** AUTOMATICALLY GENERATED, DO NOT EDIT ****** 6 | Edit corresponding definitions file and rerun 7 | the foundation hashify tool to update this file */ 8 | 9 | #define HASH_WINDOW static_hash_string("window", 6, 0xa9008b1c524585c4ULL) 10 | -------------------------------------------------------------------------------- /window/hashstrings.txt: -------------------------------------------------------------------------------- 1 | 2 | HASH_WINDOW window 3 | -------------------------------------------------------------------------------- /window/internal.h: -------------------------------------------------------------------------------- 1 | /* internal.h - Window library internals - Public Domain - 2014 Mattias Jansson 2 | * 3 | * This library provides a cross-platform window library in C11 providing basic support data types 4 | * and functions to create and manage windows in a platform-independent fashion. The latest source 5 | * code is always available at 6 | * 7 | * https://github.com/mjansson/window_lib 8 | * 9 | * This library is put in the public domain; you can redistribute it and/or modify it without any 10 | * restrictions. 11 | * 12 | */ 13 | 14 | #pragma once 15 | 16 | #include 17 | 18 | #include 19 | 20 | #if FOUNDATION_PLATFORM_WINDOWS 21 | #include 22 | #endif 23 | #if FOUNDATION_PLATFORM_LINUX 24 | #include 25 | #include 26 | #include 27 | #include 28 | #endif 29 | 30 | WINDOW_EXTERN int 31 | window_event_initialize(void); 32 | 33 | WINDOW_EXTERN void 34 | window_event_finalize(void); 35 | 36 | WINDOW_EXTERN tick_t window_event_token; 37 | 38 | #if FOUNDATION_PLATFORM_MACOS || FOUNDATION_PLATFORM_IOS 39 | 40 | WINDOW_EXTERN void 41 | window_class_reference(void); 42 | 43 | #endif 44 | 45 | #if FOUNDATION_PLATFORM_LINUX || FOUNDATION_PLATFORM_APPLE 46 | 47 | WINDOW_EXTERN void 48 | window_native_initialize(void); 49 | 50 | WINDOW_EXTERN void 51 | window_native_finalize(void); 52 | 53 | #endif 54 | 55 | WINDOW_EXTERN bool window_app_started; 56 | WINDOW_EXTERN bool window_app_paused; 57 | -------------------------------------------------------------------------------- /window/types.h: -------------------------------------------------------------------------------- 1 | /* types.h - Window library types - Public Domain - 2014 Mattias Jansson 2 | * 3 | * This library provides a cross-platform window library in C11 providing basic support data types 4 | * and functions to create and manage windows in a platform-independent fashion. The latest source 5 | * code is always available at 6 | * 7 | * https://github.com/mjansson/window_lib 8 | * 9 | * This library is put in the public domain; you can redistribute it and/or modify it without any 10 | * restrictions. 11 | * 12 | */ 13 | 14 | #pragma once 15 | 16 | #include 17 | 18 | #include 19 | #include 20 | 21 | #if FOUNDATION_PLATFORM_LINUX 22 | #include 23 | #endif 24 | 25 | typedef enum window_event_id { 26 | /*! Window was created */ 27 | WINDOWEVENT_CREATE = 1, 28 | /*! Window was resized */ 29 | WINDOWEVENT_RESIZE, 30 | /*! Window was moved */ 31 | WINDOWEVENT_MOVE, 32 | /*! Window close requested */ 33 | WINDOWEVENT_CLOSE, 34 | /*! Window was destroyed */ 35 | WINDOWEVENT_DESTROY, 36 | /*! Window was shown */ 37 | WINDOWEVENT_SHOW, 38 | /*! Window was hidden */ 39 | WINDOWEVENT_HIDE, 40 | /*! Window got focus */ 41 | WINDOWEVENT_GOTFOCUS, 42 | /*! Window lost focus */ 43 | WINDOWEVENT_LOSTFOCUS, 44 | /*! Window needs to be redrawn */ 45 | WINDOWEVENT_REDRAW, 46 | /*! Native event */ 47 | WINDOWEVENT_NATIVE 48 | } window_event_id; 49 | 50 | #define WINDOW_ADAPTER_DEFAULT ((unsigned int)-1) 51 | 52 | #define WINDOW_FLAG_NOSHOW 0x0001 53 | #define WINDOW_FLAG_NOSYSTEMMENU 0x0002 54 | #define WINDOW_FLAG_FULLSCREEN 0x0004 55 | #define WINDOW_FLAG_NORESIZE 0x0008 56 | 57 | typedef struct window_config_t window_config_t; 58 | typedef struct window_t window_t; 59 | 60 | struct window_config_t { 61 | int unused; 62 | }; 63 | 64 | struct window_t { 65 | #if FOUNDATION_PLATFORM_WINDOWS 66 | unsigned int adapter; 67 | void* hwnd; 68 | void* instance; 69 | bool created; 70 | bool cursor_lock; 71 | int cursor_pos_x; 72 | int cursor_pos_y; 73 | unsigned int wstyle; 74 | bool is_resizing; 75 | #elif FOUNDATION_PLATFORM_MACOS 76 | void* nswindow; 77 | void* delegate; 78 | #elif FOUNDATION_PLATFORM_LINUX 79 | unsigned int adapter; 80 | bool created; 81 | Display* display; 82 | unsigned int screen; 83 | XVisualInfo* visual; 84 | Window drawable; 85 | Atom atom_delete; 86 | XIM xim; 87 | XIC xic; 88 | bool focus; 89 | bool visible; 90 | #elif FOUNDATION_PLATFORM_IOS 91 | void* uiwindow; 92 | unsigned int tag; 93 | #elif FOUNDATION_PLATFORM_ANDROID 94 | unsigned int adapter; 95 | int width; 96 | int height; 97 | void* native; 98 | #endif 99 | unsigned int flags; 100 | bool is_visible; 101 | tick_t last_paint; 102 | tick_t last_resize; 103 | }; 104 | 105 | #if FOUNDATION_PLATFORM_MACOS 106 | #ifdef __OBJC__ 107 | 108 | #include 109 | #import 110 | 111 | @interface WindowView : NSView { 112 | @public 113 | } 114 | + (void)referenceClass; 115 | @end 116 | 117 | @interface WindowViewController : NSViewController { 118 | @public 119 | } 120 | + (void)referenceClass; 121 | @end 122 | 123 | #endif 124 | #endif 125 | 126 | #if FOUNDATION_PLATFORM_IOS 127 | #ifdef __OBJC__ 128 | 129 | #include 130 | 131 | @interface WindowView : UIView { 132 | @public 133 | id display_link; 134 | CGPoint begin_touch; 135 | CGPoint last_touch; 136 | tick_t begin_touch_time; 137 | UIView* keyboard_view; 138 | } 139 | + (void)referenceClass; 140 | @end 141 | 142 | IB_DESIGNABLE 143 | @interface WindowViewController : UIViewController { 144 | @public 145 | } 146 | @property (nonatomic) IBInspectable BOOL hideStatusBar; 147 | + (void)referenceClass; 148 | @end 149 | 150 | #endif 151 | #endif 152 | 153 | typedef void (*window_draw_fn)(window_t* window); 154 | -------------------------------------------------------------------------------- /window/version.c: -------------------------------------------------------------------------------- 1 | /* ****** AUTOMATICALLY GENERATED, DO NOT EDIT ****** 2 | This file is generated from the git describe command. 3 | Run the configure script to regenerate this file */ 4 | 5 | #include 6 | #include 7 | 8 | version_t 9 | window_module_version(void) { 10 | return version_make(0, 0, 1, 0, 0x0); 11 | } 12 | -------------------------------------------------------------------------------- /window/window.c: -------------------------------------------------------------------------------- 1 | /* window.c - Window library - Public Domain - 2014 Mattias Jansson 2 | * 3 | * This library provides a cross-platform window library in C11 providing basic support data types 4 | * and functions to create and manage windows in a platform-independent fashion. The latest source 5 | * code is always available at 6 | * 7 | * https://github.com/mjansson/window_lib 8 | * 9 | * This library is put in the public domain; you can redistribute it and/or modify it without any 10 | * restrictions. 11 | * 12 | */ 13 | 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | 20 | static bool window_initialized = false; 21 | 22 | #if FOUNDATION_PLATFORM_LINUX 23 | 24 | static int 25 | x11_error_handler(Display* display, XErrorEvent* event) { 26 | char errmsg[512]; 27 | XGetErrorText(display, event->error_code, errmsg, sizeof(errmsg)); 28 | log_warnf(HASH_WINDOW, WARNING_SYSTEM_CALL_FAIL, STRING_CONST("X error event occurred: %s"), errmsg); 29 | 30 | void* frame[64]; 31 | size_t frame_count = stacktrace_capture(frame, sizeof(frame) / sizeof(frame[0]), 0); 32 | if (frame_count) { 33 | size_t capacity = 8 * 1024; 34 | char* buffer = memory_allocate(HASH_WINDOW, capacity, 0, MEMORY_PERSISTENT); 35 | string_t stacktrace = stacktrace_resolve(buffer, capacity, frame, frame_count, 0); 36 | log_infof(HASH_WINDOW, STRING_CONST("Stack trace:\n%.*s"), STRING_FORMAT(stacktrace)); 37 | memory_deallocate(buffer); 38 | } 39 | return 0; 40 | } 41 | 42 | #endif 43 | 44 | int 45 | window_module_initialize(const window_config_t config) { 46 | FOUNDATION_UNUSED(config); 47 | if (window_initialized) 48 | return 0; 49 | 50 | if (window_event_initialize() < 0) 51 | return -1; 52 | 53 | #if FOUNDATION_PLATFORM_MACOS || FOUNDATION_PLATFORM_IOS 54 | window_class_reference(); 55 | #endif 56 | 57 | #if FOUNDATION_PLATFORM_LINUX 58 | XInitThreads(); 59 | XSetErrorHandler(x11_error_handler); 60 | #endif 61 | 62 | #if FOUNDATION_PLATFORM_APPLE || FOUNDATION_PLATFORM_LINUX 63 | window_native_initialize(); 64 | #endif 65 | 66 | window_initialized = true; 67 | 68 | return 0; 69 | } 70 | 71 | void 72 | window_module_finalize(void) { 73 | #if FOUNDATION_PLATFORM_APPLE || FOUNDATION_PLATFORM_LINUX 74 | window_native_finalize(); 75 | #endif 76 | 77 | window_event_finalize(); 78 | 79 | window_initialized = false; 80 | } 81 | 82 | bool 83 | window_module_is_initialized(void) { 84 | return window_initialized; 85 | } 86 | -------------------------------------------------------------------------------- /window/window.h: -------------------------------------------------------------------------------- 1 | /* window.h - Window library - Public Domain - 2014 Mattias Jansson 2 | * 3 | * This library provides a cross-platform window library in C11 providing basic support data types 4 | * and functions to create and manage windows in a platform-independent fashion. The latest source 5 | * code is always available at 6 | * 7 | * https://github.com/mjansson/window_lib 8 | * 9 | * This library is put in the public domain; you can redistribute it and/or modify it without any 10 | * restrictions. 11 | * 12 | */ 13 | 14 | #pragma once 15 | 16 | #include 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | WINDOW_API int 23 | window_module_initialize(const window_config_t config); 24 | 25 | WINDOW_API void 26 | window_module_finalize(void); 27 | 28 | WINDOW_API bool 29 | window_module_is_initialized(void); 30 | 31 | WINDOW_API version_t 32 | window_module_version(void); 33 | 34 | //! Main window message loop. Blocks until application termination 35 | // \return 0 if success, <0 if error 36 | WINDOW_API int 37 | window_message_loop(void); 38 | 39 | //! Signal main window message loop to quit 40 | WINDOW_API void 41 | window_message_quit(void); 42 | 43 | WINDOW_API void 44 | window_finalize(window_t* window); 45 | 46 | WINDOW_API void 47 | window_deallocate(window_t* window); 48 | 49 | WINDOW_API unsigned int 50 | window_adapter(window_t* window); 51 | 52 | WINDOW_API void 53 | window_maximize(window_t* window); 54 | 55 | WINDOW_API void 56 | window_minimize(window_t* window); 57 | 58 | WINDOW_API void 59 | window_restore(window_t* window); 60 | 61 | WINDOW_API void 62 | window_resize(window_t* window, int width, int height); 63 | 64 | WINDOW_API void 65 | window_move(window_t* window, int x, int y); 66 | 67 | WINDOW_API void 68 | window_close(window_t* window); 69 | 70 | WINDOW_API bool 71 | window_is_open(window_t* window); 72 | 73 | WINDOW_API bool 74 | window_is_visible(window_t* window); 75 | 76 | WINDOW_API bool 77 | window_is_maximized(window_t* window); 78 | 79 | WINDOW_API bool 80 | window_is_minimized(window_t* window); 81 | 82 | WINDOW_API bool 83 | window_has_focus(window_t* window); 84 | 85 | WINDOW_API void 86 | window_show_cursor(window_t* window, bool show, bool lock); 87 | 88 | WINDOW_API void 89 | window_set_cursor_pos(window_t* window, int x, int y); 90 | 91 | WINDOW_API bool 92 | window_is_cursor_locked(window_t* window); 93 | 94 | WINDOW_API void 95 | window_set_title(window_t* window, const char* title, size_t length); 96 | 97 | WINDOW_API unsigned int 98 | window_width(window_t* window); 99 | 100 | WINDOW_API unsigned int 101 | window_height(window_t* window); 102 | 103 | WINDOW_API int 104 | window_position_x(window_t* window); 105 | 106 | WINDOW_API int 107 | window_position_y(window_t* window); 108 | 109 | WINDOW_API void 110 | window_fit_to_screen(window_t* window); 111 | 112 | WINDOW_API int 113 | window_screen_width(unsigned int adapter); 114 | 115 | WINDOW_API int 116 | window_screen_height(unsigned int adapter); 117 | 118 | #if FOUNDATION_PLATFORM_WINDOWS 119 | 120 | WINDOW_API void 121 | window_create(window_t* window, unsigned int adapter, const char* title, size_t length, unsigned int width, 122 | unsigned int height, unsigned int flags); 123 | 124 | WINDOW_API window_t* 125 | window_allocate(void* hwnd); 126 | 127 | WINDOW_API void 128 | window_initialize(window_t* window, void* hwnd); 129 | 130 | WINDOW_API void* 131 | window_hwnd(window_t* window); 132 | 133 | WINDOW_API void* 134 | window_hinstance(window_t* window); 135 | 136 | WINDOW_API void* 137 | window_hdc(window_t* window); 138 | 139 | WINDOW_API void 140 | window_release_hdc(void* hwnd, void* hdc); 141 | 142 | #elif FOUNDATION_PLATFORM_MACOS 143 | 144 | WINDOW_API window_t* 145 | window_allocate(void* nswindow); 146 | 147 | WINDOW_API void 148 | window_initialize(window_t* window, void* nswindow); 149 | 150 | WINDOW_API void* 151 | window_view(window_t* window, unsigned int tag); // NSView* 152 | 153 | #elif FOUNDATION_PLATFORM_LINUX 154 | 155 | WINDOW_API window_t* 156 | window_allocate(void); 157 | 158 | WINDOW_API void 159 | window_create(window_t* window, unsigned int adapter, const char* title, size_t length, unsigned int width, 160 | unsigned int height, unsigned int flags); 161 | 162 | WINDOW_API void* 163 | window_display(window_t* window); 164 | 165 | WINDOW_API int 166 | window_screen(window_t* window); 167 | 168 | WINDOW_API unsigned long 169 | window_drawable(window_t* window); 170 | 171 | WINDOW_API void* 172 | window_visual(window_t* window); 173 | 174 | #elif FOUNDATION_PLATFORM_IOS 175 | 176 | WINDOW_API window_t* 177 | window_allocate(void* uiwindow); 178 | 179 | WINDOW_API void 180 | window_initialize(window_t* window, void* uiwindow); 181 | 182 | WINDOW_API void* 183 | window_view(window_t* window, unsigned int tag); // UIView* 184 | 185 | WINDOW_API void* 186 | window_layer(window_t* window, void* view); // CAEAGLLayer* 187 | 188 | WINDOW_API int 189 | window_view_width(window_t* window, void* view); 190 | 191 | WINDOW_API int 192 | window_view_height(window_t* window, void* view); 193 | 194 | WINDOW_API void 195 | window_add_displaylink(window_t* window, window_draw_fn drawfn); 196 | 197 | WINDOW_API void 198 | window_show_keyboard(window_t* window); 199 | 200 | WINDOW_API void 201 | window_hide_keyboard(window_t* window); 202 | 203 | #elif FOUNDATION_PLATFORM_ANDROID 204 | 205 | WINDOW_API window_t* 206 | window_allocate(void* native); 207 | 208 | WINDOW_API void 209 | window_initialize(window_t* window, void* native); 210 | 211 | WINDOW_API void* 212 | window_native(window_t* window); 213 | 214 | WINDOW_API void* 215 | window_display(window_t* window); 216 | 217 | WINDOW_API void 218 | window_show_keyboard(window_t* window); 219 | 220 | WINDOW_API void 221 | window_hide_keyboard(window_t* window); 222 | 223 | #endif 224 | -------------------------------------------------------------------------------- /window/window_android.c: -------------------------------------------------------------------------------- 1 | /* window_android.c - Window library - Public Domain - 2014 Mattias Jansson 2 | * 3 | * This library provides a cross-platform window library in C11 providing basic support data types 4 | * and functions to create and manage windows in a platform-independent fashion. The latest source 5 | * code is always available at 6 | * 7 | * https://github.com/mjansson/window_lib 8 | * 9 | * This library is put in the public domain; you can redistribute it and/or modify it without any 10 | * restrictions. 11 | * 12 | */ 13 | 14 | #include 15 | #include 16 | 17 | #if FOUNDATION_PLATFORM_ANDROID 18 | 19 | #include 20 | #include 21 | 22 | window_t* 23 | window_allocate(void* native) { 24 | window_t* window = memory_allocate(0, sizeof(window_t), 0, MEMORY_PERSISTENT | MEMORY_ZERO_INITIALIZED); 25 | window_initialize(window, native); 26 | return window; 27 | } 28 | 29 | void 30 | window_initialize(window_t* window, void* native) { 31 | } 32 | 33 | void 34 | window_finalize(window_t* window) { 35 | } 36 | 37 | void* 38 | window_native(window_t* window) { 39 | return 0; 40 | } 41 | 42 | void* 43 | window_display(window_t* window) { 44 | return 0; 45 | } 46 | 47 | void 48 | window_show_keyboard(window_t* window) { 49 | } 50 | 51 | void 52 | window_hide_keyboard(window_t* window) { 53 | } 54 | 55 | void 56 | window_deallocate(window_t* window) { 57 | window_finalize(window); 58 | memory_deallocate(window); 59 | } 60 | 61 | unsigned int 62 | window_adapter(window_t* window) { 63 | return WINDOW_ADAPTER_DEFAULT; 64 | } 65 | 66 | void 67 | window_maximize(window_t* window) { 68 | } 69 | 70 | void 71 | window_minimize(window_t* window) { 72 | } 73 | 74 | void 75 | window_restore(window_t* window) { 76 | } 77 | 78 | void 79 | window_resize(window_t* window, unsigned int width, unsigned int height) { 80 | } 81 | 82 | void 83 | window_move(window_t* window, int x, int y) { 84 | } 85 | 86 | bool 87 | window_is_open(window_t* window) { 88 | return true; 89 | } 90 | 91 | bool 92 | window_is_visible(window_t* window) { 93 | return true; 94 | } 95 | 96 | bool 97 | window_is_maximized(window_t* window) { 98 | return false; 99 | } 100 | 101 | bool 102 | window_is_minimized(window_t* window) { 103 | return false; 104 | } 105 | 106 | bool 107 | window_has_focus(window_t* window) { 108 | return true; 109 | } 110 | 111 | void 112 | window_show_cursor(window_t* window, bool show, bool lock) { 113 | } 114 | 115 | void 116 | window_set_cursor_pos(window_t* window, int x, int y) { 117 | } 118 | 119 | bool 120 | window_is_cursor_locked(window_t* window) { 121 | return false; 122 | } 123 | 124 | void 125 | window_set_title(window_t* window, const char* title, size_t length) { 126 | } 127 | 128 | int 129 | window_width(window_t* window) { 130 | return 0; 131 | } 132 | 133 | int 134 | window_height(window_t* window) { 135 | return 0; 136 | } 137 | 138 | int 139 | window_position_x(window_t* window) { 140 | return 0; 141 | } 142 | 143 | int 144 | window_position_y(window_t* window) { 145 | return 0; 146 | } 147 | 148 | void 149 | window_fit_to_screen(window_t* window) { 150 | } 151 | 152 | #endif 153 | -------------------------------------------------------------------------------- /window/window_ios.m: -------------------------------------------------------------------------------- 1 | /* window_ios.m - Window library - Public Domain - 2014 Mattias Jansson 2 | * 3 | * This library provides a cross-platform window library in C11 providing basic support data types 4 | * and functions to create and manage windows in a platform-independent fashion. The latest source 5 | * code is always available at 6 | * 7 | * https://github.com/mjansson/window_lib 8 | * 9 | * This library is put in the public domain; you can redistribute it and/or modify it without any 10 | * restrictions. 11 | * 12 | */ 13 | 14 | #include 15 | 16 | #if FOUNDATION_PLATFORM_IOS 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #import 23 | #import 24 | #import 25 | 26 | volatile int _dummy_window_class_reference = 0; 27 | 28 | @interface WindowKeyboardView : UIView 29 | @end 30 | 31 | void 32 | _window_native_initialize(void) { 33 | } 34 | 35 | void 36 | _window_native_finalize(void) { 37 | } 38 | 39 | window_t* 40 | window_allocate_from_uiwindow(void* uiwindow) { 41 | window_t* window = 42 | memory_allocate(0, sizeof(window_t), 0, MEMORY_PERSISTENT | MEMORY_ZERO_INITIALIZED); 43 | window->uiwindow = uiwindow; 44 | return window; 45 | } 46 | 47 | void* 48 | window_view(window_t* window, unsigned int tag) { 49 | if (!window || !window->uiwindow) 50 | return 0; 51 | 52 | UIWindow* uiwindow = (__bridge UIWindow*)(window->uiwindow); 53 | UIView* view = [uiwindow viewWithTag:tag]; 54 | if (!view) 55 | view = [[uiwindow subviews] objectAtIndex:tag]; 56 | if (!view) 57 | view = [[uiwindow subviews] objectAtIndex:0]; 58 | return (__bridge void*)(view); 59 | } 60 | 61 | void* 62 | window_layer(window_t* window, void* view) { 63 | return (__bridge void*)(view ? [(__bridge UIView*)view layer] : 0); 64 | } 65 | 66 | int 67 | window_view_width(window_t* window, void* view) { 68 | if (view) { 69 | CGRect rect = [(__bridge UIView*)view frame]; 70 | CGFloat scale = [(__bridge UIView*)view contentScaleFactor]; 71 | return (int)(rect.size.width * scale); 72 | } 73 | return 0; 74 | } 75 | 76 | int 77 | window_view_height(window_t* window, void* view) { 78 | if (view) { 79 | CGRect rect = [(__bridge UIView*)view frame]; 80 | CGFloat scale = [(__bridge UIView*)view contentScaleFactor]; 81 | return (int)(rect.size.height * scale); 82 | } 83 | return 0; 84 | } 85 | 86 | @interface WindowDisplayLink : NSObject { 87 | @public 88 | window_t* target_window; 89 | window_draw_fn draw_fn; 90 | } 91 | 92 | + (void)referenceClass; 93 | + (id)fromDrawFn:(window_draw_fn)fn window:(window_t*)window; 94 | - (id)initWithDrawFn:(window_draw_fn)fn window:(window_t*)window; 95 | ; 96 | - (void)callDraw:(id)obj; 97 | 98 | @end 99 | 100 | @implementation WindowDisplayLink 101 | 102 | + (void)referenceClass { 103 | log_debugf(HASH_WINDOW, "WindowDisplayLink class referenced"); 104 | ++_dummy_window_class_reference; 105 | } 106 | 107 | + (id)fromDrawFn:(window_draw_fn)fn window:(window_t*)window { 108 | return [[self alloc] initWithDrawFn:fn window:window]; 109 | } 110 | 111 | - (id)initWithDrawFn:(window_draw_fn)fn window:(window_t*)window { 112 | draw_fn = fn; 113 | target_window = window; 114 | return self; 115 | } 116 | 117 | - (void)callDraw:(id)obj { 118 | draw_fn(target_window); 119 | } 120 | 121 | @end 122 | 123 | void 124 | window_add_displaylink(window_t* window, window_draw_fn drawfn) { 125 | id wrapper = [WindowDisplayLink fromDrawFn:drawfn window:window]; 126 | id display_link = 127 | [NSClassFromString(@"CADisplayLink") displayLinkWithTarget:wrapper 128 | selector:@selector(callDraw:)]; 129 | [display_link setFrameInterval:1]; 130 | [display_link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; 131 | } 132 | 133 | void 134 | window_show_keyboard(window_t* window) { 135 | } 136 | 137 | void 138 | window_hide_keyboard(window_t* window) { 139 | } 140 | 141 | void 142 | window_deallocate(window_t* window) { 143 | memory_deallocate(window); 144 | } 145 | 146 | unsigned int 147 | window_adapter(window_t* window) { 148 | return WINDOW_ADAPTER_DEFAULT; 149 | } 150 | 151 | void 152 | window_maximize(window_t* window) { 153 | } 154 | 155 | void 156 | window_minimize(window_t* window) { 157 | } 158 | 159 | void 160 | window_restore(window_t* window) { 161 | } 162 | 163 | void 164 | window_resize(window_t* window, unsigned int width, unsigned int height) { 165 | } 166 | 167 | void 168 | window_move(window_t* window, int x, int y) { 169 | } 170 | 171 | bool 172 | window_is_open(window_t* window) { 173 | return window && window->uiwindow && _window_app_started; 174 | } 175 | 176 | bool 177 | window_is_visible(window_t* window) { 178 | return window_is_open(window) && !_window_app_paused; 179 | } 180 | 181 | bool 182 | window_is_maximized(window_t* window) { 183 | return window_is_open(window) && !_window_app_paused; 184 | } 185 | 186 | bool 187 | window_is_minimized(window_t* window) { 188 | return window_is_open(window) && _window_app_paused; 189 | } 190 | 191 | bool 192 | window_has_focus(window_t* window) { 193 | return window_is_open(window) && !_window_app_paused; 194 | } 195 | 196 | void 197 | window_show_cursor(window_t* window, bool show, bool lock) { 198 | } 199 | 200 | void 201 | window_set_cursor_pos(window_t* window, int x, int y) { 202 | } 203 | 204 | bool 205 | window_is_cursor_locked(window_t* window) { 206 | return false; 207 | } 208 | 209 | void 210 | window_set_title(window_t* window, const char* title, size_t length) { 211 | } 212 | 213 | int 214 | window_width(window_t* window) { 215 | if (window && window->uiwindow) { 216 | UIWindow* uiwindow = (__bridge UIWindow*)(window->uiwindow); 217 | CGRect rect = [uiwindow frame]; 218 | CGFloat scale = [uiwindow contentScaleFactor]; 219 | return (int)(rect.size.width * scale); 220 | } 221 | return 0; 222 | } 223 | 224 | int 225 | window_height(window_t* window) { 226 | if (window && window->uiwindow) { 227 | UIWindow* uiwindow = (__bridge UIWindow*)(window->uiwindow); 228 | CGRect rect = [uiwindow frame]; 229 | CGFloat scale = [uiwindow contentScaleFactor]; 230 | return (int)(rect.size.height * scale); 231 | } 232 | return 0; 233 | } 234 | 235 | int 236 | window_position_x(window_t* window) { 237 | return 0; 238 | } 239 | 240 | int 241 | window_position_y(window_t* window) { 242 | return 0; 243 | } 244 | 245 | void 246 | window_fit_to_screen(window_t* window) { 247 | } 248 | 249 | @implementation WindowKeyboardView 250 | 251 | + (void)referenceClass { 252 | log_debugf(HASH_WINDOW, "WindowKeyboardView class referenced"); 253 | ++_dummy_window_class_reference; 254 | } 255 | 256 | - (void)insertText:(NSString*)text { 257 | /*log_debugf( HASH_WINDOW, "iOS keyboard text: %s", [text UTF8String] ); 258 | unsigned int glyph = [text characterAtIndex:0]; 259 | input_event_post_key( INPUTEVENT_CHAR, glyph, 0 ); 260 | if( ( glyph == 10 ) || ( glyph == 13 ) ) 261 | { 262 | input_event_post_key( INPUTEVENT_KEYDOWN, KEY_RETURN, 0 ); 263 | input_event_post_key( INPUTEVENT_KEYUP, KEY_RETURN, 0 ); 264 | }*/ 265 | } 266 | 267 | - (void)deleteBackward { 268 | /*log_debugf( HASH_WINDOW, "iOS keyboard backspace" ); 269 | input_event_post_key( INPUTEVENT_KEYDOWN, KEY_BACKSPACE, 0 ); 270 | input_event_post_key( INPUTEVENT_KEYUP, KEY_BACKSPACE, 0 );*/ 271 | } 272 | 273 | - (BOOL)hasText { 274 | return YES; 275 | } 276 | - (BOOL)canBecomeFirstResponder { 277 | return YES; 278 | } 279 | 280 | @end 281 | 282 | @implementation WindowView 283 | 284 | + (void)referenceClass { 285 | log_debugf(HASH_WINDOW, "WindowView class referenced"); 286 | ++_dummy_window_class_reference; 287 | } 288 | 289 | + (Class)layerClass { 290 | return [CAEAGLLayer class]; 291 | } 292 | 293 | - (BOOL)canBecomeFirstResponder { 294 | return YES; 295 | } 296 | 297 | - (id)initWithFrame:(CGRect)frame { 298 | if ((self = [super initWithFrame:frame])) { 299 | UIScreen* main_screen = [UIScreen mainScreen]; 300 | CGFloat screen_width = main_screen.currentMode.size.width; 301 | CGFloat screen_height = main_screen.currentMode.size.height; 302 | 303 | if ((frame.size.width < screen_width) && (frame.size.height < screen_height)) { 304 | int wscale = (int)(0.5 + (screen_width / frame.size.width)); 305 | int hscale = (int)(0.5 + (screen_height / frame.size.height)); 306 | self.contentScaleFactor = (wscale > hscale) ? wscale : hscale; 307 | } 308 | 309 | log_debugf(HASH_WINDOW, 310 | "WindowView initWithFrame, setting up layer (class %s) %dx%d (%.1f)", 311 | class_getName([[self layer] class]), screen_width, screen_height, 312 | self.contentScaleFactor); 313 | CAEAGLLayer* layer = (CAEAGLLayer*)self.layer; 314 | layer.opaque = TRUE; 315 | if (self.contentScaleFactor > 1) 316 | layer.contentsScale = self.contentScaleFactor; 317 | layer.drawableProperties = 318 | [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:FALSE], 319 | kEAGLDrawablePropertyRetainedBacking, 320 | kEAGLColorFormatRGBA8, 321 | kEAGLDrawablePropertyColorFormat, nil]; 322 | 323 | keyboard_view = 0; 324 | } 325 | return self; 326 | } 327 | 328 | - (id)initWithCoder:(NSCoder*)coder { 329 | if ((self = [super initWithCoder:coder])) { 330 | UIScreen* main_screen = [UIScreen mainScreen]; 331 | CGFloat screen_width = main_screen.currentMode.size.width; 332 | CGFloat screen_height = main_screen.currentMode.size.height; 333 | 334 | CGRect frame = [main_screen applicationFrame]; 335 | if ((frame.size.width < screen_width) && (frame.size.height < screen_height)) { 336 | int wscale = (int)(0.5 + (screen_width / frame.size.width)); 337 | int hscale = (int)(0.5 + (screen_height / frame.size.height)); 338 | self.contentScaleFactor = (wscale > hscale) ? wscale : hscale; 339 | } 340 | 341 | log_debugf(HASH_WINDOW, 342 | "WindowView initWithCoder, setting up layer (class %s) %dx%d (%.1f)", 343 | class_getName([[self layer] class]), (int)screen_width, (int)screen_height, 344 | self.contentScaleFactor); 345 | CAEAGLLayer* layer = (CAEAGLLayer*)self.layer; 346 | layer.opaque = TRUE; 347 | if (self.contentScaleFactor > 1) 348 | layer.contentsScale = self.contentScaleFactor; 349 | layer.drawableProperties = 350 | [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:FALSE], 351 | kEAGLDrawablePropertyRetainedBacking, 352 | kEAGLColorFormatRGBA8, 353 | kEAGLDrawablePropertyColorFormat, nil]; 354 | 355 | keyboard_view = 0; 356 | } 357 | return self; 358 | } 359 | 360 | - (void)didMoveToWindow { 361 | if ([self window]) 362 | [self window].contentScaleFactor = self.contentScaleFactor; 363 | } 364 | 365 | - (void)dealloc { 366 | } 367 | 368 | @end 369 | 370 | @implementation WindowViewController 371 | 372 | @synthesize hideStatusBar; 373 | 374 | + (void)referenceClass { 375 | log_debugf(HASH_WINDOW, "WindowViewController class referenced"); 376 | ++_dummy_window_class_reference; 377 | } 378 | 379 | - (void)viewDidLoad { 380 | if (self.hideStatusBar) { 381 | if ([self respondsToSelector:@selector(setNeedsStatusBarAppearanceUpdate)]) 382 | [self setNeedsStatusBarAppearanceUpdate]; 383 | else 384 | [[UIApplication sharedApplication] setStatusBarHidden:YES 385 | withAnimation:UIStatusBarAnimationNone]; 386 | } 387 | } 388 | 389 | - (BOOL)prefersStatusBarHidden { 390 | return self.hideStatusBar; 391 | } 392 | 393 | @end 394 | 395 | void 396 | _window_class_reference(void) { 397 | [WindowDisplayLink referenceClass]; 398 | [WindowKeyboardView referenceClass]; 399 | [WindowView referenceClass]; 400 | [WindowViewController referenceClass]; 401 | } 402 | 403 | #endif 404 | -------------------------------------------------------------------------------- /window/window_macos.m: -------------------------------------------------------------------------------- 1 | /* window_osx.m - Window library - Public Domain - 2014 Mattias Jansson 2 | * 3 | * This library provides a cross-platform window library in C11 providing basic support data types 4 | * and functions to create and manage windows in a platform-independent fashion. The latest source 5 | * code is always available at 6 | * 7 | * https://github.com/mjansson/window_lib 8 | * 9 | * This library is put in the public domain; you can redistribute it and/or modify it without any 10 | * restrictions. 11 | * 12 | */ 13 | 14 | #include 15 | 16 | #if FOUNDATION_PLATFORM_MACOS 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #import 23 | 24 | static volatile int dummy_window_class_reference = 0; 25 | static semaphore_t window_quit_semaphore; 26 | static bool window_exit_loop; 27 | 28 | void 29 | window_native_initialize(void) { 30 | semaphore_initialize(&window_quit_semaphore, 0); 31 | window_exit_loop = 0; 32 | } 33 | 34 | void 35 | window_native_finalize(void) { 36 | semaphore_finalize(&window_quit_semaphore); 37 | } 38 | 39 | @interface WindowDelegate : NSObject 40 | @property (nonatomic, assign) window_t* window; 41 | @end 42 | 43 | @implementation WindowView 44 | 45 | + (void)referenceClass { 46 | log_debug(0, STRING_CONST("WindowView class referenced")); 47 | ++dummy_window_class_reference; 48 | } 49 | 50 | + (Class)layerClass { 51 | return [CAMetalLayer class]; 52 | } 53 | 54 | - (CALayer*)makeBackingLayer { 55 | return [CAMetalLayer layer]; 56 | } 57 | 58 | - (BOOL)acceptsFirstResponder { 59 | return YES; 60 | } 61 | 62 | - (BOOL)acceptsFirstMouse { 63 | return YES; 64 | } 65 | 66 | - (BOOL)isOpaque { 67 | return YES; 68 | } 69 | 70 | @end 71 | 72 | @implementation WindowViewController 73 | 74 | + (void)referenceClass { 75 | log_debug(0, STRING_CONST("WindowViewController class referenced")); 76 | ++dummy_window_class_reference; 77 | } 78 | 79 | @end 80 | 81 | window_t* 82 | window_allocate(void* nswindow) { 83 | window_t* window = memory_allocate(0, sizeof(window_t), 0, MEMORY_PERSISTENT | MEMORY_ZERO_INITIALIZED); 84 | window_initialize(window, nswindow); 85 | return window; 86 | } 87 | 88 | void 89 | window_initialize(window_t* window, void* nswindow) { 90 | window->nswindow = nswindow; 91 | 92 | WindowDelegate* delegate = [[WindowDelegate alloc] init]; 93 | delegate.window = window; 94 | window->delegate = (__bridge_retained void*)delegate; 95 | if (window->nswindow) { 96 | dispatch_sync(dispatch_get_main_queue(), ^{ 97 | [(__bridge NSWindow*)window->nswindow setDelegate:delegate]; 98 | }); 99 | } 100 | window_event_post(WINDOWEVENT_CREATE, window); 101 | 102 | if (window_is_visible(window)) 103 | window_event_post(WINDOWEVENT_SHOW, window); 104 | if (window_has_focus(window)) 105 | window_event_post(WINDOWEVENT_GOTFOCUS, window); 106 | window_event_post(WINDOWEVENT_REDRAW, window); 107 | } 108 | 109 | void 110 | window_finalize(window_t* window) { 111 | if (window->delegate) 112 | CFRelease(window->delegate); 113 | window->delegate = nullptr; 114 | window->nswindow = nullptr; 115 | } 116 | 117 | void 118 | window_deallocate(window_t* window) { 119 | window_finalize(window); 120 | memory_deallocate(window); 121 | } 122 | 123 | void* 124 | window_view(window_t* window, unsigned int tag) { 125 | FOUNDATION_UNUSED(tag); 126 | __block void* view = nullptr; 127 | dispatch_sync(dispatch_get_main_queue(), ^{ 128 | view = (__bridge void*)((window && window->nswindow) ? [(__bridge NSWindow*)window->nswindow contentView] : 0); 129 | }); 130 | return view; 131 | } 132 | 133 | unsigned int 134 | window_adapter(window_t* window) { 135 | FOUNDATION_UNUSED(window); 136 | return (unsigned int)WINDOW_ADAPTER_DEFAULT; 137 | } 138 | 139 | void 140 | window_maximize(window_t* window) { 141 | if (!window || !window->nswindow) 142 | return; 143 | 144 | NSWindow* nswindow = (__bridge NSWindow*)window->nswindow; 145 | dispatch_sync(dispatch_get_main_queue(), ^{ 146 | if ([nswindow isZoomed]) 147 | return; 148 | 149 | [nswindow zoom:nil]; 150 | }); 151 | } 152 | 153 | void 154 | window_minimize(window_t* window) { 155 | if (!window || !window->nswindow) 156 | return; 157 | 158 | dispatch_sync(dispatch_get_main_queue(), ^{ 159 | [(__bridge NSWindow*)window->nswindow miniaturize:nil]; 160 | }); 161 | } 162 | 163 | void 164 | window_restore(window_t* window) { 165 | if (!window || !window->nswindow) 166 | return; 167 | 168 | dispatch_sync(dispatch_get_main_queue(), ^{ 169 | NSWindow* nswindow = (__bridge NSWindow*)window->nswindow; 170 | if ([nswindow isMiniaturized]) 171 | [nswindow deminiaturize:nil]; 172 | else if ([nswindow isZoomed]) 173 | [nswindow zoom:nil]; 174 | }); 175 | } 176 | 177 | void 178 | window_resize(window_t* window, int width, int height) { 179 | if (!window || !window->nswindow) 180 | return; 181 | 182 | dispatch_sync(dispatch_get_main_queue(), ^{ 183 | NSWindow* nswindow = (__bridge NSWindow*)window->nswindow; 184 | if ([nswindow isZoomed]) 185 | [nswindow zoom:nil]; 186 | 187 | NSRect frame_rect = [nswindow frame]; 188 | 189 | NSRect new_rect = frame_rect; 190 | new_rect.size.width = width; 191 | new_rect.size.height = height; 192 | new_rect = [nswindow frameRectForContentRect:new_rect]; 193 | if (!math_real_eq((real)new_rect.size.width, (real)frame_rect.size.width, 100) || 194 | !math_real_eq((real)new_rect.size.height, (real)frame_rect.size.height, 100)) { 195 | NSUInteger style_mask = [nswindow styleMask]; 196 | NSUInteger resize_mask = style_mask | NSWindowStyleMaskResizable; 197 | [nswindow setStyleMask:resize_mask]; 198 | [nswindow setFrame:new_rect display:TRUE]; 199 | [nswindow setStyleMask:style_mask]; 200 | } 201 | }); 202 | } 203 | 204 | void 205 | window_move(window_t* window, int x, int y) { 206 | if (!window || !window->nswindow) 207 | return; 208 | 209 | NSWindow* nswindow = (__bridge NSWindow*)window->nswindow; 210 | NSPoint pt = {x, y}; 211 | dispatch_sync(dispatch_get_main_queue(), ^{ 212 | [nswindow setFrameOrigin:pt]; 213 | }); 214 | } 215 | 216 | bool 217 | window_is_open(window_t* window) { 218 | if (!window || !window->nswindow) 219 | return false; 220 | return true; 221 | } 222 | 223 | bool 224 | window_is_visible(window_t* window) { 225 | if (!window || !window->nswindow) 226 | return false; 227 | 228 | __block bool is_visible = false; 229 | dispatch_sync(dispatch_get_main_queue(), ^{ 230 | is_visible = [(__bridge NSWindow*)window->nswindow isVisible]; 231 | }); 232 | return is_visible; 233 | } 234 | 235 | bool 236 | window_is_maximized(window_t* window) { 237 | if (!window || !window->nswindow) 238 | return false; 239 | 240 | __block bool is_maxi = false; 241 | dispatch_sync(dispatch_get_main_queue(), ^{ 242 | is_maxi = [(__bridge NSWindow*)window->nswindow isZoomed]; 243 | }); 244 | return is_maxi; 245 | } 246 | 247 | bool 248 | window_is_minimized(window_t* window) { 249 | if (!window || !window->nswindow) 250 | return false; 251 | 252 | __block bool is_mini = false; 253 | dispatch_sync(dispatch_get_main_queue(), ^{ 254 | is_mini = [(__bridge NSWindow*)window->nswindow isMiniaturized]; 255 | }); 256 | return is_mini; 257 | } 258 | 259 | bool 260 | window_has_focus(window_t* window) { 261 | __block bool has_focus = false; 262 | dispatch_sync(dispatch_get_main_queue(), ^{ 263 | @autoreleasepool { 264 | bool active = [[NSRunningApplication currentApplication] isActive]; 265 | has_focus = 266 | active && (window && window->nswindow && ([NSApp mainWindow] == (__bridge NSWindow*)(window->nswindow))); 267 | } 268 | }); 269 | return has_focus; 270 | } 271 | 272 | void 273 | window_show_cursor(window_t* window, bool show, bool lock) { 274 | FOUNDATION_UNUSED(window); 275 | FOUNDATION_UNUSED(show); 276 | FOUNDATION_UNUSED(lock); 277 | } 278 | 279 | void 280 | window_set_cursor_pos(window_t* window, int x, int y) { 281 | FOUNDATION_UNUSED(window); 282 | FOUNDATION_UNUSED(x); 283 | FOUNDATION_UNUSED(y); 284 | } 285 | 286 | bool 287 | window_is_cursor_locked(window_t* window) { 288 | FOUNDATION_UNUSED(window); 289 | return false; 290 | } 291 | 292 | void 293 | window_set_title(window_t* window, const char* title, size_t length) { 294 | if (!window || !window->nswindow) 295 | return; 296 | 297 | @autoreleasepool { 298 | NSString* nsstr = [[NSString alloc] initWithBytes:title length:length encoding:NSUTF8StringEncoding]; 299 | if (nsstr) 300 | [(__bridge NSWindow*)window->nswindow setTitle:nsstr]; 301 | } 302 | } 303 | 304 | unsigned int 305 | window_width(window_t* window) { 306 | if (window && window->nswindow) { 307 | __block NSRect rect; 308 | dispatch_sync(dispatch_get_main_queue(), ^{ 309 | rect = [(__bridge NSWindow*)window->nswindow 310 | contentRectForFrameRect:[(__bridge NSWindow*)window->nswindow frame]]; 311 | }); 312 | return (uint)rect.size.width; 313 | } 314 | return 0; 315 | } 316 | 317 | unsigned int 318 | window_height(window_t* window) { 319 | if (window && window->nswindow) { 320 | __block NSRect rect; 321 | dispatch_sync(dispatch_get_main_queue(), ^{ 322 | rect = [(__bridge NSWindow*)window->nswindow 323 | contentRectForFrameRect:[(__bridge NSWindow*)window->nswindow frame]]; 324 | }); 325 | return (uint)rect.size.height; 326 | } 327 | return 0; 328 | } 329 | 330 | int 331 | window_position_x(window_t* window) { 332 | if (window && window->nswindow) { 333 | __block NSRect rect; 334 | dispatch_sync(dispatch_get_main_queue(), ^{ 335 | rect = [(__bridge NSWindow*)window->nswindow frame]; 336 | }); 337 | return (int)rect.origin.x; 338 | } 339 | return 0; 340 | } 341 | 342 | int 343 | window_position_y(window_t* window) { 344 | if (window && window->nswindow) { 345 | __block NSRect rect; 346 | dispatch_sync(dispatch_get_main_queue(), ^{ 347 | rect = [(__bridge NSWindow*)window->nswindow frame]; 348 | }); 349 | return (int)rect.origin.y; 350 | } 351 | return 0; 352 | } 353 | 354 | int 355 | window_screen_width(unsigned int adapter) { 356 | FOUNDATION_UNUSED(adapter); 357 | return 0; 358 | } 359 | 360 | int 361 | window_screen_height(unsigned int adapter) { 362 | FOUNDATION_UNUSED(adapter); 363 | return 0; 364 | } 365 | 366 | void 367 | window_fit_to_screen(window_t* window) { 368 | if (!window || !window->nswindow) 369 | return; 370 | 371 | dispatch_async(dispatch_get_main_queue(), ^{ 372 | NSWindow* nswindow = (__bridge NSWindow*)window->nswindow; 373 | NSScreen* screen = [nswindow screen]; 374 | NSRect frame_rect = [nswindow frame]; 375 | 376 | NSUInteger style_mask = [nswindow styleMask]; 377 | NSUInteger resize_mask = style_mask | NSWindowStyleMaskResizable; 378 | [nswindow setStyleMask:resize_mask]; 379 | 380 | NSRect new_rect = [nswindow constrainFrameRect:frame_rect toScreen:screen]; 381 | if ((new_rect.size.width < frame_rect.size.width) || (new_rect.size.height < frame_rect.size.height)) { 382 | // Maintain aspect 383 | double width_factor = new_rect.size.width / frame_rect.size.width; 384 | double height_factor = new_rect.size.height / frame_rect.size.height; 385 | 386 | if (width_factor < height_factor) 387 | new_rect.size.height = new_rect.size.height * width_factor; 388 | else 389 | new_rect.size.width = new_rect.size.width * height_factor; 390 | 391 | [nswindow setFrame:new_rect display:TRUE]; 392 | } 393 | 394 | [nswindow setStyleMask:style_mask]; 395 | }); 396 | } 397 | 398 | int 399 | window_message_loop(void) { 400 | while (!window_exit_loop) { 401 | semaphore_wait(&window_quit_semaphore); 402 | } 403 | return 0; 404 | } 405 | 406 | void 407 | window_message_quit(void) { 408 | window_exit_loop = true; 409 | semaphore_post(&window_quit_semaphore); 410 | } 411 | 412 | void 413 | window_class_reference(void) { 414 | [WindowView referenceClass]; 415 | [WindowViewController referenceClass]; 416 | } 417 | 418 | @implementation WindowDelegate 419 | 420 | @synthesize window; 421 | 422 | - (void)windowDidResize:(NSNotification*)notification { 423 | FOUNDATION_UNUSED(notification); 424 | } 425 | 426 | - (void)windowDidExpose:(NSNotification*)notification { 427 | FOUNDATION_UNUSED(notification); 428 | window_event_post(WINDOWEVENT_SHOW, self.window); 429 | } 430 | 431 | - (void)windowDidMove:(NSNotification*)notification { 432 | FOUNDATION_UNUSED(notification); 433 | } 434 | 435 | - (void)windowDidBecomeKey:(NSNotification*)notification { 436 | FOUNDATION_UNUSED(notification); 437 | } 438 | 439 | - (void)windowDidResignKey:(NSNotification*)notification { 440 | FOUNDATION_UNUSED(notification); 441 | } 442 | 443 | - (void)windowDidBecomeMain:(NSNotification*)notification { 444 | FOUNDATION_UNUSED(notification); 445 | } 446 | 447 | - (void)windowDidResignMain:(NSNotification*)notification { 448 | FOUNDATION_UNUSED(notification); 449 | } 450 | 451 | - (void)windowDidMiniaturize:(NSNotification*)notification { 452 | FOUNDATION_UNUSED(notification); 453 | window_event_post(WINDOWEVENT_RESIZE, self.window); 454 | window_event_post(WINDOWEVENT_LOSTFOCUS, self.window); 455 | } 456 | 457 | - (void)windowDidDeminiaturize:(NSNotification*)notification { 458 | FOUNDATION_UNUSED(notification); 459 | window_event_post(WINDOWEVENT_RESIZE, self.window); 460 | window_event_post(WINDOWEVENT_REDRAW, self.window); 461 | if (window_has_focus(self.window)) 462 | window_event_post(WINDOWEVENT_GOTFOCUS, self.window); 463 | } 464 | 465 | - (void)windowDidEndLiveResize:(NSNotification*)notification { 466 | FOUNDATION_UNUSED(notification); 467 | window_event_post(WINDOWEVENT_RESIZE, self.window); 468 | window_event_post(WINDOWEVENT_REDRAW, self.window); 469 | } 470 | 471 | - (void)windowDidEnterFullScreen:(NSNotification*)notification { 472 | FOUNDATION_UNUSED(notification); 473 | } 474 | 475 | - (void)windowDidExitFullScreen:(NSNotification*)notification { 476 | FOUNDATION_UNUSED(notification); 477 | } 478 | 479 | - (void)windowWillClose:(NSNotification*)notification { 480 | FOUNDATION_UNUSED(notification); 481 | window_event_post(WINDOWEVENT_CLOSE, self.window); 482 | } 483 | 484 | @end 485 | 486 | #endif 487 | --------------------------------------------------------------------------------