├── .clang-format ├── .clang-tidy ├── .github └── workflows │ ├── build_linux.yml │ └── build_windows.yml ├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── LICENSE ├── README.md ├── embed-helper ├── CMakeLists.txt └── main.cpp ├── examples ├── advanced │ ├── CMakeLists.txt │ └── main.cpp ├── embedded │ ├── CMakeLists.txt │ ├── README.md │ ├── dist │ │ ├── img_logo.gif │ │ ├── index.html │ │ ├── index.js │ │ └── style.css │ ├── embedded │ │ ├── img_logo.gif.hpp │ │ ├── include.hpp │ │ ├── index.html.hpp │ │ ├── index.js.hpp │ │ ├── style.css.hpp │ │ └── webview_base.hpp │ └── main.cpp └── simple │ ├── CMakeLists.txt │ └── main.cpp └── webview ├── include ├── core │ ├── basewindow.hpp │ ├── linux │ │ └── window.hpp │ ├── resource.hpp │ └── windows │ │ ├── mimes.hpp │ │ └── window.hpp ├── javascript │ ├── call.hpp │ ├── function.hpp │ └── promise.hpp ├── json │ └── bindings.hpp ├── misc │ ├── helpers.hpp │ └── traits.hpp └── webview.hpp └── src ├── core ├── basewindow.cpp ├── linux │ └── window.cpp └── windows │ └── window.cpp └── javascript ├── function.cpp └── promise.cpp /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | AccessModifierOffset: -2 4 | AlignAfterOpenBracket: Align 5 | AlignConsecutiveMacros: false 6 | AlignConsecutiveAssignments: false 7 | AlignConsecutiveDeclarations: false 8 | AlignEscapedNewlines: Right 9 | AlignOperands: true 10 | AlignTrailingComments: true 11 | AllowAllArgumentsOnNextLine: true 12 | AllowAllConstructorInitializersOnNextLine: true 13 | AllowAllParametersOfDeclarationOnNextLine: true 14 | AllowShortBlocksOnASingleLine: Never 15 | AllowShortCaseLabelsOnASingleLine: false 16 | AllowShortFunctionsOnASingleLine: Empty 17 | AllowShortLambdasOnASingleLine: All 18 | AllowShortIfStatementsOnASingleLine: Never 19 | AllowShortLoopsOnASingleLine: false 20 | AlwaysBreakAfterDefinitionReturnType: None 21 | AlwaysBreakAfterReturnType: None 22 | AlwaysBreakBeforeMultilineStrings: false 23 | AlwaysBreakTemplateDeclarations: MultiLine 24 | BinPackArguments: true 25 | BinPackParameters: true 26 | BraceWrapping: 27 | AfterCaseLabel: false 28 | AfterClass: true 29 | AfterControlStatement: true 30 | AfterEnum: true 31 | AfterFunction: true 32 | AfterNamespace: true 33 | AfterObjCDeclaration: true 34 | AfterStruct: true 35 | AfterUnion: false 36 | AfterExternBlock: true 37 | BeforeCatch: true 38 | BeforeElse: true 39 | IndentBraces: false 40 | SplitEmptyFunction: true 41 | SplitEmptyRecord: true 42 | SplitEmptyNamespace: true 43 | BreakBeforeBinaryOperators: None 44 | BreakBeforeBraces: Custom 45 | BreakBeforeInheritanceComma: false 46 | BreakInheritanceList: BeforeColon 47 | BreakBeforeTernaryOperators: true 48 | BreakConstructorInitializersBeforeComma: false 49 | BreakConstructorInitializers: BeforeColon 50 | BreakAfterJavaFieldAnnotations: false 51 | BreakStringLiterals: true 52 | ColumnLimit: 120 53 | CommentPragmas: '^ IWYU pragma:' 54 | CompactNamespaces: false 55 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 56 | ConstructorInitializerIndentWidth: 4 57 | ContinuationIndentWidth: 4 58 | Cpp11BracedListStyle: true 59 | DeriveLineEnding: true 60 | DerivePointerAlignment: false 61 | DisableFormat: false 62 | ExperimentalAutoDetectBinPacking: false 63 | FixNamespaceComments: true 64 | IndentCaseLabels: false 65 | IndentGotoLabels: true 66 | IndentPPDirectives: None 67 | IndentWidth: 4 68 | IndentWrappedFunctionNames: false 69 | JavaScriptQuotes: Leave 70 | JavaScriptWrapImports: true 71 | KeepEmptyLinesAtTheStartOfBlocks: true 72 | MacroBlockBegin: '' 73 | MacroBlockEnd: '' 74 | MaxEmptyLinesToKeep: 1 75 | NamespaceIndentation: All 76 | ObjCBinPackProtocolList: Auto 77 | ObjCBlockIndentWidth: 2 78 | ObjCSpaceAfterProperty: false 79 | ObjCSpaceBeforeProtocolList: true 80 | PenaltyBreakAssignment: 2 81 | PenaltyBreakBeforeFirstCallParameter: 19 82 | PenaltyBreakComment: 300 83 | PenaltyBreakFirstLessLess: 120 84 | PenaltyBreakString: 1000 85 | PenaltyBreakTemplateDeclaration: 10 86 | PenaltyExcessCharacter: 1000000 87 | PenaltyReturnTypeOnItsOwnLine: 1000 88 | PointerAlignment: Right 89 | ReflowComments: true 90 | SortIncludes: true 91 | SortUsingDeclarations: true 92 | SpaceAfterCStyleCast: false 93 | SpaceAfterLogicalNot: false 94 | SpaceAfterTemplateKeyword: true 95 | SpaceBeforeAssignmentOperators: true 96 | SpaceBeforeCpp11BracedList: false 97 | SpaceBeforeCtorInitializerColon: true 98 | SpaceBeforeInheritanceColon: true 99 | SpaceBeforeParens: ControlStatements 100 | SpaceBeforeRangeBasedForLoopColon: true 101 | SpaceInEmptyBlock: false 102 | SpaceInEmptyParentheses: false 103 | SpacesBeforeTrailingComments: 1 104 | SpacesInAngles: false 105 | SpacesInConditionalStatement: false 106 | SpacesInContainerLiterals: true 107 | SpacesInCStyleCastParentheses: false 108 | SpacesInParentheses: false 109 | SpacesInSquareBrackets: false 110 | SpaceBeforeSquareBrackets: false 111 | Standard: Latest 112 | StatementMacros: 113 | - Q_UNUSED 114 | - QT_REQUIRE_VERSION 115 | TabWidth: 4 116 | UseCRLF: false 117 | UseTab: Never -------------------------------------------------------------------------------- /.clang-tidy: -------------------------------------------------------------------------------- 1 | Checks: "*,\ 2 | -google-runtime-int,\ 3 | -google-explicit-constructor,\ 4 | -llvm-header-guard,\ 5 | -llvmlibc-*,\ 6 | -readability-magic-numbers,\ 7 | -cppcoreguidelines-avoid-magic-numbers,\ 8 | -cppcoreguidelines-pro-bounds-constant-array-index,\ 9 | -cppcoreguidelines-pro-bounds-pointer-arithmetic,\ 10 | -cppcoreguidelines-pro-type-reinterpret-cast,\ 11 | -cppcoreguidelines-no-malloc,\ 12 | -cppcoreguidelines-owning-memory,\ 13 | -cppcoreguidelines-macro-usage,\ 14 | -cppcoreguidelines-pro-type-vararg,\ 15 | -cppcoreguidelines-pro-bounds-array-to-pointer-decay,\ 16 | -fuchsia-overloaded-operator,\ 17 | -fuchsia-default-arguments,\ 18 | -fuchsia-multiple-inheritance,\ 19 | -fuchsia-default-arguments-calls,\ 20 | -fuchsia-trailing-return,\ 21 | -modernize-use-trailing-return-type,\ 22 | -misc-definitions-in-headers,\ 23 | -cert-err58-cpp,\ 24 | -clang-diagnostic-padded,\ 25 | -modernize-concat-nested-namespaces,\ 26 | -altera-struct-pack-align,\ 27 | -modernize-use-nodiscard,\ 28 | -misc-non-private-member-variables-in-classes,\ 29 | -cppcoreguidelines-pro-type-member-init,\ 30 | -fuchsia-statically-constructed-objects,\ 31 | -cppcoreguidelines-avoid-non-const-global-variables,\ 32 | -readability-function-cognitive-complexity,\ 33 | -modernize-use-emplace,\ 34 | -cppcoreguidelines-interfaces-global-init,\ 35 | -modernize-loop-convert,\ 36 | -modernize-avoid-c-arrays,\ 37 | -cppcoreguidelines-avoid-c-arrays,\ 38 | -cert-env33-c,\ 39 | -abseil-*,\ 40 | -fuchsia-default-arguments-declarations,\ 41 | -readability-redundant-access-specifiers,\ 42 | -readability-convert-member-functions-to-static,\ 43 | -readability-implicit-bool-conversion,\ 44 | -bugprone-inaccurate-erase,\ 45 | -readability-uppercase-literal-suffix,\ 46 | -hicpp*,\ 47 | -readability-braces-around-statements,\ 48 | -google-readability-braces-around-statements,\ 49 | -cppcoreguidelines-non-private-member-variables-in-classes,\ 50 | -cppcoreguidelines-pro-type-union-access,\ 51 | -readability-static-accessed-through-instance,\ 52 | -cppcoreguidelines-special-member-functions,\ 53 | -readability-isolate-declaration" -------------------------------------------------------------------------------- /.github/workflows/build_linux.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | paths-ignore: 4 | - "**/README.md" 5 | - "**/build_windows.yml" 6 | pull_request: 7 | 8 | name: Build on Linux 9 | jobs: 10 | build-linux: 11 | runs-on: ubuntu-20.04 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | language: ["cpp"] 16 | 17 | steps: 18 | - name: Checkout 19 | uses: actions/checkout@v2 20 | with: 21 | submodules: recursive 22 | 23 | - name: Install build dependencies 24 | run: "sudo apt-get update && sudo apt-get install git build-essential cmake libwebkit2gtk-4.0-dev" 25 | 26 | - name: Compile 27 | run: "mkdir build && cd build && cmake ../examples/simple && cmake --build . --config Release" 28 | -------------------------------------------------------------------------------- /.github/workflows/build_windows.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | paths-ignore: 4 | - "**/README.md" 5 | - "**/build_linux.yml" 6 | pull_request: 7 | 8 | name: Build on Windows 9 | jobs: 10 | build-windows: 11 | runs-on: windows-latest 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | language: ["cpp"] 16 | 17 | steps: 18 | - name: Setup Node.js environment 19 | uses: actions/setup-node@v2.1.5 20 | 21 | - name: Setup NuGet.exe for use with actions 22 | uses: NuGet/setup-nuget@v1.0.5 23 | 24 | - name: Checkout 25 | uses: actions/checkout@v2 26 | with: 27 | submodules: recursive 28 | 29 | - name: Compile 30 | run: "mkdir build && cd build && cmake ../examples/simple && cmake --build . --config Release" -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | cmake-build-debug 3 | .idea 4 | .vscode 5 | .history 6 | .cache 7 | example_build -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib/json"] 2 | path = lib/json 3 | url = https://github.com/nlohmann/json/ 4 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1) 2 | project(webview VERSION 0.2 DESCRIPTION "A cross-platform C++ webview library") 3 | option(WINDOWS_8 "Replaces the call to SetProcessDpiAwarenessContext call with SetProcessDpiAwareness to support Windows 8.1" OFF) 4 | 5 | file(GLOB src 6 | "webview/src/*.cpp" 7 | "webview/src/*/*.cpp" 8 | "webview/src/*/*/*.cpp" 9 | ) 10 | 11 | add_library(webview STATIC ${src}) 12 | 13 | if (WIN32) 14 | target_compile_options(webview PRIVATE /W4) 15 | 16 | find_program(NUGET_EXE NAMES nuget) 17 | if(NOT NUGET_EXE) 18 | message("NUGET.EXE not found.") 19 | message(FATAL_ERROR "Please install this executable, and run CMake again.") 20 | endif() 21 | 22 | exec_program(${NUGET_EXE} 23 | ARGS install "Microsoft.Web.WebView2" -Version 1.0.865-prerelease -ExcludeVersion -OutputDirectory ${CMAKE_BINARY_DIR}/packages) 24 | exec_program(${NUGET_EXE} 25 | ARGS install "Microsoft.Windows.ImplementationLibrary" -ExcludeVersion -OutputDirectory ${CMAKE_BINARY_DIR}/packages) 26 | 27 | if (WINDOWS_8) 28 | target_link_libraries(webview INTERFACE Shcore.lib) 29 | target_compile_definitions(webview PRIVATE WEBVIEWPP_WINDOWS_8=1) 30 | endif() 31 | 32 | target_link_libraries(webview INTERFACE Version.lib Shlwapi.lib ${CMAKE_BINARY_DIR}/packages/Microsoft.Web.WebView2/build/native/x64/WebView2LoaderStatic.lib ${CMAKE_BINARY_DIR}/packages/Microsoft.Windows.ImplementationLibrary/build/native/Microsoft.Windows.ImplementationLibrary.targets) 33 | target_include_directories(webview SYSTEM PUBLIC ${CMAKE_BINARY_DIR}/packages/Microsoft.Web.WebView2/build/native/include ${CMAKE_BINARY_DIR}/packages/Microsoft.Windows.ImplementationLibrary/include) 34 | elseif(UNIX) 35 | if (CMAKE_BUILD_TYPE STREQUAL "Debug") 36 | target_compile_options(webview PRIVATE -Wall -Wextra -Werror -pedantic -Wno-unused-lambda-capture) 37 | endif() 38 | 39 | find_package(PkgConfig REQUIRED) 40 | pkg_check_modules(GTK3 REQUIRED gtk+-3.0) 41 | pkg_check_modules(WEBKIT2 REQUIRED webkit2gtk-4.0) 42 | 43 | target_link_libraries(webview INTERFACE ${GTK3_LIBRARIES} ${WEBKIT2_LIBRARIES} pthread) 44 | target_include_directories(webview SYSTEM PUBLIC ${GTK3_INCLUDE_DIRS} ${WEBKIT2_INCLUDE_DIRS} ${PROJECT_SOURCE_DIR}) 45 | endif() 46 | 47 | target_include_directories(webview SYSTEM PUBLIC "webview/include/") 48 | target_include_directories(webview SYSTEM PUBLIC "lib/json/single_include/nlohmann") 49 | 50 | target_compile_features(webview PRIVATE cxx_std_17) 51 | set_target_properties(webview PROPERTIES 52 | CXX_STANDARD 17 53 | CXX_EXTENSIONS OFF 54 | CXX_STANDARD_REQUIRED ON) 55 | 56 | set_target_properties(webview PROPERTIES VERSION ${PROJECT_VERSION}) 57 | set_target_properties(webview PROPERTIES PROJECT_NAME ${PROJECT_NAME}) 58 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Soundux 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Archived 2 | This project has been superseded by [saucer](https://github.com/saucer/saucer). 3 | 4 | --- 5 | 6 | 7 | ## webviewpp 8 | A cross-platform C++17 library that allows you to create a simple webview. 9 | 10 | ## Compatibility 11 | | Platform | Used Browser | GUI | 12 | | -------- | ------------------------------------------------------------------------------- | ------ | 13 | | Windows | [Webview2](https://docs.microsoft.com/microsoft-edge/webview2/) (Edge Chromium) | WinAPI | 14 | | Linux | WebKit2GTK | GTK | 15 | 16 | ### Supported Windows Versions 17 | | Version | Remarks | 18 | | ------- | ------- | 19 | | 11 | Will not require Webview2 Runtime or Canary-Edge build | 20 | | 10 | Explicit installation of the [`Webview2 Runtime`](https://developer.microsoft.com/microsoft-edge/webview2/#download-section) may be required | 21 | | 8 | Requires `WINDOWS_8` to be set to `ON` from your CMakeLists | 22 | 23 | ## Usage 24 | 25 | - Add the library to your project 26 | - ```cmake 27 | add_subdirectory(/path/to/webviewpp EXCLUDE_FROM_ALL) 28 | link_libraries(webview) 29 | ``` 30 | - Use the library 31 | - See [documentation](#documentation) 32 | - See `examples` for examples 33 | 34 | ## Dependencies 35 | - Windows 36 | - (Runtime) [Webview2](https://developer.microsoft.com/microsoft-edge/webview2/#download-section) or Edge Chromium Canary Build 37 | - Linux 38 | - (Runtime & Build) webkit2gtk 39 | 40 | ## Example 41 | ```cpp 42 | #include 43 | 44 | int main() 45 | { 46 | Webview::Window webview("webview", 800, 900); 47 | webview.expose(Webview::Function("addTen", [](int num) { 48 | return num + 10; 49 | })); 50 | 51 | webview.show(); 52 | webview.run(); 53 | return 0; 54 | } 55 | ``` 56 | 57 | For more examples see [`examples`](https://github.com/Soundux/webviewpp/tree/master/examples) 58 | 59 | ## Embedding 60 | webviewpp supports embedding of all required files. 61 | To embed your files you have to use the [embed-helper](https://github.com/Soundux/webviewpp/tree/master/embed-helper). 62 | 63 | Usage: 64 | - Compile the embed-helper 65 | - ```bash 66 | mkdir build && cd build && cmake .. && cmake --build . --config Release 67 | ``` 68 | - Run the embed-helper 69 | - ```bash 70 | ./embed_helper 71 | ``` 72 | - Add the parent folder of the `embedded` folder to your include directories 73 | - Change `setUrl` calls to 74 | - `embedded:///` on Linux 75 | - `file:///embedded/` on Windows 76 | 77 | > For an example see [examples/embedded](https://github.com/Soundux/webviewpp/tree/master/examples/embedded) 78 | 79 | ## Documentation 80 | ### Window::hide 81 | 82 | ``` cpp 83 | void hide(); 84 | ``` 85 | 86 | > Hides the window 87 | 88 | ----- 89 | 90 | ### Window::show 91 | 92 | ``` cpp 93 | void show(); 94 | ``` 95 | 96 | > Shows the window 97 | 98 | ----- 99 | 100 | ### Window::isHidden 101 | 102 | ``` cpp 103 | bool isHidden(); 104 | ``` 105 | 106 | **Returns:** 107 | > Whether or the window is hidden 108 | 109 | ----- 110 | 111 | ### Window::setSize 112 | 113 | ``` cpp 114 | void setSize(std::size_t, std::size_t); 115 | ``` 116 | 117 | > Sets the window size 118 | 119 | ----- 120 | 121 | ### Window::getSize 122 | 123 | ``` cpp 124 | std::pair getSize(); 125 | ``` 126 | 127 | **Returns:** 128 | > The width and height in form of an `std::pair` 129 | 130 | ----- 131 | 132 | ### Window::getTitle 133 | 134 | ``` cpp 135 | std::string getTitle(); 136 | ``` 137 | 138 | **Returns:** 139 | > The title of the window 140 | 141 | ----- 142 | 143 | ### Window::setTitle 144 | 145 | ``` cpp 146 | void setTitle(std::string); 147 | ``` 148 | 149 | > Sets the window title 150 | 151 | ----- 152 | 153 | ### Window::run 154 | 155 | ``` cpp 156 | void run(); 157 | ``` 158 | 159 | > Runs the mainloop 160 | 161 | **Remarks:** 162 | > Is blocking 163 | 164 | ----- 165 | 166 | ### Window::exit 167 | 168 | ``` cpp 169 | void exit(); 170 | ``` 171 | 172 | > Closes the webview 173 | 174 | ----- 175 | 176 | ### Window::getUrl 177 | 178 | ``` cpp 179 | std::string getUrl(); 180 | ``` 181 | 182 | **Returns:** 183 | > The current url 184 | 185 | ----- 186 | 187 | ### Window::setUrl 188 | 189 | ``` cpp 190 | void setUrl(std::string); 191 | ``` 192 | 193 | > Navigates to the given url 194 | 195 | ----- 196 | 197 | ### Window::enableContextMenu 198 | 199 | ``` cpp 200 | void enableContextMenu(bool); 201 | ``` 202 | 203 | > Enables the context menu 204 | 205 | ----- 206 | 207 | ### Window::enableDevTools 208 | 209 | ``` cpp 210 | void enableDevTools(bool); 211 | ``` 212 | 213 | > Enables the developer tools 214 | 215 | ----- 216 | 217 | ### Window::expose 218 | 219 | ``` cpp 220 | void expose(Webview::Function const&); 221 | ``` 222 | 223 | > Exposes the given function 224 | 225 | **Remarks:** 226 | > If the given Function is an `AsyncFunction` it will be run in a new thread 227 | 228 | ----- 229 | 230 | ### Window::callFunction 231 | 232 | ``` cpp 233 | template 234 | std::future callFunction(Webview::JavaScriptFunction&& function); 235 | ``` 236 | 237 | > Calls the given javascript function 238 | 239 | **Returns:** 240 | > The result of the javascript function call as `T` 241 | 242 | **Preconditions** 243 | > `T` must be serializable by nlohmann::json 244 | 245 | **Remarks:** 246 | > You should never call `.get()` on the returned future in a **non async** context as it will freeze the webview 247 | 248 | ----- 249 | 250 | ### Window::runCode 251 | 252 | ``` cpp 253 | void runCode(std::string const&); 254 | ``` 255 | 256 | > Runs the given javascript code 257 | 258 | ----- 259 | 260 | ### Window::injectCode 261 | 262 | ``` cpp 263 | void injectCode(std::string const&); 264 | ``` 265 | 266 | > Makes the given javascript code run on document load 267 | 268 | ----- 269 | 270 | ### Window::setCloseCallback 271 | 272 | ``` cpp 273 | void setCloseCallback(std::function); 274 | ``` 275 | 276 | > Sets the close-callback to the given callback 277 | 278 | **Remarks:** 279 | > If the callback returns `true` the webview will not close 280 | 281 | ----- 282 | 283 | ### Window::setNavigateCallback 284 | 285 | ``` cpp 286 | void setNavigateCallback(std::function); 287 | ``` 288 | 289 | > Sets the navigate-callback to the given callback 290 | 291 | ----- 292 | 293 | ### Window::setResizeCallback 294 | 295 | ``` cpp 296 | void setResizeCallback(std::function); 297 | ``` 298 | 299 | > Sets the resize-callback to the given callback 300 | 301 | ----- 302 | 303 | > This work was originally based on the work of [MichaelKim](https://github.com/MichaelKim/webview) 304 | 305 | -------------------------------------------------------------------------------- /embed-helper/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0.0) 2 | project(embed_helper VERSION 0.1.0) 3 | 4 | add_executable(embed_helper main.cpp) 5 | 6 | target_compile_features(embed_helper PRIVATE cxx_std_17) 7 | set_target_properties(embed_helper PROPERTIES CMAKE_CXX_STANDARD 17) 8 | set_target_properties(embed_helper PROPERTIES CMAKE_CXX_EXTENSIONS Off) 9 | set_target_properties(embed_helper PROPERTIES CMAKE_CXX_STANDARD_REQUIRED On) 10 | 11 | set_target_properties(embed_helper PROPERTIES VERSION ${PROJECT_VERSION}) 12 | set_target_properties(embed_helper PROPERTIES PROJECT_NAME ${PROJECT_NAME}) -------------------------------------------------------------------------------- /embed-helper/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | int main(int argc, char **args) 10 | { 11 | if (argc < 2) 12 | { 13 | std::cerr << "Too few arguments!" << std::endl; 14 | return 1; 15 | } 16 | 17 | if (std::filesystem::exists(args[1])) 18 | { 19 | std::filesystem::create_directory("embedded"); 20 | std::ofstream output("embedded/webview_base.hpp"); 21 | output << "#pragma once" << std::endl 22 | << "#include " << std::endl 23 | << "#include " << std::endl 24 | << "#include " << std::endl 25 | << "namespace Webview {" << std::endl 26 | << "namespace Embedded {" << std::endl 27 | << "inline std::map files;" << std::endl 28 | << "}" << std::endl 29 | << "}" << std::endl; 30 | output.close(); 31 | std::vector filesToInclude; 32 | 33 | std::filesystem::recursive_directory_iterator iterator(args[1]); 34 | 35 | for (const auto &file : iterator) 36 | { 37 | if (file.path().filename().string().at(0) == '.' || !file.is_regular_file()) 38 | continue; 39 | 40 | std::cout << "Embedding: " << file.path() << std::endl; 41 | 42 | filesToInclude.emplace_back(file.path().filename().string() + ".hpp"); 43 | auto fileFunc = file.path().filename().string(); 44 | std::replace(fileFunc.begin(), fileFunc.end(), '.', '_'); 45 | std::replace(fileFunc.begin(), fileFunc.end(), '-', '_'); 46 | 47 | std::ofstream fileStream("embedded/" + file.path().filename().string() + ".hpp"); 48 | fileStream << "#pragma once" << std::endl 49 | << "#include \"webview_base.hpp\"" << std::endl 50 | << "namespace Webview::Embedded {" << std::endl 51 | << "inline unsigned char embed_file_" << fileFunc << "[] = {"; 52 | 53 | std::ifstream fileDataStream(file.path(), std::ios::binary); 54 | std::vector buffer(std::istreambuf_iterator(fileDataStream), {}); 55 | 56 | for (auto it = buffer.begin(); it != buffer.end(); it++) 57 | { 58 | fileStream << "0x" << std::setw(2) << std::setfill('0') << std::hex << static_cast(*it); 59 | if (std::distance(it, buffer.end()) > 1) 60 | { 61 | fileStream << ","; 62 | } 63 | } 64 | fileStream << "};"; 65 | 66 | fileStream << "inline auto webview_embed_file_" << fileFunc << " = []() -> bool { files.insert({\"" 67 | << file.path().filename().string() << "\", {" << std::dec << buffer.size() << "," 68 | << "embed_file_" << fileFunc << "}});" 69 | << "return true; }();" << std::endl 70 | << "}"; 71 | fileStream.close(); 72 | } 73 | 74 | std::ofstream includeFile("embedded/include.hpp"); 75 | includeFile << "#pragma once" << std::endl << "#include \"webview_base.hpp\"" << std::endl; 76 | for (const auto &file : filesToInclude) 77 | { 78 | includeFile << "#include \"" + file << "\"" << std::endl; 79 | } 80 | includeFile.close(); 81 | } 82 | else 83 | { 84 | std::cerr << "Invalid path!" << std::endl; 85 | } 86 | 87 | return 0; 88 | } 89 | -------------------------------------------------------------------------------- /examples/advanced/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1) 2 | project(webview-example VERSION 0.1) 3 | 4 | add_executable(webview-example "main.cpp") 5 | add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../../ ${CMAKE_CURRENT_SOURCE_DIR}/../../example_build EXCLUDE_FROM_ALL) 6 | target_link_libraries(webview-example webview) 7 | 8 | target_compile_features(webview-example PUBLIC cxx_std_17) 9 | set_target_properties(webview-example PROPERTIES CMAKE_CXX_STANDARD 17) 10 | set_target_properties(webview-example PROPERTIES CMAKE_CXX_EXTENSIONS Off) 11 | set_target_properties(webview-example PROPERTIES CMAKE_CXX_STANDARD_REQUIRED On) 12 | set_target_properties(webview-example PROPERTIES VERSION ${PROJECT_VERSION}) 13 | set_target_properties(webview-example PROPERTIES PROJECT_NAME ${PROJECT_NAME}) -------------------------------------------------------------------------------- /examples/advanced/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | struct CustomType 7 | { 8 | int a; 9 | std::string b; 10 | }; 11 | 12 | namespace nlohmann 13 | { 14 | template <> struct adl_serializer 15 | { 16 | static void to_json(json &j, const CustomType &obj) 17 | { 18 | j = {{"a", obj.a}, {"b", obj.b}}; 19 | } 20 | static void from_json(const json &j, CustomType &obj) 21 | { 22 | j.at("a").get_to(obj.a); 23 | j.at("b").get_to(obj.b); 24 | } 25 | }; 26 | } // namespace nlohmann 27 | 28 | int main() 29 | { 30 | #if defined(_WIN32) 31 | Webview::Window webview("webview", 800, 900); //* We have to provide an identifier on windows 32 | #else 33 | Webview::Window webview(800, 900); 34 | #endif 35 | 36 | webview.setTitle("Example"); 37 | webview.enableDevTools(true); 38 | webview.enableContextMenu(true); 39 | 40 | webview.expose(Webview::Function("test", [](int someInt) { return someInt + 10; })); 41 | 42 | webview.expose(Webview::AsyncFunction("asyncTest", [](Webview::Promise promise, int someInt) { 43 | std::this_thread::sleep_for(std::chrono::seconds(5)); 44 | promise.resolve(someInt + 10); 45 | })); 46 | 47 | webview.expose(Webview::Function("returnCustomType", [](int a, std::string b) { 48 | return CustomType{a, std::move(b)}; 49 | })); 50 | 51 | webview.expose(Webview::Function("takeCustomType", [](const CustomType &a) { return a.a; })); 52 | 53 | webview.expose(Webview::AsyncFunction("pow", [&webview](Webview::Promise promise, int a, int b) { 54 | //! You should never call a javascript function in a non async context! 55 | auto pow = webview.callFunction(Webview::JavaScriptFunction("Math.pow", a, b)); 56 | promise.resolve(pow.get()); 57 | })); 58 | 59 | webview.setCloseCallback([] { 60 | //* If we return `true` the window will not close! 61 | return true; 62 | }); 63 | 64 | webview.setUrl("https://ddg.gg"); 65 | webview.show(); 66 | webview.run(); 67 | 68 | return 0; 69 | } -------------------------------------------------------------------------------- /examples/embedded/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1) 2 | project(webview-example VERSION 0.1) 3 | 4 | add_executable(webview-example "main.cpp") 5 | add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../../ ${CMAKE_CURRENT_SOURCE_DIR}/../../example_build EXCLUDE_FROM_ALL) 6 | 7 | target_link_libraries(webview-example webview) 8 | target_include_directories(webview PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) # This directory contains the embedded folder - thats why we have to add it as a include directory 9 | 10 | target_compile_features(webview-example PUBLIC cxx_std_17) 11 | set_target_properties(webview-example PROPERTIES CMAKE_CXX_STANDARD 17) 12 | set_target_properties(webview-example PROPERTIES CMAKE_CXX_EXTENSIONS Off) 13 | set_target_properties(webview-example PROPERTIES CMAKE_CXX_STANDARD_REQUIRED On) 14 | set_target_properties(webview-example PROPERTIES VERSION ${PROJECT_VERSION}) 15 | set_target_properties(webview-example PROPERTIES PROJECT_NAME ${PROJECT_NAME}) -------------------------------------------------------------------------------- /examples/embedded/README.md: -------------------------------------------------------------------------------- 1 | # Embedded Example 2 | 3 | The `embedded` folder was generated by executing: 4 | ```bash 5 | embed_helper ./dist 6 | ``` 7 | 8 | --- 9 | 10 | The most important part of the `CMakeLists.txt` is the line 11 | ```cmake 12 | target_include_directories(webview PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) # This directory contains the embedded folder - thats why we have to add it as a include directory 13 | ``` -------------------------------------------------------------------------------- /examples/embedded/dist/img_logo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Soundux/webviewpp/7843623ec88751812ed6dbdef75979397d023fac/examples/embedded/dist/img_logo.gif -------------------------------------------------------------------------------- /examples/embedded/dist/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |

Drag the W3Schools image into the rectangle:

9 | 10 |
11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /examples/embedded/dist/index.js: -------------------------------------------------------------------------------- 1 | function allowDrop(ev) { 2 | ev.preventDefault(); 3 | } 4 | 5 | function drag(ev) { 6 | ev.dataTransfer.setData("text", ev.target.id); 7 | } 8 | 9 | function drop(ev) { 10 | ev.preventDefault(); 11 | var data = ev.dataTransfer.getData("text"); 12 | ev.target.appendChild(document.getElementById(data)); 13 | } 14 | -------------------------------------------------------------------------------- /examples/embedded/dist/style.css: -------------------------------------------------------------------------------- 1 | #div1 { 2 | width: 350px; 3 | height: 70px; 4 | padding: 10px; 5 | border: 1px solid #aaaaaa; 6 | } 7 | -------------------------------------------------------------------------------- /examples/embedded/embedded/img_logo.gif.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "webview_base.hpp" 3 | namespace Webview::Embedded { 4 | inline unsigned char embed_file_img_logo_gif[] = {0x47,0x49,0x46,0x38,0x39,0x61,0x50,0x01,0x45,0x00,0xe6,0x00,0x00,0xe0,0xe0,0xe0,0xff,0xff,0xff,0xca,0xc9,0xc9,0x90,0xc1,0x40,0x54,0x54,0x53,0x8f,0x8c,0x8c,0x70,0x6e,0x6d,0xb3,0xb1,0xb1,0xb8,0xcf,0x91,0xa4,0xc8,0x69,0xfb,0xfb,0xfb,0x96,0xc2,0x48,0xdb,0xde,0xd6,0xcd,0xd8,0xb8,0xaf,0xcb,0x7e,0xec,0xeb,0xeb,0xc2,0xd4,0xa4,0xf0,0xee,0xee,0xd3,0xd2,0xd1,0xa0,0x9e,0x9e,0xf4,0xf3,0xf3,0xb4,0xce,0x88,0x9b,0xc4,0x53,0x5a,0x5a,0x59,0xbe,0xbc,0xbc,0x9f,0xc6,0x5d,0xd6,0xdc,0xcc,0x7f,0x7d,0x7c,0x62,0x60,0x5f,0xfa,0xfa,0xf9,0xd2,0xda,0xc2,0xe3,0xe1,0xe1,0xa9,0xc9,0x74,0xee,0xed,0xed,0xe0,0xde,0xdf,0xc7,0xc7,0xc7,0x87,0x85,0x84,0xe7,0xe6,0xe6,0xaa,0xa8,0xa7,0xc8,0xd6,0xae,0xe2,0xe0,0xe0,0xd5,0xd3,0xd3,0xf7,0xf6,0xf6,0x68,0x67,0x66,0xbd,0xd1,0x9a,0xf2,0xf2,0xf2,0x77,0x75,0x74,0xd8,0xd6,0xd6,0x98,0x95,0x95,0xf8,0xf9,0xf9,0xdc,0xda,0xda,0xf2,0xf1,0xf0,0xe5,0xe4,0xe4,0xf1,0xf0,0xf0,0xd7,0xd5,0xd5,0xeb,0xe9,0xe8,0xdb,0xd9,0xd9,0x9f,0xc2,0x65,0xed,0xf4,0xe2,0xdf,0xde,0xdd,0xe5,0xe3,0xe3,0x95,0xc2,0x47,0xad,0xc4,0x88,0xe0,0xeb,0xca,0xaa,0xcd,0x6d,0xbf,0xd8,0x90,0xd2,0xd0,0xcf,0xc6,0xc8,0xc2,0xaa,0xc4,0x81,0xde,0xdc,0xdb,0x9e,0xc7,0x55,0xc3,0xc8,0xba,0xe9,0xe8,0xe8,0x9c,0xc2,0x5b,0xb5,0xc6,0x99,0xd9,0xe7,0xbe,0xa3,0xc3,0x6e,0xb1,0xd1,0x7a,0xc5,0xdb,0x9b,0xda,0xd8,0xd7,0xd0,0xce,0xce,0xbf,0xc7,0xb1,0xbc,0xc7,0xa9,0xe4,0xe2,0xe2,0xe9,0xe7,0xe7,0xcc,0xde,0xa5,0xea,0xe9,0xe8,0xdf,0xdd,0xdd,0xd9,0xd7,0xd7,0xe6,0xef,0xd6,0xb8,0xc6,0xa1,0xf5,0xf8,0xee,0x97,0xc4,0x49,0xd3,0xd1,0xd1,0xa6,0xc3,0x78,0xd6,0xd4,0xd4,0x98,0xc2,0x51,0xa5,0xca,0x60,0xd3,0xe3,0xb1,0xb1,0xc5,0x90,0xd4,0xd2,0xd3,0xf3,0xf3,0xf3,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0xf9,0x04,0x01,0x00,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x00,0x50,0x01,0x45,0x00,0x00,0x07,0xff,0x80,0x00,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x00,0x47,0x5a,0x44,0x39,0x03,0x90,0x49,0x44,0x47,0x8a,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,0xa0,0xa1,0xa2,0xa3,0xa4,0x9a,0x52,0x3e,0x4c,0x60,0x90,0xab,0xac,0x3d,0x4a,0xa5,0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0x8b,0x4a,0x44,0x49,0xac,0xbe,0xbf,0x03,0x51,0xb9,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xb3,0xa7,0x4c,0x3d,0xc0,0xce,0xbe,0x39,0xc9,0xd2,0xd3,0xd4,0xd5,0xd6,0xa5,0x47,0xbb,0xbd,0xcf,0xdc,0xbf,0xc2,0xd7,0xe0,0xe1,0xe2,0xe3,0xc4,0x43,0xcb,0xcd,0xdd,0xe9,0xbf,0x3e,0xe4,0xed,0xee,0xef,0xf0,0x95,0x51,0x4a,0x5e,0xdb,0xea,0xf7,0xbf,0xd1,0xf1,0xfb,0xfc,0xfd,0xc9,0xe6,0x3e,0x72,0xa0,0xc3,0x47,0x10,0x98,0xbf,0x83,0x08,0x13,0x8e,0x1a,0x42,0xcf,0x5e,0x41,0x7c,0x60,0x72,0x48,0x1c,0x08,0xe9,0x9b,0xc2,0x8b,0x18,0x33,0x12,0x1a,0x42,0x84,0xe2,0x43,0x75,0x4c,0xb4,0x0c,0x29,0x74,0xc4,0x07,0xba,0x31,0x1a,0x53,0xaa,0xf4,0xe7,0xc1,0xc2,0x47,0x82,0x09,0x34,0x28,0x62,0x00,0x62,0x80,0x83,0x95,0x38,0x73,0x8e,0x63,0xe0,0xf2,0xe5,0x3d,0x16,0x98,0x1c,0x58,0xd0,0x49,0xb4,0xa8,0x34,0x04,0x3e,0xef,0x41,0xd0,0x04,0x82,0x81,0xd1,0xa7,0x50,0x6f,0x65,0x48,0x9a,0xae,0x42,0x21,0x06,0x2c,0x40,0x24,0x48,0x00,0xa2,0xc1,0x55,0x99,0x51,0xc3,0x8a,0x1d,0x45,0xb5,0xdb,0x02,0xa7,0x83,0x3c,0x2c,0xf8,0x75,0x73,0xac,0xdb,0xb7,0xa0,0xff,0xca,0x72,0xb3,0x3a,0x48,0xc3,0x5a,0x60,0x40,0xad,0x1d,0x20,0xc0,0xb7,0xaf,0xdf,0xbf,0x06,0x60,0x48,0x48,0x56,0xc0,0x6f,0x81,0x77,0x7f,0x0f,0xc0,0xbd,0x24,0xf7,0x99,0xd7,0x41,0x0e,0x9e,0x0d,0xd5,0xfb,0xb7,0x72,0xe5,0x0b,0x18,0x90,0x15,0xee,0x7b,0xd8,0x5d,0xe2,0xc5,0x96,0x12,0x34,0x36,0x48,0xe8,0xae,0x33,0x0f,0x94,0x2d,0xab,0xe6,0x7b,0x61,0xb0,0xb1,0xcd,0x7c,0x3b,0xb7,0xfb,0x0c,0x5a,0x51,0x85,0xd1,0xbf,0x0a,0x75,0x7b,0x4c,0x6d,0xef,0xea,0xd5,0xb2,0x89,0xc1,0x26,0x10,0x7c,0x1c,0xed,0xda,0x88,0x20,0xe0,0xf6,0x55,0xf7,0xc4,0x6e,0x6b,0x12,0x0e,0x48,0x9f,0x4e,0xfd,0x00,0x0c,0x03,0x95,0x57,0x1c,0x1b,0x5e,0x5c,0xdc,0x71,0xe4,0x86,0x34,0x2c,0x67,0x95,0xb5,0x67,0x37,0xd4,0xfc,0x5c,0x54,0xde,0x6e,0x18,0xb1,0x5f,0xc5,0xe0,0x11,0x99,0x1e,0xbf,0x6a,0xeb,0xb3,0x04,0xa0,0x0a,0xe8,0xd7,0x5f,0xe8,0xc0,0xfe,0x02,0xf0,0x0d,0xf2,0x5f,0x77,0x8a,0x98,0xb0,0x5e,0x21,0x18,0xc0,0x30,0xe0,0x82,0x13,0x20,0x12,0xdd,0x82,0xfb,0x8d,0x20,0xc8,0x70,0x06,0x2c,0x68,0x82,0x6b,0x89,0x48,0x30,0xc1,0x06,0x06,0x74,0x68,0x80,0x0b,0x30,0x48,0x58,0x89,0x09,0x24,0x78,0xd8,0x61,0x01,0x99,0x1d,0xf2,0x9d,0x20,0x09,0x42,0xf8,0x5f,0x83,0x99,0x34,0x80,0xc0,0x8c,0x34,0xd2,0xc8,0x1b,0x21,0x10,0x38,0xb0,0xd5,0x8e,0x08,0x80,0x65,0x48,0x8d,0x40,0x06,0x19,0xe4,0x09,0x68,0x21,0x52,0x13,0x7d,0x09,0xb0,0x80,0x9e,0xff,0x72,0xc0,0x2c,0xe0,0x63,0x27,0x7f,0x15,0xc2,0x5d,0x21,0x51,0x66,0xe2,0x9b,0x5f,0x84,0x98,0xc0,0xc1,0x6f,0x7d,0x19,0x60,0x88,0x04,0x1b,0x70,0x09,0xdf,0x70,0xab,0x6d,0x20,0xa2,0x21,0x05,0x5c,0xb0,0x1a,0x09,0x18,0x16,0xa2,0xe5,0x6a,0x06,0x9c,0x39,0xc8,0x77,0x6f,0x72,0x49,0x80,0x97,0x96,0x30,0x80,0xc0,0x7c,0xbf,0x20,0x50,0x08,0x0b,0x7c,0xb2,0x02,0xc2,0x93,0x82,0x50,0xe5,0x40,0x91,0x85,0x20,0x55,0x50,0x06,0x0e,0x28,0xfa,0x8c,0x9f,0x83,0x34,0x00,0xcc,0xa1,0xa1,0x54,0x29,0x60,0x7b,0x84,0x58,0x7a,0x09,0x99,0x78,0x02,0x70,0xa5,0x9d,0x9d,0xb2,0xa8,0xa6,0x98,0x13,0xda,0xc9,0x9a,0x9c,0x00,0x48,0xb0,0x82,0x9d,0x1c,0xa4,0x48,0x48,0x98,0x5c,0x5e,0x00,0xe3,0x9c,0xef,0x0d,0x82,0x81,0xa9,0x7c,0x85,0x8a,0x08,0x03,0x53,0x75,0x03,0xa9,0x20,0x91,0x99,0x85,0xde,0x20,0x65,0x65,0x80,0x88,0xa4,0xf8,0x50,0x2a,0x48,0xa0,0xac,0xfc,0x0a,0x00,0xb2,0x90,0x24,0x49,0xa8,0x27,0x9a,0x02,0x30,0x65,0xa6,0x58,0x5e,0x22,0x01,0x0c,0x95,0xcd,0xba,0x2a,0xae,0xa1,0x4a,0x30,0x2a,0xa9,0xd6,0xe2,0x4a,0x80,0x0b,0x85,0xa8,0x67,0x2a,0x07,0x6d,0x72,0x8b,0xab,0xab,0x00,0x1c,0x87,0x1d,0xb8,0x96,0xf4,0xea,0xeb,0x20,0xb7,0xa9,0xb3,0xc0,0xb0,0x00,0xc8,0x95,0xd7,0x55,0x30,0x11,0x12,0xac,0x33,0x4b,0x0d,0xe2,0xa8,0x4d,0xa5,0x54,0x7b,0x2d,0xad,0x7d,0x11,0xf2,0x29,0xa8,0x83,0x48,0xf0,0x17,0x07,0x2e,0xea,0x37,0x2b,0xff,0x00,0xb0,0xfa,0xb5,0x02,0x09,0x0b,0x8a,0x38,0x1c,0x07,0x26,0xce,0xeb,0x17,0x86,0x13,0xfc,0x75,0x01,0x09,0xd2,0xc1,0xb0,0xa5,0x5f,0x1b,0x0c,0x32,0xc2,0xb8,0x7c,0x6d,0x60,0xc2,0x01,0x13,0x88,0xcc,0x17,0x07,0xd8,0xf6,0x15,0xe0,0xc4,0x15,0x17,0x70,0xf1,0x21,0x07,0x43,0x62,0x41,0x05,0x41,0x3e,0xe6,0x01,0x5b,0x27,0x34,0x00,0x81,0x68,0xac,0xe0,0x47,0x6c,0xd3,0x3b,0x26,0x60,0xde,0x00,0x16,0xec,0x38,0xf5,0x00,0xc6,0x1e,0x62,0x6f,0x3a,0x4e,0x0b,0x72,0xb4,0x33,0x67,0x11,0x72,0x24,0x24,0x59,0x8f,0xa2,0x30,0xa6,0x0c,0xf3,0xe5,0xb0,0xb9,0x2b,0x60,0xf8,0x70,0x9b,0x8a,0x8c,0xf0,0xd7,0x0a,0x01,0x22,0xb2,0xb0,0x20,0x0f,0x07,0xb8,0x32,0x6b,0xf0,0xaa,0xfa,0x97,0x6b,0x19,0xf3,0xf5,0x73,0xe0,0x04,0xcc,0x4a,0xdb,0xc3,0xa8,0x6e,0x32,0xdf,0x02,0x05,0x27,0x32,0x30,0x24,0x8d,0x03,0xeb,0x0b,0x6f,0xcc,0x11,0x72,0xb0,0xb3,0x41,0x23,0xf2,0x78,0x37,0x5d,0x4b,0x0e,0x8c,0xb3,0x0c,0xf0,0x89,0x28,0x28,0x67,0x73,0x46,0x65,0xb6,0x78,0x9b,0x5b,0xf7,0xdb,0x98,0x0c,0x77,0x41,0xe2,0x68,0xa2,0x3d,0x88,0xcd,0xf0,0xdd,0xea,0xd7,0xcf,0x00,0xc8,0x7d,0xbb,0x20,0x30,0xb7,0x6c,0xc8,0xde,0x04,0xf8,0x1e,0x6f,0xad,0x9e,0xfe,0x05,0x3b,0x26,0xce,0xb1,0x72,0xe3,0x21,0x0c,0xf8,0xe2,0xac,0x20,0x3c,0xb1,0x42,0x57,0xbf,0xac,0x24,0xda,0x2c,0x21,0xcd,0x57,0x7f,0x08,0x93,0x03,0x30,0xdb,0xf4,0x55,0x5b,0x43,0xf2,0x7c,0xff,0xd0,0x03,0xb0,0x80,0x40,0x05,0x8d,0x9e,0xf0,0x49,0xe9,0xb1,0x9d,0xde,0xf0,0x20,0x0f,0x73,0x29,0x9b,0xed,0x7d,0x51,0xcc,0x20,0xdc,0x36,0x0b,0xaf,0xc8,0xdd,0x82,0xd0,0x2e,0x88,0xbb,0xac,0x41,0x84,0xba,0x62,0x06,0x00,0xfa,0xf1,0x05,0x5e,0x83,0x00,0x20,0x01,0x70,0x26,0x08,0xda,0x48,0xcc,0x2f,0xf6,0x1b,0xd0,0x04,0xe0,0x06,0x34,0x56,0x94,0x2d,0x11,0xd0,0x82,0xc4,0xb4,0x00,0x90,0xaf,0x68,0x3d,0x6d,0x15,0xd6,0x5b,0xc5,0xf3,0x2a,0x17,0x1e,0x04,0x34,0x80,0x01,0x5f,0x7b,0xc6,0xf4,0x08,0xc1,0x02,0x1e,0x11,0xca,0x2e,0xe9,0xb0,0x00,0xbf,0x32,0xc1,0x3e,0xe2,0xb8,0x4f,0x6d,0x2e,0xab,0xd8,0x06,0x60,0xc6,0x97,0x00,0xf1,0x70,0x4d,0x84,0x00,0x1e,0x81,0x62,0x67,0xba,0x42,0xf8,0xaf,0x5c,0x5d,0xb2,0x9b,0x5f,0xbc,0xf4,0x30,0x44,0x34,0xb1,0x81,0xc4,0x03,0xc0,0x0f,0x55,0xc3,0x26,0x45,0x30,0x0d,0x12,0x6d,0x51,0xc4,0xc1,0x26,0x63,0x88,0xe4,0x81,0xb0,0x50,0xda,0x33,0xd8,0xf5,0x08,0x41,0x42,0x2b,0x72,0x63,0x83,0x33,0x09,0xdf,0x33,0xf6,0xc5,0x89,0x1a,0x16,0xa7,0x5a,0x8a,0xf0,0x9b,0x5f,0xd0,0x25,0x08,0x12,0x98,0x4b,0x78,0x7f,0x31,0xc1,0xa6,0x64,0xd7,0x3f,0xe2,0xd9,0x4c,0x57,0x97,0x4a,0x22,0x99,0x9c,0x68,0xa9,0xe3,0x90,0xe9,0x37,0x74,0x44,0xc4,0x15,0x07,0xf0,0xbc,0x0a,0xd6,0xe7,0x58,0x24,0x2c,0x23,0x00,0x2e,0xa7,0x9b,0x30,0x2a,0x02,0x86,0xc0,0x88,0x9c,0xfa,0x2a,0xc1,0xab,0x80,0x6d,0xc2,0xff,0x8d,0x37,0x24,0x80,0x26,0x0c,0xe4,0x97,0x0b,0x44,0xcc,0x66,0x5c,0x4a,0x11,0xcc,0x70,0x77,0x08,0xfe,0x01,0xe0,0x88,0x76,0x4c,0x62,0x2b,0x97,0x08,0x00,0x52,0xbe,0xcf,0x10,0x4f,0x1c,0x9e,0xce,0x5e,0x65,0x2e,0x04,0x12,0x62,0x91,0x8d,0xfc,0xd1,0xf7,0x0e,0x91,0xc1,0x01,0x7c,0x10,0x12,0x21,0x14,0x5f,0x25,0xbf,0x68,0x09,0x0d,0x2c,0x72,0x00,0x09,0x58,0x9e,0x05,0x9a,0x92,0x88,0x13,0x5c,0x4d,0x1d,0x68,0x4c,0x04,0x28,0x73,0x86,0x43,0x1a,0x56,0x0b,0x03,0x13,0x80,0x10,0xe1,0x3a,0x63,0x33,0x12,0xec,0xb1,0x88,0x84,0x38,0xe2,0xc7,0x10,0x11,0x38,0x74,0x21,0xee,0x10,0x25,0xeb,0x8b,0x29,0xa1,0xb8,0x4b,0x42,0x80,0x53,0x9c,0x7f,0x19,0x22,0x07,0x87,0xa9,0x08,0x2f,0x42,0x62,0x74,0x82,0x38,0x58,0xd9,0x24,0x49,0x49,0x32,0x5a,0xb2,0x99,0x0d,0x48,0x28,0x40,0x99,0x64,0x01,0x08,0x20,0x8a,0x01,0x10,0x50,0xe3,0x3d,0x96,0x67,0x89,0x6d,0xa6,0x4d,0x94,0x99,0xb0,0xe5,0x2d,0x2d,0xa1,0x40,0x3a,0xc6,0xf2,0x66,0x14,0x24,0x62,0xfb,0x8c,0x48,0x3c,0x8d,0x12,0xa0,0x6e,0x82,0x10,0x97,0x5f,0x60,0x40,0xcf,0x91,0x92,0xb4,0x2f,0x89,0x5c,0x91,0x22,0xe2,0x99,0xab,0x44,0x70,0x4f,0x83,0x95,0x10,0x0f,0x2b,0x22,0x37,0x88,0xad,0x65,0x91,0xa0,0x63,0x3c,0xa6,0x31,0x6d,0x9a,0x09,0xb5,0xf8,0xc2,0x6a,0x54,0xf9,0x17,0x26,0xf2,0x48,0x08,0xfe,0xc1,0x31,0x11,0x23,0xf8,0x96,0x3c,0x33,0x41,0xd3,0x73,0xb1,0xe8,0x2f,0xfa,0xff,0x53,0x22,0x3a,0x67,0x17,0x45,0x98,0xb5,0xad,0x10,0x84,0x13,0xd1,0x00,0x09,0x80,0x99,0x42,0x54,0xb5,0x70,0x17,0x45,0x69,0x81,0x68,0xb9,0x2b,0x5f,0x64,0x00,0xa0,0x85,0x58,0x64,0xd8,0x58,0xe8,0x8b,0x4d,0x52,0x8f,0x99,0x01,0x0d,0x2a,0x18,0xf1,0x6a,0x88,0x0c,0xf0,0xf4,0x58,0xde,0x93,0x0b,0x45,0x2b,0x01,0xbc,0x0b,0x6c,0x60,0x3f,0x7f,0x1c,0x50,0x95,0x30,0x10,0xb2,0xc6,0xa2,0x92,0x2f,0x89,0xac,0x8e,0x64,0x27,0x00,0x33,0xd9,0xa0,0x92,0x03,0x1c,0x93,0xac,0x6b,0x5c,0x79,0x44,0x24,0xf6,0x65,0x05,0x7a,0x2c,0x20,0x2a,0x85,0xf7,0x30,0x59,0x0d,0x66,0x04,0x1f,0xbd,0x19,0x37,0x4f,0x6a,0x2b,0xc9,0x52,0x67,0x02,0x42,0x14,0xc4,0xd2,0xb6,0x32,0xbd,0xcd,0x2d,0x80,0x68,0x49,0x4b,0x68,0x42,0xc1,0xe2,0x4f,0xaa,0x15,0xcc,0x03,0x9b,0xe3,0xe2,0x5d,0x91,0x69,0x39,0xbd,0x0e,0x77,0xa8,0x9a,0x1b,0x40,0x05,0xe0,0xea,0xb5,0xcd,0xe1,0x63,0x01,0x20,0x40,0xc0,0x33,0x7f,0xf1,0x24,0xe6,0x12,0x22,0xb5,0xe6,0x3a,0x50,0xfc,0x4c,0xb5,0xb3,0xec,0x86,0xb6,0x80,0xb8,0x1a,0x13,0x1f,0x5f,0x19,0x45,0x00,0x48,0x35,0x56,0x72,0xc2,0xee,0x6f,0xbe,0xab,0xcb,0x1e,0x72,0xd5,0x5c,0x30,0x72,0x54,0xd7,0x42,0xa7,0x8e,0x5f,0x8d,0x2d,0x1d,0x37,0x02,0xaa,0x08,0x97,0x49,0xdc,0xe4,0x40,0x62,0x01,0x0e,0x38,0x01,0x58,0x3c,0x70,0x82,0x0a,0x5c,0xf3,0x17,0x0b,0xb8,0x66,0x05,0x7c,0x74,0x53,0xb6,0x14,0x62,0x85,0x0e,0x9a,0x62,0xff,0x76,0x31,0xba,0x5d,0x2e,0xe9,0x2f,0xbb,0xba,0x3a,0xab,0x6a,0xc4,0xbb,0xd5,0x3e,0xd6,0x53,0x10,0x2f,0xb3,0x53,0x59,0x0b,0x71,0xde,0xd5,0xfc,0x4c,0x5e,0x6c,0x13,0xa3,0x07,0xd3,0x12,0xd8,0xfd,0x42,0x4f,0xa2,0xbf,0xe0,0xa9,0x7e,0x95,0x69,0x50,0xbe,0x16,0x22,0x85,0x3e,0xf1,0xeb,0x00,0xa2,0x9b,0xaf,0x2c,0x0a,0xe2,0xbe,0x16,0x44,0x54,0x44,0x2f,0x81,0x01,0xe0,0x4d,0x18,0x87,0x15,0x06,0xe2,0x6a,0x7f,0xf3,0xd5,0xfe,0x18,0xb9,0x32,0x1c,0x76,0xe9,0x7b,0xdd,0x4b,0x08,0x09,0x3c,0x56,0x63,0xbe,0xac,0xe3,0x6f,0x2e,0xc0,0xde,0x96,0xb2,0xd6,0xc3,0xac,0x3a,0x93,0x7c,0x6f,0x3c,0x5d,0xe7,0x61,0xaf,0x83,0x4d,0xa2,0xe8,0x8c,0x19,0xc9,0x5f,0xe4,0xca,0xe7,0x25,0x43,0x9b,0xca,0xd1,0x3c,0x90,0x80,0x0a,0xf4,0xea,0xa1,0x68,0xee,0xde,0x72,0xb1,0xe7,0x12,0xeb,0xba,0xa9,0x44,0x8e,0x0d,0x74,0xc8,0x58,0x24,0xe8,0x90,0x6d,0x60,0x82,0x86,0x28,0xb4,0x87,0x5c,0xc0,0x4a,0x5b,0x15,0xc0,0x05,0x81,0x4e,0x51,0xcd,0x3c,0x84,0x3b,0x40,0x77,0x28,0xcb,0x07,0xd8,0x40,0x61,0x19,0x5d,0x09,0xd4,0x96,0x38,0x30,0x21,0x0d,0x99,0xab,0x2c,0x5d,0xe8,0x9f,0xcd,0xb6,0xce,0x87,0xd0,0x00,0x0b,0x74,0x14,0xb5,0x1d,0xfd,0x15,0xb8,0x53,0x83,0xae,0x43,0x0f,0xd1,0xea,0x42,0x9c,0x3a,0x01,0x3c,0xad,0xb5,0x19,0x9f,0x91,0x81,0xa9,0x81,0xa0,0x02,0x09,0x8e,0xe8,0x09,0x32,0xd0,0x00,0xe8,0x4a,0x2d,0x79,0x3e,0x16,0x84,0x06,0x20,0xff,0x30,0xa3,0x13,0x1a,0x22,0x58,0x83,0x8d,0x8f,0xb4,0x8b,0x42,0x3e,0x41,0xad,0x3a,0x32,0xd2,0xb5,0xc0,0x09,0x12,0x80,0x94,0x3a,0x4b,0x97,0xdb,0x06,0x5e,0xc5,0x5f,0x15,0x31,0xb0,0x60,0x4e,0xfb,0xdc,0x38,0x29,0xe6,0x7f,0xd1,0xb7,0x2f,0x5c,0x13,0x1b,0x12,0xc5,0xce,0x11,0x04,0x12,0x7c,0x60,0xc6,0x5d,0x42,0x03,0xf7,0x05,0x01,0xba,0xf7,0x4d,0x94,0xec,0xd9,0x04,0x01,0x91,0xb1,0x26,0xbc,0x77,0x5c,0x01,0x10,0x9c,0xe0,0x7c,0x64,0x53,0xc7,0x9e,0x11,0xa1,0x81,0x3d,0x1d,0x95,0xdf,0x10,0xc7,0xc9,0x54,0x70,0x5d,0xb5,0x01,0x40,0x6b,0xde,0xb7,0xed,0x5e,0x8b,0xc1,0xe6,0x00,0x08,0x18,0x4d,0x46,0x65,0x86,0x66,0xc4,0x47,0xae,0x91,0x60,0x01,0xbc,0x02,0x05,0x07,0xb9,0x05,0x36,0x3e,0x9e,0x64,0x93,0xfc,0xe5,0xfd,0x60,0x01,0x24,0x7e,0x0d,0x28,0xfa,0x10,0x64,0xdc,0x30,0xcf,0xb9,0x3b,0xbe,0xc6,0x72,0x9b,0xbb,0x55,0xe7,0x40,0xe7,0x87,0xcf,0x1f,0xc2,0x85,0x2c,0x04,0xfd,0xe8,0xef,0x00,0xc2,0xd0,0xf1,0x01,0x84,0x2d,0x20,0xfd,0xe9,0xe4,0x70,0xc2,0xd2,0xbb,0x11,0x86,0x20,0x18,0x1d,0xea,0x58,0x0f,0xc7,0x12,0xa6,0xee,0x0b,0x2e,0x34,0xc1,0x09,0x3f,0xc8,0xba,0xd8,0xc5,0xb1,0x05,0xae,0x57,0x5d,0x0c,0x3a,0x18,0xbb,0xda,0xc7,0x61,0x04,0xfa,0x18,0xe1,0xeb,0x61,0x5f,0xbb,0xdc,0xc7,0x11,0x84,0xd1,0x00,0x21,0x08,0x4b,0x48,0xfb,0xdc,0xf7,0x3e,0x0e,0x1d,0x24,0xe5,0xed,0x55,0x88,0x3b,0xdf,0x07,0x4f,0x8e,0xff,0xba,0x13,0xe4,0xee,0x79,0x27,0xbc,0xe2,0x93,0xde,0x0d,0xc0,0x0b,0x7e,0xf1,0x90,0x77,0x47,0x15,0xda,0xce,0x0a,0x20,0x38,0x21,0xf1,0x91,0xcf,0xfc,0x3e,0x74,0xf0,0x83,0x1f,0xe8,0x5d,0xf3,0xa0,0x7f,0x87,0x02,0x46,0x4f,0xfa,0xd2,0x93,0x3e,0x06,0x0a,0xe8,0x40,0x0c,0x62,0xa0,0xfa,0xd4,0x9b,0xfe,0xf5,0xa3,0x0f,0xbd,0xec,0x37,0x61,0xfa,0x0e,0x74,0x40,0x05,0x2a,0xa0,0x80,0xee,0x5b,0xd0,0x82,0x19,0xcc,0x20,0x02,0xc0,0x8f,0x40,0x08,0x86,0x1f,0x82,0x07,0x18,0xff,0xf8,0xc7,0x27,0x7e,0x08,0x82,0x1f,0x81,0x1a,0xd4,0x80,0xf7,0xba,0xd7,0xbd,0x0a,0x6c,0x6f,0xfa,0xd9,0x87,0xbe,0xf4,0xb7,0xdf,0xbd,0xf3,0x81,0x5f,0xfc,0x07,0x58,0x81,0x0a,0x25,0x08,0x3f,0x0d,0x78,0xf0,0x81,0xf2,0x7f,0x00,0x05,0xe8,0x17,0x81,0xfa,0xd7,0x2f,0x02,0xf4,0xa3,0x7f,0x0a,0xe5,0x9f,0x02,0x0f,0xc2,0x5f,0x02,0x2a,0x58,0x21,0xf9,0xc0,0x9f,0x41,0x0b,0xa4,0x4f,0xfd,0xd8,0x5b,0x5f,0xf1,0xd9,0x47,0x01,0xbd,0xc7,0x7d,0xc6,0x77,0x03,0xe2,0x57,0x7e,0x28,0x20,0x02,0x3b,0xb0,0x03,0x45,0x20,0x03,0x32,0x80,0x03,0x58,0xf0,0x02,0x12,0x68,0x03,0x36,0x90,0x02,0x16,0x78,0x81,0x14,0x28,0x81,0x4f,0x80,0x03,0x0e,0x28,0x03,0x45,0x70,0x05,0xed,0x57,0x7e,0x34,0x10,0x7e,0x54,0x70,0x03,0x0f,0xb0,0x7c,0xcd,0x57,0x06,0xd2,0xa7,0x02,0xfe,0xf7,0x7f,0x7b,0x97,0x7b,0x02,0x58,0x03,0xc0,0x57,0x80,0x48,0x50,0x02,0xe3,0x77,0x7e,0x22,0x70,0xca,0x05,0x0d,0x08,0x81,0x13,0x78,0x81,0x5d,0x20,0x04,0x40,0x08,0x05,0x42,0x08,0x05,0x40,0x28,0x04,0x5d,0x40,0x06,0x16,0x68,0x03,0x2f,0xb0,0x81,0x1e,0xb8,0x03,0x21,0xf8,0x01,0x23,0x58,0x02,0x26,0xf8,0x00,0xf9,0xb7,0x7f,0x14,0x30,0x7d,0x0a,0xe0,0x82,0x7c,0x17,0x80,0x03,0x28,0x7c,0x0f,0x70,0x03,0x06,0x68,0x83,0x08,0xa8,0x80,0x3b,0xe0,0x80,0x38,0x80,0x03,0x4f,0x20,0x81,0x2f,0x50,0x81,0x5f,0x70,0x81,0x16,0xf8,0x05,0x4a,0xa8,0x81,0x1c,0xd8,0x84,0x3b,0x80,0x02,0xe5,0xc7,0x03,0x23,0x88,0x04,0x26,0x88,0x82,0xfa,0xc7,0x7f,0x2d,0xa8,0x85,0x6b,0x77,0x7a,0x31,0x00,0x83,0xbc,0x17,0x7c,0xdd,0x67,0x05,0x35,0x68,0x83,0x3c,0x40,0x7e,0x08,0x98,0x7e,0x20,0xc8,0x7e,0xeb,0x87,0x7e,0xe6,0xc7,0x03,0x53,0x10,0x85,0x48,0xa0,0x87,0xc6,0x87,0x82,0xcf,0xc7,0x7f,0x1d,0x50,0x7a,0x80,0xb8,0x78,0xb5,0x17,0x80,0xbb,0xe7,0x7b,0xcc,0x47,0x7c,0xc8,0x77,0x8a,0xc8,0x47,0x7c,0xcc,0x57,0x03,0x7d,0x18,0x7d,0xb8,0x87,0x7a,0x9e,0xf8,0x89,0xb2,0x08,0x7b,0xa5,0xb7,0x7a,0xb6,0xc7,0x7a,0xb7,0x48,0x7d,0xb0,0x48,0x8b,0x59,0x28,0x8b,0xd6,0x17,0x08,0x00,0x3b};inline auto webview_embed_file_img_logo_gif = []() -> bool { files.insert({"img_logo.gif", {3181,embed_file_img_logo_gif}});return true; }(); 5 | } -------------------------------------------------------------------------------- /examples/embedded/embedded/include.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "webview_base.hpp" 3 | #include "img_logo.gif.hpp" 4 | #include "index.html.hpp" 5 | #include "index.js.hpp" 6 | #include "style.css.hpp" 7 | -------------------------------------------------------------------------------- /examples/embedded/embedded/index.html.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "webview_base.hpp" 3 | namespace Webview::Embedded { 4 | inline unsigned char embed_file_index_html[] = {0x3c,0x21,0x44,0x4f,0x43,0x54,0x59,0x50,0x45,0x20,0x68,0x74,0x6d,0x6c,0x3e,0x0a,0x3c,0x68,0x74,0x6d,0x6c,0x3e,0x0a,0x20,0x20,0x20,0x20,0x3c,0x68,0x65,0x61,0x64,0x3e,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x6c,0x69,0x6e,0x6b,0x20,0x72,0x65,0x6c,0x3d,0x22,0x73,0x74,0x79,0x6c,0x65,0x73,0x68,0x65,0x65,0x74,0x22,0x20,0x68,0x72,0x65,0x66,0x3d,0x22,0x73,0x74,0x79,0x6c,0x65,0x2e,0x63,0x73,0x73,0x22,0x20,0x2f,0x3e,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x73,0x63,0x72,0x69,0x70,0x74,0x20,0x73,0x72,0x63,0x3d,0x22,0x69,0x6e,0x64,0x65,0x78,0x2e,0x6a,0x73,0x22,0x3e,0x3c,0x2f,0x73,0x63,0x72,0x69,0x70,0x74,0x3e,0x0a,0x20,0x20,0x20,0x20,0x3c,0x2f,0x68,0x65,0x61,0x64,0x3e,0x0a,0x20,0x20,0x20,0x20,0x3c,0x62,0x6f,0x64,0x79,0x3e,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x70,0x3e,0x44,0x72,0x61,0x67,0x20,0x74,0x68,0x65,0x20,0x57,0x33,0x53,0x63,0x68,0x6f,0x6f,0x6c,0x73,0x20,0x69,0x6d,0x61,0x67,0x65,0x20,0x69,0x6e,0x74,0x6f,0x20,0x74,0x68,0x65,0x20,0x72,0x65,0x63,0x74,0x61,0x6e,0x67,0x6c,0x65,0x3a,0x3c,0x2f,0x70,0x3e,0x0a,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x64,0x69,0x76,0x20,0x69,0x64,0x3d,0x22,0x64,0x69,0x76,0x31,0x22,0x20,0x6f,0x6e,0x64,0x72,0x6f,0x70,0x3d,0x22,0x64,0x72,0x6f,0x70,0x28,0x65,0x76,0x65,0x6e,0x74,0x29,0x22,0x20,0x6f,0x6e,0x64,0x72,0x61,0x67,0x6f,0x76,0x65,0x72,0x3d,0x22,0x61,0x6c,0x6c,0x6f,0x77,0x44,0x72,0x6f,0x70,0x28,0x65,0x76,0x65,0x6e,0x74,0x29,0x22,0x3e,0x3c,0x2f,0x64,0x69,0x76,0x3e,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x62,0x72,0x3e,0x0a,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x3c,0x69,0x6d,0x67,0x20,0x69,0x64,0x3d,0x22,0x64,0x72,0x61,0x67,0x31,0x22,0x20,0x73,0x72,0x63,0x3d,0x22,0x69,0x6d,0x67,0x5f,0x6c,0x6f,0x67,0x6f,0x2e,0x67,0x69,0x66,0x22,0x20,0x64,0x72,0x61,0x67,0x67,0x61,0x62,0x6c,0x65,0x3d,0x22,0x74,0x72,0x75,0x65,0x22,0x20,0x6f,0x6e,0x64,0x72,0x61,0x67,0x73,0x74,0x61,0x72,0x74,0x3d,0x22,0x64,0x72,0x61,0x67,0x28,0x65,0x76,0x65,0x6e,0x74,0x29,0x22,0x20,0x77,0x69,0x64,0x74,0x68,0x3d,0x22,0x33,0x33,0x36,0x22,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3d,0x22,0x36,0x39,0x22,0x3e,0x0a,0x20,0x20,0x20,0x20,0x3c,0x2f,0x62,0x6f,0x64,0x79,0x3e,0x0a,0x3c,0x2f,0x68,0x74,0x6d,0x6c,0x3e,0x0a};inline auto webview_embed_file_index_html = []() -> bool { files.insert({"index.html", {435,embed_file_index_html}});return true; }(); 5 | } -------------------------------------------------------------------------------- /examples/embedded/embedded/index.js.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "webview_base.hpp" 3 | namespace Webview::Embedded { 4 | inline unsigned char embed_file_index_js[] = {0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x61,0x6c,0x6c,0x6f,0x77,0x44,0x72,0x6f,0x70,0x28,0x65,0x76,0x29,0x20,0x7b,0x0a,0x20,0x20,0x65,0x76,0x2e,0x70,0x72,0x65,0x76,0x65,0x6e,0x74,0x44,0x65,0x66,0x61,0x75,0x6c,0x74,0x28,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x64,0x72,0x61,0x67,0x28,0x65,0x76,0x29,0x20,0x7b,0x0a,0x20,0x20,0x65,0x76,0x2e,0x64,0x61,0x74,0x61,0x54,0x72,0x61,0x6e,0x73,0x66,0x65,0x72,0x2e,0x73,0x65,0x74,0x44,0x61,0x74,0x61,0x28,0x22,0x74,0x65,0x78,0x74,0x22,0x2c,0x20,0x65,0x76,0x2e,0x74,0x61,0x72,0x67,0x65,0x74,0x2e,0x69,0x64,0x29,0x3b,0x0a,0x7d,0x0a,0x0a,0x66,0x75,0x6e,0x63,0x74,0x69,0x6f,0x6e,0x20,0x64,0x72,0x6f,0x70,0x28,0x65,0x76,0x29,0x20,0x7b,0x0a,0x20,0x20,0x65,0x76,0x2e,0x70,0x72,0x65,0x76,0x65,0x6e,0x74,0x44,0x65,0x66,0x61,0x75,0x6c,0x74,0x28,0x29,0x3b,0x0a,0x20,0x20,0x76,0x61,0x72,0x20,0x64,0x61,0x74,0x61,0x20,0x3d,0x20,0x65,0x76,0x2e,0x64,0x61,0x74,0x61,0x54,0x72,0x61,0x6e,0x73,0x66,0x65,0x72,0x2e,0x67,0x65,0x74,0x44,0x61,0x74,0x61,0x28,0x22,0x74,0x65,0x78,0x74,0x22,0x29,0x3b,0x0a,0x20,0x20,0x65,0x76,0x2e,0x74,0x61,0x72,0x67,0x65,0x74,0x2e,0x61,0x70,0x70,0x65,0x6e,0x64,0x43,0x68,0x69,0x6c,0x64,0x28,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x2e,0x67,0x65,0x74,0x45,0x6c,0x65,0x6d,0x65,0x6e,0x74,0x42,0x79,0x49,0x64,0x28,0x64,0x61,0x74,0x61,0x29,0x29,0x3b,0x0a,0x7d,0x0a};inline auto webview_embed_file_index_js = []() -> bool { files.insert({"index.js", {270,embed_file_index_js}});return true; }(); 5 | } -------------------------------------------------------------------------------- /examples/embedded/embedded/style.css.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "webview_base.hpp" 3 | namespace Webview::Embedded { 4 | inline unsigned char embed_file_style_css[] = {0x23,0x64,0x69,0x76,0x31,0x20,0x7b,0x0a,0x20,0x20,0x77,0x69,0x64,0x74,0x68,0x3a,0x20,0x33,0x35,0x30,0x70,0x78,0x3b,0x0a,0x20,0x20,0x68,0x65,0x69,0x67,0x68,0x74,0x3a,0x20,0x37,0x30,0x70,0x78,0x3b,0x0a,0x20,0x20,0x70,0x61,0x64,0x64,0x69,0x6e,0x67,0x3a,0x20,0x31,0x30,0x70,0x78,0x3b,0x0a,0x20,0x20,0x62,0x6f,0x72,0x64,0x65,0x72,0x3a,0x20,0x31,0x70,0x78,0x20,0x73,0x6f,0x6c,0x69,0x64,0x20,0x23,0x61,0x61,0x61,0x61,0x61,0x61,0x3b,0x0a,0x7d,0x0a};inline auto webview_embed_file_style_css = []() -> bool { files.insert({"style.css", {88,embed_file_style_css}});return true; }(); 5 | } -------------------------------------------------------------------------------- /examples/embedded/embedded/webview_base.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | namespace Webview { 6 | namespace Embedded { 7 | inline std::map files; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /examples/embedded/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | Webview::Window webview("webview", 800, 900); 6 | webview.setTitle("Embedded Example"); 7 | webview.enableDevTools(true); 8 | 9 | #if defined(_WIN32) 10 | webview.setUrl("file:///embedded/index.html"); 11 | #else 12 | webview.setUrl("embedded:///index.html"); 13 | #endif 14 | 15 | webview.show(); 16 | webview.run(); 17 | return 0; 18 | } -------------------------------------------------------------------------------- /examples/simple/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1) 2 | project(webview-example VERSION 0.1) 3 | 4 | add_executable(webview-example "main.cpp") 5 | add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../../ ${CMAKE_CURRENT_SOURCE_DIR}/../../example_build EXCLUDE_FROM_ALL) 6 | target_link_libraries(webview-example webview) 7 | 8 | target_compile_features(webview-example PUBLIC cxx_std_17) 9 | set_target_properties(webview-example PROPERTIES CMAKE_CXX_STANDARD 17) 10 | set_target_properties(webview-example PROPERTIES CMAKE_CXX_EXTENSIONS Off) 11 | set_target_properties(webview-example PROPERTIES CMAKE_CXX_STANDARD_REQUIRED On) 12 | set_target_properties(webview-example PROPERTIES VERSION ${PROJECT_VERSION}) 13 | set_target_properties(webview-example PROPERTIES PROJECT_NAME ${PROJECT_NAME}) -------------------------------------------------------------------------------- /examples/simple/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main() 6 | { 7 | #if defined(_WIN32) 8 | Webview::Window webview("webview", 800, 900); //* We have to provide an identifier on windows 9 | #else 10 | Webview::Window webview(800, 900); 11 | #endif 12 | webview.setTitle("Example"); 13 | webview.enableDevTools(true); 14 | 15 | // Call me using the dev tools! 16 | webview.expose(Webview::Function("testCallback", [](const std::string &someString, int someInt) { 17 | std::cout << "Got " << someString << " and " << someInt; 18 | return someInt * 10; 19 | })); 20 | 21 | webview.setUrl("https://ddg.gg"); 22 | webview.show(); 23 | webview.run(); 24 | 25 | return 0; 26 | } -------------------------------------------------------------------------------- /webview/include/core/basewindow.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "resource.hpp" 9 | #include 10 | 11 | #if __has_include() 12 | #define WEBVIEW_EMBEDDED 13 | #include 14 | #endif 15 | 16 | namespace Webview 17 | { 18 | class Promise; 19 | class BaseWindow 20 | { 21 | friend class Promise; 22 | 23 | protected: 24 | std::size_t width; 25 | std::size_t height; 26 | 27 | std::string url; 28 | std::string title; 29 | std::string identifier; //* Only required on windows 30 | 31 | bool hidden = true; 32 | bool isContextMenuAllowed = true; 33 | 34 | std::function closeCallback; 35 | std::function navigateCallback; 36 | std::function resizeCallback; 37 | 38 | static const std::string setupRpc; 39 | static const std::string resolveCall; 40 | static const std::string resolveNativeCall; 41 | static const std::string resolveNativeFunction; 42 | static const std::string callbackFunctionDefinition; 43 | 44 | std::mutex functionsMutex; 45 | std::map> functions; 46 | 47 | std::mutex nativeCallRequestsMutex; 48 | std::map nativeCallRequests; 49 | 50 | protected: 51 | virtual bool onClose(); 52 | virtual void onNavigate(std::string); 53 | virtual void onResize(std::size_t, std::size_t); 54 | 55 | #if defined(WEBVIEW_EMBEDDED) 56 | Resource getResource(const std::string &); 57 | #endif 58 | 59 | virtual std::string formatCode(const std::string &); 60 | virtual void handleRawCallRequest(const std::string &); 61 | JavaScriptFunction &callFunctionInternal(JavaScriptFunction &&); 62 | 63 | public: 64 | BaseWindow(const BaseWindow &) = delete; 65 | virtual BaseWindow &operator=(const BaseWindow &) = delete; 66 | BaseWindow(std::string identifier, std::size_t width, std::size_t height); 67 | 68 | /// \effects Hides the window 69 | virtual void hide(); 70 | /// \effects Shows the window 71 | virtual void show(); 72 | /// \returns Whether or the window is hidden 73 | virtual bool isHidden(); 74 | 75 | /// \effects Sets the window size 76 | virtual void setSize(std::size_t, std::size_t); 77 | /// \returns The width and height in form of an `std::pair` 78 | virtual std::pair getSize(); 79 | 80 | /// \returns The title of the window 81 | virtual std::string getTitle(); 82 | /// \effects Sets the window title 83 | virtual void setTitle(std::string); 84 | 85 | /// \effects Runs the mainloop 86 | /// \remarks Is blocking 87 | virtual void run() = 0; 88 | /// \effects Closes the webview 89 | virtual void exit() = 0; 90 | 91 | /// \returns The current url 92 | virtual std::string getUrl(); 93 | /// \effects Navigates to the given url 94 | virtual void setUrl(std::string); 95 | 96 | /// \effects Enables the context menu 97 | virtual void enableContextMenu(bool); 98 | /// \effects Enables the developer tools 99 | virtual void enableDevTools(bool) = 0; 100 | 101 | /// \effects Exposes the given function 102 | /// \remarks If the given Function is an `AsyncFunction` it will be run in a new thread 103 | void expose(const Function &); 104 | /// \effects Calls the given javascript function 105 | /// \returns The result of the javascript function call as `T` 106 | /// \preconditions `T` must be serializable by nlohmann::json 107 | /// \remarks You should never call `.get()` on the returned future in a **non async** context as it will 108 | /// freeze the webview 109 | template std::future callFunction(JavaScriptFunction &&function) 110 | { 111 | auto &future = callFunctionInternal(std::forward(function)); 112 | auto result = future.getResult(); 113 | 114 | return std::async(std::launch::async, [result] { 115 | if constexpr (!std::is_same_v) 116 | { 117 | return result.get().get(); 118 | } 119 | }); 120 | } 121 | 122 | /// \effects Runs the given javascript code 123 | virtual void runCode(const std::string &) = 0; 124 | /// \effects Makes the given javascript code run on document load 125 | virtual void injectCode(const std::string &) = 0; 126 | 127 | /// \effects Sets the close-callback to the given callback 128 | /// \remarks If the callback returns `true` the webview will not close 129 | virtual void setCloseCallback(std::function); 130 | /// \effects Sets the navigate-callback to the given callback 131 | virtual void setNavigateCallback(std::function); 132 | /// \effects Sets the resize-callback to the given callback 133 | virtual void setResizeCallback(std::function); 134 | }; 135 | } // namespace Webview -------------------------------------------------------------------------------- /webview/include/core/linux/window.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #if defined(__linux__) 3 | #include 4 | #include 5 | #include 6 | 7 | namespace Webview 8 | { 9 | class Window : public BaseWindow 10 | { 11 | GtkWidget *window; 12 | GtkWidget *webview; 13 | 14 | static void destroy(GtkWidget *, gpointer); 15 | static gboolean closed(GtkWidget *, GdkEvent *, gpointer); 16 | static gboolean resize(WebKitWebView *, GdkEvent *, gpointer); 17 | 18 | #if defined(WEBVIEW_EMBEDDED) 19 | static void onUriRequested(WebKitURISchemeRequest *, gpointer); 20 | #endif 21 | 22 | static void loadChanged(WebKitWebView *, WebKitLoadEvent, gpointer); 23 | static void messageReceived(WebKitUserContentManager *, WebKitJavascriptResult *, gpointer); 24 | static gboolean contextMenu(WebKitWebView *, GtkWidget *, WebKitHitTestResultContext *, gboolean, gpointer); 25 | 26 | private: 27 | void runOnIdle(std::function); 28 | 29 | public: 30 | Window(std::size_t width, std::size_t height); 31 | Window(const std::string &identifier, std::size_t width, 32 | std::size_t height); //* Identifier is not required on linux. 33 | 34 | void hide() override; 35 | void show() override; 36 | 37 | void run() override; 38 | void exit() override; 39 | 40 | std::string getUrl() override; 41 | void setUrl(std::string newUrl) override; 42 | void setTitle(std::string newTitle) override; 43 | void setSize(std::size_t newWidth, std::size_t newHeight) override; 44 | 45 | void enableDevTools(bool state) override; 46 | void runCode(const std::string &code) override; 47 | void injectCode(const std::string &code) override; 48 | }; 49 | } // namespace Webview 50 | #endif -------------------------------------------------------------------------------- /webview/include/core/resource.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | namespace Webview 5 | { 6 | struct Resource 7 | { 8 | const std::size_t size; 9 | const unsigned char *data; 10 | }; 11 | } // namespace Webview -------------------------------------------------------------------------------- /webview/include/core/windows/mimes.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | //* Taken from https://github.com/samuelneff/MimeTypeMap/blob/master/MimeTypeMap.cs 6 | //? This is a little cursed, I tried to get WebView2 to automatically deduce the mimeType but I couldn't get that to 7 | //? work - I also tried setting Content-Type to * or not setting it at all but that resulted in the file being 8 | //? downloaded, so that's why I have to resort to this on windows - If you know how to do this properly please open a PR 9 | inline std::map mimeTypeList = { 10 | {".323", "text/h323"}, 11 | {".3g2", "video/3gpp2"}, 12 | {".3gp", "video/3gpp"}, 13 | {".3gp2", "video/3gpp2"}, 14 | {".3gpp", "video/3gpp"}, 15 | {".7z", "application/x-7z-compressed"}, 16 | {".aa", "audio/audible"}, 17 | {".AAC", "audio/aac"}, 18 | {".aaf", "application/octet-stream"}, 19 | {".aax", "audio/vnd.audible.aax"}, 20 | {".ac3", "audio/ac3"}, 21 | {".aca", "application/octet-stream"}, 22 | {".accda", "application/msaccess.addin"}, 23 | {".accdb", "application/msaccess"}, 24 | {".accdc", "application/msaccess.cab"}, 25 | {".accde", "application/msaccess"}, 26 | {".accdr", "application/msaccess.runtime"}, 27 | {".accdt", "application/msaccess"}, 28 | {".accdw", "application/msaccess.webapplication"}, 29 | {".accft", "application/msaccess.ftemplate"}, 30 | {".acx", "application/internet-property-stream"}, 31 | {".AddIn", "text/xml"}, 32 | {".ade", "application/msaccess"}, 33 | {".adobebridge", "application/x-bridge-url"}, 34 | {".adp", "application/msaccess"}, 35 | {".ADT", "audio/vnd.dlna.adts"}, 36 | {".ADTS", "audio/aac"}, 37 | {".afm", "application/octet-stream"}, 38 | {".ai", "application/postscript"}, 39 | {".aif", "audio/aiff"}, 40 | {".aifc", "audio/aiff"}, 41 | {".aiff", "audio/aiff"}, 42 | {".air", "application/vnd.adobe.air-application-installer-package+zip"}, 43 | {".amc", "application/mpeg"}, 44 | {".anx", "application/annodex"}, 45 | {".apk", "application/vnd.android.package-archive"}, 46 | {".apng", "image/apng"}, 47 | {".application", "application/x-ms-application"}, 48 | {".art", "image/x-jg"}, 49 | {".asa", "application/xml"}, 50 | {".asax", "application/xml"}, 51 | {".ascx", "application/xml"}, 52 | {".asd", "application/octet-stream"}, 53 | {".asf", "video/x-ms-asf"}, 54 | {".ashx", "application/xml"}, 55 | {".asi", "application/octet-stream"}, 56 | {".asm", "text/plain"}, 57 | {".asmx", "application/xml"}, 58 | {".aspx", "application/xml"}, 59 | {".asr", "video/x-ms-asf"}, 60 | {".asx", "video/x-ms-asf"}, 61 | {".atom", "application/atom+xml"}, 62 | {".au", "audio/basic"}, 63 | {".avci", "image/avci"}, 64 | {".avcs", "image/avcs"}, 65 | {".avi", "video/x-msvideo"}, 66 | {".avif", "image/avif"}, 67 | {".avifs", "image/avif-sequence"}, 68 | {".axa", "audio/annodex"}, 69 | {".axs", "application/olescript"}, 70 | {".axv", "video/annodex"}, 71 | {".bas", "text/plain"}, 72 | {".bcpio", "application/x-bcpio"}, 73 | {".bin", "application/octet-stream"}, 74 | {".bmp", "image/bmp"}, 75 | {".c", "text/plain"}, 76 | {".cab", "application/octet-stream"}, 77 | {".caf", "audio/x-caf"}, 78 | {".calx", "application/vnd.ms-office.calx"}, 79 | {".cat", "application/vnd.ms-pki.seccat"}, 80 | {".cc", "text/plain"}, 81 | {".cd", "text/plain"}, 82 | {".cdda", "audio/aiff"}, 83 | {".cdf", "application/x-cdf"}, 84 | {".cer", "application/x-x509-ca-cert"}, 85 | {".cfg", "text/plain"}, 86 | {".chm", "application/octet-stream"}, 87 | {".class", "application/x-java-applet"}, 88 | {".clp", "application/x-msclip"}, 89 | {".cmd", "text/plain"}, 90 | {".cmx", "image/x-cmx"}, 91 | {".cnf", "text/plain"}, 92 | {".cod", "image/cis-cod"}, 93 | {".config", "application/xml"}, 94 | {".contact", "text/x-ms-contact"}, 95 | {".coverage", "application/xml"}, 96 | {".cpio", "application/x-cpio"}, 97 | {".cpp", "text/plain"}, 98 | {".crd", "application/x-mscardfile"}, 99 | {".crl", "application/pkix-crl"}, 100 | {".crt", "application/x-x509-ca-cert"}, 101 | {".cs", "text/plain"}, 102 | {".csdproj", "text/plain"}, 103 | {".csh", "application/x-csh"}, 104 | {".csproj", "text/plain"}, 105 | {".css", "text/css"}, 106 | {".csv", "text/csv"}, 107 | {".cur", "application/octet-stream"}, 108 | {".czx", "application/x-czx"}, 109 | {".cxx", "text/plain"}, 110 | {".dat", "application/octet-stream"}, 111 | {".datasource", "application/xml"}, 112 | {".dbproj", "text/plain"}, 113 | {".dcr", "application/x-director"}, 114 | {".def", "text/plain"}, 115 | {".deploy", "application/octet-stream"}, 116 | {".der", "application/x-x509-ca-cert"}, 117 | {".dgml", "application/xml"}, 118 | {".dib", "image/bmp"}, 119 | {".dif", "video/x-dv"}, 120 | {".dir", "application/x-director"}, 121 | {".disco", "text/xml"}, 122 | {".divx", "video/divx"}, 123 | {".dll", "application/x-msdownload"}, 124 | {".dll.config", "text/xml"}, 125 | {".dlm", "text/dlm"}, 126 | {".doc", "application/msword"}, 127 | {".docm", "application/vnd.ms-word.document.macroEnabled.12"}, 128 | {".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"}, 129 | {".dot", "application/msword"}, 130 | {".dotm", "application/vnd.ms-word.template.macroEnabled.12"}, 131 | {".dotx", "application/vnd.openxmlformats-officedocument.wordprocessingml.template"}, 132 | {".dsp", "application/octet-stream"}, 133 | {".dsw", "text/plain"}, 134 | {".dtd", "text/xml"}, 135 | {".dtsConfig", "text/xml"}, 136 | {".dv", "video/x-dv"}, 137 | {".dvi", "application/x-dvi"}, 138 | {".dwf", "drawing/x-dwf"}, 139 | {".dwg", "application/acad"}, 140 | {".dwp", "application/octet-stream"}, 141 | {".dxf", "application/x-dxf"}, 142 | {".dxr", "application/x-director"}, 143 | {".eml", "message/rfc822"}, 144 | {".emf", "image/emf"}, 145 | {".emz", "application/octet-stream"}, 146 | {".eot", "application/vnd.ms-fontobject"}, 147 | {".eps", "application/postscript"}, 148 | {".es", "application/ecmascript"}, 149 | {".etl", "application/etl"}, 150 | {".etx", "text/x-setext"}, 151 | {".evy", "application/envoy"}, 152 | {".exe", "application/vnd.microsoft.portable-executable"}, 153 | {".exe.config", "text/xml"}, 154 | {".f4v", "video/mp4"}, 155 | {".fdf", "application/vnd.fdf"}, 156 | {".fif", "application/fractals"}, 157 | {".filters", "application/xml"}, 158 | {".fla", "application/octet-stream"}, 159 | {".flac", "audio/flac"}, 160 | {".flr", "x-world/x-vrml"}, 161 | {".flv", "video/x-flv"}, 162 | {".fsscript", "application/fsharp-script"}, 163 | {".fsx", "application/fsharp-script"}, 164 | {".generictest", "application/xml"}, 165 | {".gif", "image/gif"}, 166 | {".gpx", "application/gpx+xml"}, 167 | {".group", "text/x-ms-group"}, 168 | {".gsm", "audio/x-gsm"}, 169 | {".gtar", "application/x-gtar"}, 170 | {".gz", "application/x-gzip"}, 171 | {".h", "text/plain"}, 172 | {".hdf", "application/x-hdf"}, 173 | {".hdml", "text/x-hdml"}, 174 | {".heic", "image/heic"}, 175 | {".heics", "image/heic-sequence"}, 176 | {".heif", "image/heif"}, 177 | {".heifs", "image/heif-sequence"}, 178 | {".hhc", "application/x-oleobject"}, 179 | {".hhk", "application/octet-stream"}, 180 | {".hhp", "application/octet-stream"}, 181 | {".hlp", "application/winhlp"}, 182 | {".hpp", "text/plain"}, 183 | {".hqx", "application/mac-binhex40"}, 184 | {".hta", "application/hta"}, 185 | {".htc", "text/x-component"}, 186 | {".htm", "text/html"}, 187 | {".html", "text/html"}, 188 | {".htt", "text/webviewhtml"}, 189 | {".hxa", "application/xml"}, 190 | {".hxc", "application/xml"}, 191 | {".hxd", "application/octet-stream"}, 192 | {".hxe", "application/xml"}, 193 | {".hxf", "application/xml"}, 194 | {".hxh", "application/octet-stream"}, 195 | {".hxi", "application/octet-stream"}, 196 | {".hxk", "application/xml"}, 197 | {".hxq", "application/octet-stream"}, 198 | {".hxr", "application/octet-stream"}, 199 | {".hxs", "application/octet-stream"}, 200 | {".hxt", "text/html"}, 201 | {".hxv", "application/xml"}, 202 | {".hxw", "application/octet-stream"}, 203 | {".hxx", "text/plain"}, 204 | {".i", "text/plain"}, 205 | {".ical", "text/calendar"}, 206 | {".icalendar", "text/calendar"}, 207 | {".ico", "image/x-icon"}, 208 | {".ics", "text/calendar"}, 209 | {".idl", "text/plain"}, 210 | {".ief", "image/ief"}, 211 | {".ifb", "text/calendar"}, 212 | {".iii", "application/x-iphone"}, 213 | {".inc", "text/plain"}, 214 | {".inf", "application/octet-stream"}, 215 | {".ini", "text/plain"}, 216 | {".inl", "text/plain"}, 217 | {".ins", "application/x-internet-signup"}, 218 | {".ipa", "application/x-itunes-ipa"}, 219 | {".ipg", "application/x-itunes-ipg"}, 220 | {".ipproj", "text/plain"}, 221 | {".ipsw", "application/x-itunes-ipsw"}, 222 | {".iqy", "text/x-ms-iqy"}, 223 | {".isp", "application/x-internet-signup"}, 224 | {".isma", "application/octet-stream"}, 225 | {".ismv", "application/octet-stream"}, 226 | {".ite", "application/x-itunes-ite"}, 227 | {".itlp", "application/x-itunes-itlp"}, 228 | {".itms", "application/x-itunes-itms"}, 229 | {".itpc", "application/x-itunes-itpc"}, 230 | {".IVF", "video/x-ivf"}, 231 | {".jar", "application/java-archive"}, 232 | {".java", "application/octet-stream"}, 233 | {".jck", "application/liquidmotion"}, 234 | {".jcz", "application/liquidmotion"}, 235 | {".jfif", "image/pjpeg"}, 236 | {".jnlp", "application/x-java-jnlp-file"}, 237 | {".jpb", "application/octet-stream"}, 238 | {".jpe", "image/jpeg"}, 239 | {".jpeg", "image/jpeg"}, 240 | {".jpg", "image/jpeg"}, 241 | {".js", "application/javascript"}, 242 | {".json", "application/json"}, 243 | {".jsx", "text/jscript"}, 244 | {".jsxbin", "text/plain"}, 245 | {".latex", "application/x-latex"}, 246 | {".library-ms", "application/windows-library+xml"}, 247 | {".lit", "application/x-ms-reader"}, 248 | {".loadtest", "application/xml"}, 249 | {".lpk", "application/octet-stream"}, 250 | {".lsf", "video/x-la-asf"}, 251 | {".lst", "text/plain"}, 252 | {".lsx", "video/x-la-asf"}, 253 | {".lzh", "application/octet-stream"}, 254 | {".m13", "application/x-msmediaview"}, 255 | {".m14", "application/x-msmediaview"}, 256 | {".m1v", "video/mpeg"}, 257 | {".m2t", "video/vnd.dlna.mpeg-tts"}, 258 | {".m2ts", "video/vnd.dlna.mpeg-tts"}, 259 | {".m2v", "video/mpeg"}, 260 | {".m3u", "audio/x-mpegurl"}, 261 | {".m3u8", "audio/x-mpegurl"}, 262 | {".m4a", "audio/m4a"}, 263 | {".m4b", "audio/m4b"}, 264 | {".m4p", "audio/m4p"}, 265 | {".m4r", "audio/x-m4r"}, 266 | {".m4v", "video/x-m4v"}, 267 | {".mac", "image/x-macpaint"}, 268 | {".mak", "text/plain"}, 269 | {".man", "application/x-troff-man"}, 270 | {".manifest", "application/x-ms-manifest"}, 271 | {".map", "text/plain"}, 272 | {".master", "application/xml"}, 273 | {".mbox", "application/mbox"}, 274 | {".mda", "application/msaccess"}, 275 | {".mdb", "application/x-msaccess"}, 276 | {".mde", "application/msaccess"}, 277 | {".mdp", "application/octet-stream"}, 278 | {".me", "application/x-troff-me"}, 279 | {".mfp", "application/x-shockwave-flash"}, 280 | {".mht", "message/rfc822"}, 281 | {".mhtml", "message/rfc822"}, 282 | {".mid", "audio/mid"}, 283 | {".midi", "audio/mid"}, 284 | {".mix", "application/octet-stream"}, 285 | {".mk", "text/plain"}, 286 | {".mk3d", "video/x-matroska-3d"}, 287 | {".mka", "audio/x-matroska"}, 288 | {".mkv", "video/x-matroska"}, 289 | {".mmf", "application/x-smaf"}, 290 | {".mno", "text/xml"}, 291 | {".mny", "application/x-msmoney"}, 292 | {".mod", "video/mpeg"}, 293 | {".mov", "video/quicktime"}, 294 | {".movie", "video/x-sgi-movie"}, 295 | {".mp2", "video/mpeg"}, 296 | {".mp2v", "video/mpeg"}, 297 | {".mp3", "audio/mpeg"}, 298 | {".mp4", "video/mp4"}, 299 | {".mp4v", "video/mp4"}, 300 | {".mpa", "video/mpeg"}, 301 | {".mpe", "video/mpeg"}, 302 | {".mpeg", "video/mpeg"}, 303 | {".mpf", "application/vnd.ms-mediapackage"}, 304 | {".mpg", "video/mpeg"}, 305 | {".mpp", "application/vnd.ms-project"}, 306 | {".mpv2", "video/mpeg"}, 307 | {".mqv", "video/quicktime"}, 308 | {".ms", "application/x-troff-ms"}, 309 | {".msg", "application/vnd.ms-outlook"}, 310 | {".msi", "application/octet-stream"}, 311 | {".mso", "application/octet-stream"}, 312 | {".mts", "video/vnd.dlna.mpeg-tts"}, 313 | {".mtx", "application/xml"}, 314 | {".mvb", "application/x-msmediaview"}, 315 | {".mvc", "application/x-miva-compiled"}, 316 | {".mxf", "application/mxf"}, 317 | {".mxp", "application/x-mmxp"}, 318 | {".nc", "application/x-netcdf"}, 319 | {".nsc", "video/x-ms-asf"}, 320 | {".nws", "message/rfc822"}, 321 | {".ocx", "application/octet-stream"}, 322 | {".oda", "application/oda"}, 323 | {".odb", "application/vnd.oasis.opendocument.database"}, 324 | {".odc", "application/vnd.oasis.opendocument.chart"}, 325 | {".odf", "application/vnd.oasis.opendocument.formula"}, 326 | {".odg", "application/vnd.oasis.opendocument.graphics"}, 327 | {".odh", "text/plain"}, 328 | {".odi", "application/vnd.oasis.opendocument.image"}, 329 | {".odl", "text/plain"}, 330 | {".odm", "application/vnd.oasis.opendocument.text-master"}, 331 | {".odp", "application/vnd.oasis.opendocument.presentation"}, 332 | {".ods", "application/vnd.oasis.opendocument.spreadsheet"}, 333 | {".odt", "application/vnd.oasis.opendocument.text"}, 334 | {".oga", "audio/ogg"}, 335 | {".ogg", "audio/ogg"}, 336 | {".ogv", "video/ogg"}, 337 | {".ogx", "application/ogg"}, 338 | {".one", "application/onenote"}, 339 | {".onea", "application/onenote"}, 340 | {".onepkg", "application/onenote"}, 341 | {".onetmp", "application/onenote"}, 342 | {".onetoc", "application/onenote"}, 343 | {".onetoc2", "application/onenote"}, 344 | {".opus", "audio/ogg"}, 345 | {".orderedtest", "application/xml"}, 346 | {".osdx", "application/opensearchdescription+xml"}, 347 | {".otf", "application/font-sfnt"}, 348 | {".otg", "application/vnd.oasis.opendocument.graphics-template"}, 349 | {".oth", "application/vnd.oasis.opendocument.text-web"}, 350 | {".otp", "application/vnd.oasis.opendocument.presentation-template"}, 351 | {".ots", "application/vnd.oasis.opendocument.spreadsheet-template"}, 352 | {".ott", "application/vnd.oasis.opendocument.text-template"}, 353 | {".oxps", "application/oxps"}, 354 | {".oxt", "application/vnd.openofficeorg.extension"}, 355 | {".p10", "application/pkcs10"}, 356 | {".p12", "application/x-pkcs12"}, 357 | {".p7b", "application/x-pkcs7-certificates"}, 358 | {".p7c", "application/pkcs7-mime"}, 359 | {".p7m", "application/pkcs7-mime"}, 360 | {".p7r", "application/x-pkcs7-certreqresp"}, 361 | {".p7s", "application/pkcs7-signature"}, 362 | {".pbm", "image/x-portable-bitmap"}, 363 | {".pcast", "application/x-podcast"}, 364 | {".pct", "image/pict"}, 365 | {".pcx", "application/octet-stream"}, 366 | {".pcz", "application/octet-stream"}, 367 | {".pdf", "application/pdf"}, 368 | {".pfb", "application/octet-stream"}, 369 | {".pfm", "application/octet-stream"}, 370 | {".pfx", "application/x-pkcs12"}, 371 | {".pgm", "image/x-portable-graymap"}, 372 | {".pic", "image/pict"}, 373 | {".pict", "image/pict"}, 374 | {".pkgdef", "text/plain"}, 375 | {".pkgundef", "text/plain"}, 376 | {".pko", "application/vnd.ms-pki.pko"}, 377 | {".pls", "audio/scpls"}, 378 | {".pma", "application/x-perfmon"}, 379 | {".pmc", "application/x-perfmon"}, 380 | {".pml", "application/x-perfmon"}, 381 | {".pmr", "application/x-perfmon"}, 382 | {".pmw", "application/x-perfmon"}, 383 | {".png", "image/png"}, 384 | {".pnm", "image/x-portable-anymap"}, 385 | {".pnt", "image/x-macpaint"}, 386 | {".pntg", "image/x-macpaint"}, 387 | {".pnz", "image/png"}, 388 | {".pot", "application/vnd.ms-powerpoint"}, 389 | {".potm", "application/vnd.ms-powerpoint.template.macroEnabled.12"}, 390 | {".potx", "application/vnd.openxmlformats-officedocument.presentationml.template"}, 391 | {".ppa", "application/vnd.ms-powerpoint"}, 392 | {".ppam", "application/vnd.ms-powerpoint.addin.macroEnabled.12"}, 393 | {".ppm", "image/x-portable-pixmap"}, 394 | {".pps", "application/vnd.ms-powerpoint"}, 395 | {".ppsm", "application/vnd.ms-powerpoint.slideshow.macroEnabled.12"}, 396 | {".ppsx", "application/vnd.openxmlformats-officedocument.presentationml.slideshow"}, 397 | {".ppt", "application/vnd.ms-powerpoint"}, 398 | {".pptm", "application/vnd.ms-powerpoint.presentation.macroEnabled.12"}, 399 | {".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"}, 400 | {".prf", "application/pics-rules"}, 401 | {".prm", "application/octet-stream"}, 402 | {".prx", "application/octet-stream"}, 403 | {".ps", "application/postscript"}, 404 | {".psc1", "application/PowerShell"}, 405 | {".psd", "application/octet-stream"}, 406 | {".psess", "application/xml"}, 407 | {".psm", "application/octet-stream"}, 408 | {".psp", "application/octet-stream"}, 409 | {".pst", "application/vnd.ms-outlook"}, 410 | {".pub", "application/x-mspublisher"}, 411 | {".pwz", "application/vnd.ms-powerpoint"}, 412 | {".qht", "text/x-html-insertion"}, 413 | {".qhtm", "text/x-html-insertion"}, 414 | {".qt", "video/quicktime"}, 415 | {".qti", "image/x-quicktime"}, 416 | {".qtif", "image/x-quicktime"}, 417 | {".qtl", "application/x-quicktimeplayer"}, 418 | {".qxd", "application/octet-stream"}, 419 | {".ra", "audio/x-pn-realaudio"}, 420 | {".ram", "audio/x-pn-realaudio"}, 421 | {".rar", "application/x-rar-compressed"}, 422 | {".ras", "image/x-cmu-raster"}, 423 | {".rat", "application/rat-file"}, 424 | {".rc", "text/plain"}, 425 | {".rc2", "text/plain"}, 426 | {".rct", "text/plain"}, 427 | {".rdlc", "application/xml"}, 428 | {".reg", "text/plain"}, 429 | {".resx", "application/xml"}, 430 | {".rf", "image/vnd.rn-realflash"}, 431 | {".rgb", "image/x-rgb"}, 432 | {".rgs", "text/plain"}, 433 | {".rm", "application/vnd.rn-realmedia"}, 434 | {".rmi", "audio/mid"}, 435 | {".rmp", "application/vnd.rn-rn_music_package"}, 436 | {".rmvb", "application/vnd.rn-realmedia-vbr"}, 437 | {".roff", "application/x-troff"}, 438 | {".rpm", "audio/x-pn-realaudio-plugin"}, 439 | {".rqy", "text/x-ms-rqy"}, 440 | {".rtf", "application/rtf"}, 441 | {".rtx", "text/richtext"}, 442 | {".rvt", "application/octet-stream"}, 443 | {".ruleset", "application/xml"}, 444 | {".s", "text/plain"}, 445 | {".safariextz", "application/x-safari-safariextz"}, 446 | {".scd", "application/x-msschedule"}, 447 | {".scr", "text/plain"}, 448 | {".sct", "text/scriptlet"}, 449 | {".sd2", "audio/x-sd2"}, 450 | {".sdp", "application/sdp"}, 451 | {".sea", "application/octet-stream"}, 452 | {".searchConnector-ms", "application/windows-search-connector+xml"}, 453 | {".setpay", "application/set-payment-initiation"}, 454 | {".setreg", "application/set-registration-initiation"}, 455 | {".settings", "application/xml"}, 456 | {".sgimb", "application/x-sgimb"}, 457 | {".sgml", "text/sgml"}, 458 | {".sh", "application/x-sh"}, 459 | {".shar", "application/x-shar"}, 460 | {".shtml", "text/html"}, 461 | {".sit", "application/x-stuffit"}, 462 | {".sitemap", "application/xml"}, 463 | {".skin", "application/xml"}, 464 | {".skp", "application/x-koan"}, 465 | {".sldm", "application/vnd.ms-powerpoint.slide.macroEnabled.12"}, 466 | {".sldx", "application/vnd.openxmlformats-officedocument.presentationml.slide"}, 467 | {".slk", "application/vnd.ms-excel"}, 468 | {".sln", "text/plain"}, 469 | {".slupkg-ms", "application/x-ms-license"}, 470 | {".smd", "audio/x-smd"}, 471 | {".smi", "application/octet-stream"}, 472 | {".smx", "audio/x-smd"}, 473 | {".smz", "audio/x-smd"}, 474 | {".snd", "audio/basic"}, 475 | {".snippet", "application/xml"}, 476 | {".snp", "application/octet-stream"}, 477 | {".sql", "application/sql"}, 478 | {".sol", "text/plain"}, 479 | {".sor", "text/plain"}, 480 | {".spc", "application/x-pkcs7-certificates"}, 481 | {".spl", "application/futuresplash"}, 482 | {".spx", "audio/ogg"}, 483 | {".src", "application/x-wais-source"}, 484 | {".srf", "text/plain"}, 485 | {".SSISDeploymentManifest", "text/xml"}, 486 | {".ssm", "application/streamingmedia"}, 487 | {".sst", "application/vnd.ms-pki.certstore"}, 488 | {".stl", "application/vnd.ms-pki.stl"}, 489 | {".sv4cpio", "application/x-sv4cpio"}, 490 | {".sv4crc", "application/x-sv4crc"}, 491 | {".svc", "application/xml"}, 492 | {".svg", "image/svg+xml"}, 493 | {".swf", "application/x-shockwave-flash"}, 494 | {".step", "application/step"}, 495 | {".stp", "application/step"}, 496 | {".t", "application/x-troff"}, 497 | {".tar", "application/x-tar"}, 498 | {".tcl", "application/x-tcl"}, 499 | {".testrunconfig", "application/xml"}, 500 | {".testsettings", "application/xml"}, 501 | {".tex", "application/x-tex"}, 502 | {".texi", "application/x-texinfo"}, 503 | {".texinfo", "application/x-texinfo"}, 504 | {".tgz", "application/x-compressed"}, 505 | {".thmx", "application/vnd.ms-officetheme"}, 506 | {".thn", "application/octet-stream"}, 507 | {".tif", "image/tiff"}, 508 | {".tiff", "image/tiff"}, 509 | {".tlh", "text/plain"}, 510 | {".tli", "text/plain"}, 511 | {".toc", "application/octet-stream"}, 512 | {".tr", "application/x-troff"}, 513 | {".trm", "application/x-msterminal"}, 514 | {".trx", "application/xml"}, 515 | {".ts", "video/vnd.dlna.mpeg-tts"}, 516 | {".tsv", "text/tab-separated-values"}, 517 | {".ttf", "application/font-sfnt"}, 518 | {".tts", "video/vnd.dlna.mpeg-tts"}, 519 | {".txt", "text/plain"}, 520 | {".u32", "application/octet-stream"}, 521 | {".uls", "text/iuls"}, 522 | {".user", "text/plain"}, 523 | {".ustar", "application/x-ustar"}, 524 | {".vb", "text/plain"}, 525 | {".vbdproj", "text/plain"}, 526 | {".vbk", "video/mpeg"}, 527 | {".vbproj", "text/plain"}, 528 | {".vbs", "text/vbscript"}, 529 | {".vcf", "text/x-vcard"}, 530 | {".vcproj", "application/xml"}, 531 | {".vcs", "text/plain"}, 532 | {".vcxproj", "application/xml"}, 533 | {".vddproj", "text/plain"}, 534 | {".vdp", "text/plain"}, 535 | {".vdproj", "text/plain"}, 536 | {".vdx", "application/vnd.ms-visio.viewer"}, 537 | {".vml", "text/xml"}, 538 | {".vscontent", "application/xml"}, 539 | {".vsct", "text/xml"}, 540 | {".vsd", "application/vnd.visio"}, 541 | {".vsi", "application/ms-vsi"}, 542 | {".vsix", "application/vsix"}, 543 | {".vsixlangpack", "text/xml"}, 544 | {".vsixmanifest", "text/xml"}, 545 | {".vsmdi", "application/xml"}, 546 | {".vspscc", "text/plain"}, 547 | {".vss", "application/vnd.visio"}, 548 | {".vsscc", "text/plain"}, 549 | {".vssettings", "text/xml"}, 550 | {".vssscc", "text/plain"}, 551 | {".vst", "application/vnd.visio"}, 552 | {".vstemplate", "text/xml"}, 553 | {".vsto", "application/x-ms-vsto"}, 554 | {".vsw", "application/vnd.visio"}, 555 | {".vsx", "application/vnd.visio"}, 556 | {".vtt", "text/vtt"}, 557 | {".vtx", "application/vnd.visio"}, 558 | {".wasm", "application/wasm"}, 559 | {".wav", "audio/wav"}, 560 | {".wave", "audio/wav"}, 561 | {".wax", "audio/x-ms-wax"}, 562 | {".wbk", "application/msword"}, 563 | {".wbmp", "image/vnd.wap.wbmp"}, 564 | {".wcm", "application/vnd.ms-works"}, 565 | {".wdb", "application/vnd.ms-works"}, 566 | {".wdp", "image/vnd.ms-photo"}, 567 | {".webarchive", "application/x-safari-webarchive"}, 568 | {".webm", "video/webm"}, 569 | {".webp", "image/webp"}, /* https://en.wikipedia.org/wiki/WebP */ 570 | {".webtest", "application/xml"}, 571 | {".wiq", "application/xml"}, 572 | {".wiz", "application/msword"}, 573 | {".wks", "application/vnd.ms-works"}, 574 | {".WLMP", "application/wlmoviemaker"}, 575 | {".wlpginstall", "application/x-wlpg-detect"}, 576 | {".wlpginstall3", "application/x-wlpg3-detect"}, 577 | {".wm", "video/x-ms-wm"}, 578 | {".wma", "audio/x-ms-wma"}, 579 | {".wmd", "application/x-ms-wmd"}, 580 | {".wmf", "application/x-msmetafile"}, 581 | {".wml", "text/vnd.wap.wml"}, 582 | {".wmlc", "application/vnd.wap.wmlc"}, 583 | {".wmls", "text/vnd.wap.wmlscript"}, 584 | {".wmlsc", "application/vnd.wap.wmlscriptc"}, 585 | {".wmp", "video/x-ms-wmp"}, 586 | {".wmv", "video/x-ms-wmv"}, 587 | {".wmx", "video/x-ms-wmx"}, 588 | {".wmz", "application/x-ms-wmz"}, 589 | {".woff", "application/font-woff"}, 590 | {".woff2", "application/font-woff2"}, 591 | {".wpl", "application/vnd.ms-wpl"}, 592 | {".wps", "application/vnd.ms-works"}, 593 | {".wri", "application/x-mswrite"}, 594 | {".wrl", "x-world/x-vrml"}, 595 | {".wrz", "x-world/x-vrml"}, 596 | {".wsc", "text/scriptlet"}, 597 | {".wsdl", "text/xml"}, 598 | {".wvx", "video/x-ms-wvx"}, 599 | {".x", "application/directx"}, 600 | {".xaf", "x-world/x-vrml"}, 601 | {".xaml", "application/xaml+xml"}, 602 | {".xap", "application/x-silverlight-app"}, 603 | {".xbap", "application/x-ms-xbap"}, 604 | {".xbm", "image/x-xbitmap"}, 605 | {".xdr", "text/plain"}, 606 | {".xht", "application/xhtml+xml"}, 607 | {".xhtml", "application/xhtml+xml"}, 608 | {".xla", "application/vnd.ms-excel"}, 609 | {".xlam", "application/vnd.ms-excel.addin.macroEnabled.12"}, 610 | {".xlc", "application/vnd.ms-excel"}, 611 | {".xld", "application/vnd.ms-excel"}, 612 | {".xlk", "application/vnd.ms-excel"}, 613 | {".xll", "application/vnd.ms-excel"}, 614 | {".xlm", "application/vnd.ms-excel"}, 615 | {".xls", "application/vnd.ms-excel"}, 616 | {".xlsb", "application/vnd.ms-excel.sheet.binary.macroEnabled.12"}, 617 | {".xlsm", "application/vnd.ms-excel.sheet.macroEnabled.12"}, 618 | {".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}, 619 | {".xlt", "application/vnd.ms-excel"}, 620 | {".xltm", "application/vnd.ms-excel.template.macroEnabled.12"}, 621 | {".xltx", "application/vnd.openxmlformats-officedocument.spreadsheetml.template"}, 622 | {".xlw", "application/vnd.ms-excel"}, 623 | {".xml", "text/xml"}, 624 | {".xmp", "application/octet-stream"}, 625 | {".xmta", "application/xml"}, 626 | {".xof", "x-world/x-vrml"}, 627 | {".XOML", "text/plain"}, 628 | {".xpm", "image/x-xpixmap"}, 629 | {".xps", "application/vnd.ms-xpsdocument"}, 630 | {".xrm-ms", "text/xml"}, 631 | {".xsc", "application/xml"}, 632 | {".xsd", "text/xml"}, 633 | {".xsf", "text/xml"}, 634 | {".xsl", "text/xml"}, 635 | {".xslt", "text/xml"}, 636 | {".xsn", "application/octet-stream"}, 637 | {".xss", "application/xml"}, 638 | {".xspf", "application/xspf+xml"}, 639 | {".xtp", "application/octet-stream"}, 640 | {".xwd", "image/x-xwindowdump"}, 641 | {".z", "application/x-compress"}, 642 | {".zip", "application/zip"}, 643 | }; -------------------------------------------------------------------------------- /webview/include/core/windows/window.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #if defined(_WIN32) 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | 11 | namespace Webview 12 | { 13 | class Window : public BaseWindow 14 | { 15 | static constexpr auto WM_CALL = WM_USER + 2; 16 | HINSTANCE instance = nullptr; 17 | HWND hwnd = nullptr; 18 | 19 | std::vector> runOnControllerCreated; 20 | wil::com_ptr webViewController; 21 | wil::com_ptr webViewWindow; 22 | 23 | static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 24 | 25 | #if defined(WEBVIEW_EMBEDDED) 26 | HRESULT onWebResourceRequested(ICoreWebView2 *, ICoreWebView2WebResourceRequestedEventArgs *); 27 | #endif 28 | 29 | HRESULT onNavigationCompleted(ICoreWebView2 *, ICoreWebView2NavigationCompletedEventArgs *); 30 | HRESULT onMessageReceived(ICoreWebView2 *, ICoreWebView2WebMessageReceivedEventArgs *); 31 | HRESULT onControllerCreated(ICoreWebView2Controller *); 32 | HRESULT createEnvironment(const std::string &); 33 | 34 | private: 35 | std::wstring widen(const std::string &); 36 | std::string narrow(const std::wstring &); 37 | void dispatchMessage(std::function); 38 | void onResize(std::size_t width, std::size_t height) override; 39 | 40 | public: 41 | Window(std::string identifier, std::size_t width, std::size_t height); 42 | void disableAcceleratorKeys(bool); 43 | 44 | void hide() override; 45 | void show() override; 46 | 47 | void run() override; 48 | void exit() override; 49 | 50 | std::string getUrl() override; 51 | void setUrl(std::string newUrl) override; 52 | void setTitle(std::string newTitle) override; 53 | void setSize(std::size_t newWidth, std::size_t newHeight) override; 54 | 55 | void enableDevTools(bool state) override; 56 | void enableContextMenu(bool state) override; 57 | void runCode(const std::string &code) override; 58 | void injectCode(const std::string &code) override; 59 | }; 60 | } // namespace Webview 61 | #endif -------------------------------------------------------------------------------- /webview/include/javascript/call.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | namespace Webview 7 | { 8 | struct FunctionCallRequest 9 | { 10 | std::uint32_t seq; 11 | std::string function; 12 | nlohmann::json params; 13 | }; 14 | 15 | struct NativeCallResponse 16 | { 17 | std::uint32_t seq; 18 | nlohmann::json result; 19 | }; 20 | } // namespace Webview -------------------------------------------------------------------------------- /webview/include/javascript/function.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | namespace Webview 12 | { 13 | class Promise; 14 | class BaseWindow; 15 | 16 | class Function 17 | { 18 | protected: 19 | std::string name; 20 | std::function parserFunction; 21 | 22 | public: 23 | Function() = default; 24 | virtual ~Function() = default; 25 | template Function(std::string name, const func_t &function) : name(std::move(name)) 26 | { 27 | using func_traits = Traits::func_traits; 28 | using rtn_t = typename func_traits::return_t; 29 | using arg_t = typename func_traits::arg_t; 30 | 31 | // NOLINTNEXTLINE 32 | parserFunction = [this, function](const nlohmann::json &j) -> nlohmann::json { 33 | arg_t packedArgs; 34 | Helpers::setTuple(packedArgs, [&j](auto index, auto &val) { 35 | if (j.size() > index) 36 | { 37 | if (!j.at(index).is_null()) 38 | { 39 | if constexpr (Traits::is_optional>::value || 40 | Traits::is_shared_ptr>::value) 41 | { 42 | val = 43 | j.at(index) 44 | .template get::value_type>>(); 45 | } 46 | else 47 | { 48 | j.at(index).get_to(val); 49 | } 50 | } 51 | } 52 | }); 53 | 54 | if constexpr (std::is_void_v) 55 | { 56 | //* If the function return type is void we just need to call it and ignore the return type 57 | auto unpack = [function](auto &&...args) { function(args...); }; 58 | std::apply(unpack, packedArgs); 59 | } 60 | else 61 | { 62 | //* In case the return type is nothing special, we just want to save the return value of the 63 | //* function to rtn and then convert rtn to json 64 | 65 | rtn_t rtn; 66 | 67 | auto unpack = [&rtn, function](auto &&...args) { rtn = std::move(function(args...)); }; 68 | std::apply(unpack, packedArgs); 69 | 70 | if constexpr (Traits::is_optional::value || Traits::is_shared_ptr::value) 71 | { 72 | //* Just to make sure this wont break with optionals 73 | if (rtn) 74 | { 75 | return nlohmann::json(*rtn); 76 | } 77 | } 78 | else 79 | { 80 | return nlohmann::json(rtn); 81 | } 82 | } 83 | 84 | return nullptr; 85 | }; 86 | } 87 | 88 | std::string getName() const; 89 | std::function getFunc() const; 90 | }; 91 | 92 | class AsyncFunction : public Function 93 | { 94 | protected: 95 | std::function parserFunction; 96 | 97 | public: 98 | template AsyncFunction(std::string name, const func_t &function) : Function() 99 | { 100 | this->name = std::move(name); 101 | 102 | using func_traits = Traits::func_traits; 103 | using rtn_t = typename func_traits::return_t; 104 | using arg_t = typename func_traits::arg_t; 105 | 106 | static_assert(std::is_same_v); 107 | static_assert(std::is_same_v(std::declval()))>, Promise>); 108 | 109 | // NOLINTNEXTLINE 110 | parserFunction = [this, function](BaseWindow &parent, const nlohmann::json &j, std::uint32_t seq) { 111 | //* Return type is always void 112 | Traits::ignore_first packedArgs; 113 | Helpers::setTuple(packedArgs, [&j](auto index, auto &val) { 114 | if (j.size() > index) 115 | { 116 | j.at(index).get_to(val); 117 | } 118 | }); 119 | 120 | auto unpack = [&parent, function, seq](auto &&...args) { function(Promise(parent, seq), args...); }; 121 | std::apply(unpack, packedArgs); 122 | }; 123 | } 124 | 125 | ~AsyncFunction() override = default; 126 | std::function getFunc() const; 127 | }; 128 | 129 | class JavaScriptFunction 130 | { 131 | 132 | std::string name; 133 | 134 | std::mutex resultMutex; 135 | std::promise result; 136 | 137 | std::mutex argumentsMutex; 138 | std::vector arguments; 139 | 140 | public: 141 | template JavaScriptFunction(std::string name, const T &...params) : name(std::move(name)) 142 | { 143 | std::lock_guard guard(argumentsMutex); 144 | auto unpack = [this](auto &&arg) { arguments.emplace_back(nlohmann::json(arg)); }; 145 | (unpack(params), ...); 146 | } 147 | JavaScriptFunction(JavaScriptFunction &); 148 | 149 | std::string getName() const; 150 | std::vector getArguments() const; 151 | 152 | void resolve(const nlohmann::json &); 153 | std::shared_future getResult(); 154 | }; 155 | } // namespace Webview -------------------------------------------------------------------------------- /webview/include/javascript/promise.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | namespace Webview 7 | { 8 | class BaseWindow; 9 | class Promise 10 | { 11 | std::uint32_t id; 12 | BaseWindow &parent; 13 | 14 | public: 15 | Promise(BaseWindow &parent, std::uint32_t id); 16 | 17 | void discard() const; 18 | void resolve(const nlohmann::json &) const; 19 | 20 | template void resolve(const std::optional &result) 21 | { 22 | if (result) 23 | { 24 | resolve(*result); 25 | } 26 | else 27 | { 28 | discard(); 29 | } 30 | } 31 | }; 32 | } // namespace Webview -------------------------------------------------------------------------------- /webview/include/json/bindings.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | namespace nlohmann 6 | { 7 | template <> struct adl_serializer 8 | { 9 | static void to_json(json &j, const Webview::FunctionCallRequest &obj) 10 | { 11 | j = {{"function", obj.function}, {"params", obj.params}, {"seq", obj.seq}}; 12 | } 13 | static void from_json(const json &j, Webview::FunctionCallRequest &obj) 14 | { 15 | j.at("seq").get_to(obj.seq); 16 | j.at("params").get_to(obj.params); 17 | j.at("function").get_to(obj.function); 18 | } 19 | }; 20 | 21 | template <> struct adl_serializer 22 | { 23 | static void to_json(json &j, const Webview::NativeCallResponse &obj) 24 | { 25 | j = {{"result", obj.result}, {"seq", obj.seq}}; 26 | } 27 | static void from_json(const json &j, Webview::NativeCallResponse &obj) 28 | { 29 | j.at("seq").get_to(obj.seq); 30 | j.at("result").get_to(obj.result); 31 | } 32 | }; 33 | } // namespace nlohmann -------------------------------------------------------------------------------- /webview/include/misc/helpers.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | 6 | namespace Webview 7 | { 8 | namespace Helpers 9 | { 10 | template = 0)> * = nullptr> 11 | void setTupleImpl(Tuple &tuple, Function func) 12 | { 13 | if constexpr (I >= 0) 14 | { 15 | func(I, std::get(tuple)); 16 | if constexpr (I > 0) 17 | { 18 | setTupleImpl(tuple, func); 19 | } 20 | } 21 | } 22 | template void setTuple(Tuple &tuple, Function func) 23 | { 24 | constexpr int size = std::tuple_size_v - 1; 25 | if constexpr (size >= 0) 26 | { 27 | setTupleImpl(tuple, func); 28 | } 29 | } 30 | } // namespace Helpers 31 | } // namespace Webview -------------------------------------------------------------------------------- /webview/include/misc/traits.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | namespace Webview 8 | { 9 | namespace Traits 10 | { 11 | template struct func_traits : public func_traits 12 | { 13 | }; 14 | template 15 | struct func_traits 16 | { 17 | enum 18 | { 19 | arg_count = sizeof...(Args) 20 | }; 21 | using arg_t = std::tuple...>; 22 | using return_t = ReturnType; 23 | }; 24 | template struct is_optional 25 | { 26 | private: 27 | static std::uint8_t test(...); 28 | template static auto test(std::optional *) -> std::uint16_t; 29 | 30 | public: 31 | static const bool value = sizeof(test(reinterpret_cast(0))) == sizeof(std::uint16_t); 32 | }; 33 | template struct is_shared_ptr 34 | { 35 | private: 36 | static std::uint8_t test(...); 37 | template static auto test(std::shared_ptr *) -> std::uint16_t; 38 | 39 | public: 40 | static const bool value = sizeof(test(reinterpret_cast(0))) == sizeof(std::uint16_t); 41 | }; 42 | 43 | template struct has_type; 44 | template struct has_type> : std::false_type 45 | { 46 | }; 47 | template 48 | struct has_type> : has_type> 49 | { 50 | }; 51 | template struct has_type> : std::true_type 52 | { 53 | }; 54 | 55 | template 56 | constexpr auto ignoreFirstImpl([[maybe_unused]] const std::tuple &tuple) 57 | { 58 | return std::tuple(); 59 | } 60 | template using ignore_first = decltype(ignoreFirstImpl(std::declval())); 61 | } // namespace Traits 62 | } // namespace Webview -------------------------------------------------------------------------------- /webview/include/webview.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if defined(__linux__) 4 | #include 5 | #elif defined(_WIN32) 6 | #include 7 | #endif -------------------------------------------------------------------------------- /webview/src/core/basewindow.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | const std::string Webview::BaseWindow::callbackFunctionDefinition = R"js( 9 | async function {0}(...param) 10 | { 11 | const seq = ++window._rpc_seq; 12 | const promise = new Promise((resolve) => { 13 | window._rpc[seq] = { 14 | resolve: resolve 15 | }; 16 | }); 17 | window.external.invoke(JSON.stringify({ 18 | "seq": seq, 19 | "params": param, 20 | "function": "{0}" 21 | })); 22 | return JSON.parse(await promise); 23 | } 24 | )js"; 25 | const std::string Webview::BaseWindow::setupRpc = "window._rpc = {}; window._rpc_seq = 0;"; 26 | const std::string Webview::BaseWindow::resolveCall = R"js( 27 | window._rpc[{0}].resolve(`{1}`); 28 | delete window._rpc[{0}]; 29 | )js"; 30 | const std::string Webview::BaseWindow::resolveNativeCall = R"js( 31 | window.external.invoke(JSON.stringify({ 32 | "seq": {0}, 33 | "result": {1} ? {1} : null 34 | })); 35 | )js"; 36 | 37 | Webview::BaseWindow::BaseWindow(std::string identifier, std::size_t width, std::size_t height) 38 | : width(width), height(height), identifier(std::move(identifier)) 39 | { 40 | } 41 | 42 | bool Webview::BaseWindow::onClose() 43 | { 44 | if (closeCallback) 45 | { 46 | return closeCallback(); 47 | } 48 | return false; 49 | } 50 | 51 | void Webview::BaseWindow::onResize(std::size_t newWidth, std ::size_t newHeight) 52 | { 53 | if (resizeCallback) 54 | { 55 | resizeCallback(newWidth, newHeight); 56 | } 57 | } 58 | 59 | void Webview::BaseWindow::onNavigate(std::string newUrl) 60 | { 61 | url = std::move(newUrl); 62 | 63 | if (navigateCallback) 64 | { 65 | navigateCallback(url); 66 | } 67 | } 68 | 69 | void Webview::BaseWindow::handleRawCallRequest(const std::string &rawRequest) 70 | { 71 | auto parsed = nlohmann::json::parse(rawRequest, nullptr, false); 72 | if (!parsed.is_discarded()) 73 | { 74 | if (parsed.find("result") != parsed.end()) 75 | { 76 | std::lock_guard lock(nativeCallRequestsMutex); 77 | auto request = parsed.get(); 78 | if (nativeCallRequests.find(request.seq) != nativeCallRequests.end()) 79 | { 80 | auto &function = nativeCallRequests.at(request.seq); 81 | function.resolve(request.result); 82 | nativeCallRequests.erase(request.seq); 83 | } 84 | } 85 | else 86 | { 87 | std::lock_guard lock(functionsMutex); 88 | auto request = parsed.get(); 89 | const auto &function = functions.at(request.function); 90 | 91 | if (const auto *asyncFunction = dynamic_cast(function.get()); asyncFunction) 92 | { 93 | auto future = std::make_shared>(); 94 | *future = std::async(std::launch::async, [future, request, asyncFunction, this]() { 95 | asyncFunction->getFunc()(*this, request.params, request.seq); 96 | }); 97 | } 98 | else 99 | { 100 | const auto &result = function->getFunc()(request.params); 101 | 102 | auto responseCode = 103 | std::regex_replace(resolveCall, std::regex(R"(\{0\})"), std::to_string(request.seq)); 104 | responseCode = std::regex_replace(responseCode, std::regex(R"(\{1\})"), result.dump()); 105 | runCode(responseCode); 106 | } 107 | } 108 | } 109 | } 110 | 111 | void Webview::BaseWindow::hide() 112 | { 113 | hidden = true; 114 | } 115 | 116 | void Webview::BaseWindow::show() 117 | { 118 | hidden = false; 119 | } 120 | 121 | bool Webview::BaseWindow::isHidden() 122 | { 123 | return hidden; 124 | } 125 | 126 | void Webview::BaseWindow::setSize(std::size_t newWidth, std::size_t newHeight) 127 | { 128 | width = newWidth; 129 | height = newHeight; 130 | } 131 | 132 | std::pair Webview::BaseWindow::getSize() 133 | { 134 | return std::make_pair(width, height); 135 | } 136 | 137 | std::string Webview::BaseWindow::getTitle() 138 | { 139 | return title; 140 | } 141 | 142 | void Webview::BaseWindow::setTitle(std::string newTitle) 143 | { 144 | title = std::move(newTitle); 145 | } 146 | 147 | std::string Webview::BaseWindow::getUrl() 148 | { 149 | return url; 150 | } 151 | 152 | void Webview::BaseWindow::setUrl(std::string newUrl) 153 | { 154 | url = std::move(newUrl); 155 | } 156 | 157 | void Webview::BaseWindow::setCloseCallback(std::function callback) 158 | { 159 | closeCallback = std::move(callback); 160 | } 161 | 162 | void Webview::BaseWindow::setNavigateCallback(std::function callback) 163 | { 164 | navigateCallback = std::move(callback); 165 | } 166 | 167 | void Webview::BaseWindow::setResizeCallback(std::function callback) 168 | { 169 | resizeCallback = std::move(callback); 170 | } 171 | 172 | void Webview::BaseWindow::expose(const Function &function) 173 | { 174 | std::shared_ptr ptr; 175 | 176 | try 177 | { 178 | const auto &asyncFunction = dynamic_cast(function); 179 | ptr = std::make_shared(asyncFunction); 180 | } 181 | catch ([[maybe_unused]] const std::exception &e) 182 | { 183 | ptr = std::make_shared(function); 184 | } 185 | 186 | std::lock_guard lock(functionsMutex); 187 | functions.emplace(function.getName(), ptr); 188 | injectCode(std::regex_replace(callbackFunctionDefinition, std::regex(R"(\{0\})"), function.getName())); 189 | } 190 | 191 | std::string Webview::BaseWindow::formatCode(const std::string &code) 192 | { 193 | auto formattedCode = std::regex_replace(code, std::regex(R"rgx(\\")rgx"), R"(\\\")"); 194 | formattedCode = std::regex_replace(formattedCode, std::regex(R"rgx(\\n)rgx"), R"(\\n)"); 195 | formattedCode = std::regex_replace(formattedCode, std::regex(R"rgx(\\t)rgx"), R"(\\t)"); 196 | 197 | return formattedCode; 198 | } 199 | 200 | #if defined(WEBVIEW_EMBEDDED) 201 | Webview::Resource Webview::BaseWindow::getResource(const std::string &resource) 202 | { 203 | if (Embedded::files.find(resource) != Embedded::files.end()) 204 | { 205 | return Embedded::files.at(resource); 206 | } 207 | 208 | throw std::runtime_error("Failed to find requested resource"); 209 | } 210 | #endif 211 | 212 | void Webview::BaseWindow::enableContextMenu(bool state) 213 | { 214 | isContextMenuAllowed = state; 215 | } 216 | 217 | Webview::JavaScriptFunction &Webview::BaseWindow::callFunctionInternal(Webview::JavaScriptFunction &&function) 218 | { 219 | static std::atomic seq = 0; 220 | auto sequence = ++seq; 221 | 222 | auto call = function.getName() + "("; 223 | for (const auto &argument : function.getArguments()) 224 | { 225 | call += argument.dump() + ","; 226 | } 227 | if (!function.getArguments().empty()) 228 | { 229 | call.back() = ')'; 230 | } 231 | else 232 | { 233 | call += ")"; 234 | } 235 | 236 | auto code = std::regex_replace(resolveNativeCall, std::regex(R"(\{0\})"), std::to_string(sequence)); 237 | code = std::regex_replace(code, std::regex(R"(\{1\})"), call); 238 | runCode(code); 239 | 240 | std::lock_guard lock(nativeCallRequestsMutex); 241 | return nativeCallRequests.emplace(sequence, function).first->second; 242 | } -------------------------------------------------------------------------------- /webview/src/core/linux/window.cpp: -------------------------------------------------------------------------------- 1 | #if defined(__linux__) 2 | #include 3 | #include 4 | 5 | Webview::Window::Window(std::size_t width, std::size_t height) : BaseWindow("", width, height) 6 | { 7 | if (gtk_init_check(nullptr, nullptr) == 0) 8 | { 9 | throw std::runtime_error("Gtk init check failed"); 10 | } 11 | 12 | window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 13 | gtk_window_set_resizable(reinterpret_cast(window), true); 14 | gtk_window_set_default_size(reinterpret_cast(window), static_cast(width), 15 | static_cast(height)); 16 | gtk_window_set_position(reinterpret_cast(window), GTK_WIN_POS_CENTER); 17 | 18 | GtkWidget *scrollView = gtk_scrolled_window_new(nullptr, nullptr); 19 | gtk_container_add(reinterpret_cast(window), scrollView); 20 | 21 | WebKitUserContentManager *contentManager = webkit_user_content_manager_new(); 22 | webkit_user_content_manager_register_script_message_handler(contentManager, "external"); 23 | 24 | webview = webkit_web_view_new_with_user_content_manager(contentManager); 25 | gtk_container_add(reinterpret_cast(scrollView), webview); 26 | 27 | g_signal_connect(window, "destroy", reinterpret_cast(destroy), this); 28 | g_signal_connect(window, "delete_event", reinterpret_cast(closed), this); 29 | g_signal_connect(window, "configure-event", reinterpret_cast(resize), this); 30 | 31 | #if defined(WEBVIEW_EMBEDDED) 32 | webkit_web_context_register_uri_scheme(webkit_web_context_get_default(), "embedded", onUriRequested, this, nullptr); 33 | #endif 34 | 35 | g_signal_connect(contentManager, "script-message-received::external", reinterpret_cast(messageReceived), 36 | this); 37 | g_signal_connect(reinterpret_cast(webview), "load-changed", reinterpret_cast(loadChanged), 38 | this); 39 | g_signal_connect(reinterpret_cast(webview), "context-menu", reinterpret_cast(contextMenu), 40 | this); 41 | 42 | injectCode("window.external={invoke:arg=>window.webkit." 43 | "messageHandlers.external.postMessage(arg)};"); 44 | injectCode(setupRpc); 45 | 46 | gtk_widget_grab_focus(webview); 47 | gtk_widget_show_all(scrollView); 48 | } 49 | 50 | Webview::Window::Window([[maybe_unused]] const std::string &identifier, std::size_t width, std::size_t height) 51 | : Window(width, height) 52 | { 53 | } 54 | 55 | void Webview::Window::show() 56 | { 57 | BaseWindow::show(); 58 | gtk_widget_grab_focus(window); 59 | gtk_widget_show(window); 60 | } 61 | 62 | void Webview::Window::hide() 63 | { 64 | BaseWindow::hide(); 65 | gtk_widget_hide(window); 66 | } 67 | 68 | void Webview::Window::run() 69 | { 70 | while (window) 71 | { 72 | gtk_main_iteration_do(true); 73 | } 74 | } 75 | 76 | void Webview::Window::exit() 77 | { 78 | gtk_widget_destroy(window); 79 | } 80 | 81 | void Webview::Window::setUrl(std::string newUrl) 82 | { 83 | BaseWindow::setUrl(newUrl); 84 | webkit_web_view_load_uri(reinterpret_cast(webview), url.c_str()); 85 | } 86 | 87 | void Webview::Window::setTitle(std::string newTitle) 88 | { 89 | BaseWindow::setTitle(newTitle); 90 | gtk_window_set_title(reinterpret_cast(window), title.c_str()); 91 | } 92 | 93 | void Webview::Window::setSize(std::size_t newWidth, std::size_t newHeight) 94 | { 95 | BaseWindow::setSize(newWidth, newHeight); 96 | gtk_window_resize(reinterpret_cast(window), static_cast(width), static_cast(height)); 97 | } 98 | 99 | void Webview::Window::enableDevTools(bool state) 100 | { 101 | WebKitSettings *settings = webkit_web_view_get_settings(reinterpret_cast(webview)); // NOLINT 102 | webkit_settings_set_enable_write_console_messages_to_stdout(settings, state); 103 | webkit_settings_set_enable_developer_extras(settings, state); 104 | } 105 | 106 | void Webview::Window::runOnIdle(std::function func) 107 | { 108 | auto *funcPtr = new std::function(std::move(func)); 109 | 110 | g_idle_add( 111 | [](gpointer data) -> gboolean { 112 | auto *func = reinterpret_cast *>(data); 113 | (*func)(); 114 | 115 | delete func; 116 | return FALSE; 117 | }, 118 | funcPtr); 119 | } 120 | 121 | void Webview::Window::runCode(const std::string &code) 122 | { 123 | runOnIdle([this, code] { 124 | webkit_web_view_run_javascript(reinterpret_cast(webview), formatCode(code).c_str(), nullptr, 125 | nullptr, nullptr); 126 | }); 127 | } 128 | 129 | void Webview::Window::injectCode(const std::string &code) 130 | { 131 | auto *manager = webkit_web_view_get_user_content_manager(reinterpret_cast(webview)); 132 | webkit_user_content_manager_add_script( 133 | manager, webkit_user_script_new(formatCode(code).c_str(), WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES, 134 | WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_START, nullptr, nullptr)); 135 | } 136 | 137 | gboolean Webview::Window::contextMenu([[maybe_unused]] WebKitWebView *webkitwebview, [[maybe_unused]] GtkWidget *widget, 138 | [[maybe_unused]] WebKitHitTestResultContext *result, 139 | [[maybe_unused]] gboolean with_keyboard, gpointer arg) 140 | { 141 | auto *webview = reinterpret_cast(arg); 142 | if (webview->isContextMenuAllowed) 143 | { 144 | return 0; 145 | } 146 | return 1; 147 | } 148 | 149 | void Webview::Window::destroy([[maybe_unused]] GtkWidget *widget, gpointer arg) 150 | { 151 | auto *webview = reinterpret_cast(arg); 152 | webview->window = nullptr; 153 | } 154 | 155 | void Webview::Window::loadChanged(WebKitWebView *webkitwebview, [[maybe_unused]] WebKitLoadEvent event, 156 | [[maybe_unused]] gpointer arg) 157 | { 158 | if (event == WEBKIT_LOAD_FINISHED) 159 | { 160 | auto *webview = reinterpret_cast(arg); 161 | webview->onNavigate(webkit_web_view_get_uri(webkitwebview)); 162 | } 163 | } 164 | 165 | gboolean Webview::Window::resize([[maybe_unused]] WebKitWebView *webkitwebview, GdkEvent *event, gpointer arg) 166 | { 167 | auto *gtkEvent = reinterpret_cast(event); 168 | auto *webview = reinterpret_cast(arg); 169 | 170 | webview->onResize(gtkEvent->width, gtkEvent->height); 171 | return 0; 172 | } 173 | 174 | gboolean Webview::Window::closed([[maybe_unused]] GtkWidget *widget, [[maybe_unused]] GdkEvent *event, gpointer data) 175 | { 176 | auto *webview = reinterpret_cast(data); 177 | 178 | if (webview->onClose()) 179 | { 180 | return TRUE; 181 | } 182 | 183 | return FALSE; 184 | } 185 | 186 | void Webview::Window::messageReceived([[maybe_unused]] WebKitUserContentManager *contentManager, 187 | WebKitJavascriptResult *result, gpointer arg) 188 | { 189 | auto *webview = reinterpret_cast(arg); 190 | 191 | auto *value = webkit_javascript_result_get_js_value(result); 192 | webview->handleRawCallRequest(jsc_value_to_string(value)); 193 | } 194 | 195 | std::string Webview::Window::getUrl() 196 | { 197 | return webkit_web_view_get_uri(reinterpret_cast(webview)); 198 | } 199 | 200 | #if defined(WEBVIEW_EMBEDDED) 201 | void Webview::Window::onUriRequested(WebKitURISchemeRequest *request, [[maybe_unused]] gpointer userData) 202 | { 203 | auto *webview = reinterpret_cast(userData); 204 | GInputStream *stream = nullptr; 205 | 206 | std::string uri = webkit_uri_scheme_request_get_uri(request); 207 | if (uri.size() > 11) 208 | { 209 | uri = uri.substr(11); 210 | auto fileName = uri.substr(uri.find_last_of('/') + 1); 211 | auto resourceData = webview->getResource(fileName); 212 | 213 | if (resourceData.data) 214 | { 215 | stream = 216 | g_memory_input_stream_new_from_data(resourceData.data, static_cast(resourceData.size), g_free); 217 | webkit_uri_scheme_request_finish(request, stream, static_cast(resourceData.size), nullptr); 218 | } 219 | } 220 | } 221 | #endif 222 | #endif -------------------------------------------------------------------------------- /webview/src/core/windows/window.cpp: -------------------------------------------------------------------------------- 1 | #if defined(_WIN32) 2 | #include 3 | #include 4 | #include 5 | 6 | #if defined(WEBVIEWPP_WINDOWS_8) 7 | #include 8 | #endif 9 | 10 | #if defined(WEBVIEW_EMBEDDED) 11 | #include 12 | #include 13 | #endif 14 | 15 | Webview::Window::Window(std::string identifier, std::size_t width, std::size_t height) 16 | : BaseWindow(std::move(identifier), width, height), instance(GetModuleHandle(nullptr)) 17 | { 18 | if (!instance) 19 | { 20 | throw std::runtime_error("GetModuleHandle returned nullptr"); 21 | } 22 | 23 | WNDCLASSEX wndClass; 24 | wndClass.style = 0; 25 | wndClass.cbClsExtra = 0; 26 | wndClass.cbWndExtra = 0; 27 | wndClass.hInstance = instance; 28 | wndClass.lpfnWndProc = WndProc; 29 | wndClass.lpszMenuName = nullptr; 30 | wndClass.cbSize = sizeof(WNDCLASSEX); 31 | wndClass.lpszClassName = this->identifier.c_str(); 32 | wndClass.hCursor = LoadCursor(nullptr, IDC_ARROW); // NOLINT 33 | wndClass.hIcon = LoadIcon(nullptr, IDI_APPLICATION); // NOLINT 34 | wndClass.hIconSm = LoadIcon(nullptr, IDI_APPLICATION); // NOLINT 35 | wndClass.hbrBackground = reinterpret_cast(COLOR_WINDOW + 1); 36 | 37 | if (!RegisterClassEx(&wndClass)) 38 | { 39 | throw std::runtime_error("Failed to register class"); 40 | } 41 | 42 | hwnd = CreateWindow(this->identifier.c_str(), nullptr, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, width, 43 | height, nullptr, nullptr, instance, nullptr); 44 | if (!hwnd) 45 | { 46 | throw std::runtime_error("Failed to create window"); 47 | } 48 | 49 | #if defined(WEBVIEWPP_WINDOWS_8) 50 | 51 | SetProcessDpiAwareness(PROCESS_SYSTEM_DPI_AWARE); // NOLINT 52 | #else 53 | SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE); // NOLINT 54 | #endif 55 | 56 | RECT rect; 57 | GetWindowRect(hwnd, &rect); 58 | auto x = (GetSystemMetrics(SM_CXSCREEN) - width) / 2; 59 | auto y = (GetSystemMetrics(SM_CYSCREEN) - height) / 2; 60 | SetWindowPos(hwnd, nullptr, x, y, width, height, 0); 61 | 62 | SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast(this)); 63 | ShowWindow(hwnd, SW_SHOWDEFAULT); 64 | UpdateWindow(hwnd); 65 | SetFocus(hwnd); 66 | 67 | char *buffer = nullptr; 68 | std::size_t bufferLength = 0; 69 | _dupenv_s(&buffer, &bufferLength, "LOCALAPPDATA"); 70 | 71 | std::string appdata(buffer, bufferLength); 72 | appdata += "\\MicrosoftEdge"; 73 | 74 | if (FAILED(createEnvironment(appdata))) 75 | { 76 | throw std::runtime_error("Failed to create environment"); 77 | } 78 | } 79 | 80 | LRESULT CALLBACK Webview::Window::Window::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 81 | { 82 | auto *webview = reinterpret_cast(GetWindowLongPtr(hwnd, GWLP_USERDATA)); 83 | 84 | if (webview) 85 | { 86 | switch (msg) 87 | { 88 | case WM_SIZE: 89 | webview->onResize(LOWORD(lParam), HIWORD(lParam)); 90 | break; 91 | case WM_CLOSE: 92 | if (webview) 93 | { 94 | if (webview->onClose()) 95 | { 96 | return 0; 97 | } 98 | 99 | DestroyWindow(webview->hwnd); 100 | webview->hwnd = nullptr; 101 | } 102 | break; 103 | case WM_QUIT: 104 | webview->onClose(); 105 | DestroyWindow(hwnd); 106 | break; 107 | case WM_CALL: { 108 | auto *func = reinterpret_cast *>(wParam); 109 | (*func)(); 110 | delete func; 111 | } 112 | break; 113 | default: 114 | return DefWindowProc(hwnd, msg, wParam, lParam); 115 | } 116 | } 117 | else 118 | { 119 | return DefWindowProc(hwnd, msg, wParam, lParam); 120 | } 121 | 122 | return 0; 123 | } 124 | 125 | HRESULT Webview::Window::Window::createEnvironment(const std::string &appdata) 126 | { 127 | return CreateCoreWebView2EnvironmentWithOptions( 128 | nullptr, widen(appdata).c_str(), nullptr, 129 | Microsoft::WRL::Callback( 130 | [this](auto res, ICoreWebView2Environment *env) -> HRESULT { 131 | if (FAILED(res)) 132 | { 133 | return res; 134 | } 135 | 136 | return env->CreateCoreWebView2Controller( 137 | hwnd, Microsoft::WRL::Callback( 138 | [&](auto result, ICoreWebView2Controller *controller) { 139 | if (FAILED(result)) 140 | { 141 | return result; 142 | } 143 | return onControllerCreated(controller); 144 | }) 145 | .Get()); 146 | }) 147 | .Get()); 148 | } 149 | 150 | HRESULT Webview::Window::Window::onControllerCreated(ICoreWebView2Controller *controller) 151 | { 152 | if (!controller) 153 | { 154 | throw std::runtime_error("Failed to create controller"); 155 | } 156 | 157 | webViewController = controller; 158 | webViewController->get_CoreWebView2(&webViewWindow); 159 | 160 | EventRegistrationToken navigationCompleted; 161 | webViewWindow->add_NavigationCompleted( 162 | Microsoft::WRL::Callback([this](auto *sender, auto *args) { 163 | return onNavigationCompleted(sender, args); 164 | }).Get(), 165 | &navigationCompleted); 166 | 167 | #if defined(WEBVIEW_EMBEDDED) 168 | webViewWindow->AddWebResourceRequestedFilter(L"*", COREWEBVIEW2_WEB_RESOURCE_CONTEXT_ALL); 169 | EventRegistrationToken webResourceRequested; 170 | webViewWindow->add_WebResourceRequested( 171 | Microsoft::WRL::Callback([=](auto *sender, auto *args) { 172 | return onWebResourceRequested(sender, args); 173 | }).Get(), 174 | &webResourceRequested); 175 | #endif 176 | 177 | EventRegistrationToken messageReceived; 178 | webViewWindow->add_WebMessageReceived( 179 | Microsoft::WRL::Callback([=](auto *sender, auto *args) { 180 | return onMessageReceived(sender, args); 181 | }).Get(), 182 | &messageReceived); 183 | 184 | injectCode("window.external.invoke=arg=>window.chrome.webview.postMessage(arg);"); 185 | injectCode(setupRpc); 186 | 187 | for (const auto &func : runOnControllerCreated) 188 | { 189 | func(); 190 | } 191 | runOnControllerCreated.clear(); 192 | 193 | return S_OK; 194 | } 195 | 196 | HRESULT Webview::Window::Window::onMessageReceived([[maybe_unused]] ICoreWebView2 *sender, 197 | ICoreWebView2WebMessageReceivedEventArgs *args) 198 | { 199 | LPWSTR raw = nullptr; 200 | args->TryGetWebMessageAsString(&raw); 201 | 202 | auto message = narrow(raw); 203 | BaseWindow::handleRawCallRequest(message); 204 | 205 | CoTaskMemFree(raw); 206 | return S_OK; 207 | } 208 | 209 | HRESULT Webview::Window::Window::onNavigationCompleted([[maybe_unused]] ICoreWebView2 *sender, 210 | [[maybe_unused]] ICoreWebView2NavigationCompletedEventArgs *args) 211 | { 212 | //* This fix is fucking retarded. I can't do anything about this until WebView2 fixes this 213 | //* https://github.com/MicrosoftEdge/WebView2Feedback/issues/1077 214 | 215 | static bool first = true; 216 | if (first && hidden) 217 | { 218 | hide(); 219 | first = false; 220 | } 221 | 222 | wil::unique_cotaskmem_string uri; 223 | webViewWindow->get_Source(&uri); 224 | 225 | BaseWindow::onNavigate(narrow(uri.get())); 226 | return S_OK; 227 | } 228 | 229 | #if defined(WEBVIEW_EMBEDDED) 230 | HRESULT Webview::Window::Window::onWebResourceRequested([[maybe_unused]] ICoreWebView2 *sender, 231 | ICoreWebView2WebResourceRequestedEventArgs *args) 232 | { 233 | ICoreWebView2WebResourceRequest *req = nullptr; 234 | args->get_Request(&req); 235 | 236 | LPWSTR rawURI{}; 237 | req->get_Uri(&rawURI); 238 | 239 | auto uri = narrow(rawURI); 240 | 241 | if (uri.length() > 16 && uri.substr(0, 16) == "file:///embedded") 242 | { 243 | auto fileName = uri.substr(uri.find_last_of('/') + 1); 244 | auto mime = fileName.substr(fileName.find_last_of('.')); 245 | 246 | auto content = getResource(fileName); 247 | if (content.data) 248 | { 249 | wil::com_ptr env; 250 | wil::com_ptr webview2; 251 | webViewWindow->QueryInterface(IID_PPV_ARGS(&webview2)); 252 | webview2->get_Environment(&env); 253 | 254 | wil::com_ptr stream = SHCreateMemStream(content.data, content.size); 255 | 256 | wil::com_ptr response; 257 | env->CreateWebResourceResponse(stream.get(), 200, L"OK", 258 | widen("Content-Type: " + mimeTypeList.at(mime)).c_str(), &response); 259 | 260 | args->put_Response(response.get()); 261 | } 262 | } 263 | return S_OK; 264 | } 265 | #endif 266 | 267 | void Webview::Window::Window::hide() 268 | { 269 | BaseWindow::hide(); 270 | ShowWindow(hwnd, SW_HIDE); 271 | } 272 | 273 | void Webview::Window::Window::show() 274 | { 275 | BaseWindow::show(); 276 | 277 | ShowWindow(hwnd, SW_SHOW); 278 | UpdateWindow(hwnd); 279 | SetFocus(hwnd); 280 | } 281 | 282 | void Webview::Window::Window::run() 283 | { 284 | MSG msg; 285 | while (hwnd && GetMessage(&msg, nullptr, 0, 0) != 0) 286 | { 287 | TranslateMessage(&msg); 288 | DispatchMessage(&msg); 289 | } 290 | } 291 | 292 | void Webview::Window::Window::exit() 293 | { 294 | PostMessage(hwnd, WM_QUIT, 0, 0); 295 | } 296 | 297 | void Webview::Window::setUrl(std::string newUrl) 298 | { 299 | if (!webViewController) 300 | { 301 | runOnControllerCreated.emplace_back([newUrl = std::move(newUrl), this] { setUrl(newUrl); }); 302 | return; 303 | } 304 | 305 | BaseWindow::setUrl(newUrl); 306 | webViewWindow->Navigate(widen(url).c_str()); 307 | } 308 | 309 | void Webview::Window::setTitle(std::string newTitle) 310 | { 311 | BaseWindow::setTitle(newTitle); 312 | SetWindowText(hwnd, title.c_str()); 313 | } 314 | 315 | void Webview::Window::setSize(std::size_t newWidth, std::size_t newHeight) 316 | { 317 | BaseWindow::setSize(newWidth, newHeight); 318 | SetWindowPos(hwnd, nullptr, 0, 0, width, height, SWP_NOMOVE | SWP_NOZORDER | SWP_NOOWNERZORDER); 319 | } 320 | 321 | void Webview::Window::enableDevTools(bool state) 322 | { 323 | if (!webViewController) 324 | { 325 | runOnControllerCreated.emplace_back([=] { enableDevTools(state); }); 326 | return; 327 | } 328 | 329 | wil::com_ptr settings; 330 | 331 | webViewWindow->get_Settings(&settings); 332 | settings->put_AreDevToolsEnabled(state); 333 | } 334 | 335 | void Webview::Window::enableContextMenu(bool state) 336 | { 337 | if (!webViewController) 338 | { 339 | runOnControllerCreated.emplace_back([=] { enableContextMenu(state); }); 340 | return; 341 | } 342 | 343 | wil::com_ptr settings; 344 | 345 | webViewWindow->get_Settings(&settings); 346 | settings->put_AreDefaultContextMenusEnabled(state); 347 | } 348 | 349 | void Webview::Window::dispatchMessage(std::function func) 350 | { 351 | auto *funcPtr = new std::function(std::move(func)); 352 | PostMessage(hwnd, WM_CALL, reinterpret_cast(funcPtr), 0); 353 | } 354 | 355 | void Webview::Window::runCode(const std::string &code) 356 | { 357 | if (!webViewController) 358 | { 359 | runOnControllerCreated.emplace_back([=] { runCode(code); }); 360 | return; 361 | } 362 | dispatchMessage([this, code] { webViewWindow->ExecuteScript(widen(formatCode(code)).c_str(), nullptr); }); 363 | } 364 | 365 | void Webview::Window::injectCode(const std::string &code) 366 | { 367 | if (!webViewController) 368 | { 369 | runOnControllerCreated.emplace_back([=] { injectCode(code); }); 370 | return; 371 | } 372 | webViewWindow->AddScriptToExecuteOnDocumentCreated(widen(formatCode(code)).c_str(), nullptr); 373 | } 374 | 375 | void Webview::Window::onResize([[maybe_unused]] std::size_t _width, [[maybe_unused]] std::size_t _height) 376 | { 377 | auto [newWidth, newHeight] = getSize(); //* Yes. I do this because what we get through the WndProc is bullshit 378 | 379 | BaseWindow::onResize(newWidth, newHeight); 380 | 381 | if (!webViewController) 382 | { 383 | runOnControllerCreated.emplace_back([=] { onResize(newWidth, newHeight); }); 384 | return; 385 | } 386 | 387 | RECT rc; 388 | GetClientRect(hwnd, &rc); 389 | webViewController->put_Bounds(rc); 390 | } 391 | 392 | std::wstring Webview::Window::Window::widen(const std::string &str) 393 | { 394 | auto wsz = MultiByteToWideChar(65001, 0, str.c_str(), -1, nullptr, 0); 395 | if (!wsz) 396 | { 397 | return std::wstring(); 398 | } 399 | 400 | std::wstring out(wsz, 0); 401 | MultiByteToWideChar(65001, 0, str.c_str(), -1, &out[0], wsz); 402 | out.resize(wsz - 1); 403 | return out; 404 | } 405 | std::string Webview::Window::Window::narrow(const std::wstring &wstr) 406 | { 407 | auto sz = 408 | WideCharToMultiByte(65001, 0, wstr.c_str(), static_cast(wstr.length()), nullptr, 0, nullptr, nullptr); 409 | if (!sz) 410 | { 411 | return std::string(); 412 | } 413 | 414 | std::string out(sz, 0); 415 | WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), -1, &out[0], sz, nullptr, nullptr); 416 | return out; 417 | } 418 | 419 | std::string Webview::Window::Window::getUrl() 420 | { 421 | wil::unique_cotaskmem_string uri; 422 | webViewWindow->get_Source(&uri); 423 | 424 | return narrow(uri.get()); 425 | } 426 | 427 | void Webview::Window::Window::disableAcceleratorKeys(bool state) 428 | { 429 | if (!webViewController) 430 | { 431 | runOnControllerCreated.emplace_back([=] { disableAcceleratorKeys(state); }); 432 | return; 433 | } 434 | 435 | wil::com_ptr settings; 436 | webViewWindow->get_Settings(&settings); 437 | 438 | auto experimentalSettings = settings.try_query(); 439 | if (experimentalSettings) 440 | { 441 | experimentalSettings->put_AreBrowserAcceleratorKeysEnabled(!state); 442 | } 443 | } 444 | 445 | #endif -------------------------------------------------------------------------------- /webview/src/javascript/function.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | std::function Webview::Function::getFunc() const 6 | { 7 | return parserFunction; 8 | } 9 | 10 | std::string Webview::Function::getName() const 11 | { 12 | return name; 13 | } 14 | 15 | std::function Webview::AsyncFunction::getFunc() 16 | const 17 | { 18 | return parserFunction; 19 | } 20 | 21 | std::vector Webview::JavaScriptFunction::getArguments() const 22 | { 23 | return arguments; 24 | } 25 | 26 | std::string Webview::JavaScriptFunction::getName() const 27 | { 28 | return name; 29 | } 30 | 31 | void Webview::JavaScriptFunction::resolve(const nlohmann::json &result) 32 | { 33 | std::lock_guard guard(argumentsMutex); 34 | this->result.set_value(result); 35 | } 36 | 37 | std::shared_future Webview::JavaScriptFunction::getResult() 38 | { 39 | std::lock_guard guard(argumentsMutex); 40 | return result.get_future(); 41 | } 42 | 43 | Webview::JavaScriptFunction::JavaScriptFunction(JavaScriptFunction &other) 44 | : name(other.name), result((std::lock_guard(other.resultMutex), std::move(other.result))), 45 | arguments((std::lock_guard(other.argumentsMutex), std::move(other.arguments))) 46 | { 47 | } -------------------------------------------------------------------------------- /webview/src/javascript/promise.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | Webview::Promise::Promise(Webview::BaseWindow &parent, std::uint32_t id) : id(id), parent(parent) {} 6 | 7 | void Webview::Promise::discard() const 8 | { 9 | resolve(nullptr); 10 | } 11 | 12 | void Webview::Promise::resolve(const nlohmann::json &result) const 13 | { 14 | auto code = std::regex_replace(BaseWindow::resolveCall, std::regex(R"(\{0\})"), std::to_string(id)); 15 | code = std::regex_replace(code, std::regex(R"(\{1\})"), result.dump()); 16 | parent.runCode(code); 17 | } --------------------------------------------------------------------------------