Full Code of webview/webview for AI

master cbbdee44afff cached
144 files
555.0 KB
143.9k tokens
679 symbols
1 requests
Download .txt
Showing preview only (595K chars total). Download the full file or copy to clipboard to get everything.
Repository: webview/webview
Branch: master
Commit: cbbdee44afff
Files: 144
Total size: 555.0 KB

Directory structure:
gitextract_dbzse5fk/

├── .clang-format
├── .clang-tidy
├── .gitattributes
├── .github/
│   ├── actions/
│   │   ├── cmake/
│   │   │   └── action.yaml
│   │   └── setup-env/
│   │       └── action.yaml
│   ├── issue_template.md
│   └── workflows/
│       ├── build.yaml
│       ├── build_matrix.csv
│       ├── build_matrix_schema.json
│       ├── check.yaml
│       ├── ci.yaml
│       ├── csv.js
│       └── draft-release.yaml
├── .gitignore
├── CHANGELOG.md
├── CMakeLists.txt
├── CONTRIBUTING.md
├── LICENSE
├── MIGRATION.md
├── README.md
├── cmake/
│   ├── clang_format.cmake
│   ├── extract_version.cmake
│   ├── internal.cmake
│   ├── modules/
│   │   └── FindMSWebView2.cmake
│   ├── toolchains/
│   │   ├── arm64-windows-msvc.cmake
│   │   ├── host-gnu.cmake
│   │   ├── host-llvm.cmake
│   │   ├── i686-w64-mingw32.cmake
│   │   ├── i686-windows-msvc.cmake
│   │   ├── universal-macos-llvm.cmake
│   │   ├── x86_64-msys2-gnu-ucrt64.cmake
│   │   ├── x86_64-msys2-llvm-clang64.cmake
│   │   ├── x86_64-w64-mingw32.cmake
│   │   └── x86_64-windows-msvc.cmake
│   ├── webview-config.cmake.in
│   └── webview.cmake
├── compatibility/
│   ├── CMakeLists.txt
│   └── mingw/
│       ├── CMakeLists.txt
│       └── include/
│           └── EventToken.h
├── core/
│   ├── CMakeLists.txt
│   ├── include/
│   │   ├── webview/
│   │   │   ├── api.h
│   │   │   ├── backends.hh
│   │   │   ├── c_api_impl.hh
│   │   │   ├── detail/
│   │   │   │   ├── backends/
│   │   │   │   │   ├── cocoa_webkit.hh
│   │   │   │   │   ├── gtk_webkitgtk.hh
│   │   │   │   │   └── win32_edge.hh
│   │   │   │   ├── basic_result.hh
│   │   │   │   ├── engine_base.hh
│   │   │   │   ├── exceptions.hh
│   │   │   │   ├── json.hh
│   │   │   │   ├── native_library.hh
│   │   │   │   ├── optional.hh
│   │   │   │   ├── platform/
│   │   │   │   │   ├── darwin/
│   │   │   │   │   │   ├── cocoa/
│   │   │   │   │   │   │   ├── NSApplication.hh
│   │   │   │   │   │   │   ├── NSBundle.hh
│   │   │   │   │   │   │   ├── NSEvent.hh
│   │   │   │   │   │   │   ├── NSInvocation.hh
│   │   │   │   │   │   │   ├── NSMethodSignature.hh
│   │   │   │   │   │   │   ├── NSNotification.hh
│   │   │   │   │   │   │   ├── NSNumber.hh
│   │   │   │   │   │   │   ├── NSObject.hh
│   │   │   │   │   │   │   ├── NSOpenPanel.hh
│   │   │   │   │   │   │   ├── NSPoint.hh
│   │   │   │   │   │   │   ├── NSRect.hh
│   │   │   │   │   │   │   ├── NSSavePanel.hh
│   │   │   │   │   │   │   ├── NSSize.hh
│   │   │   │   │   │   │   ├── NSString.hh
│   │   │   │   │   │   │   ├── NSURL.hh
│   │   │   │   │   │   │   ├── NSURLRequest.hh
│   │   │   │   │   │   │   ├── NSValue.hh
│   │   │   │   │   │   │   ├── NSView.hh
│   │   │   │   │   │   │   ├── NSWindow.hh
│   │   │   │   │   │   │   ├── cocoa.hh
│   │   │   │   │   │   │   └── types.hh
│   │   │   │   │   │   ├── objc/
│   │   │   │   │   │   │   ├── Class.hh
│   │   │   │   │   │   │   ├── autoreleasepool.hh
│   │   │   │   │   │   │   ├── invoke.hh
│   │   │   │   │   │   │   ├── memory.hh
│   │   │   │   │   │   │   └── objc.hh
│   │   │   │   │   │   └── webkit/
│   │   │   │   │   │       ├── WKOpenPanelParameters.hh
│   │   │   │   │   │       ├── WKScriptMessage.hh
│   │   │   │   │   │       ├── WKUserContentController.hh
│   │   │   │   │   │       ├── WKUserScript.hh
│   │   │   │   │   │       ├── WKWebView.hh
│   │   │   │   │   │       ├── WKWebViewConfiguration.hh
│   │   │   │   │   │       └── webkit.hh
│   │   │   │   │   ├── linux/
│   │   │   │   │   │   ├── gtk/
│   │   │   │   │   │   │   └── compat.hh
│   │   │   │   │   │   └── webkitgtk/
│   │   │   │   │   │       ├── compat.hh
│   │   │   │   │   │       └── dmabuf.hh
│   │   │   │   │   └── windows/
│   │   │   │   │       ├── com_init_wrapper.hh
│   │   │   │   │       ├── dpi.hh
│   │   │   │   │       ├── dwmapi.hh
│   │   │   │   │       ├── iid.hh
│   │   │   │   │       ├── ntdll.hh
│   │   │   │   │       ├── reg_key.hh
│   │   │   │   │       ├── shcore.hh
│   │   │   │   │       ├── theme.hh
│   │   │   │   │       ├── user32.hh
│   │   │   │   │       ├── version.hh
│   │   │   │   │       └── webview2/
│   │   │   │   │           └── loader.hh
│   │   │   │   ├── user_script.hh
│   │   │   │   └── utility/
│   │   │   │       └── string.hh
│   │   │   ├── errors.h
│   │   │   ├── errors.hh
│   │   │   ├── json_deprecated.hh
│   │   │   ├── macros.h
│   │   │   ├── types.h
│   │   │   ├── types.hh
│   │   │   ├── version.h
│   │   │   └── webview.h
│   │   └── webview.h
│   ├── src/
│   │   └── webview.cc
│   └── tests/
│       ├── CMakeLists.txt
│       └── src/
│           ├── functional_tests.cc
│           └── unit_tests.cc
├── docs/
│   ├── CMakeLists.txt
│   └── api/
│       ├── CMakeLists.txt
│       └── Doxyfile.in
├── examples/
│   ├── CMakeLists.txt
│   ├── basic.c
│   ├── basic.cc
│   ├── bind.c
│   ├── bind.cc
│   └── resources/
│       ├── macos/
│       │   ├── app_icon.icns
│       │   └── resources.cmake
│       └── windows/
│           ├── resources.cmake
│           ├── resources.rc
│           └── version.rc.in
├── gcovr.cfg
├── gcovr.ci.cfg
├── packaging/
│   ├── CMakeLists.txt
│   ├── external_package.cmake.in
│   └── test/
│       ├── .gitignore
│       └── CMakeLists.txt
├── scripts/
│   └── amalgamate/
│       ├── amalgamate.py
│       └── test/
│           ├── .gitignore
│           ├── main.c
│           ├── main.cc
│           └── webview.cc
├── test_driver/
│   ├── CMakeLists.txt
│   ├── cmake/
│   │   ├── discovery.cmake
│   │   └── generate_includes.cmake
│   ├── include/
│   │   └── webview/
│   │       └── test_driver.hh
│   └── src/
│       └── test_driver.cc
└── webview.i

================================================
FILE CONTENTS
================================================

================================================
FILE: .clang-format
================================================
---
Language:        Cpp
# BasedOnStyle:  LLVM
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Right
AlignOperands:   true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: false
BinPackArguments: true
BinPackParameters: true
BraceWrapping:   
  AfterClass:      false
  AfterControlStatement: false
  AfterEnum:       false
  AfterFunction:   false
  AfterNamespace:  false
  AfterObjCDeclaration: false
  AfterStruct:     false
  AfterUnion:      false
  AfterExternBlock: false
  BeforeCatch:     false
  BeforeElse:      false
  IndentBraces:    false
  SplitEmptyFunction: true
  SplitEmptyRecord: true
  SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit:     80
CommentPragmas:  '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat:   false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:   
  - foreach
  - Q_FOREACH
  - BOOST_FOREACH
IncludeBlocks:   Preserve
IncludeCategories: 
  - Regex:           '^"(llvm|llvm-c|clang|clang-c)/'
    Priority:        2
  - Regex:           '^(<|"(gtest|gmock|isl|json)/)'
    Priority:        3
  - Regex:           '.*'
    Priority:        1
IncludeIsMainRegex: '(Test)?$'
IndentCaseLabels: false
IndentPPDirectives: None
IndentWidth:     2
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd:   ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerAlignment: Right
ReflowComments:  false
SortIncludes:    true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles:  false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard:        Cpp11
TabWidth:        8
UseTab:          Never
...



================================================
FILE: .clang-tidy
================================================
---
# We should aim to fix the code and re-enable most of the rules here.
# The following were disabled due to false positives:
# - clang-analyzer-cplusplus.NewDeleteLeaks: Finds a leak inside std::function (clang-tidy 15.0.7)
Checks: >
    bugprone-*,
    cert-*,
    clang-analyzer-*,
    clang-diagnostic-*,
    cppcoreguidelines-*,
    hicpp-*,
    misc-*,
    modernize-*,
    performance-*,
    portability-*,
    readability-*,
    -bugprone-easily-swappable-parameters,
    -bugprone-branch-clone,
    -cert-env33-c,
    -clang-analyzer-core.CallAndMessage,
    -clang-analyzer-optin.cplusplus.UninitializedObject,
    -clang-analyzer-security.insecureAPI.strcpy,
    -clang-analyzer-cplusplus.NewDeleteLeaks,
    -clang-diagnostic-unused-parameter,
    -cppcoreguidelines-avoid-c-arrays,
    -cppcoreguidelines-avoid-magic-numbers,
    -cppcoreguidelines-init-variables,
    -cppcoreguidelines-macro-usage,
    -cppcoreguidelines-owning-memory,
    -cppcoreguidelines-explicit-virtual-functions,
    -cppcoreguidelines-pro-bounds-array-to-pointer-decay,
    -cppcoreguidelines-pro-bounds-pointer-arithmetic,
    -cppcoreguidelines-pro-type-cstyle-cast,
    -cppcoreguidelines-pro-type-vararg,
    -cppcoreguidelines-special-member-functions,
    -hicpp-avoid-c-arrays,
    -hicpp-explicit-conversions,
    -hicpp-no-array-decay,
    -hicpp-signed-bitwise,
    -hicpp-special-member-functions,
    -hicpp-use-override,
    -hicpp-vararg,
    -misc-definitions-in-headers,
    -misc-include-cleaner,
    -misc-non-private-member-variables-in-classes,
    -modernize-avoid-c-arrays,
    -modernize-make-unique,
    -modernize-pass-by-value,
    -modernize-use-nodiscard,
    -modernize-use-override,
    -modernize-use-trailing-return-type,
    -modernize-use-using,
    -performance-enum-size,
    -performance-unnecessary-value-param,
    -readability-convert-member-functions-to-static,
    -readability-else-after-return,
    -readability-qualified-auto,
    -readability-function-cognitive-complexity,
    -readability-implicit-bool-conversion,
    -readability-inconsistent-declaration-parameter-name,
    -readability-magic-numbers
CheckOptions:
  # We use short variables like "w"
  - key:   readability-identifier-length.MinimumVariableNameLength
    value: 1
  # We use short parameters like "w"
  - key:   readability-identifier-length.MinimumParameterNameLength
    value: 1
  # We have many value variables that aren't declared as const.
  - key:   misc-const-correctness.AnalyzeValues
    value: 0
HeaderFilterRegex: webview\.h$


================================================
FILE: .gitattributes
================================================
*.h linguist-language=c


================================================
FILE: .github/actions/cmake/action.yaml
================================================
name: CMake build
description: Build project using CMake
inputs:
  artifacts-name:
    description: Artifacts name
    required: false
  build-dir:
    description: CMake build directory
    required: false
    default: build
  build-config-debug:
    description: CMake build config for debug
    required: false
    default: Debug
  build-config-release:
    description: CMake build config for release
    required: false
    default: Release
  build-config-profile:
    description: CMake build config for profiling
    required: false
    default: Profile
  coverage:
    description: Enable code coverage?
    required: false
  cmake-options:
    description: Sets extra CMake options in the form ["K=V", ...]
    required: false
  gcov:
    description: gcov executable
    required: false
    default: gcov
  gcovr-config:
    description: gcovr config file
    required: false
    default: gcovr.ci.cfg
  gcovr-version:
    description: gcovr version
    required: false
    default: '7.2'
  generator:
    description: CMake generator
    required: false
    default: Ninja
  package:
    description: Package?
    required: false
  package-source:
    description: Package source code?
    required: false
  shell:
    description: Shell
    required: false
    default: bash
  source-dir:
    description: CMake source directory
    required: false
    default: .
  test-timeout:
    description: Test timeout in seconds
    required: false
    default: '60'
  test-wrapper-cmd:
    description: Test wrapper command
    required: false
  upload-coverage-artifacts:
    description: Upload coverage artifacts?
    required: false
  upload-package-artifacts:
    description: Upload package artifacts?
    required: false
runs:
  using: composite
  steps:
    - if: inputs.coverage != '' && fromJson(inputs.coverage)
      name: gcov version
      run: ${{ inputs.gcov }} --version
      shell: ${{ inputs.shell }}

    - if: inputs.coverage != '' && fromJson(inputs.coverage)
      name: Install gcovr
      run: pip install "gcovr==${{ inputs.gcovr-version }}"
      shell: ${{ inputs.shell }}

    - name: Generate build config names
      id: generate-build-config-names
      run: |
        configs=()
        if [[ "${{ inputs.coverage }}" == "true" ]]; then
          configs+=("${{ inputs.build-config-profile }}")
        else
          configs+=("${{ inputs.build-config-debug }}")
          configs+=("${{ inputs.build-config-release }}")
        fi
        echo "configs=${configs[@]}" >> "${GITHUB_OUTPUT}"
      shell: bash

    - name: Parse CMake options
      uses: actions/github-script@v7
      id: cmake-options
      env:
        OPTIONS: ${{ inputs.cmake-options }}
      with:
        script: return JSON.parse(process.env.OPTIONS).join("\n")
        result-encoding: string

    - name: Configure
      env:
        OPTIONS: ${{ steps.cmake-options.outputs.result }}
      run: |
        cmake_cmd=(
          cmake
          -G "${{ inputs.generator }}"
          -B "${{ inputs.build-dir }}"
          -S "${{ inputs.source-dir }}"
        )
        while read opt; do
          if [[ ! -z "${opt}" ]]; then
            cmake_cmd+=(-D "${opt}")
          fi
        done << EOF
        ${OPTIONS}
        EOF
        "${cmake_cmd[@]}"
      shell: ${{ inputs.shell }}

    - name: Build
      run: |
        configs=(${{ steps.generate-build-config-names.outputs.configs }})
        for config in "${configs[@]}"; do
          cmake_cmd=(
            cmake
            --build "${{ inputs.build-dir }}"
            --config "${config}"
          )
          "${cmake_cmd[@]}"
        done
      shell: ${{ inputs.shell }}

    - name: Test
      run: |
        configs=(${{ steps.generate-build-config-names.outputs.configs }})
        for config in "${configs[@]}"; do
          cmake_cmd=()
          if [[ ! -z "${{ inputs.test-wrapper-cmd }}" ]]; then
            cmake_cmd+=("${{ inputs.test-wrapper-cmd }}")
          fi
          cmake_cmd+=(
            ctest
            --test-dir "${{ inputs.build-dir }}"
            --output-on-failure
            --build-config "${config}"
          )
          if [[ ! -z "${{ inputs.test-timeout }}" ]]; then
            cmake_cmd+=(--timeout "${{ inputs.test-timeout }}")
          fi
          "${cmake_cmd[@]}"
        done
      shell: ${{ inputs.shell }}

    - if: inputs.package != '' && fromJson(inputs.package)
      name: Create packages
      run: cpack -G External -C "${{ inputs.build-config-debug }};${{ inputs.build-config-release }}" --config CPackConfig.cmake
      working-directory: ${{ inputs.build-dir }}
      shell: ${{ inputs.shell }}

    - if: inputs.package-source != '' && fromJson(inputs.package-source)
      name: Create source package
      run: cpack --config CPackSourceConfig.cmake
      working-directory: ${{ inputs.build-dir }}
      shell: ${{ inputs.shell }}

    - if: inputs.coverage != '' && fromJson(inputs.coverage)
      name: Generate coverage data
      id: prepare-coverage-artifacts
      run: |
        artifact_dir="temp_${RANDOM}/${{ inputs.artifacts-name }}"

        gcovr_args=(
          --config "${{ inputs.gcovr-config }}"
          --json "${artifact_dir}/coverage.json"
        )
        if [[ ! -z "${{ inputs.gcov }}" ]]; then
          gcovr_args+=(--gcov-executable "${{ inputs.gcov }}")
        fi

        mkdir -p "${artifact_dir}"
        gcovr "${gcovr_args[@]}"

        echo "upload-dir=${artifact_dir}" >> "${GITHUB_OUTPUT}"
      shell: ${{ inputs.shell }}

    - if: (inputs.upload-package-artifacts != '' && fromJson(inputs.upload-package-artifacts)) && ((inputs.package != '' && fromJson(inputs.package)) || (inputs.package-source != '' && fromJson(inputs.package-source)))
      name: Upload package artifacts
      uses: actions/upload-artifact@v4
      with:
        name: package_${{ inputs.artifacts-name }}
        path: |
          ${{ inputs.build-dir }}/*.gz
          ${{ inputs.build-dir }}/*.zip
        retention-days: 1
        if-no-files-found: error

    - if: (inputs.upload-coverage-artifacts != '' && fromJson(inputs.upload-coverage-artifacts)) && (inputs.coverage != '' && fromJson(inputs.coverage))
      name: Upload coverage artifacts
      uses: actions/upload-artifact@v4
      with:
        name: test_coverage_data_${{ inputs.artifacts-name }}
        path: ${{ steps.prepare-coverage-artifacts.outputs.upload-dir }}
        retention-days: 1
        if-no-files-found: error

    - if: inputs.coverage != '' && fromJson(inputs.coverage)
      name: Clean up temporary coverage files
      run: rm -rf "${{ steps.prepare-coverage-artifacts.outputs.upload-dir }}"
      shell: ${{ inputs.shell }}


================================================
FILE: .github/actions/setup-env/action.yaml
================================================
name: Set up environment
description: Sets up the environment by checking out code, installing required packages, etc.
inputs:
  apt:
    description: APT package names
    required: false
  msys:
    description: MSYS2 environment
    required: false
  msys-pacboy:
    description: MSYS2 packages (pacboy)
    required: false
  webkitgtk-api:
    description: WebKitGTK API version
    required: false
runs:
  using: composite
  steps:
    - if: runner.os == 'Linux'
      name: Get APT packages for WebKitGTK
      id: apt-webkitgtk
      run: |
        packages=()
        if [[ "${{ inputs.webkitgtk-api }}" == "6.0" ]]; then
          packages+=(libgtk-4-dev libwebkitgtk-6.0-dev)
        elif [[ "${{ inputs.webkitgtk-api }}" == "4.1" ]]; then
          packages+=(libgtk-3-dev libwebkit2gtk-4.1-dev)
        elif [[ "${{ inputs.webkitgtk-api }}" == "4.0" ]]; then
          packages+=(libgtk-3-dev libwebkit2gtk-4.0-dev)
        fi
        echo "packages=${packages[@]}" >> "${GITHUB_OUTPUT}"
      shell: bash

    - if: runner.os == 'Linux'
      name: Install packages (APT)
      run: |
        packages=(${{ inputs.apt }} ${{ steps.apt-webkitgtk.outputs.packages }})
        sudo apt-get update
        sudo apt-get install --no-install-recommends -y \
          cmake \
          doxygen \
          graphviz \
          ninja-build \
          python3 \
          python3-lxml \
          python3-markupsafe \
          python3-pip \
          xvfb \
          "${packages[@]}"
      shell: bash

    - if: runner.os == 'Windows' && inputs.msys != ''
      name: Set up MSYS2
      uses: msys2/setup-msys2@v2
      with:
        msystem: ${{ inputs.msys }}
        update: false
        install: base-devel
        pacboy: >-
          cmake:p
          ninja:p
          python:p
          python-lxml:p
          python-markupsafe:p
          python-pip:p
          toolchain:p
          ${{ inputs.msys-pacboy }}


================================================
FILE: .github/issue_template.md
================================================
<!--

Thanks for filing an issue! If this is a question or feature request, just delete
everything here and write out the request, providing as much context as you can.

-->

### What OS are you using (`uname -a`, or Windows version)?

<!-- 
Please specify your operating system version and architecture (i686/amd64 etc).
If you're running Windows - please also provide your IE version.
-->

### What programming language are you using (C/C++/Go/Rust)?

<!--
`gcc --version`
`clang --version`
`go version`
`rustc --version`
-->

### What did you expect to see and what you saw instead?

<!--
Your issue may already be reported! Please search on the issue tracker before creating a new one.
If your issue has not been reported yet - please describe your problem with as much details as you can.
Thanks you.
-->


================================================
FILE: .github/workflows/build.yaml
================================================
name: Build
on:
  workflow_call:
    inputs:
      coverage:
        type: boolean
        description: Enable code coverage?
        required: false
        default: true
      gcovr-version:
        type: string
        description: gcovr version
        required: false
      pr:
        type: boolean
        description: Is this a pull request build?
        required: false
        default: false
jobs:
  load-matrix:
    runs-on: ubuntu-22.04
    outputs:
      matrix: ${{ steps.load-matrix.outputs.result }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Load matrix file
        id: load-matrix
        uses: actions/github-script@v7
        env:
          PR: ${{ inputs.pr }}
          ENABLE_COVERAGE: ${{ inputs.coverage }}
        with:
          script: |
            const csv = require("./.github/workflows/csv.js");
            const path = require("node:path");
            const schema = require("./.github/workflows/build_matrix_schema.json");
            let include = csv.loadFile(path.join(".github", "workflows", "build_matrix.csv"), schema);

            // Generate IDs that match line numbers in the CSV file, making it more
            // convenient to work with the file and review changes made to it.
            [...include.keys()].forEach(n => include[n].id = 2 + n);

            // Filters
            include = include.filter(x => JSON.parse(process.env.PR) === x["pr-only"]);
            include = include.filter(x => x["job-type"] !== "coverage" || JSON.parse(process.env.ENABLE_COVERAGE));

            const matrix = { include };
            console.log(matrix);
            return matrix;

  build:
    needs: load-matrix
    name: ${{ matrix.job-type }} (${{ matrix.id }}, ${{ matrix.os }}, c++${{ matrix.cxx-std }}, ${{ matrix.arch }}, ${{ matrix.toolchain }}${{ matrix.toolchain-executable-suffix }}${{ matrix.job-name-suffix }})
    runs-on: ${{ matrix.image }}
    strategy:
      fail-fast: false
      matrix: ${{ fromJson(needs.load-matrix.outputs.matrix) }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Set up environment
        uses: ./.github/actions/setup-env
        with:
          apt: ${{ matrix.apt }}
          msys: ${{ matrix.msys }}
          msys-pacboy: ${{ matrix.msys-pacboy }}
          webkitgtk-api: ${{ matrix.webkitgtk-api }}

      - name: Build CMake options
        uses: actions/github-script@v7
        id: cmake-options
        env:
          MATRIX: ${{ toJson(matrix) }}
        with:
          script: |
            const matrix = JSON.parse(process.env.MATRIX);
            const option = (k, v) => v === undefined ? undefined : [k, ({
                boolean: () => v ? "ON" : "OFF"
              }[typeof v] || (() => v))()
            ].join("=");
            return [
              option("CMAKE_CXX_STANDARD", matrix["cxx-std"]),
              option("CMAKE_OSX_DEPLOYMENT_TARGET", matrix["osx-deployment-target"]),
              option("CMAKE_TOOLCHAIN_FILE", `cmake/toolchains/${matrix["arch"]}-${matrix["toolchain"]}.cmake`),
              option("WEBVIEW_BUILD_AMALGAMATION", matrix["package-amalgamation"]),
              option("WEBVIEW_BUILD_DOCS", matrix["package-docs"]),
              option("WEBVIEW_TOOLCHAIN_EXECUTABLE_SUFFIX", matrix["toolchain-executable-suffix"]),
              option("WEBVIEW_USE_STATIC_MSVC_RUNTIME", matrix["msvc-mt"]),
              // We check formatting separately
              option("WEBVIEW_ENABLE_CLANG_FORMAT", false),
              option("WEBVIEW_ENABLE_CLANG_TIDY", matrix["checks"]),
              // Please enable strict clang-tidy when issues have been fixed
              option("WEBVIEW_STRICT_CLANG_TIDY", matrix["strict-clang-tidy"]),
              option("WEBVIEW_WEBKITGTK_API", matrix["webkitgtk-api"]),
              // Packaging
              option("WEBVIEW_ENABLE_PACKAGING", matrix["package"]),
              option("WEBVIEW_PACKAGE_AMALGAMATION", matrix["package-amalgamation"]),
              option("WEBVIEW_PACKAGE_DOCS", matrix["package-docs"]),
              option("WEBVIEW_PACKAGE_HEADERS", matrix["package-headers"]),
              option("WEBVIEW_PACKAGE_LIB", matrix["package-lib"]),
            ].filter(v => v !== undefined).filter(v => {
              console.log(v);
              return true;
            });

      - name: CMake
        uses: ./.github/actions/cmake
        with:
          artifacts-name: ${{ matrix.id }}
          build-dir: build
          cmake-options: ${{ steps.cmake-options.outputs.result }}
          generator: ${{ matrix.generator }}
          package: ${{ matrix.package }}
          package-source: ${{ matrix.package-source }}
          shell: ${{ matrix.shell }}
          source-dir: .
          test-wrapper-cmd: ${{ matrix.test-wrapper-cmd }}
          upload-package-artifacts: ${{ matrix.package && !inputs.pr }}
          # Specific to code coverage
          coverage: ${{ inputs.coverage && matrix.job-type == 'coverage' }}
          gcov: ${{ matrix.gcov }}
          gcovr-version: ${{ inputs.gcovr-version }}
          upload-coverage-artifacts: ${{ inputs.coverage && matrix.job-type == 'coverage' && !inputs.pr }}


================================================
FILE: .github/workflows/build_matrix.csv
================================================
job-type,os,image,arch,cxx-std,toolchain,toolchain-executable-suffix,generator,pr-only,checks,strict-clang-tidy,package,package-amalgamation,package-docs,package-headers,package-lib,package-source,shell,msvc-mt,msys,msys-pacboy,apt,gcov,osx-deployment-target,test-wrapper-cmd,webkitgtk-api,job-name-suffix,comments
package,linux,ubuntu-22.04,host,11,gnu,-12,Ninja Multi-Config,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,gcc-12 g++-12,,,xvfb-run,6.0,", webkitgtk6.0",
package,linux,ubuntu-22.04,host,14,gnu,-12,Ninja Multi-Config,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,gcc-12 g++-12,,,xvfb-run,6.0,", webkitgtk6.0",
package,linux,ubuntu-22.04,host,17,gnu,-12,Ninja Multi-Config,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,gcc-12 g++-12,,,xvfb-run,6.0,", webkitgtk6.0",
package,linux,ubuntu-22.04,host,20,gnu,-12,Ninja Multi-Config,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,gcc-12 g++-12,,,xvfb-run,6.0,", webkitgtk6.0",
package,linux,ubuntu-22.04,host,23,gnu,-12,Ninja Multi-Config,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,gcc-12 g++-12,,,xvfb-run,6.0,", webkitgtk6.0",
package,linux,ubuntu-22.04,host,11,gnu,-12,Ninja Multi-Config,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,gcc-12 g++-12,,,xvfb-run,4.1,", webkitgtk4.1",
package,linux,ubuntu-22.04,host,14,gnu,-12,Ninja Multi-Config,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,gcc-12 g++-12,,,xvfb-run,4.1,", webkitgtk4.1",
package,linux,ubuntu-22.04,host,17,gnu,-12,Ninja Multi-Config,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,gcc-12 g++-12,,,xvfb-run,4.1,", webkitgtk4.1",
package,linux,ubuntu-22.04,host,20,gnu,-12,Ninja Multi-Config,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,gcc-12 g++-12,,,xvfb-run,4.1,", webkitgtk4.1",
package,linux,ubuntu-22.04,host,23,gnu,-12,Ninja Multi-Config,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,gcc-12 g++-12,,,xvfb-run,4.1,", webkitgtk4.1",
package,linux,ubuntu-22.04,host,11,gnu,-12,Ninja Multi-Config,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,gcc-12 g++-12,,,xvfb-run,4.0,", webkitgtk4.0",
package,linux,ubuntu-22.04,host,14,gnu,-12,Ninja Multi-Config,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,gcc-12 g++-12,,,xvfb-run,4.0,", webkitgtk4.0",
package,linux,ubuntu-22.04,host,17,gnu,-12,Ninja Multi-Config,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,gcc-12 g++-12,,,xvfb-run,4.0,", webkitgtk4.0",
package,linux,ubuntu-22.04,host,20,gnu,-12,Ninja Multi-Config,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,gcc-12 g++-12,,,xvfb-run,4.0,", webkitgtk4.0",
package,linux,ubuntu-22.04,host,11,llvm,-15,Ninja Multi-Config,FALSE,TRUE,TRUE,TRUE,TRUE,TRUE,TRUE,FALSE,TRUE,bash,,,,clang-15 clang++-15 clang-tidy-15,,,xvfb-run,6.0,", webkitgtk6.0",
package,linux,ubuntu-22.04,host,14,llvm,-15,Ninja Multi-Config,TRUE,TRUE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,clang-15 clang++-15 clang-tidy-15,,,xvfb-run,6.0,", webkitgtk6.0",
package,linux,ubuntu-22.04,host,17,llvm,-15,Ninja Multi-Config,TRUE,TRUE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,clang-15 clang++-15 clang-tidy-15,,,xvfb-run,6.0,", webkitgtk6.0",
package,linux,ubuntu-22.04,host,20,llvm,-15,Ninja Multi-Config,TRUE,TRUE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,clang-15 clang++-15 clang-tidy-15,,,xvfb-run,6.0,", webkitgtk6.0",
package,linux,ubuntu-22.04,host,23,llvm,-15,Ninja Multi-Config,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,clang-15 clang++-15 clang-tidy-15,,,xvfb-run,6.0,", webkitgtk6.0",Checks disabled because clang-tidy-15 segfaults
package,linux,ubuntu-22.04,host,11,llvm,-15,Ninja Multi-Config,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,clang-15 clang++-15 clang-tidy-15,,,xvfb-run,4.1,", webkitgtk4.1",
package,linux,ubuntu-22.04,host,14,llvm,-15,Ninja Multi-Config,TRUE,TRUE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,clang-15 clang++-15 clang-tidy-15,,,xvfb-run,4.1,", webkitgtk4.1",
package,linux,ubuntu-22.04,host,17,llvm,-15,Ninja Multi-Config,TRUE,TRUE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,clang-15 clang++-15 clang-tidy-15,,,xvfb-run,4.1,", webkitgtk4.1",
package,linux,ubuntu-22.04,host,20,llvm,-15,Ninja Multi-Config,TRUE,TRUE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,clang-15 clang++-15 clang-tidy-15,,,xvfb-run,4.1,", webkitgtk4.1",
package,linux,ubuntu-22.04,host,23,llvm,-15,Ninja Multi-Config,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,clang-15 clang++-15 clang-tidy-15,,,xvfb-run,4.1,", webkitgtk4.1",Checks disabled because clang-tidy-15 segfaults
package,linux,ubuntu-22.04,host,11,llvm,-15,Ninja Multi-Config,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,clang-15 clang++-15 clang-tidy-15,,,xvfb-run,4.0,", webkitgtk4.0",
package,linux,ubuntu-22.04,host,14,llvm,-15,Ninja Multi-Config,TRUE,TRUE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,clang-15 clang++-15 clang-tidy-15,,,xvfb-run,4.0,", webkitgtk4.0",
package,linux,ubuntu-22.04,host,17,llvm,-15,Ninja Multi-Config,TRUE,TRUE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,clang-15 clang++-15 clang-tidy-15,,,xvfb-run,4.0,", webkitgtk4.0",
package,linux,ubuntu-22.04,host,20,llvm,-15,Ninja Multi-Config,TRUE,TRUE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,clang-15 clang++-15 clang-tidy-15,,,xvfb-run,4.0,", webkitgtk4.0",
package,linux,ubuntu-22.04,host,11,gnu,-10,Ninja Multi-Config,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,gcc-10 g++-10,,,xvfb-run,4.0,", webkitgtk4.0",Previously used the ubuntu-20.04 image where GCC 10 was latest
package,linux,ubuntu-22.04,host,11,llvm,-12,Ninja Multi-Config,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,clang-12 clang++-12 clang-tidy-12,,,xvfb-run,4.0,", webkitgtk4.0",Previously used the ubuntu-20.04 image where Clang 12 was latest
package,macos,macos-14,universal,11,macos-llvm,,Xcode,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,TRUE,FALSE,bash,,,,,,10.9,,,,
package,macos,macos-14,universal,14,macos-llvm,,Xcode,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,,,10.9,,,,
package,macos,macos-14,universal,17,macos-llvm,,Xcode,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,,,10.9,,,,
package,macos,macos-14,universal,20,macos-llvm,,Xcode,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,,,10.9,,,,
package,macos,macos-14,universal,23,macos-llvm,,Xcode,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,,,10.9,,,,
package,windows,ubuntu-22.04,x86_64,11,w64-mingw32,-posix,Ninja Multi-Config,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,mingw-w64,,,,,,
package,windows,ubuntu-22.04,x86_64,14,w64-mingw32,-posix,Ninja Multi-Config,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,mingw-w64,,,,,,
package,windows,ubuntu-22.04,x86_64,17,w64-mingw32,-posix,Ninja Multi-Config,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,mingw-w64,,,,,,
package,windows,ubuntu-22.04,x86_64,20,w64-mingw32,-posix,Ninja Multi-Config,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,mingw-w64,,,,,,
package,windows,ubuntu-22.04,i686,11,w64-mingw32,-posix,Ninja Multi-Config,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,mingw-w64,,,,,,
package,windows,windows-2022,arm64,14,windows-msvc,,Visual Studio 17 2022,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,TRUE,FALSE,bash,TRUE,,,,,,,,", mt",
package,windows,windows-2022,x86_64,14,windows-msvc,,Visual Studio 17 2022,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,TRUE,FALSE,bash,TRUE,,,,,,,,", mt",
package,windows,windows-2022,i686,14,windows-msvc,,Visual Studio 17 2022,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,TRUE,FALSE,bash,TRUE,,,,,,,,", mt",
package,windows,windows-2022,arm64,14,windows-msvc,,Visual Studio 17 2022,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,TRUE,FALSE,bash,FALSE,,,,,,,,", md",
package,windows,windows-2022,x86_64,14,windows-msvc,,Visual Studio 17 2022,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,TRUE,FALSE,bash,FALSE,,,,,,,,", md",
package,windows,windows-2022,x86_64,17,windows-msvc,,Visual Studio 17 2022,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,FALSE,,,,,,,,", md",
package,windows,windows-2022,x86_64,20,windows-msvc,,Visual Studio 17 2022,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,FALSE,,,,,,,,", md",
package,windows,windows-2022,x86_64,23,windows-msvc,,Visual Studio 17 2022,TRUE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,FALSE,,,,,,,,", md",
package,windows,windows-2022,i686,14,windows-msvc,,Visual Studio 17 2022,FALSE,FALSE,TRUE,TRUE,FALSE,FALSE,FALSE,TRUE,FALSE,bash,FALSE,,,,,,,,", md",
package,windows,windows-2022,x86_64,11,msys2-gnu-ucrt64,,Ninja Multi-Config,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,msys2 {0},,UCRT64,,,,,,,", UCRT64",
package,windows,windows-2022,x86_64,11,msys2-llvm-clang64,,Ninja Multi-Config,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,msys2 {0},,CLANG64,clang-tools-extra:p,,,,,,", CLANG64",Please enable strict clang-tidy when issues have been fixed.
package,windows,windows-2022,x86_64,14,msys2-llvm-clang64,,Ninja Multi-Config,TRUE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,msys2 {0},,CLANG64,clang-tools-extra:p,,,,,,", CLANG64",Please enable strict clang-tidy when issues have been fixed.
package,windows,windows-2022,x86_64,17,msys2-llvm-clang64,,Ninja Multi-Config,TRUE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,msys2 {0},,CLANG64,clang-tools-extra:p,,,,,,", CLANG64",Please enable strict clang-tidy when issues have been fixed.
package,windows,windows-2022,x86_64,20,msys2-llvm-clang64,,Ninja Multi-Config,TRUE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,msys2 {0},,CLANG64,clang-tools-extra:p,,,,,,", CLANG64",Please enable strict clang-tidy when issues have been fixed.
package,windows,windows-2022,x86_64,23,msys2-llvm-clang64,,Ninja Multi-Config,TRUE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,msys2 {0},,CLANG64,clang-tools-extra:p,,,,,,", CLANG64",Please enable strict clang-tidy when issues have been fixed.
coverage,linux,ubuntu-22.04,host,11,llvm,,Ninja Multi-Config,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,clang-15 clang++-15 clang-tidy-15,llvm-cov-15 gcov,,xvfb-run,6.0,", webkitgtk6.0",
coverage,linux,ubuntu-22.04,host,11,llvm,,Ninja Multi-Config,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,clang-15 clang++-15 clang-tidy-15,llvm-cov-15 gcov,,xvfb-run,4.1,", webkitgtk4.1",
coverage,linux,ubuntu-22.04,host,11,llvm,-15,Ninja Multi-Config,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,clang-15 clang++-15 clang-tidy-15,llvm-cov-15 gcov,,xvfb-run,4.0,", webkitgtk4.0",
coverage,macos,macos-14,universal,11,macos-llvm,-15,Xcode,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,bash,,,,,xcrun llvm-cov gcov,,,,,
coverage,windows,windows-2022,x86_64,11,msys2-llvm-clang64,,Ninja Multi-Config,FALSE,FALSE,TRUE,FALSE,FALSE,FALSE,FALSE,FALSE,FALSE,msys2 {0},,CLANG64,,,llvm-cov gcov,,,,", CLANG64",


================================================
FILE: .github/workflows/build_matrix_schema.json
================================================
{
    "apt": "string",
    "arch": "string",
    "checks": "boolean",
    "comments": "string",
    "cxx-std": "number",
    "gcov": "string",
    "generator": "string",
    "image": "string",
    "job-name-suffix": "string",
    "job-type": "string",
    "msvc-mt": "boolean",
    "msys": "string",
    "msys-pacboy": "string",
    "os": "string",
    "osx-deployment-target": "string",
    "package": "boolean",
    "package-amalgamation": "boolean",
    "package-docs": "boolean",
    "package-headers": "boolean",
    "package-lib": "boolean",
    "package-source": "boolean",
    "pr-only": "boolean",
    "shell": "string",
    "strict-clang-tidy": "boolean",
    "test-wrapper-cmd": "string",
    "toolchain": "string",
    "toolchain-executable-suffix": "string",
    "webkitgtk-api": "string"
}


================================================
FILE: .github/workflows/check.yaml
================================================
name: Check
on:
  workflow_call:
jobs:
  format:
    runs-on: ubuntu-22.04
    steps:
      - uses: actions/checkout@v4
      - run: sudo apt-get update
      - run: sudo apt-get install --no-install-recommends -y clang-format-15
      - run: cmake -B build -S . -D WEBVIEW_BUILD=OFF -D WEBVIEW_CLANG_FORMAT_EXE=clang-format-15
      - run: cmake --build build --target webview_format_check

  amalgamate:
    runs-on: ${{ matrix.image }}
    strategy:
      fail-fast: false
      matrix:
        image:
          - macos-14
          - ubuntu-22.04
          - windows-2022
        python-version:
          - "3.9"
          - "3.10"
          - "3.11"
          - "3.12"
        build-type:
          - header
          - shared
          - static
        include:
          - image: macos-14
            clang-format-exe: clang-format
          - image: ubuntu-22.04
            clang-format-exe: clang-format-15
            test-wrapper-cmd: xvfb-run
          - image: windows-2022
            clang-format-exe: clang-format
    steps:
      - uses: actions/checkout@v4

      - name: Set up environment
        uses: ./.github/actions/setup-env
        with:
          apt: gcc-12 g++-12
          msys-pacboy: clang-tools-extra:p
          webkitgtk-api: "6.0"

      - name: Install dependencies (Linux)
        if: runner.os == 'Linux'
        run: sudo apt-get update && sudo apt-get install --no-install-recommends -y clang-format-15

      - name: Install dependencies (macOS)
        if: runner.os == 'macOS'
        run: brew install clang-format

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}

      - name: Generate amalgamated header
        run: |
          python3 scripts/amalgamate/amalgamate.py \
            --clang-format-exe "${{ matrix.clang-format-exe }}" \
            --base core \
            --search include \
            --output scripts/amalgamate/generated/webview_amalgamation.h \
            src
        shell: bash

      - name: Test (${{ matrix.build-type }}, Linux)
        if: runner.os == 'Linux'
        run: |
          mkdir -p build
          if [[ "${{ matrix.build-type }}" == "header" ]]; then
            c++ main.cc --std=c++11 $(pkg-config --cflags --libs gtk4 webkitgtk-6.0) -ldl -I../generated -o build/main
          elif [[ "${{ matrix.build-type }}" == "shared" ]]; then
            c++ webview.cc --shared --std=c++11 -fPIC $(pkg-config --cflags --libs gtk4 webkitgtk-6.0) -ldl -I../generated -DWEBVIEW_BUILD_SHARED -o build/libwebview.so
            cc main.c build/libwebview.so --std=c99 -I../generated -DWEBVIEW_SHARED -o build/main
          elif [[ "${{ matrix.build-type }}" == "static" ]]; then
            c++ webview.cc -c --std=c++11 $(pkg-config --cflags gtk4 webkitgtk-6.0) -ldl -I../generated -DWEBVIEW_STATIC -o build/webview.o
            cc main.c build/webview.o --std=c99 $(pkg-config --libs gtk4 webkitgtk-6.0) -lstdc++ -I../generated -DWEBVIEW_STATIC -o build/main
          fi
          xvfb-run build/main
        shell: bash
        working-directory: scripts/amalgamate/test

      - name: Test (${{ matrix.build-type }}, macOS)
        if: runner.os == 'macOS'
        run: |
          mkdir -p build
          if [[ "${{ matrix.build-type }}" == "header" ]]; then
            c++ main.cc --std=c++11 -framework WebKit -ldl -I../generated -o build/main
          elif [[ "${{ matrix.build-type }}" == "shared" ]]; then
            c++ webview.cc --shared --std=c++11 -fPIC -framework WebKit -ldl -I../generated -DWEBVIEW_BUILD_SHARED -o build/libwebview.so
            cc main.c build/libwebview.so --std=c99 -I../generated -DWEBVIEW_SHARED -o build/main
          elif [[ "${{ matrix.build-type }}" == "static" ]]; then
            c++ webview.cc -c --std=c++11 -framework WebKit -ldl -I../generated -DWEBVIEW_STATIC -o build/webview.o
            cc main.c build/webview.o --std=c99 -framework WebKit -lstdc++ -I../generated -DWEBVIEW_STATIC -o build/main
          fi
          build/main
        shell: bash
        working-directory: scripts/amalgamate/test

      - name: Test (${{ matrix.build-type }}, Windows)
        if: runner.os == 'Windows'
        run: |
          mswebview2_version=1.0.1150.38
          mswebview2_zip=$(mktemp)
          mswebview2_dir=$(mktemp -d)
          mswebview2_include_dir="${mswebview2_dir}/build/native/include"
          curl -sSLo "${mswebview2_zip}" "https://www.nuget.org/api/v2/package/Microsoft.Web.WebView2/${mswebview2_version}"
          unzip -q "${mswebview2_zip}" -d "${mswebview2_dir}"
          libs=(-ladvapi32 -lole32 -lshell32 -lshlwapi -luser32 -lversion)
          mkdir -p build
          if [[ "${{ matrix.build-type }}" == "header" ]]; then
            g++ main.cc --std=c++14  "${libs[@]}" "-I${mswebview2_include_dir}" -I../generated -o build/main
          elif [[ "${{ matrix.build-type }}" == "shared" ]]; then
            g++ webview.cc --shared --std=c++14 -fPIC  "${libs[@]}" "-I${mswebview2_include_dir}" -I../generated -DWEBVIEW_BUILD_SHARED -o build/libwebview.so
            gcc main.c build/libwebview.so --std=c99 -I../generated -DWEBVIEW_SHARED -o build/main
          elif [[ "${{ matrix.build-type }}" == "static" ]]; then
            g++ webview.cc -c --std=c++14 "-I${mswebview2_include_dir}" -I../generated -DWEBVIEW_STATIC -o build/webview.o
            gcc main.c build/webview.o --std=c99 "${libs[@]}" -lstdc++ -I../generated -DWEBVIEW_STATIC -o build/main
          fi
          build/main
        shell: bash
        working-directory: scripts/amalgamate/test


================================================
FILE: .github/workflows/ci.yaml
================================================
name: CI
on: [push, pull_request]
defaults:
  run:
    shell: bash
jobs:
  init:
    runs-on: ubuntu-22.04
    outputs:
      gcovr-version: ${{ steps.vars.outputs.gcovr-version }}
    steps:
      - id: vars
        run: |
          echo "gcovr-version=7.2" >> "${GITHUB_OUTPUT}"

  check:
    uses: ./.github/workflows/check.yaml

  build:
    needs:
      - check
      - init
    uses: ./.github/workflows/build.yaml
    with:
      gcovr-version: ${{ needs.init.outputs.gcovr-version }}

  build-pr:
    if: github.event_name == 'pull_request'
    needs:
      - check
      - init
    uses: ./.github/workflows/build.yaml
    with:
      gcovr-version: ${{ needs.init.outputs.gcovr-version }}
      pr: true

  merge-package-artifacts:
    needs: build
    runs-on: ubuntu-22.04
    steps:
      - name: Merge package artifacts
        uses: actions/upload-artifact/merge@v4
        with:
          name: package
          pattern: package_*
          delete-merged: true
          retention-days: 1

  generate-coverage-report:
    needs:
      - build
      - init
    runs-on: ubuntu-22.04
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Install Python
        run: >
          sudo apt-get update && sudo apt-get install --no-install-recommends -y
          python3
          python3-lxml
          python3-markupsafe
          python3-pip

      - name: Install gcovr
        run: pip install "gcovr==${{ needs.init.outputs.gcovr-version }}"

      - name: Merge test coverage artifacts
        uses: actions/upload-artifact/merge@v4
        with:
          name: test_coverage_data
          pattern: test_coverage_data_*
          delete-merged: true
          retention-days: 1
          separate-directories: true

      - name: Download merged test coverage artifacts
        uses: actions/download-artifact@v4
        with:
          name: test_coverage_data

      - name: Generate report
        id: generate-report
        run: |
          tracefile_args=()
          while read f; do
            tracefile_args+=(--add-tracefile "${f}")
          done <<< "$(find . -type f -name "coverage.json")"

          artifact_dir="temp_${RANDOM}/report"
          mkdir -p "${artifact_dir}/html"

          gcovr --config gcovr.ci.cfg --json "${artifact_dir}/gcovr.json" "${tracefile_args[@]}"
          gcovr --config gcovr.ci.cfg --coveralls "${artifact_dir}/coveralls.json" --add-tracefile "${artifact_dir}/gcovr.json"
          gcovr --config gcovr.ci.cfg --json-summary "${artifact_dir}/summary.json" --add-tracefile "${artifact_dir}/gcovr.json"
          gcovr --config gcovr.ci.cfg --html-details "${artifact_dir}/html/index.html" --add-tracefile "${artifact_dir}/gcovr.json"

          echo "upload-dir=${artifact_dir}" >> "${GITHUB_OUTPUT}"

      - name: Upload report artifacts
        uses: actions/upload-artifact@v4
        with:
          name: test_coverage_report
          path: ${{ steps.generate-report.outputs.upload-dir }}
          retention-days: 1
          if-no-files-found: error

      - name: Add report to CI job summary
        uses: actions/github-script@v7
        with:
          script: |
            const numberOr = (value, alternative) => Number.isNaN(value = parseInt(value)) ? alternative : value;
            const percentValue = (value, percentSymbol = "%") => numberOr(value, "-") + percentSymbol;
            const data = require("./${{ steps.generate-report.outputs.upload-dir }}/summary.json");
            await core.summary
              .addHeading("Test Coverage Summary")
              .addTable([
                [
                  { data: "Lines", header: true },
                  { data: "Functions", header: true },
                  { data: "Branches", header: true }
                ],
                [
                  `${percentValue(data.line_percent)} ${data.line_covered}/${data.line_total}`,
                  `${percentValue(data.function_percent)} ${data.function_covered}/${data.function_total}`,
                  `${percentValue(data.branch_percent)} ${data.branch_covered}/${data.branch_total}`
                ]
              ])
              .addTable([
                [
                  { data: "File", header: true },
                  { data: "Lines", header: true },
                  { data: "Functions", header: true },
                  { data: "Branches", header: true }
                ],
                ...data.files.map(file => [
                  file.filename,
                  `${percentValue(file.line_percent)} ${file.line_covered}/${file.line_total}`,
                  `${percentValue(file.function_percent)} ${file.function_covered}/${file.function_total}`,
                  `${percentValue(file.branch_percent)} ${file.branch_covered}/${file.branch_total}`
                ])
              ])
              .write();


================================================
FILE: .github/workflows/csv.js
================================================
/**
 * A simple CSV parser that should be "good enough" for basic needs.
 */

const fs = require("node:fs");

function parseRow(line) {
    const row = [];
    let quoted = false;
    let chars = [];
    for (let i = 0; i < line.length; ++i) {
        const c = line.charAt(i);
        const next = line.charAt(i + 1);
        if (quoted) {
            if (c !== '"') {
                chars.push(line.charCodeAt(i));
                continue;
            }
            if (next === '"') {
                chars.push(line.charCodeAt(i));
                ++i;
                continue;
            }
            quoted = false;
            continue;
        }
        switch (c) {
            case '"':
                if (next === '"') {
                    chars.push(line.charCodeAt(i));
                    ++i;
                    continue;
                }
                quoted = true;
                break;
            case ",":
                row.push(String.fromCodePoint(...chars));
                chars = [];
                break;
            default:
                chars.push(line.charCodeAt(i));
                break;
        }
    }
    row.push(String.fromCodePoint(...chars));
    return row;
}

function parseRows(lines) {
    return lines.map(parseRow);
}

function extractLines(content) {
    return content.split("\n").filter(s => s.length > 0);
}

function transform(key, value, schema) {
    const type = schema[key];
    const converters = {
        boolean(v) { return ["1", "true", "TRUE"].includes(v); },
        string(v) { return v; },
        number(v) { return parseInt(v); },
    };
    return converters[type](value);
}

function processRows(rows, schema) {
    if (rows.length === 0) {
        return [];
    }
    const result = [];
    const header = rows[0];
    if (rows.length === 1) {
        return result;
    }
    for (let i = 1; i < rows.length; ++i) {
        const rowObject = {};
        for (const j in header) {
            rowObject[header[j]] = transform(header[j], rows[i][j], schema);
        }
        result.push(rowObject);
    }
    return result;
}

function loadString(content, schema) {
    return processRows(parseRows(extractLines(content)), schema);
}

function loadFile(filePath, schema) {
    return loadString(fs.readFileSync(filePath, "utf-8"), schema);
}

module.exports = {
    loadString,
    loadFile
};


================================================
FILE: .github/workflows/draft-release.yaml
================================================
name: Draft Release
on:
  workflow_dispatch:
defaults:
  run:
    shell: bash
concurrency:
  group: ${{ github.ref }}
  cancel-in-progress: true
jobs:
  init:
    runs-on: ubuntu-22.04
    outputs:
      gcovr-version: ${{ steps.vars.outputs.gcovr-version }}
      release-tag: ${{ steps.vars.outputs.release-tag }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - id: vars
        run: |
          version="$(cmake -P cmake/extract_version.cmake)"
          echo "gcovr-version=7.2" >> "${GITHUB_OUTPUT}"
          echo "release-tag=${version}" >> "${GITHUB_OUTPUT}"

  check:
    uses: ./.github/workflows/check.yaml

  build:
    needs:
      - check
      - init
    uses: ./.github/workflows/build.yaml
    with:
      coverage: false
      gcovr-version: ${{ needs.init.outputs.gcovr-version }}

  process-artifacts:
    needs: build
    runs-on: ubuntu-22.04
    steps:
      - name: Merge package artifacts
        uses: actions/upload-artifact/merge@v4
        with:
          name: package
          pattern: package_*
          delete-merged: true
          retention-days: 1

      - name: Download package artifacts
        uses: actions/download-artifact@v4
        with:
          name: package
          path: dist

      - name: Create checksum file
        run: sha256sum * > SHA256SUMS
        working-directory: dist
        shell: bash

      - name: Upload checksum artifacts
        uses: actions/upload-artifact@v4
        with:
          name: package_checksum
          path: dist/*SUMS
          retention-days: 1
          if-no-files-found: error

  create-github-release-draft:
    needs:
      - process-artifacts
      - init
    runs-on: ubuntu-22.04
    permissions:
      contents: write
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Download package artifacts
        uses: actions/download-artifact@v4
        with:
          pattern: package*
          path: dist
          merge-multiple: true

      - name: List artifacts
        run: find dist/

      - name: Verify checksums
        run: sha256sum --check SHA256SUMS
        working-directory: dist

      - name: Create GitHub Release
        env:
          GH_TOKEN: ${{ github.token }}
          RELEASE_TAG: ${{ needs.init.outputs.release-tag }}
        run: gh release create --draft "${RELEASE_TAG}" dist/*


================================================
FILE: .gitignore
================================================
# Build artifacts
/build


================================================
FILE: CHANGELOG.md
================================================
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [0.12.0] - 2024-09-11

### Added

- Use CMake `cxx_std_11` compile feature ([#1135](https://github.com/webview/webview/pull/1135))

### Fixed

- ODR issues caused by functions not being marked with `inline` ([#1138](https://github.com/webview/webview/pull/1138))

### Breaking Changes

- Synchronize CMake alias targets and export names ([#1140](https://github.com/webview/webview/pull/1140))

## [0.11.0] - 2024-08-29

### Added

- New compile-time options for controlling `WEBVIEW_API` ([#893](https://github.com/webview/webview/pull/893))
- Support for WebKitGTK API 4.1 ([#1022](https://github.com/webview/webview/pull/1022))
- Support for WebKitGTK API 6.0 and GTK 4 ([#1125](https://github.com/webview/webview/pull/1125))
- CMake build system ([#1130](https://github.com/webview/webview/pull/1130))

### Changed

- Disable status bar (Windows/WebView2) ([#1028](https://github.com/webview/webview/pull/1028))
- Reworked handling and reporting of errors ([#1099](https://github.com/webview/webview/pull/1099))

### Breaking Changes

- `WEBVIEW_API` is now `inline` by default for C++ ([#893](https://github.com/webview/webview/pull/893))
- Treat result of binding function as JSON, not JS ([#1002](https://github.com/webview/webview/pull/1002))
- App lifecycle separation ([#1005](https://github.com/webview/webview/pull/1005))

## [0.10.0] - 2023-09-16

This is the first release since the library rewrite by [zserge](https://github.com/zserge) ([#315](https://github.com/webview/webview/pull/315)), and is a necessary one that allows us to prepare for future changes in the library.

Due to the vast amount of contributions that are in this release on top of the changes and removals introduced in the library rewrite, we've picked a few contributions aside from the rewrite that had a significant impact compared to the previous release.

### Added

Windows:

- Microsoft Edge WebView2 backend ([#315](https://github.com/webview/webview/pull/315))
- Custom WebView2Loader implementation ([#783](https://github.com/webview/webview/pull/783))
- DPI scaling for Windows 10 and later ([#982](https://github.com/webview/webview/pull/982))
- Add support for dark title bar on Windows 10 and later ([#996](https://github.com/webview/webview/pull/996))

### Removed

- MSHTML backend ([#315](https://github.com/webview/webview/pull/315))
- Go binding ([#1009](https://github.com/webview/webview/pull/1009)) — moved to [webview/webview_go](https://github.com/webview/webview_go)

## [0.1.1] - 2020-01-21

## [0.1.0] - 2018-05-09

[unreleased]: https://github.com/webview/webview/compare/0.12.0...HEAD
[0.12.0]:     https://github.com/webview/webview/compare/0.11.0...0.12.0
[0.11.0]:     https://github.com/webview/webview/compare/0.10.0...0.11.0
[0.10.0]:     https://github.com/webview/webview/compare/0.1.1...0.10.0
[0.1.1]:      https://github.com/webview/webview/compare/0.1.0...0.1.1
[0.1.0]:      https://github.com/webview/webview/releases/tag/0.1.0


================================================
FILE: CMakeLists.txt
================================================
cmake_minimum_required(VERSION 3.16)

include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/internal.cmake")
webview_extract_version()

project(
    webview
    VERSION "${WEBVIEW_VERSION_NUMBER}"
    DESCRIPTION "A tiny cross-platform webview library for C/C++ to build modern cross-platform GUIs."
    HOMEPAGE_URL https://github.com/webview/webview)

webview_init()

if(WEBVIEW_BUILD)
    add_subdirectory(compatibility)

    if(WEBVIEW_BUILD_TESTS)
        include(CTest)
        add_subdirectory(test_driver)
    endif()

    add_subdirectory(core)

    if(WEBVIEW_BUILD_EXAMPLES)
        add_subdirectory(examples)
    endif()

    if(WEBVIEW_BUILD_DOCS)
        add_subdirectory(docs)
    endif()

    if(WEBVIEW_INSTALL_TARGETS)
        webview_install_targets()
    endif()

    if(WEBVIEW_ENABLE_PACKAGING)
        add_subdirectory(packaging)
    endif()
endif()


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing

Contributing to the webview project is always welcome! We are especially in need of MacOs developers. Active maintainers who review pull requests and triage issues are listed here.
- @justjosias
- @dandeto
- @nicklasfrahm

### Guidelines for Contributing Examples

All examples will be held to the same standard as the main codebase.

Additionally, examples should...
- Be cross platform except under certain circumstances
- Highlight a subset of the webview library's API
- Be well documented
- Have a simple goal in mind and lack large dependencies
- Link to external libraries instead of copying them to the webview repo


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2017 Serge Zaitsev
Copyright (c) 2022 Steffen André Langnes

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: MIGRATION.md
================================================
# Migration

## v0.11.0 to v0.12.0

Some CMake targets names have been replaced in order to match the exported/installed target names:

Old target         | Replacement
----------         | -----------
`webview::headers` | `webview::core`
`webview::shared`  | `webview::core_shared`
`webview::static`  | `webview::core_static`

## v0.10.0 to v0.11.0

### New Defaults for `WEBVIEW_API`

Language | Old default | New default
-------- | ----------- | -----------
C++      | `extern`    | `inline`
C        | `extern`    | `extern`

If you relied on the old default being `extern` when using a C++ compiler then you should either define `WEBVIEW_STATIC` or `WEBVIEW_API=extern`.

### Behavior of `webview_return()`

`webview_return()` no longer evaluates the passed-in result as JavaScript but instead parses it as JSON. The new behavior is consistent with the documented behavior while the old behavior wasn't. Use `webview_eval()` if you need to evaluate JavaScript code.

### Application Lifecycle

If you relied on the library's management of the application lifecycle when passing in an existing window to the library then you should now either manage the lifecycle by yourself or let the library create the window.

Specific things that are now only done by the library when the window is created for you:

Platform | What
-------- | ----
Linux    | Call to `gtk_init_check()`.
Windows  | COM initialization and DPI awareness enablement.

## v0.1.1 to v0.10.0

1. Use opaque `webview_t` type instead of `struct webview`. Size, title and URL are controlled via API setter functions. Invoke callback has been replaced with `webview_bind()` and `webview_return()` to make native function bindings inter-operate with JS.
2. If you have been using simplified `webview()` API to only open a single URL
   in a webview window - this function has been removed. You now have to create
   a new webview instance, configure and run it explicitly.
3. `webview_init()` is replaced by `webview_create()` which creates a new webview instance.
4. `webview_exit()` has been replaced with more meaningful `webview_destroy()`.
5. Main UI loop with `webview_loop()` inside has been replaced with `webview_run()` runs infinitely until the webview window is closed.
6. `webview_terminate()` remains the same.
7. `webview_dispatch()` remains the same.
8. `webview_set_title()` remains the same.
9. `webview_set_color()` has been removed. Use `webview_get_window` and native
   window APIs to control colors, transparency and other native window
   properties. At some point these APIs might be brought back.
10. `webview_set_fullscreen()` has been removed, see above.
11. `webview_dialog()` has been removed. But I'd like to see it added back as a separate independent module or library.
12. `webview_eval()` remains the same.
13. `webview_inject_css()` has been removed. Use `webview_eval()` to create style tag manually.
14. `webview_debug()` has been removed. Use whatever fits best to your programming language and environment to debug your GUI apps.


================================================
FILE: README.md
================================================
# webview

<a href="https://discord.gg/24KMecn" title="Join the chat at Discord"><img src="https://assets-global.website-files.com/6257adef93867e50d84d30e2/636e0b5061df29d55a92d945_full_logo_blurple_RGB.svg" alt="Discord" height="20" /></a>
[![Build Status](https://img.shields.io/github/actions/workflow/status/webview/webview/ci.yaml?branch=master)](https://github.com/webview/webview/actions)

A tiny cross-platform webview library for C/C++ to build modern cross-platform GUIs.

The goal of the project is to create a common HTML5 UI abstraction layer for the most widely used platforms.

It supports two-way JavaScript bindings (to call JavaScript from C/C++ and to call C/C++ from JavaScript).

> [!NOTE]
> Language binding for Go [has moved][webview_go]. Versions <= 0.1.1 are available in *this* repository.

## Platform Support

Platform | Technologies
-------- | ------------
Linux    | [GTK][gtk], [WebKitGTK][webkitgtk]
macOS    | Cocoa, [WebKit][webkit]
Windows  | [Windows API][win32-api], [WebView2][ms-webview2]

## Documentation

The most up-to-date documentation is right in the source code. Improving the documentation is a continuous effort and you are more than welcome to contribute.

## Prerequisites

Your compiler must support minimum C++11.

This project uses CMake and Ninja, and while recommended for your convenience, these tools aren't required for using the library.

### Linux and BSD

The [GTK][gtk] and [WebKitGTK][webkitgtk] libraries are required for development and distribution. You need to check your package repositories regarding which packages to install.

#### Packages

* Debian:
  * WebKitGTK 6.0, GTK 4:
    * Development: `apt install libgtk-4-dev libwebkitgtk-6.0-dev`
    * Production: `apt install libgtk-4-1 libwebkitgtk-6.0-4`
  * WebKitGTK 4.1, GTK 3, libsoup 3:
    * Development: `apt install libgtk-3-dev libwebkit2gtk-4.1-dev`
    * Production: `apt install libgtk-3-0 libwebkit2gtk-4.1-0`
  * WebKitGTK 4.0, GTK 3, libsoup 2:
    * Development: `apt install libgtk-3-dev libwebkit2gtk-4.0-dev`
    * Production: `apt install libgtk-3-0 libwebkit2gtk-4.0-37`
* Fedora:
  * WebKitGTK 6.0, GTK 4:
    * Development: `dnf install gtk4-devel webkitgtk6.0-devel`
    * Production: `dnf install gtk4 webkitgtk6.0`
  * WebKitGTK 4.1, GTK 3, libsoup 3:
    * Development: `dnf install gtk3-devel webkit2gtk4.1-devel`
    * Production: `dnf install gtk3 webkit2gtk4.1`
  * WebKitGTK 4.0, GTK 3, libsoup 2:
    * Development: `dnf install gtk3-devel webkit2gtk4.0-devel`
    * Production: `dnf install gtk3 webkit2gtk4.0`
* FreeBSD:
  * GTK 4: `pkg install webkit2-gtk4`
  * GTK 3: `pkg install webkit2-gtk3`

#### Library Dependencies

* Linux:
  * Use `pkg-config` with `--cflags` and `--libs` to get the compiler/linker options for one of these sets of modules:
    * `gtk4 webkitgtk-6.0`
    * `gtk+-3.0 webkit2gtk-4.1`
    * `gtk+-3.0 webkit2gtk-4.0`
  * Link libraries: `dl`
* macOS:
  * Link frameworks: `WebKit`
  * Link libraries: `dl`
* Windows:
  * [WebView2 from NuGet](https://www.nuget.org/packages/Microsoft.Web.WebView2).
  * Windows libraries: `advapi32 ole32 shell32 shlwapi user32 version`

#### BSD

* Execution on BSD-based systems may require adding the `wxallowed` option (see [mount(8)](https://man.openbsd.org/mount.8))  to your fstab to bypass [W^X](https://en.wikipedia.org/wiki/W%5EX "write xor execute") memory protection for your executable. Please see if it works without disabling this security feature first.

### Windows

Your compiler must support C++14 and we recommend to pair it with an up-to-date Windows 10 SDK.

For Visual C++ we recommend Visual Studio 2022 or later. There are some [requirements when using MinGW-w64](#mingw-w64-requirements).

Developers and end-users must have the [WebView2 runtime][ms-webview2-rt] installed on their system for any version of Windows before Windows 11.

## Getting Started

If you are a developer of this project then please go to the [development section](#development).

You will have a working app, but you are encouraged to explore the [available examples][examples].

Create the following files in a new directory:

`.gitignore`:
```
# Build artifacts
/build
```

### C++ Example

`CMakeLists.txt`:
```cmake
cmake_minimum_required(VERSION 3.16)
project(example LANGUAGES CXX)

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")

include(FetchContent)

FetchContent_Declare(
    webview
    GIT_REPOSITORY https://github.com/webview/webview
    GIT_TAG 0.12.0)
FetchContent_MakeAvailable(webview)

add_executable(example WIN32)
target_sources(example PRIVATE main.cc)
target_link_libraries(example PRIVATE webview::core)
```

`main.cc`:
```cpp
#include "webview/webview.h"

#include <iostream>

#ifdef _WIN32
int WINAPI WinMain(HINSTANCE /*hInst*/, HINSTANCE /*hPrevInst*/,
                   LPSTR /*lpCmdLine*/, int /*nCmdShow*/) {
#else
int main() {
#endif
  try {
    webview::webview w(false, nullptr);
    w.set_title("Basic Example");
    w.set_size(480, 320, WEBVIEW_HINT_NONE);
    w.set_html("Thanks for using webview!");
    w.run();
  } catch (const webview::exception &e) {
    std::cerr << e.what() << '\n';
    return 1;
  }

  return 0;
}
```

### C Example

`CMakeLists.txt`:
```cmake
cmake_minimum_required(VERSION 3.16)
project(example LANGUAGES C CXX)

set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")

include(FetchContent)

FetchContent_Declare(
    webview
    GIT_REPOSITORY https://github.com/webview/webview
    GIT_TAG 0.12.0)
FetchContent_MakeAvailable(webview)

add_executable(example WIN32)
target_sources(example PRIVATE main.c)
target_link_libraries(example PRIVATE webview::core_static)
```

`main.c`:
```cpp
#include "webview/webview.h"
#include <stddef.h>

#ifdef _WIN32
#include <windows.h>
#endif

#ifdef _WIN32
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine,
                   int nCmdShow) {
  (void)hInst;
  (void)hPrevInst;
  (void)lpCmdLine;
  (void)nCmdShow;
#else
int main(void) {
#endif
  webview_t w = webview_create(0, NULL);
  webview_set_title(w, "Basic Example");
  webview_set_size(w, 480, 320, WEBVIEW_HINT_NONE);
  webview_set_html(w, "Thanks for using webview!");
  webview_run(w);
  webview_destroy(w);
  return 0;
}
```

### Building the Example

Build the project:

```sh
cmake -G Ninja -B build -S . -D CMAKE_BUILD_TYPE=Release
cmake --build build
```

Find the executable in the `build/bin` directory.

### Building Amalgamated Library

An amalgamated library can be built when building the project using CMake, or the `amalgamate.py` script can be invoked directly.

The latter is described below.

```sh
python3 scripts/amalgamate/amalgamate.py --base core --search include --output webview_amalgamation.h src
```

See `python3 scripts/amalgamate/amalgamate.py --help` for script usage.

### Non-CMake Usage

Here's an example for invoking GCC/Clang-like compilers directly. Use the `main.cc` file from the previous example.

Place either the amalgamated `webview.h` header or all of the individual files into `libs/webview`, and `WebView2.h` from [MS WebView2][ms-webview2-sdk] into `libs`.

Build the project on your chosen platform.

<details>
  <summary>macOS</summary>
  <pre><code>c++ main.cc -O2 --std=c++11 -Ilibs -framework WebKit -ldl -o example</code></pre>
</details>

<details>
  <summary>Linux</summary>
  <pre><code>c++ main.cc -O2 --std=c++11 -Ilibs $(pkg-config --cflags --libs gtk+-3.0 webkit2gtk-4.1) -ldl -o example</code></pre>
</details>

<details>
  <summary>Windows</summary>
  <pre><code>c++ main.cc -O2 --std=c++14 -static -mwindows -Ilibs -ladvapi32 -lole32 -lshell32 -lshlwapi -luser32 -lversion -o example</code></pre>
</details>

## Customization

### CMake Targets

The following CMake targets are available:

Name                   | Description
----                   | -----------
`webview::core`        | Headers for C++.
`webview::core_shared` | Shared library for C.
`webview::core_static` | Static library for C.

Special targets for on-demand checks and related tasks:

Name                   | Description
----                   | -----------
`webview_format_check` | Check files with clang-format.
`webview_reformat`     | Reformat files with clang-format.

### CMake Options

The following boolean options can be used when building the webview project standalone or when building it as part of your project (e.g. with FetchContent).

Option                            | Description
------                            | -----------
`WEBVIEW_BUILD`                   | Enable building
`WEBVIEW_BUILD_AMALGAMATION`      | Build amalgamated library
`WEBVIEW_BUILD_DOCS`              | Build documentation
`WEBVIEW_BUILD_EXAMPLES`          | Build examples
`WEBVIEW_BUILD_SHARED_LIBRARY`    | Build shared libraries
`WEBVIEW_BUILD_STATIC_LIBRARY`    | Build static libraries
`WEBVIEW_BUILD_TESTS`             | Build tests
`WEBVIEW_ENABLE_CHECKS`           | Enable checks
`WEBVIEW_ENABLE_CLANG_FORMAT`     | Enable clang-format
`WEBVIEW_ENABLE_CLANG_TIDY`       | Enable clang-tidy
`WEBVIEW_ENABLE_PACKAGING`        | Enable packaging
`WEBVIEW_INSTALL_DOCS`            | Install documentation
`WEBVIEW_INSTALL_TARGETS`         | Install targets
`WEBVIEW_IS_CI`                   | Initialized by the `CI` environment variable
`WEBVIEW_PACKAGE_AMALGAMATION`    | Package amalgamated library
`WEBVIEW_PACKAGE_DOCS`            | Package documentation
`WEBVIEW_PACKAGE_HEADERS`         | Package headers
`WEBVIEW_PACKAGE_LIB`             | Package compiled libraries
`WEBVIEW_STRICT_CHECKS`           | Make checks strict
`WEBVIEW_STRICT_CLANG_FORMAT`     | Make clang-format check strict
`WEBVIEW_STRICT_CLANG_TIDY`       | Make clang-tidy check strict
`WEBVIEW_USE_COMPAT_MINGW`        | Use compatibility helper for MinGW
`WEBVIEW_USE_STATIC_MSVC_RUNTIME` | Use static runtime library (MSVC)

> [!NOTE]
> Checks are *enabled* by default, but aren't *enforced* by default for local development (controlled by the `WEBVIEW_IS_CI` option).

Non-boolean options:

Option                            | Description
------                            | -----------
`WEBVIEW_CLANG_FORMAT_EXE`        | Path of the `clang-format` executable.
`WEBVIEW_CLANG_TIDY_EXE`          | Path of the `clang-tidy` executable.

### Package Consumer Options

These options can be used when when using the webview CMake package.

#### Linux-specific Options

Option                          | Description
------                          | -----------
`WEBVIEW_WEBKITGTK_API`         | WebKitGTK API to interface with, e.g. `6.0`, `4.1` (recommended) or `4.0`. This will also automatically decide the GTK version. Uses the latest recommended API by default if available, or the latest known and available API. Note that there can be major differences between API versions that can affect feature availability. See webview API documentation for details on feature availability.

#### Windows-specific Options

Option                          | Description
------                          | -----------
`WEBVIEW_MSWEBVIEW2_VERSION`    | MS WebView2 version, e.g. `1.0.1150.38`.
`WEBVIEW_USE_BUILTIN_MSWEBVIEW2`| Use built-in MS WebView2.

### Compile-time Options

These options can be specified as preprocessor macros to modify the build, but are not needed when using CMake.

#### C API Linkage

Name                   | Description
----                   | -----------
`WEBVIEW_API`          | Controls C API linkage, symbol visibility and whether it's a shared library. By default this is `inline` for C++ and `extern` for C.
`WEBVIEW_BUILD_SHARED` | Modifies `WEBVIEW_API` for building a shared library.
`WEBVIEW_SHARED`       | Modifies `WEBVIEW_API` for using a shared library.
`WEBVIEW_STATIC`       | Modifies `WEBVIEW_API` for building or using a static library.

#### Backend Selection

Name                   | Description
----                   | -----------
`WEBVIEW_GTK`          | Compile the GTK/WebKitGTK backend.
`WEBVIEW_COCOA`        | Compile the Cocoa/WebKit backend.
`WEBVIEW_EDGE`         | Compile the Win32/WebView2 backend.

#### Windows-specific Options

Option                            | Description
------                            | -----------
`WEBVIEW_MSWEBVIEW2_BUILTIN_IMPL` | Enables (`1`) or disables (`0`) the built-in implementation of the WebView2 loader. Enabling this avoids the need for `WebView2Loader.dll` but if the DLL is present then the DLL takes priority. This option is enabled by default.
`WEBVIEW_MSWEBVIEW2_EXPLICIT_LINK`| Enables (`1`) or disables (`0`) explicit linking of `WebView2Loader.dll`. Enabling this avoids the need for import libraries (`*.lib`). This option is enabled by default if `WEBVIEW_MSWEBVIEW2_BUILTIN_IMPL` is enabled.

## MinGW-w64 Requirements

In order to build this library using MinGW-w64 on Windows then it must support C++14 and have an up-to-date Windows SDK.

Distributions that are known to be compatible:

* [LLVM MinGW](https://github.com/mstorsjo/llvm-mingw)
* [MSYS2](https://www.msys2.org/)
* [WinLibs](https://winlibs.com/)

## MS WebView2 Loader

Linking the WebView2 loader part of the Microsoft WebView2 SDK is not a hard requirement when using our webview library, and neither is distributing `WebView2Loader.dll` with your app.

If, however, `WebView2Loader.dll` is loadable at runtime, e.g. from the executable's directory, then it will be used; otherwise our minimalistic implementation will be used instead.

Should you wish to use the official loader then remember to distribute it along with your app unless you link it statically. Linking it statically is possible with Visual C++ but not MinGW-w64.

Here are some of the noteworthy ways our implementation of the loader differs from the official implementation:

* Does not support configuring WebView2 using environment variables such as `WEBVIEW2_BROWSER_EXECUTABLE_FOLDER`.
* Microsoft Edge Insider (preview) channels are not supported.

[Customization options](#Customization) can be used to change how the library integrates the WebView2 loader.

## Thread Safety

Since library functions generally do not have thread safety guarantees, `webview_dispatch()` (C) / `webview::dispatch()` (C++) can be used to schedule code to execute on the main/GUI thread and thereby make that execution safe in multi-threaded applications.

`webview_return()` (C) / `webview::resolve()` (C++) uses `*dispatch()` internally and is therefore safe to call from another thread.

The main/GUI thread should be the thread that calls `webview_run()` (C) / `webview::run()` (C++).

## Development

This project uses the CMake build system.

### Development Dependencies

In addition to the dependencies mentioned earlier in this document for developing *with* the webview library, the following are used during development *of* the webview library.

* Amalgamation:
  * Python >= 3.9
* Checks:
  * `clang-format`
  * `clang-tidy`
* Documentation:
  * Doxygen
  * Graphvis

### Building

```sh
cmake -G "Ninja Multi-Config" -B build -S .
cmake --build build --config CONFIG
```

Replace `CONFIG` with one of `Debug`, `Release`, or `Profile`. Use `Profile` to enable code coverage (GCC/Clang).

Run tests:

```sh
ctest --test-dir build --build-config CONFIG
```

Generate test coverage report:

```sh
gcovr
```

Find the coverage report in `build/coverage`.

### Packaging

Run this after building the `Debug` and `Release` configs of the project:

```sh
cd build
cpack -G External -C "Debug;Release" --config CPackConfig.cmake
```

### Cross-compilation

See CMake toolchain files in the `cmake/toolchains` directory.

For example, this targets Windows x64 on Linux with POSIX threads:

```sh
cmake -G "Ninja Multi-Config" -B build -S . -D CMAKE_TOOLCHAIN_FILE=cmake/toolchains/x86_64-w64-mingw32.cmake -D WEBVIEW_TOOLCHAIN_EXECUTABLE_SUFFIX=-posix
cmake --build build --config CONFIG
```

## Limitations

### Browser Features

Since a browser engine is not a full web browser it may not support every feature you may expect from a browser. If you find that a feature does not work as expected then please consult with the browser engine's documentation and [open an issue][issues-new] if you think that the library should support it.

For example, the library does not attempt to support user interaction features like `alert()`, `confirm()` and `prompt()` and other non-essential features like `console.log()`.

## Bindings

Language    | Project
----------  | -------
Ada         | [thechampagne/webview-ada](https://github.com/thechampagne/webview-ada)
Bun         | [tr1ckydev/webview-bun](https://github.com/tr1ckydev/webview-bun)
C#          | [webview/webview_csharp](https://github.com/webview/webview_csharp)
C3          | [thechampagne/webview-c3](https://github.com/thechampagne/webview-c3)
Crystal     | [naqvis/webview](https://github.com/naqvis/webview)
D           | [thechampagne/webview-d](https://github.com/thechampagne/webview-d), [ronnie-w/webviewd](https://github.com/ronnie-w/webviewd)
Deno        | [webview/webview_deno](https://github.com/webview/webview_deno)
Go          | [webview/webview_go][webview_go]
Harbour     | [EricLendvai/Harbour_WebView](https://github.com/EricLendvai/Harbour_WebView)
Haskell     | [lettier/webviewhs](https://github.com/lettier/webviewhs)
Janet       | [janet-lang/webview](https://github.com/janet-lang/webview)
Java        | [webview/webview_java](https://github.com/webview/webview_java)
Kotlin      | [Winterreisender/webviewko](https://github.com/Winterreisender/webviewko)
MoonBit     | [justjavac/moonbit-webview](https://github.com/justjavac/moonbit-webview)
Nim         | [oskca/webview](https://github.com/oskca/webview), [neroist/webview](https://github.com/neroist/webview)
Node.js     | [Winterreisender/webview-nodejs](https://github.com/Winterreisender/webview-nodejs)
Odin        | [thechampagne/webview-odin](https://github.com/thechampagne/webview-odin)
Pascal      | [PierceNg/fpwebview](http://github.com/PierceNg/fpwebview)
Python      | [congzhangzh/webview_python](https://github.com/congzhangzh/webview_python),[zserge/webview-python](https://github.com/zserge/webview-python)
PHP         | [0hr/php-webview](https://github.com/0hr/php-webview), [KingBes/pebview](https://github.com/KingBes/pebview), [happystraw/php-ext-webview](https://github.com/happystraw/php-ext-webview)
Ring        | [ysdragon/webview](https://github.com/ysdragon/webview)
Ruby        | [Maaarcocr/webview_ruby](https://github.com/Maaarcocr/webview_ruby)
Rust        | [Boscop/web-view](https://github.com/Boscop/web-view)
Swift       | [jakenvac/SwiftWebview](https://github.com/jakenvac/SwiftWebview)
V           | [malisipi/mui](https://github.com/malisipi/mui/tree/main/webview), [ttytm/webview](https://github.com/ttytm/webview)
Vala        | [taozuhong/webview-vala](https://github.com/taozuhong/webview-vala)
Zig         | [thechampagne/webview-zig](https://github.com/thechampagne/webview-zig), [happystraw/zig-webview](https://github.com/happystraw/zig-webview)

If you wish to add bindings to the list, feel free to submit a pull request or [open an issue][issues-new].

## Generating Bindings

You can generate bindings for the library by yourself using the included SWIG interface (`webview.i`).

Here are some examples to get you started. Unix-style command lines are used for conciseness.

```sh
mkdir -p build/bindings/{python,csharp,java,ruby}
swig -c++ -python -outdir build/bindings/python -o build/bindings/python/python_wrap.cpp webview.i
swig -c++ -csharp -outdir build/bindings/csharp -o build/bindings/csharp/csharp_wrap.cpp webview.i
swig -c++ -java -outdir build/bindings/java -o build/bindings/java/java_wrap.cpp webview.i
swig -c++ -ruby -outdir build/bindings/ruby -o build/bindings/ruby/ruby_wrap.cpp webview.i
```

## License

Code is distributed under MIT license, feel free to use it in your proprietary projects as well.

[examples]:          https://github.com/webview/webview/tree/master/examples
[gtk]:               https://gtk.org/
[issues]:            https://github.com/webview/docs/issues
[issues-new]:        https://github.com/webview/webview/issues/new
[webkit]:            https://webkit.org/
[webkitgtk]:         https://webkitgtk.org/
[webview]:           https://github.com/webview/webview
[webview_go]:        https://github.com/webview/webview_go
[webview.dev]:       https://webview.dev
[ms-webview2]:       https://developer.microsoft.com/en-us/microsoft-edge/webview2/
[ms-webview2-sdk]:   https://www.nuget.org/packages/Microsoft.Web.WebView2
[ms-webview2-rt]:    https://developer.microsoft.com/en-us/microsoft-edge/webview2/
[win32-api]:         https://docs.microsoft.com/en-us/windows/win32/apiindex/windows-api-list


================================================
FILE: cmake/clang_format.cmake
================================================
file(TO_CMAKE_PATH "${BINARY_DIR}" BINARY_DIR)
file(TO_CMAKE_PATH "${SOURCE_DIR}" SOURCE_DIR)

file(GLOB_RECURSE TEMP_FILES
    ${SOURCE_DIR}/*.h
    ${SOURCE_DIR}/*.hh
    ${SOURCE_DIR}/*.hpp
    ${SOURCE_DIR}/*.hxx
    ${SOURCE_DIR}/*.c
    ${SOURCE_DIR}/*.cc
    ${SOURCE_DIR}/*.cpp
    ${SOURCE_DIR}/*.cxx)

set(FILES)
foreach(FILE IN LISTS TEMP_FILES)
    file(TO_CMAKE_PATH "${FILE}" FILE)
    if(NOT FILE MATCHES "^${BINARY_DIR}(/|$)")
        list(APPEND FILES "${FILE}")
    endif()
endforeach()

if(CMD STREQUAL "check")
    set(ARGS "--dry-run")
elseif(CMD STREQUAL "reformat")
    set(ARGS "-i")
endif()

if(STRICT)
    list(APPEND ARGS "--Werror")
endif()

execute_process(COMMAND "${CLANG_FORMAT_EXE}" ${ARGS} ${FILES}
    RESULT_VARIABLE RESULT)

if(NOT RESULT EQUAL 0 AND (STRICT OR NOT RESULT EQUAL 1))
    message(FATAL_ERROR "clang-format check failed.")
endif()


================================================
FILE: cmake/extract_version.cmake
================================================
# Extracts the library's version number and prints it to stdout.

include("${CMAKE_CURRENT_LIST_DIR}/internal.cmake")
webview_extract_version()
# Need this workaround because message() prints to stderr
execute_process(COMMAND ${CMAKE_COMMAND} -E echo "${WEBVIEW_VERSION}")


================================================
FILE: cmake/internal.cmake
================================================
set(WEBVIEW_CURRENT_CMAKE_DIR "${CMAKE_CURRENT_LIST_DIR}")
include("${WEBVIEW_CURRENT_CMAKE_DIR}/webview.cmake")

# Needed when we need the project directory before calling project()
set(WEBVIEW_ROOT_DIR "${WEBVIEW_CURRENT_CMAKE_DIR}/..")

macro(webview_init)
    include(CheckCXXSourceCompiles)
    include(CMakeDependentOption)
    include(CMakePackageConfigHelpers)
    include(GNUInstallDirs)

    list(APPEND CMAKE_MODULE_PATH "${WEBVIEW_CURRENT_CMAKE_DIR}/modules")

    enable_language(C CXX)

    webview_options()
    webview_internal_options()

    # Version 0.x of the library can't guarantee backward compatibility.
    if(WEBVIEW_VERSION_NUMBER VERSION_LESS 1.0)
        set(WEBVIEW_VERSION_COMPATIBILITY "${WEBVIEW_VERSION_MAJOR}.${WEBVIEW_VERSION_MINOR}")
    else()
        set(WEBVIEW_VERSION_COMPATIBILITY "${WEBVIEW_VERSION_NUMBER}")
    endif()

    # Hide symbols by default
    set(CMAKE_CXX_VISIBILITY_PRESET hidden)
    set(CMAKE_VISIBILITY_INLINES_HIDDEN YES)

    # Use debug postfix to separate debug/release binaries for the library
    set(CMAKE_DEBUG_POSTFIX d)

    if(WEBVIEW_IS_TOP_LEVEL_BUILD)
        # Add custom build types
        if(CMAKE_CONFIGURATION_TYPES)
            list(APPEND CMAKE_CONFIGURATION_TYPES Profile)
            list(REMOVE_DUPLICATES CMAKE_CONFIGURATION_TYPES)
            set(CMAKE_CONFIGURATION_TYPES "${CMAKE_CONFIGURATION_TYPES}" CACHE STRING "" FORCE)
        endif()

        # Use custom compiler/linker flags for the "Profile" build type
        if((CMAKE_C_COMPILER_ID MATCHES "((^GNU)|Clang)$") AND (CMAKE_CXX_COMPILER_ID MATCHES "((^GNU)|Clang)$"))
            set(CMAKE_C_FLAGS_PROFILE "-g -O0 -fprofile-arcs -ftest-coverage")
            set(CMAKE_CXX_FLAGS_PROFILE "-g -O0 -fprofile-arcs -ftest-coverage")
            set(CMAKE_EXE_LINKER_FLAGS_PROFILE "-fprofile-arcs")
            set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "-fprofile-arcs")
        elseif(MSVC)
            # MSVC isn't supported but warnings are emitted if these variables are undefined
            set(CMAKE_C_FLAGS_PROFILE "/Od")
            set(CMAKE_CXX_FLAGS_PROFILE "/Od")
            set(CMAKE_EXE_LINKER_FLAGS_PROFILE "")
            set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "")
        endif()

        # Default language standards
        # All of CMAKE_<LANG>_STANDARD, CMAKE_<LANG>_REQUIRED and CMAKE_<LANG>_EXTENSIONS must be set
        # Note that we also use the cxx_std_11 compile feature for consumers
        set(CMAKE_C_STANDARD 99 CACHE STRING "")
        set(CMAKE_C_STANDARD_REQUIRED YES)
        set(CMAKE_C_EXTENSIONS NO)
        set(CMAKE_CXX_STANDARD 11 CACHE STRING "")
        set(CMAKE_CXX_STANDARD_REQUIRED YES)
        set(CMAKE_CXX_EXTENSIONS NO)

        # Enable output of compile commands
        set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

        # Enable compile warnings
        if(MSVC)
            add_compile_options(/W4)
        else()
            add_compile_options(-Wall -Wextra -Wpedantic)
        endif()

        # Set default build type for single-config generators
        get_property(IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
        if(NOT IS_MULTI_CONFIG AND NOT CMAKE_BUILD_TYPE)
            set(CMAKE_BUILD_TYPE Release CACHE STRING "" FORCE)
        endif()

        if(WEBVIEW_USE_STATIC_MSVC_RUNTIME AND MSVC AND NOT CMAKE_MSVC_RUNTIME_LIBRARY)
            # Use static MSVC runtime library
            set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
        endif()

        webview_set_install_rpath()

        if(WEBVIEW_ENABLE_CHECKS AND WEBVIEW_ENABLE_CLANG_FORMAT)
            # Allow skipping clang-format outside of CI environment

            webview_find_clang_format(${WEBVIEW_IS_CI})

            if(WEBVIEW_CLANG_FORMAT_FOUND)
                add_custom_target(webview_format_check ALL
                    COMMAND ${CMAKE_COMMAND}
                        -D CMD=check
                        -D "BINARY_DIR=${PROJECT_BINARY_DIR}"
                        -D "SOURCE_DIR=${PROJECT_SOURCE_DIR}"
                        -D "CLANG_FORMAT_EXE=${WEBVIEW_CLANG_FORMAT_EXE}"
                        -D "STRICT=$<AND:$<BOOL:${WEBVIEW_STRICT_CHECKS}>,$<BOOL:${WEBVIEW_STRICT_CLANG_FORMAT}>>"
                        -P "${WEBVIEW_CURRENT_CMAKE_DIR}/clang_format.cmake"
                    COMMENT "Checking files with clang-format..."
                    VERBATIM)
                add_custom_target(webview_reformat
                    COMMAND ${CMAKE_COMMAND}
                        -D CMD=reformat
                        -D "BINARY_DIR=${PROJECT_BINARY_DIR}"
                        -D "SOURCE_DIR=${PROJECT_SOURCE_DIR}"
                        -D "CLANG_FORMAT_EXE=${WEBVIEW_CLANG_FORMAT_EXE}"
                        -P "${WEBVIEW_CURRENT_CMAKE_DIR}/clang_format.cmake"
                    COMMENT "Reformatting files with clang-format..."
                    VERBATIM)
            else()
                message(WARNING "Skipping clang-format checks as clang-format was not found")
            endif()
        endif()

        if(WEBVIEW_ENABLE_CHECKS AND WEBVIEW_ENABLE_CLANG_TIDY)
            if((CMAKE_C_COMPILER_ID MATCHES "Clang$") AND (CMAKE_CXX_COMPILER_ID MATCHES "Clang$"))
                # Allow skipping clang-tidy outside of CI environment

                webview_find_clang_tidy(${WEBVIEW_IS_CI})

                if(WEBVIEW_CLANG_TIDY_FOUND)
                    set(WEBVIEW_CLANG_TIDY_ARGS)
                    if(WEBVIEW_STRICT_CHECKS AND WEBVIEW_STRICT_CLANG_TIDY)
                        list(APPEND WEBVIEW_CLANG_TIDY_ARGS "--warnings-as-errors=*")
                    endif()

                    set(CMAKE_C_CLANG_TIDY "${WEBVIEW_CLANG_TIDY_EXE}" ${WEBVIEW_CLANG_TIDY_ARGS})
                    set(CMAKE_CXX_CLANG_TIDY "${WEBVIEW_CLANG_TIDY_EXE}" ${WEBVIEW_CLANG_TIDY_ARGS})
                else()
                    message(WARNING "Skipping clang-tidy checks as clang-tidy was not found: ${WEBVIEW_CLANG_TIDY_EXE_HINT}")
                endif()
            else()
                # Skip check when clang isn't used with clang-tidy to avoid errors due to unsupported compiler flags
                # such as -fno-keep-inline-dllexport (tested GCC 14, Clang-Tidy 18)
                message(WARNING "Skipping clang-tidy checks with non-clang compiler.")
            endif()
        endif()
    endif()

    if(WEBVIEW_BUILD)
        webview_find_dependencies()
    endif()
endmacro()

function(webview_find_clang_format REQUIRED)
    if(WEBVIEW_CLANG_FORMAT_EXE)
        set(WEBVIEW_CLANG_FORMAT_FOUND TRUE PARENT_SCOPE)
        return()
    endif()
    set(CLANG_FORMAT_EXE_HINT "clang-format")
    set(FIND_ARGS WEBVIEW_CLANG_FORMAT_EXE "${CLANG_FORMAT_EXE_HINT}")
    if(REQUIRED)
        list(APPEND FIND_ARGS REQUIRED)
    endif()
    find_program(${FIND_ARGS})
    if(WEBVIEW_CLANG_FORMAT_EXE)
        set(WEBVIEW_CLANG_FORMAT_FOUND TRUE PARENT_SCOPE)
    else()
        set(WEBVIEW_CLANG_FORMAT_FOUND FALSE PARENT_SCOPE)
    endif()
endfunction()

function(webview_find_clang_tidy REQUIRED)
    if(WEBVIEW_CLANG_TIDY_EXE)
        set(WEBVIEW_CLANG_TIDY_FOUND TRUE PARENT_SCOPE)
        return()
    endif()
    # Using WEBVIEW_TOOLCHAIN_EXECUTABLE_SUFFIX here because we pair clang-tidy with the clang compiler
    set(WEBVIEW_CLANG_TIDY_EXE_HINT "clang-tidy${WEBVIEW_TOOLCHAIN_EXECUTABLE_SUFFIX}")
    set(FIND_ARGS WEBVIEW_CLANG_TIDY_EXE "${WEBVIEW_CLANG_TIDY_EXE_HINT}")
    if(REQUIRED)
        list(APPEND FIND_ARGS REQUIRED)
    endif()
    find_program(${FIND_ARGS})
    if(WEBVIEW_CLANG_TIDY_EXE)
        set(WEBVIEW_CLANG_TIDY_FOUND TRUE PARENT_SCOPE)
    else()
        set(WEBVIEW_CLANG_TIDY_FOUND FALSE PARENT_SCOPE)
    endif()
endfunction()

function(webview_find_doxygen REQUIRED)
    if(REQUIRED)
        list(APPEND FIND_ARGS REQUIRED)
    endif()
    list(APPEND FIND_ARGS COMPONENTS dot)
    find_package(Doxygen ${FIND_ARGS})
    set(Doxygen_FOUND "${Doxygen_FOUND}" PARENT_SCOPE)
    set(Doxygen_FOUND_EXECUTABLE "${Doxygen_FOUND_EXECUTABLE}" PARENT_SCOPE)
endfunction()

function(webview_find_python3 REQUIRED)
    if(REQUIRED)
        list(APPEND FIND_ARGS REQUIRED)
    endif()
    find_package(Python3 ${FIND_ARGS})
    set(Python3_FOUND "${Python3_FOUND}" PARENT_SCOPE)
    set(Python3_EXECUTABLE "${Python3_EXECUTABLE}" PARENT_SCOPE)
endfunction()

macro(webview_extract_version)
    file(READ "${WEBVIEW_ROOT_DIR}/core/include/webview/version.h" WEBVIEW_H_CONTENT)

    if(NOT DEFINED WEBVIEW_VERSION_MAJOR)
        string(REGEX MATCH "#define WEBVIEW_VERSION_MAJOR ([0-9]+)" WEBVIEW_VERSION_MAJOR_MATCH "${WEBVIEW_H_CONTENT}")
        set(WEBVIEW_VERSION_MAJOR "${CMAKE_MATCH_1}")
    endif()

    if(NOT DEFINED WEBVIEW_VERSION_MINOR)
        string(REGEX MATCH "#define WEBVIEW_VERSION_MINOR ([0-9]+)" WEBVIEW_VERSION_MINOR_MATCH "${WEBVIEW_H_CONTENT}")
        set(WEBVIEW_VERSION_MINOR "${CMAKE_MATCH_1}")
    endif()

    if(NOT DEFINED WEBVIEW_VERSION_PATCH)
        string(REGEX MATCH "#define WEBVIEW_VERSION_PATCH ([0-9]+)" WEBVIEW_VERSION_PATCH_MATCH "${WEBVIEW_H_CONTENT}")
        set(WEBVIEW_VERSION_PATCH "${CMAKE_MATCH_1}")
    endif()

    if(NOT DEFINED WEBVIEW_VERSION_PRE_RELEASE)
        string(REGEX MATCH "#define WEBVIEW_VERSION_PRE_RELEASE \"([^\"]*)\"" WEBVIEW_VERSION_PRE_RELEASE_MATCH "${WEBVIEW_H_CONTENT}")
        set(WEBVIEW_VERSION_PRE_RELEASE "${CMAKE_MATCH_1}")
    endif()

    if(NOT DEFINED WEBVIEW_VERSION_BUILD_METADATA)
        string(REGEX MATCH "#define WEBVIEW_VERSION_BUILD_METADATA \"([^\"]*)\"" WEBVIEW_VERSION_BUILD_METADATA_MATCH "${WEBVIEW_H_CONTENT}")
        set(WEBVIEW_VERSION_BUILD_METADATA "${CMAKE_MATCH_1}")
    endif()

    set(WEBVIEW_VERSION_NUMBER "${WEBVIEW_VERSION_MAJOR}.${WEBVIEW_VERSION_MINOR}.${WEBVIEW_VERSION_PATCH}")
    set(WEBVIEW_VERSION "${WEBVIEW_VERSION_NUMBER}${WEBVIEW_VERSION_PRE_RELEASE}${WEBVIEW_VERSION_BUILD_METADATA}")
endmacro()

macro(webview_install_targets)
    # Install headers
    install(DIRECTORY "${WEBVIEW_ROOT_DIR}/core/include/webview"
        DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
        COMPONENT webview_headers)

    # Install modules
    install(DIRECTORY "${WEBVIEW_CURRENT_CMAKE_DIR}/modules"
        DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/webview"
        COMPONENT webview_cmake)

    # Install targets
    list(APPEND WEBVIEW_INSTALL_TARGET_NAMES webview_core_headers)

    if(WEBVIEW_BUILD_SHARED_LIBRARY)
        list(APPEND WEBVIEW_INSTALL_TARGET_NAMES webview_core_shared)
    endif()

    if(WEBVIEW_BUILD_STATIC_LIBRARY)
        list(APPEND WEBVIEW_INSTALL_TARGET_NAMES webview_core_static)
    endif()

    if(CMAKE_SYSTEM_NAME STREQUAL "Windows" AND WEBVIEW_USE_COMPAT_MINGW)
        list(APPEND WEBVIEW_INSTALL_TARGET_NAMES webview_compat_mingw)
    endif()

    install(TARGETS ${WEBVIEW_INSTALL_TARGET_NAMES}
        COMPONENT webview_libraries_runtime_release
        CONFIGURATIONS Release
        RUNTIME
            DESTINATION "${CMAKE_INSTALL_BINDIR}"
        LIBRARY
            DESTINATION "${CMAKE_INSTALL_LIBDIR}"
            NAMELINK_COMPONENT webview_trash
        ARCHIVE
            DESTINATION "${CMAKE_INSTALL_LIBDIR}"
            COMPONENT webview_trash)

    install(TARGETS ${WEBVIEW_INSTALL_TARGET_NAMES}
        EXPORT webview_targets
        COMPONENT webview_libraries
        RUNTIME
            DESTINATION "${CMAKE_INSTALL_BINDIR}"
        LIBRARY
            DESTINATION "${CMAKE_INSTALL_LIBDIR}"
        ARCHIVE
            DESTINATION "${CMAKE_INSTALL_LIBDIR}")

    install(EXPORT webview_targets
        DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/webview"
        NAMESPACE webview::
        FILE webview-targets.cmake
        COMPONENT webview_cmake)

    export(EXPORT webview_targets FILE "${CMAKE_CURRENT_BINARY_DIR}/webview-targets.cmake")

    # Install package config
    configure_package_config_file(
        "${WEBVIEW_CURRENT_CMAKE_DIR}/webview-config.cmake.in"
        "${CMAKE_CURRENT_BINARY_DIR}/webview-config.cmake"
        INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/webview"
        NO_SET_AND_CHECK_MACRO
        NO_CHECK_REQUIRED_COMPONENTS_MACRO)

    write_basic_package_version_file(
        "${CMAKE_CURRENT_BINARY_DIR}/webview-config-version.cmake"
        VERSION "${WEBVIEW_VERSION_COMPATIBILITY}"
        COMPATIBILITY SameMinorVersion)

    install(
        FILES
            "${WEBVIEW_CURRENT_CMAKE_DIR}/webview.cmake"
            "${CMAKE_CURRENT_BINARY_DIR}/webview-config.cmake"
            "${CMAKE_CURRENT_BINARY_DIR}/webview-config-version.cmake"
        DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/webview"
        COMPONENT webview_cmake)
endmacro()

macro(webview_internal_options)
    if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
        set(WEBVIEW_IS_TOP_LEVEL_BUILD TRUE)
    endif()

    if(NOT DEFINED WEBVIEW_IS_CI)
        set(WEBVIEW_IS_CI FALSE)
        if("$ENV{CI}" MATCHES "^(1|true|TRUE)$")
            set(WEBVIEW_IS_CI TRUE)
        endif()
    endif()

    option(WEBVIEW_BUILD "Enable building" ON)
    cmake_dependent_option(WEBVIEW_BUILD_AMALGAMATION "Build amalgamated library" ON "WEBVIEW_BUILD;WEBVIEW_IS_TOP_LEVEL_BUILD" OFF)
    option(WEBVIEW_BUILD_DOCS "Build documentation" ${WEBVIEW_IS_TOP_LEVEL_BUILD})
    option(WEBVIEW_BUILD_TESTS "Build tests" ${WEBVIEW_IS_TOP_LEVEL_BUILD})
    option(WEBVIEW_BUILD_EXAMPLES "Build examples" ${WEBVIEW_IS_TOP_LEVEL_BUILD})
    option(WEBVIEW_INSTALL_DOCS "Install documentation" ${WEBVIEW_IS_TOP_LEVEL_BUILD})
    option(WEBVIEW_INSTALL_TARGETS "Install targets" ${WEBVIEW_IS_TOP_LEVEL_BUILD})
    option(WEBVIEW_BUILD_SHARED_LIBRARY "Build shared libraries" ON)
    option(WEBVIEW_BUILD_STATIC_LIBRARY "Build static libraries" ON)
    option(WEBVIEW_USE_COMPAT_MINGW "Use compatibility helper for MinGW" ${WEBVIEW_IS_TOP_LEVEL_BUILD})
    option(WEBVIEW_USE_STATIC_MSVC_RUNTIME "Use static runtime library (MSVC)" OFF)
    option(WEBVIEW_ENABLE_CHECKS "Enable checks" ${WEBVIEW_IS_TOP_LEVEL_BUILD})
    option(WEBVIEW_ENABLE_CLANG_FORMAT "Enable clang-format" ${WEBVIEW_ENABLE_CHECKS})
    option(WEBVIEW_ENABLE_CLANG_TIDY "Enable clang-tidy" ${WEBVIEW_ENABLE_CHECKS})
    option(WEBVIEW_ENABLE_PACKAGING "Enable packaging" ${WEBVIEW_IS_TOP_LEVEL_BUILD})
    option(WEBVIEW_STRICT_CHECKS "Make checks strict" ${WEBVIEW_IS_CI})
    cmake_dependent_option(WEBVIEW_PACKAGE_AMALGAMATION "Package amalgamated library" ON WEBVIEW_ENABLE_PACKAGING OFF)
    cmake_dependent_option(WEBVIEW_PACKAGE_DOCS "Package documentation" ON WEBVIEW_ENABLE_PACKAGING OFF)
    cmake_dependent_option(WEBVIEW_PACKAGE_HEADERS "Package headers" ON WEBVIEW_ENABLE_PACKAGING OFF)
    cmake_dependent_option(WEBVIEW_PACKAGE_LIB "Package compiled libraries" ON WEBVIEW_ENABLE_PACKAGING OFF)
    option(WEBVIEW_STRICT_CLANG_FORMAT "Make clang-format check strict" ${WEBVIEW_STRICT_CHECKS})
    option(WEBVIEW_STRICT_CLANG_TIDY "Make clang-tidy check strict" ${WEBVIEW_STRICT_CHECKS})
endmacro()

macro(webview_set_install_rpath)
    if(CMAKE_SYSTEM_NAME STREQUAL "Darwin" OR CMAKE_SYSTEM_NAME STREQUAL "Linux")
        # RPATH/RUNPATH
        if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
            set(RPATH_BASE @loader_path)
        else()
            set(RPATH_BASE $ORIGIN)
        endif()

        file(RELATIVE_PATH RPATH_SUBDIR
            "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}"
            "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}")
        set(CMAKE_INSTALL_RPATH "${RPATH_BASE}" "${RPATH_BASE}/${RPATH_SUBDIR}")
    endif()
endmacro()


================================================
FILE: cmake/modules/FindMSWebView2.cmake
================================================
if(DEFINED MSWebView2_ROOT)
    find_path(MSWebView2_INCLUDE_DIR WebView2.h
        PATHS
            "${MSWebView2_ROOT}/build/native"
            "${MSWebView2_ROOT}"
        PATH_SUFFIXES include
        NO_CMAKE_FIND_ROOT_PATH)
endif()

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(MSWebView2 REQUIRED_VARS MSWebView2_INCLUDE_DIR)

if(MSWebView2_FOUND)
    if(NOT TARGET MSWebView2::headers)
        add_library(MSWebView2::headers INTERFACE IMPORTED)
        set_target_properties(MSWebView2::headers PROPERTIES
            INTERFACE_INCLUDE_DIRECTORIES "${MSWebView2_INCLUDE_DIR}")
        target_compile_features(MSWebView2::headers INTERFACE cxx_std_11)
    endif()
endif()


================================================
FILE: cmake/toolchains/arm64-windows-msvc.cmake
================================================
set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_SYSTEM_PROCESSOR ARM64)

set(CMAKE_C_COMPILER cl)
set(CMAKE_CXX_COMPILER cl)

set(CMAKE_GENERATOR_PLATFORM ARM64 CACHE INTERNAL "")


================================================
FILE: cmake/toolchains/host-gnu.cmake
================================================
set(CMAKE_C_COMPILER "gcc${WEBVIEW_TOOLCHAIN_EXECUTABLE_SUFFIX}")
set(CMAKE_CXX_COMPILER "g++${WEBVIEW_TOOLCHAIN_EXECUTABLE_SUFFIX}")


================================================
FILE: cmake/toolchains/host-llvm.cmake
================================================
set(CMAKE_C_COMPILER "clang${WEBVIEW_TOOLCHAIN_EXECUTABLE_SUFFIX}")
set(CMAKE_CXX_COMPILER "clang++${WEBVIEW_TOOLCHAIN_EXECUTABLE_SUFFIX}")


================================================
FILE: cmake/toolchains/i686-w64-mingw32.cmake
================================================
set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_SYSTEM_PROCESSOR i686)

set(CMAKE_SYSROOT /usr/i686-w64-mingw32)
set(CMAKE_C_COMPILER "i686-w64-mingw32-gcc${WEBVIEW_TOOLCHAIN_EXECUTABLE_SUFFIX}")
set(CMAKE_CXX_COMPILER "i686-w64-mingw32-g++${WEBVIEW_TOOLCHAIN_EXECUTABLE_SUFFIX}")
set(CMAKE_RANLIB i686-w64-mingw32-ranlib)
set(CMAKE_RC_COMPILER i686-w64-mingw32-windres)

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)


================================================
FILE: cmake/toolchains/i686-windows-msvc.cmake
================================================
set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_SYSTEM_PROCESSOR x86)

set(CMAKE_C_COMPILER cl)
set(CMAKE_CXX_COMPILER cl)

set(CMAKE_GENERATOR_PLATFORM Win32 CACHE INTERNAL "")


================================================
FILE: cmake/toolchains/universal-macos-llvm.cmake
================================================
set(CMAKE_SYSTEM_NAME Darwin)

set(CMAKE_C_COMPILER "clang${WEBVIEW_TOOLCHAIN_EXECUTABLE_SUFFIX}")
set(CMAKE_CXX_COMPILER "clang++${WEBVIEW_TOOLCHAIN_EXECUTABLE_SUFFIX}")

set(CMAKE_OSX_ARCHITECTURES "arm64;x86_64" CACHE INTERNAL "")


================================================
FILE: cmake/toolchains/x86_64-msys2-gnu-ucrt64.cmake
================================================
set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_SYSTEM_PROCESSOR x86_64)

set(CMAKE_C_COMPILER "gcc${WEBVIEW_TOOLCHAIN_EXECUTABLE_SUFFIX}")
set(CMAKE_CXX_COMPILER "g++${WEBVIEW_TOOLCHAIN_EXECUTABLE_SUFFIX}")

set(MSYSTEM ucrt64 CACHE INTERNAL "")


================================================
FILE: cmake/toolchains/x86_64-msys2-llvm-clang64.cmake
================================================
set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_SYSTEM_PROCESSOR x86_64)

set(CMAKE_C_COMPILER "clang${WEBVIEW_TOOLCHAIN_EXECUTABLE_SUFFIX}")
set(CMAKE_CXX_COMPILER "clang++${WEBVIEW_TOOLCHAIN_EXECUTABLE_SUFFIX}")

set(MSYSTEM clang64 CACHE INTERNAL "")


================================================
FILE: cmake/toolchains/x86_64-w64-mingw32.cmake
================================================
set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_SYSTEM_PROCESSOR x86_64)

set(CMAKE_SYSROOT /usr/x86_64-w64-mingw32)
set(CMAKE_C_COMPILER "x86_64-w64-mingw32-gcc${WEBVIEW_TOOLCHAIN_EXECUTABLE_SUFFIX}")
set(CMAKE_CXX_COMPILER "x86_64-w64-mingw32-g++${WEBVIEW_TOOLCHAIN_EXECUTABLE_SUFFIX}")
set(CMAKE_RANLIB x86_64-w64-mingw32-ranlib)
set(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres)

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)


================================================
FILE: cmake/toolchains/x86_64-windows-msvc.cmake
================================================
set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_SYSTEM_PROCESSOR AMD64)

set(CMAKE_C_COMPILER cl)
set(CMAKE_CXX_COMPILER cl)

set(CMAKE_GENERATOR_PLATFORM x64 CACHE INTERNAL "")


================================================
FILE: cmake/webview-config.cmake.in
================================================
@PACKAGE_INIT@

include(CMakeFindDependencyMacro)
include("${CMAKE_CURRENT_LIST_DIR}/webview.cmake")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/modules")

webview_options()
webview_find_dependencies()

include("${CMAKE_CURRENT_LIST_DIR}/webview-targets.cmake")


================================================
FILE: cmake/webview.cmake
================================================
macro(webview_options)
    if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
        set(WEBVIEW_MSWEBVIEW2_VERSION "1.0.1150.38" CACHE STRING "MS WebView2 version")
        option(WEBVIEW_USE_BUILTIN_MSWEBVIEW2 "Use built-in MS WebView2" ON)
    endif()
endmacro()

macro(webview_find_dependencies)
    if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
        list(APPEND WEBVIEW_DEPENDENCIES "-framework WebKit" dl)
    elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
        if(WEBVIEW_USE_BUILTIN_MSWEBVIEW2)
            find_package(MSWebView2 QUIET)
            if(NOT MSWebView2_FOUND)
                webview_fetch_mswebview2(${WEBVIEW_MSWEBVIEW2_VERSION})
            endif()
            find_package(MSWebView2 REQUIRED)
            if(MSWebView2_FOUND)
                list(APPEND WEBVIEW_DEPENDENCIES MSWebView2::headers)
            endif()
        endif()
        list(APPEND WEBVIEW_DEPENDENCIES advapi32 ole32 shell32 shlwapi user32 version)
    else()
        find_package(PkgConfig REQUIRED)

        # List of preferred WebkitGTK modules (from most to least preferred)
        set(WEBVIEW_WEBKITGTK_PREFERRED_API_LIST webkit2gtk-4.1)
        # List of known WebkitGTK modules (from higher to lower version)
        set(WEBVIEW_WEBKITGTK_KNOWN_API_LIST webkitgtk-6.0 webkit2gtk-4.1 webkit2gtk-4.0)

        # Try to find specific WebKitGTK API
        if(NOT "${WEBVIEW_WEBKITGTK_API}" STREQUAL "")
            if(WEBVIEW_WEBKITGTK_API VERSION_EQUAL 6.0)
                pkg_check_modules(WEBVIEW_WEBKITGTK REQUIRED IMPORTED_TARGET webkitgtk-6.0)
            elseif(WEBVIEW_WEBKITGTK_API VERSION_EQUAL 4.1)
                pkg_check_modules(WEBVIEW_WEBKITGTK REQUIRED IMPORTED_TARGET webkit2gtk-4.1)
            elseif(WEBVIEW_WEBKITGTK_API VERSION_EQUAL 4.0)
                pkg_check_modules(WEBVIEW_WEBKITGTK REQUIRED IMPORTED_TARGET webkit2gtk-4.0)
            else()
                message(FATAL_ERROR "Unsupported WebKitGTK API: ${WEBVIEW_WEBKITGTK_API}")
            endif()
        endif()

        if("${WEBVIEW_WEBKITGTK_MODULE_NAME}" STREQUAL "")
            # Try to find a preferred WebKitGTK API
            pkg_search_module(WEBVIEW_WEBKITGTK IMPORTED_TARGET ${WEBVIEW_WEBKITGTK_PREFERRED_API_LIST})
            if (NOT WEBVIEW_WEBKITGTK_FOUND)
              message(STATUS "Trying to find any WebKitGTK API")
              pkg_search_module(WEBVIEW_WEBKITGTK REQUIRED IMPORTED_TARGET ${WEBVIEW_WEBKITGTK_KNOWN_API_LIST})
            endif()
        else()
            pkg_check_modules(WEBVIEW_WEBKITGTK REQUIRED IMPORTED_TARGET "${WEBVIEW_WEBKITGTK_MODULE_NAME}")
        endif()

        if("${WEBVIEW_WEBKITGTK_MODULE_NAME}" STREQUAL "webkitgtk-6.0")
            set(WEBVIEW_WEBKITGTK_API 6.0)
        elseif("${WEBVIEW_WEBKITGTK_MODULE_NAME}" STREQUAL "webkit2gtk-4.1")
            set(WEBVIEW_WEBKITGTK_API 4.1)
        elseif("${WEBVIEW_WEBKITGTK_MODULE_NAME}" STREQUAL "webkit2gtk-4.0")
            set(WEBVIEW_WEBKITGTK_API 4.0)
        else()
            message(FATAL_ERROR "Couldn't find any supported WebKitGTK API")
        endif()

        # Find matching GTK module
        if("${WEBVIEW_WEBKITGTK_API}" VERSION_GREATER_EQUAL 6.0)
            pkg_check_modules(WEBVIEW_GTK REQUIRED IMPORTED_TARGET gtk4)
        elseif("${WEBVIEW_WEBKITGTK_API}" VERSION_LESS 5.0)
            pkg_check_modules(WEBVIEW_GTK REQUIRED IMPORTED_TARGET gtk+-3.0)
        endif()

        list(APPEND WEBVIEW_DEPENDENCIES PkgConfig::WEBVIEW_WEBKITGTK PkgConfig::WEBVIEW_GTK dl)
    endif()
endmacro()

function(webview_fetch_mswebview2 VERSION)
    cmake_policy(PUSH)
    # Avoid warning related to FetchContent and DOWNLOAD_EXTRACT_TIMESTAMP
    if(POLICY CMP0135)
        cmake_policy(SET CMP0135 NEW)
    endif()
    if(NOT COMMAND FetchContent_Declare)
        include(FetchContent)
    endif()
    set(FC_NAME microsoft_web_webview2)
    FetchContent_Declare(${FC_NAME}
        URL "https://www.nuget.org/api/v2/package/Microsoft.Web.WebView2/${VERSION}")
    FetchContent_MakeAvailable(${FC_NAME})
    set(MSWebView2_ROOT "${${FC_NAME}_SOURCE_DIR}")
    set(MSWebView2_ROOT "${MSWebView2_ROOT}" PARENT_SCOPE)
    cmake_policy(POP)
endfunction()


================================================
FILE: compatibility/CMakeLists.txt
================================================
if(WEBVIEW_USE_COMPAT_MINGW)
    add_subdirectory(mingw)
endif()


================================================
FILE: compatibility/mingw/CMakeLists.txt
================================================
# Compatibility target for MinGW that can be used to work around missing
# "EventToken.h" header (used by MS WebView2) when targetting Windows.

if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
    add_library(webview_compat_mingw INTERFACE)
    add_library(webview::compat_mingw ALIAS webview_compat_mingw)
    set_target_properties(webview_compat_mingw PROPERTIES
        EXPORT_NAME compat_mingw)
    target_include_directories(
        webview_compat_mingw
        INTERFACE
            "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
            "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>")
endif()


================================================
FILE: compatibility/mingw/include/EventToken.h
================================================
#ifndef WEBVIEW_COMPAT_EVENTTOKEN_H
#define WEBVIEW_COMPAT_EVENTTOKEN_H
#ifdef _WIN32

// This compatibility header provides types used by MS WebView2. This header can
// be used as an alternative to the "EventToken.h" header normally provided by
// the Windows SDK. Depending on the MinGW distribution, this header may not be
// present, or it may be present with the name "eventtoken.h". The letter casing
// matters when cross-compiling on a system with case-sensitive file names.

#ifndef __eventtoken_h__

#ifdef __cplusplus
#include <cstdint>
#else
#include <stdint.h>
#endif

typedef struct EventRegistrationToken {
  int64_t value;
} EventRegistrationToken;
#endif // __eventtoken_h__

#endif // _WIN32
#endif // WEBVIEW_COMPAT_EVENTTOKEN_H


================================================
FILE: core/CMakeLists.txt
================================================
# Core header library
add_library(webview_core_headers INTERFACE)
add_library(webview::core ALIAS webview_core_headers)
target_include_directories(
    webview_core_headers
    INTERFACE
        "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
        "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>")
target_link_libraries(webview_core_headers INTERFACE ${WEBVIEW_DEPENDENCIES})
# Note that we also use CMAKE_CXX_STANDARD which can override this
target_compile_features(webview_core_headers INTERFACE cxx_std_11)
set_target_properties(webview_core_headers PROPERTIES
    EXPORT_NAME core)

if(CMAKE_SYSTEM_NAME STREQUAL "Windows" AND WEBVIEW_USE_COMPAT_MINGW)
    target_link_libraries(webview_core_headers INTERFACE webview::compat_mingw)
endif()

# Core shared library
if(WEBVIEW_BUILD_SHARED_LIBRARY)
    add_library(webview_core_shared SHARED)
    add_library(webview::core_shared ALIAS webview_core_shared)
    target_sources(webview_core_shared PRIVATE src/webview.cc)
    target_link_libraries(webview_core_shared PUBLIC webview_core_headers)
    set_target_properties(webview_core_shared PROPERTIES
        OUTPUT_NAME webview
        VERSION "${WEBVIEW_VERSION_NUMBER}"
        SOVERSION "${WEBVIEW_VERSION_COMPATIBILITY}"
        EXPORT_NAME core_shared)
    target_compile_definitions(webview_core_shared
        INTERFACE WEBVIEW_SHARED
        PRIVATE WEBVIEW_BUILD_SHARED)
endif()

# Core static library
if(WEBVIEW_BUILD_STATIC_LIBRARY)
    # Change .lib file name for MSVC because otherwise it would be the same for shared and static
    if(MSVC)
        set(STATIC_LIBRARY_OUTPUT_NAME webview_static)
    else()
        set(STATIC_LIBRARY_OUTPUT_NAME webview)
    endif()

    add_library(webview_core_static STATIC)
    add_library(webview::core_static ALIAS webview_core_static)
    target_sources(webview_core_static PRIVATE src/webview.cc)
    target_link_libraries(webview_core_static PUBLIC webview_core_headers)
    set_target_properties(webview_core_static PROPERTIES
        OUTPUT_NAME "${STATIC_LIBRARY_OUTPUT_NAME}"
        POSITION_INDEPENDENT_CODE ON
        EXPORT_NAME core_static)
    target_compile_definitions(webview_core_static PUBLIC WEBVIEW_STATIC)
endif()

if(WEBVIEW_BUILD_TESTS)
    add_subdirectory(tests)
endif()

if(WEBVIEW_BUILD_AMALGAMATION)
    webview_find_python3(${WEBVIEW_IS_CI})
    if(Python3_FOUND)
        webview_find_clang_format(${WEBVIEW_IS_CI})
        if(WEBVIEW_CLANG_FORMAT_EXE)
            file(GLOB_RECURSE HEADER_FILES CONFIGURE_DEPENDS include/**)
            file(GLOB_RECURSE SOURCE_FILES CONFIGURE_DEPENDS src/**)
            set(AMALGAMATION_STAMP_FILE "${CMAKE_CURRENT_BINARY_DIR}/amalgamation/webview.h.stamp")

            add_custom_command(
                OUTPUT "${AMALGAMATION_STAMP_FILE}"
                COMMAND "${CMAKE_COMMAND}" -E touch "${AMALGAMATION_STAMP_FILE}"
                COMMAND ${Python3_EXECUTABLE}
                    "${PROJECT_SOURCE_DIR}/scripts/amalgamate/amalgamate.py"
                    --clang-format-exe "${WEBVIEW_CLANG_FORMAT_EXE}"
                    --base "${CMAKE_CURRENT_SOURCE_DIR}"
                    --search include
                    --output "${CMAKE_CURRENT_BINARY_DIR}/amalgamation/webview.h"
                    ${SOURCE_FILES}
                DEPENDS ${HEADER_FILES} ${SOURCE_FILES}
                COMMENT "Building amalgamation..."
                VERBATIM)

            add_custom_target(webview_amalgamate ALL
                DEPENDS "${AMALGAMATION_STAMP_FILE}")

            install(FILES "${CMAKE_CURRENT_BINARY_DIR}/amalgamation/webview.h"
                DESTINATION .
                COMPONENT webview_amalgamation)
        else()
            message(WARNING "Skipping amalgamation as clang-format was not found")
        endif()
    else()
        message(WARNING "Skipping amalgamation as Python 3 was not found")
    endif()
endif()


================================================
FILE: core/include/webview/api.h
================================================
/*
 * MIT License
 *
 * Copyright (c) 2017 Serge Zaitsev
 * Copyright (c) 2022 Steffen André Langnes
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#ifndef WEBVIEW_API_H
#define WEBVIEW_API_H

#include "errors.h"
#include "macros.h"
#include "types.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
 * Creates a new webview instance.
 *
 * @param debug Enable developer tools if supported by the backend.
 * @param window Optional native window handle, i.e. @c GtkWindow pointer
 *        @c NSWindow pointer (Cocoa) or @c HWND (Win32). If non-null,
 *        the webview widget is embedded into the given window, and the
 *        caller is expected to assume responsibility for the window as
 *        well as application lifecycle. If the window handle is null,
 *        a new window is created and both the window and application
 *        lifecycle are managed by the webview instance.
 * @remark Win32: The function also accepts a pointer to @c HWND (Win32) in the
 *         window parameter for backward compatibility.
 * @remark Win32/WebView2: @c CoInitializeEx should be called with
 *         @c COINIT_APARTMENTTHREADED before attempting to call this function
 *         with an existing window. Omitting this step may cause WebView2
 *         initialization to fail.
 * @return @c NULL on failure. Creation can fail for various reasons such
 *         as when required runtime dependencies are missing or when window
 *         creation fails.
 * @retval WEBVIEW_ERROR_MISSING_DEPENDENCY
 *         May be returned if WebView2 is unavailable on Windows.
 */
WEBVIEW_API webview_t webview_create(int debug, void *window);

/**
 * Destroys a webview instance and closes the native window.
 *
 * @param w The webview instance.
 */
WEBVIEW_API webview_error_t webview_destroy(webview_t w);

/**
 * Runs the main loop until it's terminated.
 *
 * @param w The webview instance.
 */
WEBVIEW_API webview_error_t webview_run(webview_t w);

/**
 * Stops the main loop. It is safe to call this function from another
 * background thread.
 *
 * @param w The webview instance.
 */
WEBVIEW_API webview_error_t webview_terminate(webview_t w);

/**
 * Schedules a function to be invoked on the thread with the run/event loop.
 *
 * Since library functions generally do not have thread safety guarantees,
 * this function can be used to schedule code to execute on the main/GUI
 * thread and thereby make that execution safe in multi-threaded applications.
 *
 * @param w The webview instance.
 * @param fn The function to be invoked.
 * @param arg An optional argument passed along to the callback function.
 */
WEBVIEW_API webview_error_t webview_dispatch(webview_t w,
                                             void (*fn)(webview_t w, void *arg),
                                             void *arg);

/**
 * Returns the native handle of the window associated with the webview instance.
 * The handle can be a @c GtkWindow pointer (GTK), @c NSWindow pointer (Cocoa)
 * or @c HWND (Win32).
 *
 * @param w The webview instance.
 * @return The handle of the native window.
 */
WEBVIEW_API void *webview_get_window(webview_t w);

/**
 * Get a native handle of choice.
 *
 * @param w The webview instance.
 * @param kind The kind of handle to retrieve.
 * @return The native handle or @c NULL.
 * @since 0.11
 */
WEBVIEW_API void *webview_get_native_handle(webview_t w,
                                            webview_native_handle_kind_t kind);

/**
 * Updates the title of the native window.
 *
 * @param w The webview instance.
 * @param title The new title.
 */
WEBVIEW_API webview_error_t webview_set_title(webview_t w, const char *title);

/**
 * Updates the size of the native window.
 *
 * Remarks:
 * - Subsequent calls to this function may behave inconsistently across
 *   different versions of GTK and windowing systems (X11/Wayland).
 * - Using WEBVIEW_HINT_MAX for setting the maximum window size is not
 *   supported with GTK 4 because X11-specific functions such as
 *   gtk_window_set_geometry_hints were removed. This option has no effect
 *   when using GTK 4.
 *
 * @param w The webview instance.
 * @param width New width.
 * @param height New height.
 * @param hints Size hints.
 */
WEBVIEW_API webview_error_t webview_set_size(webview_t w, int width, int height,
                                             webview_hint_t hints);

/**
 * Navigates webview to the given URL. URL may be a properly encoded data URI.
 *
 * Example:
 * @code{.c}
 * webview_navigate(w, "https://github.com/webview/webview");
 * webview_navigate(w, "data:text/html,%3Ch1%3EHello%3C%2Fh1%3E");
 * webview_navigate(w, "data:text/html;base64,PGgxPkhlbGxvPC9oMT4=");
 * @endcode
 *
 * @param w The webview instance.
 * @param url URL.
 */
WEBVIEW_API webview_error_t webview_navigate(webview_t w, const char *url);

/**
 * Load HTML content into the webview.
 *
 * Example:
 * @code{.c}
 * webview_set_html(w, "<h1>Hello</h1>");
 * @endcode
 *
 * @param w The webview instance.
 * @param html HTML content.
 */
WEBVIEW_API webview_error_t webview_set_html(webview_t w, const char *html);

/**
 * Injects JavaScript code to be executed immediately upon loading a page.
 * The code will be executed before @c window.onload.
 *
 * @param w The webview instance.
 * @param js JS content.
 */
WEBVIEW_API webview_error_t webview_init(webview_t w, const char *js);

/**
 * Evaluates arbitrary JavaScript code.
 *
 * Use bindings if you need to communicate the result of the evaluation.
 *
 * @param w The webview instance.
 * @param js JS content.
 */
WEBVIEW_API webview_error_t webview_eval(webview_t w, const char *js);

/**
 * Binds a function pointer to a new global JavaScript function.
 *
 * Internally, JS glue code is injected to create the JS function by the
 * given name. The callback function is passed a request identifier,
 * a request string and a user-provided argument. The request string is
 * a JSON array of the arguments passed to the JS function.
 *
 * @param w The webview instance.
 * @param name Name of the JS function.
 * @param fn Callback function.
 * @param arg User argument.
 * @retval WEBVIEW_ERROR_DUPLICATE
 *         A binding already exists with the specified name.
 */
WEBVIEW_API webview_error_t webview_bind(webview_t w, const char *name,
                                         void (*fn)(const char *id,
                                                    const char *req, void *arg),
                                         void *arg);

/**
 * Removes a binding created with webview_bind().
 *
 * @param w The webview instance.
 * @param name Name of the binding.
 * @retval WEBVIEW_ERROR_NOT_FOUND No binding exists with the specified name.
 */
WEBVIEW_API webview_error_t webview_unbind(webview_t w, const char *name);

/**
 * Responds to a binding call from the JS side.
 *
 * This function is safe to call from another thread.
 *
 * @param w The webview instance.
 * @param id The identifier of the binding call. Pass along the value received
 *           in the binding handler (see webview_bind()).
 * @param status A status of zero tells the JS side that the binding call was
 *               successful; any other value indicates an error.
 * @param result The result of the binding call to be returned to the JS side.
 *               This must either be a valid JSON value or an empty string for
 *               the primitive JS value @c undefined.
 */
WEBVIEW_API webview_error_t webview_return(webview_t w, const char *id,
                                           int status, const char *result);

/**
 * Get the library's version information.
 *
 * @since 0.10
 */
WEBVIEW_API const webview_version_info_t *webview_version(void);

#ifdef __cplusplus
}
#endif

#endif // WEBVIEW_API_H


================================================
FILE: core/include/webview/backends.hh
================================================
/*
 * MIT License
 *
 * Copyright (c) 2017 Serge Zaitsev
 * Copyright (c) 2022 Steffen André Langnes
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#ifndef WEBVIEW_BACKENDS_HH
#define WEBVIEW_BACKENDS_HH

#if defined(__cplusplus) && !defined(WEBVIEW_HEADER)

#include "detail/backends/cocoa_webkit.hh"
#include "detail/backends/gtk_webkitgtk.hh"
#include "detail/backends/win32_edge.hh"

namespace webview {
using webview = browser_engine;
}

#endif // defined(__cplusplus) && !defined(WEBVIEW_HEADER)
#endif // WEBVIEW_BACKENDS_HH


================================================
FILE: core/include/webview/c_api_impl.hh
================================================
/*
 * MIT License
 *
 * Copyright (c) 2017 Serge Zaitsev
 * Copyright (c) 2022 Steffen André Langnes
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#ifndef WEBVIEW_C_API_IMPL_HH
#define WEBVIEW_C_API_IMPL_HH

#if defined(__cplusplus) && !defined(WEBVIEW_HEADER)

#include "backends.hh"
#include "errors.h"
#include "errors.hh"
#include "json_deprecated.hh"
#include "macros.h"
#include "types.h"
#include "version.h"

namespace webview {
namespace detail {

// The library's version information.
constexpr const webview_version_info_t library_version_info{
    {WEBVIEW_VERSION_MAJOR, WEBVIEW_VERSION_MINOR, WEBVIEW_VERSION_PATCH},
    WEBVIEW_VERSION_NUMBER,
    WEBVIEW_VERSION_PRE_RELEASE,
    WEBVIEW_VERSION_BUILD_METADATA};

template <typename WorkFn, typename ResultFn>
webview_error_t api_filter(WorkFn &&do_work, ResultFn &&put_result) noexcept {
  try {
    auto result = do_work();
    if (result.ok()) {
      put_result(result.value());
      return WEBVIEW_ERROR_OK;
    }
    return result.error().code();
  } catch (const exception &e) {
    return e.error().code();
  } catch (...) {
    return WEBVIEW_ERROR_UNSPECIFIED;
  }
}

template <typename WorkFn>
webview_error_t api_filter(WorkFn &&do_work) noexcept {
  try {
    auto result = do_work();
    if (result.ok()) {
      return WEBVIEW_ERROR_OK;
    }
    return result.error().code();
  } catch (const exception &e) {
    return e.error().code();
  } catch (...) {
    return WEBVIEW_ERROR_UNSPECIFIED;
  }
}

inline webview *cast_to_webview(void *w) {
  if (!w) {
    throw exception{WEBVIEW_ERROR_INVALID_ARGUMENT,
                    "Cannot cast null pointer to webview instance"};
  }
  return static_cast<webview *>(w);
}

} // namespace detail
} // namespace webview

WEBVIEW_API webview_t webview_create(int debug, void *wnd) {
  using namespace webview::detail;
  webview::webview *w{};
  auto err = api_filter(
      [=]() -> webview::result<webview::webview *> {
        return new webview::webview{static_cast<bool>(debug), wnd};
      },
      [&](webview::webview *w_) { w = w_; });
  if (err == WEBVIEW_ERROR_OK) {
    return w;
  }
  return nullptr;
}

WEBVIEW_API webview_error_t webview_destroy(webview_t w) {
  using namespace webview::detail;
  return api_filter([=]() -> webview::noresult {
    delete cast_to_webview(w);
    return {};
  });
}

WEBVIEW_API webview_error_t webview_run(webview_t w) {
  using namespace webview::detail;
  return api_filter([=] { return cast_to_webview(w)->run(); });
}

WEBVIEW_API webview_error_t webview_terminate(webview_t w) {
  using namespace webview::detail;
  return api_filter([=] { return cast_to_webview(w)->terminate(); });
}

WEBVIEW_API webview_error_t webview_dispatch(webview_t w,
                                             void (*fn)(webview_t, void *),
                                             void *arg) {
  using namespace webview::detail;
  if (!fn) {
    return WEBVIEW_ERROR_INVALID_ARGUMENT;
  }
  return api_filter(
      [=] { return cast_to_webview(w)->dispatch([=]() { fn(w, arg); }); });
}

WEBVIEW_API void *webview_get_window(webview_t w) {
  using namespace webview::detail;
  void *window = nullptr;
  auto err = api_filter([=] { return cast_to_webview(w)->window(); },
                        [&](void *value) { window = value; });
  if (err == WEBVIEW_ERROR_OK) {
    return window;
  }
  return nullptr;
}

WEBVIEW_API void *webview_get_native_handle(webview_t w,
                                            webview_native_handle_kind_t kind) {
  using namespace webview::detail;
  void *handle{};
  auto err = api_filter(
      [=]() -> webview::result<void *> {
        auto *w_ = cast_to_webview(w);
        switch (kind) {
        case WEBVIEW_NATIVE_HANDLE_KIND_UI_WINDOW:
          return w_->window();
        case WEBVIEW_NATIVE_HANDLE_KIND_UI_WIDGET:
          return w_->widget();
        case WEBVIEW_NATIVE_HANDLE_KIND_BROWSER_CONTROLLER:
          return w_->browser_controller();
        default:
          return webview::error_info{WEBVIEW_ERROR_INVALID_ARGUMENT};
        }
      },
      [&](void *handle_) { handle = handle_; });
  if (err == WEBVIEW_ERROR_OK) {
    return handle;
  }
  return nullptr;
}

WEBVIEW_API webview_error_t webview_set_title(webview_t w, const char *title) {
  using namespace webview::detail;
  if (!title) {
    return WEBVIEW_ERROR_INVALID_ARGUMENT;
  }
  return api_filter([=] { return cast_to_webview(w)->set_title(title); });
}

WEBVIEW_API webview_error_t webview_set_size(webview_t w, int width, int height,
                                             webview_hint_t hints) {
  using namespace webview::detail;
  return api_filter(
      [=] { return cast_to_webview(w)->set_size(width, height, hints); });
}

WEBVIEW_API webview_error_t webview_navigate(webview_t w, const char *url) {
  using namespace webview::detail;
  if (!url) {
    return WEBVIEW_ERROR_INVALID_ARGUMENT;
  }
  return api_filter([=] { return cast_to_webview(w)->navigate(url); });
}

WEBVIEW_API webview_error_t webview_set_html(webview_t w, const char *html) {
  using namespace webview::detail;
  if (!html) {
    return WEBVIEW_ERROR_INVALID_ARGUMENT;
  }
  return api_filter([=] { return cast_to_webview(w)->set_html(html); });
}

WEBVIEW_API webview_error_t webview_init(webview_t w, const char *js) {
  using namespace webview::detail;
  if (!js) {
    return WEBVIEW_ERROR_INVALID_ARGUMENT;
  }
  return api_filter([=] { return cast_to_webview(w)->init(js); });
}

WEBVIEW_API webview_error_t webview_eval(webview_t w, const char *js) {
  using namespace webview::detail;
  if (!js) {
    return WEBVIEW_ERROR_INVALID_ARGUMENT;
  }
  return api_filter([=] { return cast_to_webview(w)->eval(js); });
}

WEBVIEW_API webview_error_t webview_bind(webview_t w, const char *name,
                                         void (*fn)(const char *id,
                                                    const char *req, void *arg),
                                         void *arg) {
  using namespace webview::detail;
  if (!name || !fn) {
    return WEBVIEW_ERROR_INVALID_ARGUMENT;
  }
  return api_filter([=] {
    return cast_to_webview(w)->bind(
        name,
        [=](const std::string &seq, const std::string &req, void *arg_) {
          fn(seq.c_str(), req.c_str(), arg_);
        },
        arg);
  });
}

WEBVIEW_API webview_error_t webview_unbind(webview_t w, const char *name) {
  using namespace webview::detail;
  if (!name) {
    return WEBVIEW_ERROR_INVALID_ARGUMENT;
  }
  return api_filter([=] { return cast_to_webview(w)->unbind(name); });
}

WEBVIEW_API webview_error_t webview_return(webview_t w, const char *id,
                                           int status, const char *result) {
  using namespace webview::detail;
  if (!id || !result) {
    return WEBVIEW_ERROR_INVALID_ARGUMENT;
  }
  return api_filter(
      [=] { return cast_to_webview(w)->resolve(id, status, result); });
}

WEBVIEW_API const webview_version_info_t *webview_version(void) {
  return &webview::detail::library_version_info;
}

#endif // defined(__cplusplus) && !defined(WEBVIEW_HEADER)
#endif // WEBVIEW_C_API_IMPL_HH


================================================
FILE: core/include/webview/detail/backends/cocoa_webkit.hh
================================================
/*
 * MIT License
 *
 * Copyright (c) 2017 Serge Zaitsev
 * Copyright (c) 2022 Steffen André Langnes
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#ifndef WEBVIEW_BACKENDS_COCOA_WEBKIT_HH
#define WEBVIEW_BACKENDS_COCOA_WEBKIT_HH

#if defined(__cplusplus) && !defined(WEBVIEW_HEADER)

#include "../../macros.h"

#if defined(WEBVIEW_PLATFORM_DARWIN) && defined(WEBVIEW_COCOA)

//
// ====================================================================
//
// This implementation uses Cocoa WKWebView backend on macOS. It is
// written using ObjC runtime and uses WKWebView class as a browser runtime.
// You should pass "-framework Webkit" flag to the compiler.
//
// ====================================================================
//

#include "../../types.hh"
#include "../engine_base.hh"
#include "../platform/darwin/cocoa/cocoa.hh"
#include "../platform/darwin/objc/objc.hh"
#include "../platform/darwin/webkit/webkit.hh"
#include "../user_script.hh"

#include <atomic>
#include <functional>
#include <list>
#include <memory>
#include <string>

#include <objc/objc-runtime.h>

namespace webview {
namespace detail {

class user_script::impl {
public:
  impl(id script) : m_script{objc::retain(script)} {}

  ~impl() { objc::release(m_script); }

  impl(const impl &) = delete;
  impl &operator=(const impl &) = delete;
  impl(impl &&) = delete;
  impl &operator=(impl &&) = delete;

  id get_native() const { return m_script; }

private:
  id m_script{};
};

// Encapsulate backend in its own namespace to avoid polluting the parent
// namespace when pulling in commonly-used symbols from other namespaces.
// Since those commmon symbols are used a lot, this reduces the overall
// noise in the code.
namespace cocoa_webkit {

using namespace cocoa;
using namespace webkit;

class cocoa_wkwebview_engine : public engine_base {
public:
  cocoa_wkwebview_engine(bool debug, void *window)
      : engine_base{!window}, m_app{NSApplication_get_sharedApplication()} {
    window_init(window);
    window_settings(debug);
    dispatch_size_default();
  }

  cocoa_wkwebview_engine(const cocoa_wkwebview_engine &) = delete;
  cocoa_wkwebview_engine &operator=(const cocoa_wkwebview_engine &) = delete;
  cocoa_wkwebview_engine(cocoa_wkwebview_engine &&) = delete;
  cocoa_wkwebview_engine &operator=(cocoa_wkwebview_engine &&) = delete;

  virtual ~cocoa_wkwebview_engine() {
    objc::autoreleasepool arp;
    if (m_window) {
      if (m_webview) {
        if (auto ui_delegate{WKWebView_get_UIDelegate(m_webview)}) {
          WKWebView_set_UIDelegate(m_webview, nullptr);
          objc::release(ui_delegate);
        }
        objc::release(m_webview);
        m_webview = nullptr;
      }
      if (m_widget) {
        if (m_widget == NSWindow_get_contentView(m_window)) {
          NSWindow_set_contentView(m_window, nullptr);
        }
        objc::release(m_widget);
        m_widget = nullptr;
      }
      if (owns_window()) {
        // Replace delegate to avoid callbacks and other bad things during
        // destruction.
        NSWindow_set_delegate(m_window, nullptr);
        NSWindow_close(m_window);
        on_window_destroyed(true);
      }
      m_window = nullptr;
    }
    if (m_window_delegate) {
      objc::release(m_window_delegate);
      m_window_delegate = nullptr;
    }
    if (m_app_delegate) {
      NSApplication_set_delegate(m_app, nullptr);
      // Make sure to release the delegate we created.
      objc::release(m_app_delegate);
      m_app_delegate = nullptr;
    }
    if (owns_window()) {
      // Needed for the window to close immediately.
      deplete_run_loop_event_queue();
    }
    // TODO: Figure out why m_manager is still alive after the autoreleasepool
    // has been drained.
  }

protected:
  result<void *> window_impl() override {
    if (m_window) {
      return m_window;
    }
    return error_info{WEBVIEW_ERROR_INVALID_STATE};
  }

  result<void *> widget_impl() override {
    if (m_widget) {
      return m_widget;
    }
    return error_info{WEBVIEW_ERROR_INVALID_STATE};
  }

  result<void *> browser_controller_impl() override {
    if (m_webview) {
      return m_webview;
    }
    return error_info{WEBVIEW_ERROR_INVALID_STATE};
  }

  noresult terminate_impl() override {
    stop_run_loop();
    return {};
  }

  noresult run_impl() override {
    NSApplication_run(m_app);
    return {};
  }

  noresult dispatch_impl(std::function<void()> f) override {
    dispatch_async_f(dispatch_get_main_queue(), new dispatch_fn_t(f),
                     (dispatch_function_t)([](void *arg) {
                       auto f = static_cast<dispatch_fn_t *>(arg);
                       (*f)();
                       delete f;
                     }));
    return {};
  }

  noresult set_title_impl(const std::string &title) override {
    NSWindow_set_title(m_window, title);
    return {};
  }
  noresult set_size_impl(int width, int height, webview_hint_t hints) override {
    objc::autoreleasepool arp;

    auto style = static_cast<NSWindowStyleMask>(
        NSWindowStyleMaskTitled | NSWindowStyleMaskClosable |
        NSWindowStyleMaskMiniaturizable);
    if (hints != WEBVIEW_HINT_FIXED) {
      style =
          static_cast<NSWindowStyleMask>(style | NSWindowStyleMaskResizable);
    }
    NSWindow_set_styleMask(m_window, style);

    if (hints == WEBVIEW_HINT_MIN) {
      NSWindow_set_contentMinSize(m_window, NSSizeMake(width, height));
    } else if (hints == WEBVIEW_HINT_MAX) {
      NSWindow_set_contentMaxSize(m_window, NSSizeMake(width, height));
    } else {
      auto rect{NSWindow_get_frame(m_window)};
      NSWindow_setFrame(m_window,
                        NSRectMake(rect.origin.x, rect.origin.y, width, height),
                        true, false);
    }
    NSWindow_center(m_window);

    return window_show();
  }
  noresult navigate_impl(const std::string &url) override {
    objc::autoreleasepool arp;

    WKWebView_loadRequest(
        m_webview, NSURLRequest_requestWithURL(NSURL_URLWithString(url)));

    return {};
  }
  noresult set_html_impl(const std::string &html) override {
    objc::autoreleasepool arp;
    WKWebView_loadHTMLString(m_webview, NSString_stringWithUTF8String(html),
                             nullptr);
    return {};
  }
  noresult eval_impl(const std::string &js) override {
    objc::autoreleasepool arp;
    // URI is null before content has begun loading.
    auto nsurl{WKWebView_get_URL(m_webview)};
    if (!nsurl) {
      return {};
    }
    WKWebView_evaluateJavaScript(m_webview, NSString_stringWithUTF8String(js),
                                 nullptr);
    return {};
  }

  user_script add_user_script_impl(const std::string &js) override {
    objc::autoreleasepool arp;
    auto wk_script{WKUserScript_withSource(
        NSString_stringWithUTF8String(js),
        WKUserScriptInjectionTimeAtDocumentStart, true)};
    // Script is retained when added.
    WKUserContentController_addUserScript(m_manager, wk_script);
    user_script script{
        js, user_script::impl_ptr{new user_script::impl{wk_script},
                                  [](user_script::impl *p) { delete p; }}};
    return script;
  }

  void remove_all_user_scripts_impl(
      const std::list<user_script> & /*scripts*/) override {
    objc::autoreleasepool arp;
    // Removing scripts decreases the retain count of each script.
    WKUserContentController_removeAllUserScripts(m_manager);
  }

  bool are_user_scripts_equal_impl(const user_script &first,
                                   const user_script &second) override {
    auto *wk_first = first.get_impl().get_native();
    auto *wk_second = second.get_impl().get_native();
    return wk_first == wk_second;
  }

private:
  id create_app_delegate() {
    objc::autoreleasepool arp;
    constexpr auto class_name = "WebviewAppDelegate";
    // Avoid crash due to registering same class twice
    auto cls = objc_lookUpClass(class_name);
    if (!cls) {
      // Note: Avoid registering the class name "AppDelegate" as it is the
      // default name in projects created with Xcode, and using the same name
      // causes objc_registerClassPair to crash.
      cls =
          objc_allocateClassPair(objc::get_class("NSResponder"), class_name, 0);
      class_addProtocol(cls, objc_getProtocol("NSTouchBarProvider"));
      class_addMethod(
          cls,
          objc::selector("applicationShouldTerminateAfterLastWindowClosed:"),
          (IMP)(+[](id, SEL, id) -> BOOL { return NO; }), "c@:@");
      class_addMethod(cls, objc::selector("applicationDidFinishLaunching:"),
                      (IMP)(+[](id self, SEL, id notification) {
                        auto app{NSNotification_get_object(notification)};
                        auto w = get_associated_webview(self);
                        w->on_application_did_finish_launching(self, app);
                      }),
                      "v@:@");
      objc_registerClassPair(cls);
    }
    return objc::Class_new(cls);
  }
  id create_script_message_handler() {
    objc::autoreleasepool arp;
    constexpr auto class_name = "WebviewWKScriptMessageHandler";
    // Avoid crash due to registering same class twice
    auto cls = objc_lookUpClass(class_name);
    if (!cls) {
      cls =
          objc_allocateClassPair(objc::get_class("NSResponder"), class_name, 0);
      class_addProtocol(cls, objc_getProtocol("WKScriptMessageHandler"));
      class_addMethod(
          cls, objc::selector("userContentController:didReceiveScriptMessage:"),
          (IMP)(+[](id self, SEL, id, id msg) {
            auto w = get_associated_webview(self);
            w->on_message(
                NSString_get_UTF8String(WKScriptMessage_get_body(msg)));
          }),
          "v@:@@");
      objc_registerClassPair(cls);
    }
    auto instance{objc::Class_new(cls)};
    set_associated_webview(instance, this);
    return instance;
  }
  static id create_webkit_ui_delegate() {
    objc::autoreleasepool arp;
    constexpr auto class_name = "WebviewWKUIDelegate";
    // Avoid crash due to registering same class twice
    auto cls = objc_lookUpClass(class_name);
    if (!cls) {
      cls = objc_allocateClassPair(objc::get_class("NSObject"), class_name, 0);
      class_addProtocol(cls, objc_getProtocol("WKUIDelegate"));
      class_addMethod(
          cls,
          objc::selector("webView:runOpenPanelWithParameters:initiatedByFrame:"
                         "completionHandler:"),
          (IMP)(+[](id, SEL, id, id parameters, id, id completion_handler) {
            auto allows_multiple_selection{
                WKOpenPanelParameters_get_allowsMultipleSelection(parameters)};
            auto allows_directories{
                WKOpenPanelParameters_get_allowsDirectories(parameters)};

            // Show a panel for selecting files.
            auto panel{NSOpenPanel_openPanel()};
            NSOpenPanel_set_canChooseFiles(panel, true);
            NSOpenPanel_set_canChooseDirectories(panel, allows_directories);
            NSOpenPanel_set_allowsMultipleSelection(panel,
                                                    allows_multiple_selection);
            auto modal_response{NSSavePanel_runModal(panel)};

            // Get the URLs for the selected files. If the modal was canceled
            // then we pass null to the completion handler to signify
            // cancellation.
            id urls{modal_response == NSModalResponseOK
                        ? NSOpenPanel_get_URLs(panel)
                        : nullptr};

            // Invoke the completion handler block.
            auto sig{NSMethodSignature_signatureWithObjCTypes("v@?@")};
            auto invocation{NSInvocation_invocationWithMethodSignature(sig)};
            NSInvocation_set_target(invocation, completion_handler);
            NSInvocation_setArgument(invocation, &urls, 1);
            NSInvocation_invoke(invocation);
          }),
          "v@:@@@@");
      objc_registerClassPair(cls);
    }
    return objc::Class_new(cls);
  }
  static id create_window_delegate() {
    objc::autoreleasepool arp;
    constexpr auto class_name = "WebviewNSWindowDelegate";
    // Avoid crash due to registering same class twice
    auto cls = objc_lookUpClass(class_name);
    if (!cls) {
      cls = objc_allocateClassPair(objc::get_class("NSObject"), class_name, 0);
      class_addProtocol(cls, objc_getProtocol("NSWindowDelegate"));
      class_addMethod(cls, objc::selector("windowWillClose:"),
                      (IMP)(+[](id self, SEL, id notification) {
                        auto window{NSNotification_get_object(notification)};
                        auto w = get_associated_webview(self);
                        w->on_window_will_close(self, window);
                      }),
                      "v@:@");
      objc_registerClassPair(cls);
    }
    return objc::Class_new(cls);
  }
  static cocoa_wkwebview_engine *get_associated_webview(id object) {
    objc::autoreleasepool arp;
    if (id assoc_obj{objc_getAssociatedObject(object, "webview")}) {
      cocoa_wkwebview_engine *w{};
      NSValue_getValue(assoc_obj, &w, sizeof(w));
      return w;
    }
    return nullptr;
  }
  static void set_associated_webview(id object, cocoa_wkwebview_engine *w) {
    objc::autoreleasepool arp;
    objc_setAssociatedObject(object, "webview", NSValue_valueWithPointer(w),
                             OBJC_ASSOCIATION_RETAIN);
  }
  static bool is_app_bundled() noexcept {
    auto bundle = NSBundle_get_mainBundle();
    if (!bundle) {
      return false;
    }
    auto bundle_path = NSBundle_get_bundlePath(bundle);
    auto bundled =
        NSString_hasSuffix(bundle_path, NSString_stringWithUTF8String(".app"));
    return !!bundled;
  }
  void on_application_did_finish_launching(id /*delegate*/, id app) {
    // See comments related to application lifecycle in create_app_delegate().
    if (owns_window()) {
      // Stop the main run loop so that we can return
      // from the constructor.
      stop_run_loop();
    }

    // Activate the app if it is not bundled.
    // Bundled apps launched from Finder are activated automatically but
    // otherwise not. Activating the app even when it has been launched from
    // Finder does not seem to be harmful but calling this function is rarely
    // needed as proper activation is normally taken care of for us.
    // Bundled apps have a default activation policy of
    // NSApplicationActivationPolicyRegular while non-bundled apps have a
    // default activation policy of NSApplicationActivationPolicyProhibited.
    if (!is_app_bundled()) {
      // "setActivationPolicy:" must be invoked before
      // "activateIgnoringOtherApps:" for activation to work.
      NSApplication_setActivationPolicy(app,
                                        NSApplicationActivationPolicyRegular);
      // Activate the app regardless of other active apps.
      // This can be obtrusive so we only do it when necessary.
      NSApplication_activateIgnoringOtherApps(app, true);
    }

    window_init_proceed();
  }
  void on_window_will_close(id /*delegate*/, id /*window*/) {
    // Widget destroyed along with window.
    m_widget = nullptr;
    m_webview = nullptr;
    m_window = nullptr;
    dispatch([this] { on_window_destroyed(); });
  }
  void window_settings(bool debug) {
    objc::autoreleasepool arp;

    auto config{objc::autorelease(WKWebViewConfiguration_new())};

    m_manager = WKWebViewConfiguration_get_userContentController(config);

    auto preferences = WKWebViewConfiguration_get_preferences(config);
    auto yes_value = NSNumber_numberWithBool(true);

    if (debug) {
      NSObject_setValue_forKey(
          preferences, yes_value,
          NSString_stringWithUTF8String("developerExtrasEnabled"));
    }

    NSObject_setValue_forKey(
        preferences, yes_value,
        NSString_stringWithUTF8String("fullScreenEnabled"));

#if defined(__has_builtin)
#if __has_builtin(__builtin_available)
    if (__builtin_available(macOS 10.13, *)) {
      NSObject_setValue_forKey(
          preferences, yes_value,
          NSString_stringWithUTF8String("javaScriptCanAccessClipboard"));
      NSObject_setValue_forKey(
          preferences, yes_value,
          NSString_stringWithUTF8String("DOMPasteAllowed"));
    }
#else
#error __builtin_available not supported by compiler
#endif
#else
#error __has_builtin not supported by compiler
#endif

    auto ui_delegate = create_webkit_ui_delegate();
    m_webview =
        objc::retain(WKWebView_withFrame(CGRectMake(0, 0, 0, 0), config));
    // Autoresizing mask is needed to prevent the Web Inspector pane from
    // pushing the main web view out of bounds
    auto autoresizing_mask{static_cast<NSAutoresizingMaskOptions>(
        NSViewWidthSizable | NSViewMaxXMargin | NSViewHeightSizable |
        NSViewMaxYMargin)};
    NSView_set_autoresizingMask(m_webview, autoresizing_mask);
    set_associated_webview(ui_delegate, this);
    WKWebView_set_UIDelegate(m_webview, ui_delegate);

    if (debug) {
      // Explicitly make WKWebView inspectable via Safari on OS versions that
      // disable the feature by default (macOS 13.3 and later) and support
      // enabling it. According to Apple, the behavior on older OS versions is
      // for content to always be inspectable in "debug builds".
      // Testing shows that this is true for macOS 12.6 but somehow not 10.15.
      // https://webkit.org/blog/13936/enabling-the-inspection-of-web-content-in-apps/
      WKWebView_set_inspectable(m_webview, true);
    }

    auto script_message_handler =
        objc::autorelease(create_script_message_handler());
    WKUserContentController_addScriptMessageHandler(
        m_manager, script_message_handler,
        NSString_stringWithUTF8String("__webview__"));

    add_init_script("function(message) {\n\
  return window.webkit.messageHandlers.__webview__.postMessage(message);\n\
}");
    set_up_widget();
    NSWindow_set_contentView(m_window, m_widget);
    if (owns_window()) {
      NSWindow_makeKeyAndOrderFront(m_window);
    }
  }
  void set_up_widget() {
    objc::autoreleasepool arp;
    // Create a new view that can contain both the web view and the Web Inspector pane
    m_widget = objc::retain(NSView_withFrame(NSRectMake(0, 0, 0, 0)));
    // Autoresizing is needed because the Web Inspector pane is a sibling of the web view
    NSView_set_autoresizesSubviews(m_widget, true);
    NSView_addSubview(m_widget, m_webview);
    NSView_set_frame(m_webview, NSView_get_bounds(m_widget));
  }
  void stop_run_loop() {
    objc::autoreleasepool arp;
    // Request the run loop to stop. This doesn't immediately stop the loop.
    NSApplication_stop(m_app);
    // The run loop will stop after processing an NSEvent.
    auto event{NSEvent_otherEventWithType(
        NSEventTypeApplicationDefined, NSPointMake(0, 0),
        NSEventModifierFlags{}, 0, 0, nullptr, 0, 0, 0)};
    NSApplication_postEvent(m_app, event, true);
  }
  static bool get_and_set_is_first_instance() noexcept {
    static std::atomic_bool first{true};
    bool temp = first;
    if (temp) {
      first = false;
    }
    return temp;
  }
  void window_init(void *window) {
    objc::autoreleasepool arp;

    m_window = static_cast<id>(window);
    if (!owns_window()) {
      return;
    }

    // Skip application setup if this isn't the first instance of this class
    // because the launch event is only sent once.
    if (!get_and_set_is_first_instance()) {
      window_init_proceed();
      return;
    }

    m_app_delegate = create_app_delegate();
    set_associated_webview(m_app_delegate, this);
    NSApplication_set_delegate(m_app, m_app_delegate);

    // Start the main run loop so that the app delegate gets the
    // NSApplicationDidFinishLaunchingNotification notification after the run
    // loop has started in order to perform further initialization.
    // We need to return from this constructor so this run loop is only
    // temporary.
    NSApplication_run(m_app);
  }
  void window_init_proceed() {
    objc::autoreleasepool arp;

    m_window = objc::retain(NSWindow_withContentRect(
        NSRectMake(0, 0, 0, 0), NSWindowStyleMaskTitled, NSBackingStoreBuffered,
        false));
    m_window_delegate = create_window_delegate();
    set_associated_webview(m_window_delegate, this);
    NSWindow_set_delegate(m_window, m_window_delegate);
    on_window_created();
  }

  noresult window_show() {
    objc::autoreleasepool arp;
    if (m_is_window_shown) {
      return {};
    }
    m_is_window_shown = true;
    return {};
  }

  void run_event_loop_while(std::function<bool()> fn) override {
    objc::autoreleasepool arp;
    while (fn()) {
      objc::autoreleasepool arp2;
      if (auto event{NSApplication_nextEventMatchingMask(
              m_app, NSEventMaskAny, nullptr,
              NSRunLoopMode::NSDefaultRunLoopMode(), true)}) {
        NSApplication_sendEvent(m_app, event);
      }
    }
  }

  id m_app{};
  id m_app_delegate{};
  id m_window_delegate{};
  id m_window{};
  id m_widget{};
  id m_webview{};
  id m_manager{};
  bool m_is_window_shown{};
};

} // namespace cocoa_webkit
} // namespace detail

using browser_engine = detail::cocoa_webkit::cocoa_wkwebview_engine;

} // namespace webview

#endif // defined(WEBVIEW_PLATFORM_DARWIN) && defined(WEBVIEW_COCOA)
#endif // defined(__cplusplus) && !defined(WEBVIEW_HEADER)
#endif // WEBVIEW_BACKENDS_COCOA_WEBKIT_HH


================================================
FILE: core/include/webview/detail/backends/gtk_webkitgtk.hh
================================================
/*
 * MIT License
 *
 * Copyright (c) 2017 Serge Zaitsev
 * Copyright (c) 2022 Steffen André Langnes
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#ifndef WEBVIEW_BACKENDS_GTK_WEBKITGTK_HH
#define WEBVIEW_BACKENDS_GTK_WEBKITGTK_HH

#if defined(__cplusplus) && !defined(WEBVIEW_HEADER)

#include "../../macros.h"

#if defined(WEBVIEW_PLATFORM_LINUX) && defined(WEBVIEW_GTK)

//
// ====================================================================
//
// This implementation uses webkit2gtk backend. It requires GTK and
// WebKitGTK libraries. Proper compiler flags can be retrieved via:
//
//   pkg-config --cflags --libs gtk4 webkitgtk-6.0
//   pkg-config --cflags --libs gtk+-3.0 webkit2gtk-4.1
//   pkg-config --cflags --libs gtk+-3.0 webkit2gtk-4.0
//
// ====================================================================
//

#include "../../errors.hh"
#include "../../types.hh"
#include "../engine_base.hh"
#include "../platform/linux/gtk/compat.hh"
#include "../platform/linux/webkitgtk/compat.hh"
#include "../platform/linux/webkitgtk/dmabuf.hh"
#include "../user_script.hh"

#include <functional>
#include <list>
#include <memory>
#include <string>

#include <gtk/gtk.h>

#if GTK_MAJOR_VERSION >= 4

#include <jsc/jsc.h>
#include <webkit/webkit.h>

#elif GTK_MAJOR_VERSION >= 3

#include <JavaScriptCore/JavaScript.h>
#include <webkit2/webkit2.h>

#endif

#include <fcntl.h>
#include <sys/stat.h>

namespace webview {
namespace detail {

class user_script::impl {
public:
  impl(WebKitUserScript *script) : m_script{script} {
    webkit_user_script_ref(script);
  }

  ~impl() { webkit_user_script_unref(m_script); }

  impl(const impl &) = delete;
  impl &operator=(const impl &) = delete;
  impl(impl &&) = delete;
  impl &operator=(impl &&) = delete;

  WebKitUserScript *get_native() const { return m_script; }

private:
  WebKitUserScript *m_script{};
};

class gtk_webkit_engine : public engine_base {
public:
  gtk_webkit_engine(bool debug, void *window) : engine_base{!window} {
    window_init(window);
    window_settings(debug);
    dispatch_size_default();
  }

  gtk_webkit_engine(const gtk_webkit_engine &) = delete;
  gtk_webkit_engine &operator=(const gtk_webkit_engine &) = delete;
  gtk_webkit_engine(gtk_webkit_engine &&) = delete;
  gtk_webkit_engine &operator=(gtk_webkit_engine &&) = delete;

  virtual ~gtk_webkit_engine() {
    if (m_window) {
      if (owns_window()) {
        // Disconnect handlers to avoid callbacks invoked during destruction.
        g_signal_handlers_disconnect_by_data(GTK_WINDOW(m_window), this);
        gtk_window_close(GTK_WINDOW(m_window));
        on_window_destroyed(true);
      } else {
        gtk_compat::window_remove_child(GTK_WINDOW(m_window),
                                        GTK_WIDGET(m_webview));
      }
    }
    if (m_webview) {
      g_object_unref(m_webview);
    }
    if (owns_window()) {
      // Needed for the window to close immediately.
      deplete_run_loop_event_queue();
    }
  }

protected:
  result<void *> window_impl() override {
    if (m_window) {
      return m_window;
    }
    return error_info{WEBVIEW_ERROR_INVALID_STATE};
  }

  result<void *> widget_impl() override {
    if (m_webview) {
      return m_webview;
    }
    return error_info{WEBVIEW_ERROR_INVALID_STATE};
  }

  result<void *> browser_controller_impl() override {
    if (m_webview) {
      return m_webview;
    }
    return error_info{WEBVIEW_ERROR_INVALID_STATE};
  }

  noresult run_impl() override {
    m_stop_run_loop = false;
    while (!m_stop_run_loop) {
      g_main_context_iteration(nullptr, TRUE);
    }
    return {};
  }

  noresult terminate_impl() override {
    return dispatch_impl([&] { m_stop_run_loop = true; });
  }

  noresult dispatch_impl(std::function<void()> f) override {
    g_idle_add_full(G_PRIORITY_HIGH_IDLE, (GSourceFunc)([](void *fn) -> int {
                      (*static_cast<dispatch_fn_t *>(fn))();
                      return G_SOURCE_REMOVE;
                    }),
                    new std::function<void()>(f),
                    [](void *fn) { delete static_cast<dispatch_fn_t *>(fn); });
    return {};
  }

  noresult set_title_impl(const std::string &title) override {
    gtk_window_set_title(GTK_WINDOW(m_window), title.c_str());
    return {};
  }

  noresult set_size_impl(int width, int height, webview_hint_t hints) override {
    gtk_window_set_resizable(GTK_WINDOW(m_window), hints != WEBVIEW_HINT_FIXED);
    if (hints == WEBVIEW_HINT_NONE || hints == WEBVIEW_HINT_FIXED) {
      gtk_compat::window_set_size(GTK_WINDOW(m_window), width, height);
    } else if (hints == WEBVIEW_HINT_MIN) {
      gtk_widget_set_size_request(m_window, width, height);
    } else if (hints == WEBVIEW_HINT_MAX) {
      gtk_compat::window_set_max_size(GTK_WINDOW(m_window), width, height);
    } else {
      return error_info{WEBVIEW_ERROR_INVALID_ARGUMENT, "Invalid hint"};
    }
    return window_show();
  }

  noresult navigate_impl(const std::string &url) override {
    webkit_web_view_load_uri(WEBKIT_WEB_VIEW(m_webview), url.c_str());
    return {};
  }

  noresult set_html_impl(const std::string &html) override {
    webkit_web_view_load_html(WEBKIT_WEB_VIEW(m_webview), html.c_str(),
                              nullptr);
    return {};
  }

  noresult eval_impl(const std::string &js) override {
    // URI is null before content has begun loading.
    if (!webkit_web_view_get_uri(WEBKIT_WEB_VIEW(m_webview))) {
      return {};
    }
#if (WEBKIT_MAJOR_VERSION == 2 && WEBKIT_MINOR_VERSION >= 40) ||               \
    WEBKIT_MAJOR_VERSION > 2
    webkit_web_view_evaluate_javascript(WEBKIT_WEB_VIEW(m_webview), js.c_str(),
                                        static_cast<gssize>(js.size()), nullptr,
                                        nullptr, nullptr, nullptr, nullptr);
#else
    webkit_web_view_run_javascript(WEBKIT_WEB_VIEW(m_webview), js.c_str(),
                                   nullptr, nullptr, nullptr);
#endif
    return {};
  }

  user_script add_user_script_impl(const std::string &js) override {
    auto *wk_script = webkit_user_script_new(
        js.c_str(), WEBKIT_USER_CONTENT_INJECT_TOP_FRAME,
        WEBKIT_USER_SCRIPT_INJECT_AT_DOCUMENT_START, nullptr, nullptr);
    webkit_user_content_manager_add_script(m_user_content_manager, wk_script);
    user_script script{
        js, user_script::impl_ptr{new user_script::impl{wk_script},
                                  [](user_script::impl *p) { delete p; }}};
    webkit_user_script_unref(wk_script);
    return script;
  }

  void remove_all_user_scripts_impl(
      const std::list<user_script> & /*scripts*/) override {
    webkit_user_content_manager_remove_all_scripts(m_user_content_manager);
  }

  bool are_user_scripts_equal_impl(const user_script &first,
                                   const user_script &second) override {
    auto *wk_first = first.get_impl().get_native();
    auto *wk_second = second.get_impl().get_native();
    return wk_first == wk_second;
  }

private:
#if GTK_MAJOR_VERSION >= 4
  static char *get_string_from_js_result(JSCValue *r) {
    return jsc_value_to_string(r);
  }
#else
  static char *get_string_from_js_result(WebKitJavascriptResult *r) {
    char *s;
#if (WEBKIT_MAJOR_VERSION == 2 && WEBKIT_MINOR_VERSION >= 22) ||               \
    WEBKIT_MAJOR_VERSION > 2
    JSCValue *value = webkit_javascript_result_get_js_value(r);
    s = jsc_value_to_string(value);
#else
    JSGlobalContextRef ctx = webkit_javascript_result_get_global_context(r);
    JSValueRef value = webkit_javascript_result_get_value(r);
    JSStringRef js = JSValueToStringCopy(ctx, value, nullptr);
    size_t n = JSStringGetMaximumUTF8CStringSize(js);
    s = g_new(char, n);
    JSStringGetUTF8CString(js, s, n);
    JSStringRelease(js);
#endif
    return s;
  }
#endif

  void window_init(void *window) {
    m_window = static_cast<GtkWidget *>(window);
    if (owns_window()) {
      if (!gtk_compat::init_check()) {
        throw exception{WEBVIEW_ERROR_UNSPECIFIED, "GTK init failed"};
      }
      m_window = gtk_compat::window_new();
      on_window_created();
      auto on_window_destroy = +[](GtkWidget *, gpointer arg) {
        auto *w = static_cast<gtk_webkit_engine *>(arg);
        w->m_window = nullptr;
        w->on_window_destroyed();
      };
      g_signal_connect(G_OBJECT(m_window), "destroy",
                       G_CALLBACK(on_window_destroy), this);
    }
    webkit_dmabuf::apply_webkit_dmabuf_workaround();
    // Initialize webview widget
    m_webview = webkit_web_view_new();
    g_object_ref_sink(m_webview);
    WebKitUserContentManager *manager = m_user_content_manager =
        webkit_web_view_get_user_content_manager(WEBKIT_WEB_VIEW(m_webview));
    webkitgtk_compat::connect_script_message_received(
        manager, "__webview__",
        [this](WebKitUserContentManager *, const std::string &r) {
          on_message(r);
        });
    webkitgtk_compat::user_content_manager_register_script_message_handler(
        manager, "__webview__");
    add_init_script("function(message) {\n\
  return window.webkit.messageHandlers.__webview__.postMessage(message);\n\
}");
  }

  void window_settings(bool debug) {
    WebKitSettings *settings =
        webkit_web_view_get_settings(WEBKIT_WEB_VIEW(m_webview));
    webkit_settings_set_javascript_can_access_clipboard(settings, true);
    if (debug) {
      webkit_settings_set_enable_write_console_messages_to_stdout(settings,
                                                                  true);
      webkit_settings_set_enable_developer_extras(settings, true);
    }
  }

  noresult window_show() {
    if (m_is_window_shown) {
      return {};
    }
    gtk_compat::window_set_child(GTK_WINDOW(m_window), GTK_WIDGET(m_webview));
    gtk_compat::widget_set_visible(GTK_WIDGET(m_webview), true);

    if (owns_window()) {
      gtk_widget_grab_focus(GTK_WIDGET(m_webview));
      gtk_compat::widget_set_visible(GTK_WIDGET(m_window), true);
    }
    m_is_window_shown = true;
    return {};
  }

  void run_event_loop_while(std::function<bool()> fn) override {
    while (fn()) {
      g_main_context_iteration(nullptr, TRUE);
    }
  }

  GtkWidget *m_window{};
  GtkWidget *m_webview{};
  WebKitUserContentManager *m_user_content_manager{};
  bool m_stop_run_loop{};
  bool m_is_window_shown{};
};

} // namespace detail

using browser_engine = detail::gtk_webkit_engine;

} // namespace webview

#endif // defined(WEBVIEW_PLATFORM_LINUX) && defined(WEBVIEW_GTK)
#endif // defined(__cplusplus) && !defined(WEBVIEW_HEADER)
#endif // WEBVIEW_BACKENDS_GTK_WEBKITGTK_HH


================================================
FILE: core/include/webview/detail/backends/win32_edge.hh
================================================
/*
 * MIT License
 *
 * Copyright (c) 2017 Serge Zaitsev
 * Copyright (c) 2022 Steffen André Langnes
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#ifndef WEBVIEW_BACKENDS_WIN32_EDGE_HH
#define WEBVIEW_BACKENDS_WIN32_EDGE_HH

#if defined(__cplusplus) && !defined(WEBVIEW_HEADER)

#include "../../macros.h"

#if defined(WEBVIEW_PLATFORM_WINDOWS) && defined(WEBVIEW_EDGE)

//
// ====================================================================
//
// This implementation uses Win32 API to create a native window. It
// uses Edge/Chromium webview2 backend as a browser engine.
//
// ====================================================================
//

#include "../../errors.hh"
#include "../../types.hh"
#include "../engine_base.hh"
#include "../native_library.hh"
#include "../platform/windows/com_init_wrapper.hh"
#include "../platform/windows/dpi.hh"
#include "../platform/windows/iid.hh"
#include "../platform/windows/reg_key.hh"
#include "../platform/windows/theme.hh"
#include "../platform/windows/version.hh"
#include "../platform/windows/webview2/loader.hh"
#include "../user_script.hh"
#include "../utility/string.hh"

#include <atomic>
#include <cstdlib>
#include <functional>
#include <list>
#include <memory>
#include <utility>

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <windows.h>

#include <objbase.h>
#include <shlobj.h>
#include <shlwapi.h>

#ifdef _MSC_VER
#pragma comment(lib, "ole32.lib")
#pragma comment(lib, "shell32.lib")
#pragma comment(lib, "shlwapi.lib")
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "version.lib")
#endif

namespace webview {
namespace detail {

using msg_cb_t = std::function<void(const std::string)>;

class webview2_com_handler
    : public ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler,
      public ICoreWebView2CreateCoreWebView2ControllerCompletedHandler,
      public ICoreWebView2WebMessageReceivedEventHandler,
      public ICoreWebView2PermissionRequestedEventHandler {
  using webview2_com_handler_cb_t =
      std::function<void(ICoreWebView2Controller *, ICoreWebView2 *webview)>;

public:
  webview2_com_handler(HWND hwnd, msg_cb_t msgCb, webview2_com_handler_cb_t cb)
      : m_window(hwnd), m_msgCb(msgCb), m_cb(cb) {}

  virtual ~webview2_com_handler() = default;
  webview2_com_handler(const webview2_com_handler &other) = delete;
  webview2_com_handler &operator=(const webview2_com_handler &other) = delete;
  webview2_com_handler(webview2_com_handler &&other) = delete;
  webview2_com_handler &operator=(webview2_com_handler &&other) = delete;

  ULONG STDMETHODCALLTYPE AddRef() { return ++m_ref_count; }
  ULONG STDMETHODCALLTYPE Release() {
    if (m_ref_count > 1) {
      return --m_ref_count;
    }
    delete this;
    return 0;
  }
  HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID *ppv) {
    using namespace mswebview2::cast_info;

    if (!ppv) {
      return E_POINTER;
    }

    // All of the COM interfaces we implement should be added here regardless
    // of whether they are required.
    // This is just to be on the safe side in case the WebView2 Runtime ever
    // requests a pointer to an interface we implement.
    // The WebView2 Runtime must at the very least be able to get a pointer to
    // ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler when we use
    // our custom WebView2 loader implementation, and observations have shown
    // that it is the only interface requested in this case. None have been
    // observed to be requested when using the official WebView2 loader.

    if (cast_if_equal_iid(this, riid, controller_completed, ppv) ||
        cast_if_equal_iid(this, riid, environment_completed, ppv) ||
        cast_if_equal_iid(this, riid, message_received, ppv) ||
        cast_if_equal_iid(this, riid, permission_requested, ppv)) {
      return S_OK;
    }

    return E_NOINTERFACE;
  }
  HRESULT STDMETHODCALLTYPE Invoke(HRESULT res, ICoreWebView2Environment *env) {
    if (SUCCEEDED(res)) {
      res = env->CreateCoreWebView2Controller(m_window, this);
      if (SUCCEEDED(res)) {
        return S_OK;
      }
    }
    try_create_environment();
    return S_OK;
  }
  HRESULT STDMETHODCALLTYPE Invoke(HRESULT res,
                                   ICoreWebView2Controller *controller) {
    if (FAILED(res)) {
      // See try_create_environment() regarding
      // HRESULT_FROM_WIN32(ERROR_INVALID_STATE).
      // The result is E_ABORT if the parent window has been destroyed already.
      switch (res) {
      case HRESULT_FROM_WIN32(ERROR_INVALID_STATE):
      case E_ABORT:
        return S_OK;
      }
      try_create_environment();
      return S_OK;
    }

    ICoreWebView2 *webview;
    ::EventRegistrationToken token;
    controller->get_CoreWebView2(&webview);
    webview->add_WebMessageReceived(this, &token);
    webview->add_PermissionRequested(this, &token);

    m_cb(controller, webview);
    return S_OK;
  }
  HRESULT STDMETHODCALLTYPE
  Invoke(ICoreWebView2 * /*sender*/,
         ICoreWebView2WebMessageReceivedEventArgs *args) {
    LPWSTR message{};
    auto res = args->TryGetWebMessageAsString(&message);
    if (SUCCEEDED(res)) {
      m_msgCb(narrow_string(message));
    }

    CoTaskMemFree(message);
    return S_OK;
  }
  HRESULT STDMETHODCALLTYPE
  Invoke(ICoreWebView2 * /*sender*/,
         ICoreWebView2PermissionRequestedEventArgs *args) {
    COREWEBVIEW2_PERMISSION_KIND kind;
    args->get_PermissionKind(&kind);
    if (kind == COREWEBVIEW2_PERMISSION_KIND_CLIPBOARD_READ) {
      args->put_State(COREWEBVIEW2_PERMISSION_STATE_ALLOW);
    }
    return S_OK;
  }

  // Set the function that will perform the initiating logic for creating
  // the WebView2 environment.
  void set_attempt_handler(std::function<HRESULT()> attempt_handler) noexcept {
    m_attempt_handler = attempt_handler;
  }

  // Retry creating a WebView2 environment.
  // The initiating logic for creating the environment is defined by the
  // caller of set_attempt_handler().
  void try_create_environment() noexcept {
    // WebView creation fails with HRESULT_FROM_WIN32(ERROR_INVALID_STATE) if
    // a running instance using the same user data folder exists, and the
    // Environment objects have different EnvironmentOptions.
    // Source: https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/icorewebview2environment?view=webview2-1.0.1150.38
    if (m_attempts < m_max_attempts) {
      ++m_attempts;
      auto res = m_attempt_handler();
      if (SUCCEEDED(res)) {
        return;
      }
      // Not entirely sure if this error code only applies to
      // CreateCoreWebView2Controller so we check here as well.
      if (res == HRESULT_FROM_WIN32(ERROR_INVALID_STATE)) {
        return;
      }
      // Wait for m_sleep_ms before trying again.
      Sleep(m_sleep_ms);
      try_create_environment();
      return;
    }
    // Give up.
    m_cb(nullptr, nullptr);
  }

private:
  HWND m_window;
  msg_cb_t m_msgCb;
  webview2_com_handler_cb_t m_cb;
  std::atomic<ULONG> m_ref_count{1};
  std::function<HRESULT()> m_attempt_handler;
  unsigned int m_max_attempts = 60;
  unsigned int m_sleep_ms = 200;
  unsigned int m_attempts = 0;
};

class webview2_user_script_added_handler
    : public ICoreWebView2AddScriptToExecuteOnDocumentCreatedCompletedHandler {
public:
  using callback_fn = std::function<void(HRESULT errorCode, LPCWSTR id)>;

  webview2_user_script_added_handler(callback_fn cb) : m_cb{cb} {}

  virtual ~webview2_user_script_added_handler() = default;
  webview2_user_script_added_handler(
      const webview2_user_script_added_handler &other) = delete;
  webview2_user_script_added_handler &
  operator=(const webview2_user_script_added_handler &other) = delete;
  webview2_user_script_added_handler(
      webview2_user_script_added_handler &&other) = delete;
  webview2_user_script_added_handler &
  operator=(webview2_user_script_added_handler &&other) = delete;

  ULONG STDMETHODCALLTYPE AddRef() { return ++m_ref_count; }
  ULONG STDMETHODCALLTYPE Release() {
    if (m_ref_count > 1) {
      return --m_ref_count;
    }
    delete this;
    return 0;
  }

  HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, LPVOID *ppv) {
    using namespace mswebview2::cast_info;

    if (!ppv) {
      return E_POINTER;
    }

    if (cast_if_equal_iid(this, riid,
                          add_script_to_execute_on_document_created_completed,
                          ppv)) {
      return S_OK;
    }

    return E_NOINTERFACE;
  }

  HRESULT STDMETHODCALLTYPE Invoke(HRESULT res, LPCWSTR id) {
    m_cb(res, id);
    return S_OK;
  }

private:
  callback_fn m_cb;
  std::atomic<ULONG> m_ref_count{1};
};

class user_script::impl {
public:
  impl(const std::wstring &id, const std::wstring &code)
      : m_id{id}, m_code{code} {}

  impl(const impl &) = delete;
  impl &operator=(const impl &) = delete;
  impl(impl &&) = delete;
  impl &operator=(impl &&) = delete;

  const std::wstring &get_id() const { return m_id; }
  const std::wstring &get_code() const { return m_code; }

private:
  std::wstring m_id;
  std::wstring m_code;
};

class win32_edge_engine : public engine_base {
public:
  win32_edge_engine(bool debug, void *window) : engine_base{!window} {
    window_init(window);
    window_settings(debug);
    dispatch_size_default();
  }

  virtual ~win32_edge_engine() {
    if (m_com_handler) {
      m_com_handler->Release();
      m_com_handler = nullptr;
    }
    if (m_webview) {
      m_webview->Release();
      m_webview = nullptr;
    }
    if (m_controller) {
      m_controller->Release();
      m_controller = nullptr;
    }
    // Replace wndproc to avoid callbacks and other bad things during
    // destruction.
    auto wndproc = reinterpret_cast<LONG_PTR>(
        +[](HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) -> LRESULT {
          return DefWindowProcW(hwnd, msg, wp, lp);
        });
    if (m_widget) {
      SetWindowLongPtrW(m_widget, GWLP_WNDPROC, wndproc);
    }
    if (m_window && owns_window()) {
      SetWindowLongPtrW(m_window, GWLP_WNDPROC, wndproc);
    }
    if (m_widget) {
      DestroyWindow(m_widget);
      m_widget = nullptr;
    }
    if (m_window) {
      if (owns_window()) {
        DestroyWindow(m_window);
        on_window_destroyed(true);
      }
      m_window = nullptr;
    }
    if (owns_window()) {
      // Not strictly needed for windows to close immediately but aligns
      // behavior across backends.
      deplete_run_loop_event_queue();
    }
    // We need the message window in order to deplete the event queue.
    if (m_message_window) {
      SetWindowLongPtrW(m_message_window, GWLP_WNDPROC, wndproc);
      DestroyWindow(m_message_window);
      m_message_window = nullptr;
    }
  }

  win32_edge_engine(const win32_edge_engine &other) = delete;
  win32_edge_engine &operator=(const win32_edge_engine &other) = delete;
  win32_edge_engine(win32_edge_engine &&other) = delete;
  win32_edge_engine &operator=(win32_edge_engine &&other) = delete;

protected:
  noresult run_impl() override {
    MSG msg;
    while (GetMessageW(&msg, nullptr, 0, 0) > 0) {
      TranslateMessage(&msg);
      DispatchMessageW(&msg);
    }
    return {};
  }
  result<void *> window_impl() override {
    if (m_window) {
      return m_window;
    }
    return error_info{WEBVIEW_ERROR_INVALID_STATE};
  }
  result<void *> widget_impl() override {
    if (m_widget) {
      return m_widget;
    }
    return error_info{WEBVIEW_ERROR_INVALID_STATE};
  }
  result<void *> browser_controller_impl() override {
    if (m_controller) {
      return m_controller;
    }
    return error_info{WEBVIEW_ERROR_INVALID_STATE};
  }
  noresult terminate_impl() override {
    PostQuitMessage(0);
    return {};
  }
  noresult dispatch_impl(dispatch_fn_t f) override {
    PostMessageW(m_message_window, WM_APP, 0, (LPARAM) new dispatch_fn_t(f));
    return {};
  }

  noresult set_title_impl(const std::string &title) override {
    SetWindowTextW(m_window, widen_string(title).c_str());
    return {};
  }

  noresult set_size_impl(int width, int height, webview_hint_t hints) override {
    auto style = GetWindowLong(m_window, GWL_STYLE);
    if (hints == WEBVIEW_HINT_FIXED) {
      style &= ~(WS_THICKFRAME | WS_MAXIMIZEBOX);
    } else {
      style |= (WS_THICKFRAME | WS_MAXIMIZEBOX);
    }
    SetWindowLong(m_window, GWL_STYLE, style);

    if (hints == WEBVIEW_HINT_MAX) {
      m_maxsz.x = width;
      m_maxsz.y = height;
    } else if (hints == WEBVIEW_HINT_MIN) {
      m_minsz.x = width;
      m_minsz.y = height;
    } else {
      auto dpi = get_window_dpi(m_window);
      m_dpi = dpi;
      auto scaled_size =
          scale_size(width, height, get_default_window_dpi(), dpi);
      auto frame_size =
          make_window_frame_size(m_window, scaled_size.cx, scaled_size.cy, dpi);
      SetWindowPos(m_window, nullptr, 0, 0, frame_size.cx, frame_size.cy,
                   SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE |
                       SWP_FRAMECHANGED);
    }
    return window_show();
  }

  noresult navigate_impl(const std::string &url) override {
    auto wurl = widen_string(url);
    m_webview->Navigate(wurl.c_str());
    return {};
  }

  noresult eval_impl(const std::string &js) override {
    // TODO: Skip if no content has begun loading yet. Can't check with
    //       ICoreWebView2::get_Source because it returns "about:blank".
    auto wjs = widen_string(js);
    m_webview->ExecuteScript(wjs.c_str(), nullptr);
    return {};
  }

  noresult set_html_impl(const std::string &html) override {
    m_webview->NavigateToString(widen_string(html).c_str());
    return {};
  }

  user_script add_user_script_impl(const std::string &js) override {
    auto wjs = widen_string(js);
    std::wstring script_id;
    bool done{};
    webview2_user_script_added_handler handler{[&](HRESULT res, LPCWSTR id) {
      if (SUCCEEDED(res)) {
        script_id = id;
      }
      done = true;
    }};
    auto res =
        m_webview->AddScriptToExecuteOnDocumentCreated(wjs.c_str(), &handler);
    if (SUCCEEDED(res)) {
      // We want to guard against executing the default `set_size` prematurely
      set_default_size_guard(true);
      // Sadly we need to pump the event loop in order to get the script ID.
      run_event_loop_while([&] { return !done; });
      // The user's `set_size` may have been executed from the depleted event queue,
      // and if so, guard against putting the default `set_size` back onto the queue.
      if (!m_is_window_shown) {
        set_default_size_guard(false);
        dispatch_size_default();
      }
    }
    // TODO: There's a non-zero chance that we didn't get the script ID.
    //       We need to convey the error somehow.
    return user_script{
        js, user_script::impl_ptr{new user_script::impl{script_id, wjs},
                                  [](user_script::impl *p) { delete p; }}};
  }

  void
  remove_all_user_scripts_impl(const std::list<user_script> &scripts) override {
    for (const auto &script : scripts) {
      const auto &id = script.get_impl().get_id();
      m_webview->RemoveScriptToExecuteOnDocumentCreated(id.c_str());
    }
  }

  bool are_user_scripts_equal_impl(const user_script &first,
                                   const user_script &second) override {
    const auto &first_id = first.get_impl().get_id();
    const auto &second_id = second.get_impl().get_id();
    return first_id == second_id;
  }

private:
  void window_init(void *window) {
    if (!is_webview2_available()) {
      throw exception{WEBVIEW_ERROR_MISSING_DEPENDENCY,
                      "WebView2 is unavailable"};
    }

    HINSTANCE hInstance = GetModuleHandle(nullptr);

    if (owns_window()) {
      m_com_init = {COINIT_APARTMENTTHREADED};
      enable_dpi_awareness();

      HICON icon = (HICON)LoadImage(
          hInstance, IDI_APPLICATION, IMAGE_ICON, GetSystemMetrics(SM_CXICON),
          GetSystemMetrics(SM_CYICON), LR_DEFAULTCOLOR);

      // Create a top-level window.
      WNDCLASSEXW wc;
      ZeroMemory(&wc, sizeof(WNDCLASSEX));
      wc.cbSize = sizeof(WNDCLASSEX);
      wc.hInstance = hInstance;
      wc.lpszClassName = L"webview";
      wc.hIcon = icon;
      wc.lpfnWndProc = (WNDPROC)(+[](HWND hwnd, UINT msg, WPARAM wp,
                                     LPARAM lp) -> LRESULT {
        win32_edge_engine *w{};

        if (msg == WM_NCCREATE) {
          auto *lpcs{reinterpret_cast<LPCREATESTRUCT>(lp)};
          w = static_cast<win32_edge_engine *>(lpcs->lpCreateParams);
          w->m_window = hwnd;
          SetWindowLongPtrW(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(w));
          enable_non_client_dpi_scaling_if_needed(hwnd);
          apply_window_theme(hwnd);
        } else {
          w = reinterpret_cast<win32_edge_engine *>(
              GetWindowLongPtrW(hwnd, GWLP_USERDATA));
        }

        if (!w) {
          return DefWindowProcW(hwnd, msg, wp, lp);
        }

        switch (msg) {
        case WM_SIZE:
          w->resize_widget();
          break;
        case WM_CLOSE:
          DestroyWindow(hwnd);
          break;
        case WM_DESTROY:
          w->m_window = nullptr;
          SetWindowLongPtrW(hwnd, GWLP_USERDATA, 0);
          w->on_window_destroyed();
          break;
        case WM_GETMINMAXINFO: {
          auto lpmmi = (LPMINMAXINFO)lp;
          if (w->m_maxsz.x > 0 && w->m_maxsz.y > 0) {
            lpmmi->ptMaxSize = w->m_maxsz;
            lpmmi->ptMaxTrackSize = w->m_maxsz;
          }
          if (w->m_minsz.x > 0 && w->m_minsz.y > 0) {
            lpmmi->ptMinTrackSize = w->m_minsz;
          }
        } break;
        case 0x02E4 /*WM_GETDPISCALEDSIZE*/: {
          auto dpi = static_cast<int>(wp);
          auto *size{reinterpret_cast<SIZE *>(lp)};
          *size = w->get_scaled_size(w->m_dpi, dpi);
          return TRUE;
        }
        case 0x02E0 /*WM_DPICHANGED*/: {
          // Windows 10: The size we get here is exactly what we supplied to WM_GETDPISCALEDSIZE.
          // Windows 11: The size we get here is NOT what we supplied to WM_GETDPISCALEDSIZE.
          // Due to this difference, don't use the suggested bounds.
          auto dpi = static_cast<int>(HIWORD(wp));
          w->on_dpi_changed(dpi);
          break;
        }
        case WM_SETTINGCHANGE: {
          auto *area = reinterpret_cast<const wchar_t *>(lp);
          if (area) {
            w->on_system_setting_change(area);
          }
          break;
        }
        case WM_ACTIVATE:
          if (LOWORD(wp) != WA_INACTIVE) {
            w->focus_webview();
          }
          break;
        default:
          return DefWindowProcW(hwnd, msg, wp, lp);
        }
        return 0;
      });
      RegisterClassExW(&wc);

      CreateWindowW(L"webview", L"", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
                    CW_USEDEFAULT, 0, 0, nullptr, nullptr, hInstance, this);
      if (!m_window) {
        throw exception{WEBVIEW_ERROR_INVALID_STATE, "Window is null"};
      }
      on_window_created();

      m_dpi = get_window_dpi(m_window);
    } else {
      m_window = IsWindow(static_cast<HWND>(window))
                     ? static_cast<HWND>(window)
                     : *(static_cast<HWND *>(window));
      m_dpi = get_window_dpi(m_window);
    }
    // Create a window that WebView2 will be embedded into.
    WNDCLASSEXW widget_wc{};
    widget_wc.cbSize = sizeof(WNDCLASSEX);
    widget_wc.hInstance = hInstance;
    widget_wc.lpszClassName = L"webview_widget";
    widget_wc.lpfnWndProc = (WNDPROC)(+[](HWND hwnd, UINT msg, WPARAM wp,
                                          LPARAM lp) -> LRESULT {
      win32_edge_engine *w{};

      if (msg == WM_NCCREATE) {
        auto *lpcs{reinterpret_cast<LPCREATESTRUCT>(lp)};
        w = static_cast<win32_edge_engine *>(lpcs->lpCreateParams);
        w->m_widget = hwnd;
        SetWindowLongPtrW(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(w));
      } else {
        w = reinterpret_cast<win32_edge_engine *>(
            GetWindowLongPtrW(hwnd, GWLP_USERDATA));
      }

      if (!w) {
        return DefWindowProcW(hwnd, msg, wp, lp);
      }

      switch (msg) {
      case WM_SIZE:
        w->resize_webview();
        break;
      case WM_DESTROY:
        w->m_widget = nullptr;
        SetWindowLongPtrW(hwnd, GWLP_USERDATA, 0);
        break;
      default:
        return DefWindowProcW(hwnd, msg, wp, lp);
      }
      return 0;
    });
    RegisterClassExW(&widget_wc);
    CreateWindowExW(WS_EX_CONTROLPARENT, L"webview_widget", nullptr, WS_CHILD,
                    0, 0, 0, 0, m_window, nullptr, hInstance, this);
    if (!m_widget) {
      throw exception{WEBVIEW_ERROR_INVALID_STATE, "Widget window is null"};
    }

    // Create a message-only window for internal messaging.
    WNDCLASSEXW message_wc{};
    message_wc.cbSize = sizeof(WNDCLASSEX);
    message_wc.hInstance = hInstance;
    message_wc.lpszClassName = L"webview_message";
    message_wc.lpfnWndProc = (WNDPROC)(+[](HWND hwnd, UINT msg, WPARAM wp,
                                           LPARAM lp) -> LRESULT {
      win32_edge_engine *w{};

      if (msg == WM_NCCREATE) {
        auto *lpcs{reinterpret_cast<LPCREATESTRUCT>(lp)};
        w = static_cast<win32_edge_engine *>(lpcs->lpCreateParams);
        w->m_message_window = hwnd;
        SetWindowLongPtrW(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(w));
      } else {
        w = reinterpret_cast<win32_edge_engine *>(
            GetWindowLongPtrW(hwnd, GWLP_USERDATA));
      }

      if (!w) {
        return DefWindowProcW(hwnd, msg, wp, lp);
      }

      switch (msg) {
      case WM_APP:
        if (auto f = (dispatch_fn_t *)(lp)) {
          (*f)();
          delete f;
        }
        break;
      case WM_DESTROY:
        w->m_message_window = nullptr;
        SetWindowLongPtrW(hwnd, GWLP_USERDATA, 0);
        break;
      default:
        return DefWindowProcW(hwnd, msg, wp, lp);
      }
      return 0;
    });
    RegisterClassExW(&message_wc);
    CreateWindowExW(0, L"webview_message", nullptr, 0, 0, 0, 0, 0, HWND_MESSAGE,
                    nullptr, hInstance, this);
    if (!m_message_window) {
      throw exception{WEBVIEW_ERROR_INVALID_STATE, "Message window is null"};
    }
  }

  void window_settings(bool debug) {
    auto cb =
        std::bind(&win32_edge_engine::on_message, this, std::placeholders::_1);
    embed(m_widget, debug, cb).ensure_ok();
  }

  noresult window_show() {
    if (owns_window() && !m_is_window_shown) {
      ShowWindow(m_window, SW_SHOW);
      UpdateWindow(m_window);
      SetFocus(m_window);
      m_is_window_shown = true;
    }
    return {};
  }
  noresult embed(HWND wnd, bool debug, msg_cb_t cb) {
    std::atomic_flag flag = ATOMIC_FLAG_INIT;
    flag.test_and_set();

    wchar_t currentExePath[MAX_PATH];
    GetModuleFileNameW(nullptr, currentExePath, MAX_PATH);
    wchar_t *currentExeName = PathFindFileNameW(currentExePath);

    wchar_t dataPath[MAX_PATH];
    if (!SUCCEEDED(
            SHGetFolderPathW(nullptr, CSIDL_APPDATA, nullptr, 0, dataPath))) {
      return error_info{WEBVIEW_ERROR_UNSPECIFIED, "SHGetFolderPathW failed"};
    }
    wchar_t userDataFolder[MAX_PATH];
    PathCombineW(userDataFolder, dataPath, currentExeName);

    m_com_handler = new webview2_com_handler(
        wnd, cb,
        [&](ICoreWebView2Controller *controller, ICoreWebView2 *webview) {
          if (!controller || !webview) {
            flag.clear();
            return;
          }
          controller->AddRef();
          webview->AddRef();
          m_controller = controller;
          m_webview = webview;
          flag.clear();
        });

    m_com_handler->set_attempt_handler([&] {
      return m_webview2_loader.create_environment_with_options(
          nullptr, userDataFolder, nullptr, m_com_handler);
    });
    m_com_handler->try_create_environment();

    // Pump the message loop until WebView2 has finished initialization.
    bool got_quit_msg = false;
    MSG msg;
    while (flag.test_and_set() && GetMessageW(&msg, nullptr, 0, 0) >= 0) {
      if (msg.message == WM_QUIT) {
        got_quit_msg = true;
        break;
      }
      TranslateMessage(&msg);
      DispatchMessageW(&msg);
    }
    if (got_quit_msg) {
      return error_info{WEBVIEW_ERROR_CANCELED};
    }
    if (!m_controller || !m_webview) {
      return error_info{WEBVIEW_ERROR_INVALID_STATE};
    }
    ICoreWebView2Settings *settings = nullptr;
    auto res = m_webview->get_Settings(&settings);
    if (res != S_OK) {
      return error_info{WEBVIEW_ERROR_UNSPECIFIED, "get_Settings failed"};
    }
    res = settings->put_AreDevToolsEnabled(debug ? TRUE : FALSE);
    if (res != S_OK) {
      return error_info{WEBVIEW_ERROR_UNSPECIFIED,
                        "put_AreDevToolsEnabled failed"};
    }
    res = settings->put_IsStatusBarEnabled(FALSE);
    if (res != S_OK) {
      return error_info{WEBVIEW_ERROR_UNSPECIFIED,
                        "put_IsStatusBarEnabled failed"};
    }
    add_init_script("function(message) {\n\
  return window.chrome.webview.postMessage(message);\n\
}");
    resize_webview();
    m_controller->put_IsVisible(TRUE);
    ShowWindow(m_widget, SW_SHOW);
    UpdateWindow(m_widget);
    if (owns_window()) {
      focus_webview();
    }
    return {};
  }

  void resize_widget() {
    if (m_widget) {
      RECT r{};
      if (GetClientRect(GetParent(m_widget), &r)) {
        MoveWindow(m_widget, r.left, r.top, r.right - r.left, r.bottom - r.top,
                   TRUE);
      }
    }
  }

  void resize_webview() {
    if (m_widget && m_controller) {
      RECT bounds{};
      if (GetClientRect(m_widget, &bounds)) {
        m_controller->put_Bounds(bounds);
      }
    }
  }

  void focus_webview() {
    if (m_controller) {
      m_controller->MoveFocus(COREWEBVIEW2_MOVE_FOCUS_REASON_PROGRAMMATIC);
    }
  }

  bool is_webview2_available() const noexcept {
    LPWSTR version_info = nullptr;
    auto res = m_webview2_loader.get_available_browser_version_string(
        nullptr, &version_info);
    // The result will be equal to HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)
    // if the WebView2 runtime is not installed.
    auto ok = SUCCEEDED(res) && version_info;
    if (version_info) {
      CoTaskMemFree(version_info);
    }
    return ok;
  }

  void on_dpi_changed(int dpi) {
    auto scaled_size = get_scaled_size(m_dpi, dpi);
    auto frame_size =
        make_window_frame_size(m_window, scaled_size.cx, scaled_size.cy, dpi);
    SetWindowPos(m_window, nullptr, 0, 0, frame_size.cx, frame_size.cy,
                 SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE | SWP_FRAMECHANGED);
    m_dpi = dpi;
  }

  SIZE get_size() const {
    RECT bounds;
    GetClientRect(m_window, &bounds);
    auto width = bounds.right - bounds.left;
    auto height = bounds.bottom - bounds.top;
    return {width, height};
  }

  SIZE get_scaled_size(int from_dpi, int to_dpi) const {
    auto size = get_size();
    return scale_size(size.cx, size.cy, from_dpi, to_dpi);
  }

  void on_system_setting_change(const wchar_t *area) {
    // Detect light/dark mode change in system.
    if (lstrcmpW(area, L"ImmersiveColorSet") == 0) {
      apply_window_theme(m_window);
    }
  }

  void run_event_loop_while(std::function<bool()> fn) override {
    MSG msg;
    while (fn() && GetMessageW(&msg, nullptr, 0, 0) > 0) {
      TranslateMessage(&msg);
      DispatchMessageW(&msg);
    }
  }

  // The app is expected to call CoInitializeEx before
  // CreateCoreWebView2EnvironmentWithOptions.
  // Source: https://docs.microsoft.com/en-us/microsoft-edge/webview2/reference/win32/webview2-idl#createcorewebview2environmentwithoptions
  com_init_wrapper m_com_init;
  HWND m_window = nullptr;
  HWND m_widget = nullptr;
  HWND m_message_window = nullptr;
  POINT m_minsz = POINT{0, 0};
  POINT m_maxsz = POINT{0, 0};
  DWORD m_main_thread = GetCurrentThreadId();
  ICoreWebView2 *m_webview = nullptr;
  ICoreWebView2Controller *m_controller = nullptr;
  webview2_com_handler *m_com_handler = nullptr;
  mswebview2::loader m_webview2_loader;
  int m_dpi{};
  bool m_is_window_shown{};
};

} // namespace detail

using browser_engine = detail::win32_edge_engine;

} // namespace webview

#endif // defined(WEBVIEW_PLATFORM_WINDOWS) && defined(WEBVIEW_EDGE)
#endif // defined(__cplusplus) && !defined(WEBVIEW_HEADER)
#endif // WEBVIEW_BACKENDS_WIN32_EDGE_HH


================================================
FILE: core/include/webview/detail/basic_result.hh
================================================
/*
 * MIT License
 *
 * Copyright (c) 2017 Serge Zaitsev
 * Copyright (c) 2022 Steffen André Langnes
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#ifndef WEBVIEW_DETAIL_BASIC_RESULT_HH
#define WEBVIEW_DETAIL_BASIC_RESULT_HH

#if defined(__cplusplus) && !defined(WEBVIEW_HEADER)

#include "exceptions.hh"
#include "optional.hh"

#include <utility>

namespace webview {
namespace detail {

template <typename Value, typename Error, typename Exception>
class basic_result {
public:
  using value_type = Value;
  using error_type = Error;
  using exception_type = Exception;

  basic_result() : basic_result(value_type{}) {}

  basic_result(const value_type &value) : m_value{value} {}
  basic_result(value_type &&value) : m_value{std::forward<value_type>(value)} {}

  basic_result(const error_type &error) : m_error{error} {}
  basic_result(error_type &&error) : m_error{std::forward<error_type>(error)} {}

  bool ok() const { return has_value() && !has_error(); }
  bool has_value() const { return m_value.has_value(); }
  bool has_error() const { return m_error.has_value(); }

  void ensure_ok() {
    if (!ok()) {
      throw exception_type{error()};
    }
  }

  const value_type &value() const {
    if (!has_value()) {
      throw bad_access{};
    }
    return m_value.get();
  }

  const error_type &error() const {
    if (!has_error()) {
      throw bad_access{};
    }
    return m_error.get();
  }

private:
  optional<value_type> m_value;
  optional<error_type> m_error;
};

template <typename Error, typename Exception>
class basic_result<void, Error, Exception> {
public:
  using value_type = void;
  using error_type = Error;
  using exception_type = Exception;

  basic_result() = default;

  basic_result(error_type &&error) : m_error{std::forward<error_type>(error)} {}

  bool ok() const { return !has_error(); }

  bool has_error() const { return m_error.has_value(); }

  void ensure_ok() {
    if (!ok()) {
      throw exception_type{error()};
    }
  }

  const error_type &error() const {
    if (!has_error()) {
      throw bad_access{};
    }
    return m_error.get();
  }

private:
  optional<error_type> m_error;
};

} // namespace detail
} // namespace webview

#endif // defined(__cplusplus) && !defined(WEBVIEW_HEADER)
#endif // WEBVIEW_DETAIL_BASIC_RESULT_HH


================================================
FILE: core/include/webview/detail/engine_base.hh
================================================
/*
 * MIT License
 *
 * Copyright (c) 2017 Serge Zaitsev
 * Copyright (c) 2022 Steffen André Langnes
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
Download .txt
gitextract_dbzse5fk/

├── .clang-format
├── .clang-tidy
├── .gitattributes
├── .github/
│   ├── actions/
│   │   ├── cmake/
│   │   │   └── action.yaml
│   │   └── setup-env/
│   │       └── action.yaml
│   ├── issue_template.md
│   └── workflows/
│       ├── build.yaml
│       ├── build_matrix.csv
│       ├── build_matrix_schema.json
│       ├── check.yaml
│       ├── ci.yaml
│       ├── csv.js
│       └── draft-release.yaml
├── .gitignore
├── CHANGELOG.md
├── CMakeLists.txt
├── CONTRIBUTING.md
├── LICENSE
├── MIGRATION.md
├── README.md
├── cmake/
│   ├── clang_format.cmake
│   ├── extract_version.cmake
│   ├── internal.cmake
│   ├── modules/
│   │   └── FindMSWebView2.cmake
│   ├── toolchains/
│   │   ├── arm64-windows-msvc.cmake
│   │   ├── host-gnu.cmake
│   │   ├── host-llvm.cmake
│   │   ├── i686-w64-mingw32.cmake
│   │   ├── i686-windows-msvc.cmake
│   │   ├── universal-macos-llvm.cmake
│   │   ├── x86_64-msys2-gnu-ucrt64.cmake
│   │   ├── x86_64-msys2-llvm-clang64.cmake
│   │   ├── x86_64-w64-mingw32.cmake
│   │   └── x86_64-windows-msvc.cmake
│   ├── webview-config.cmake.in
│   └── webview.cmake
├── compatibility/
│   ├── CMakeLists.txt
│   └── mingw/
│       ├── CMakeLists.txt
│       └── include/
│           └── EventToken.h
├── core/
│   ├── CMakeLists.txt
│   ├── include/
│   │   ├── webview/
│   │   │   ├── api.h
│   │   │   ├── backends.hh
│   │   │   ├── c_api_impl.hh
│   │   │   ├── detail/
│   │   │   │   ├── backends/
│   │   │   │   │   ├── cocoa_webkit.hh
│   │   │   │   │   ├── gtk_webkitgtk.hh
│   │   │   │   │   └── win32_edge.hh
│   │   │   │   ├── basic_result.hh
│   │   │   │   ├── engine_base.hh
│   │   │   │   ├── exceptions.hh
│   │   │   │   ├── json.hh
│   │   │   │   ├── native_library.hh
│   │   │   │   ├── optional.hh
│   │   │   │   ├── platform/
│   │   │   │   │   ├── darwin/
│   │   │   │   │   │   ├── cocoa/
│   │   │   │   │   │   │   ├── NSApplication.hh
│   │   │   │   │   │   │   ├── NSBundle.hh
│   │   │   │   │   │   │   ├── NSEvent.hh
│   │   │   │   │   │   │   ├── NSInvocation.hh
│   │   │   │   │   │   │   ├── NSMethodSignature.hh
│   │   │   │   │   │   │   ├── NSNotification.hh
│   │   │   │   │   │   │   ├── NSNumber.hh
│   │   │   │   │   │   │   ├── NSObject.hh
│   │   │   │   │   │   │   ├── NSOpenPanel.hh
│   │   │   │   │   │   │   ├── NSPoint.hh
│   │   │   │   │   │   │   ├── NSRect.hh
│   │   │   │   │   │   │   ├── NSSavePanel.hh
│   │   │   │   │   │   │   ├── NSSize.hh
│   │   │   │   │   │   │   ├── NSString.hh
│   │   │   │   │   │   │   ├── NSURL.hh
│   │   │   │   │   │   │   ├── NSURLRequest.hh
│   │   │   │   │   │   │   ├── NSValue.hh
│   │   │   │   │   │   │   ├── NSView.hh
│   │   │   │   │   │   │   ├── NSWindow.hh
│   │   │   │   │   │   │   ├── cocoa.hh
│   │   │   │   │   │   │   └── types.hh
│   │   │   │   │   │   ├── objc/
│   │   │   │   │   │   │   ├── Class.hh
│   │   │   │   │   │   │   ├── autoreleasepool.hh
│   │   │   │   │   │   │   ├── invoke.hh
│   │   │   │   │   │   │   ├── memory.hh
│   │   │   │   │   │   │   └── objc.hh
│   │   │   │   │   │   └── webkit/
│   │   │   │   │   │       ├── WKOpenPanelParameters.hh
│   │   │   │   │   │       ├── WKScriptMessage.hh
│   │   │   │   │   │       ├── WKUserContentController.hh
│   │   │   │   │   │       ├── WKUserScript.hh
│   │   │   │   │   │       ├── WKWebView.hh
│   │   │   │   │   │       ├── WKWebViewConfiguration.hh
│   │   │   │   │   │       └── webkit.hh
│   │   │   │   │   ├── linux/
│   │   │   │   │   │   ├── gtk/
│   │   │   │   │   │   │   └── compat.hh
│   │   │   │   │   │   └── webkitgtk/
│   │   │   │   │   │       ├── compat.hh
│   │   │   │   │   │       └── dmabuf.hh
│   │   │   │   │   └── windows/
│   │   │   │   │       ├── com_init_wrapper.hh
│   │   │   │   │       ├── dpi.hh
│   │   │   │   │       ├── dwmapi.hh
│   │   │   │   │       ├── iid.hh
│   │   │   │   │       ├── ntdll.hh
│   │   │   │   │       ├── reg_key.hh
│   │   │   │   │       ├── shcore.hh
│   │   │   │   │       ├── theme.hh
│   │   │   │   │       ├── user32.hh
│   │   │   │   │       ├── version.hh
│   │   │   │   │       └── webview2/
│   │   │   │   │           └── loader.hh
│   │   │   │   ├── user_script.hh
│   │   │   │   └── utility/
│   │   │   │       └── string.hh
│   │   │   ├── errors.h
│   │   │   ├── errors.hh
│   │   │   ├── json_deprecated.hh
│   │   │   ├── macros.h
│   │   │   ├── types.h
│   │   │   ├── types.hh
│   │   │   ├── version.h
│   │   │   └── webview.h
│   │   └── webview.h
│   ├── src/
│   │   └── webview.cc
│   └── tests/
│       ├── CMakeLists.txt
│       └── src/
│           ├── functional_tests.cc
│           └── unit_tests.cc
├── docs/
│   ├── CMakeLists.txt
│   └── api/
│       ├── CMakeLists.txt
│       └── Doxyfile.in
├── examples/
│   ├── CMakeLists.txt
│   ├── basic.c
│   ├── basic.cc
│   ├── bind.c
│   ├── bind.cc
│   └── resources/
│       ├── macos/
│       │   ├── app_icon.icns
│       │   └── resources.cmake
│       └── windows/
│           ├── resources.cmake
│           ├── resources.rc
│           └── version.rc.in
├── gcovr.cfg
├── gcovr.ci.cfg
├── packaging/
│   ├── CMakeLists.txt
│   ├── external_package.cmake.in
│   └── test/
│       ├── .gitignore
│       └── CMakeLists.txt
├── scripts/
│   └── amalgamate/
│       ├── amalgamate.py
│       └── test/
│           ├── .gitignore
│           ├── main.c
│           ├── main.cc
│           └── webview.cc
├── test_driver/
│   ├── CMakeLists.txt
│   ├── cmake/
│   │   ├── discovery.cmake
│   │   └── generate_includes.cmake
│   ├── include/
│   │   └── webview/
│   │       └── test_driver.hh
│   └── src/
│       └── test_driver.cc
└── webview.i
Download .txt
SYMBOL INDEX (679 symbols across 74 files)

FILE: .github/workflows/csv.js
  function parseRow (line 7) | function parseRow(line) {
  function parseRows (line 49) | function parseRows(lines) {
  function extractLines (line 53) | function extractLines(content) {
  function transform (line 57) | function transform(key, value, schema) {
  function processRows (line 67) | function processRows(rows, schema) {
  function loadString (line 86) | function loadString(content, schema) {
  function loadFile (line 90) | function loadFile(filePath, schema) {

FILE: compatibility/mingw/include/EventToken.h
  type EventRegistrationToken (line 19) | typedef struct EventRegistrationToken {

FILE: core/include/webview/backends.hh
  type webview (line 35) | namespace webview {

FILE: core/include/webview/c_api_impl.hh
  type webview (line 39) | namespace webview {
    type detail (line 40) | namespace detail {
      function webview_error_t (line 50) | webview_error_t api_filter(WorkFn &&do_work, ResultFn &&put_result) ...
      function webview_error_t (line 66) | webview_error_t api_filter(WorkFn &&do_work) noexcept {
      function webview (line 80) | inline webview *cast_to_webview(void *w) {
  function WEBVIEW_API (line 91) | WEBVIEW_API webview_t webview_create(int debug, void *wnd) {
  function WEBVIEW_API (line 105) | WEBVIEW_API webview_error_t webview_destroy(webview_t w) {
  function WEBVIEW_API (line 113) | WEBVIEW_API webview_error_t webview_run(webview_t w) {
  function WEBVIEW_API (line 118) | WEBVIEW_API webview_error_t webview_terminate(webview_t w) {
  function WEBVIEW_API (line 123) | WEBVIEW_API webview_error_t webview_dispatch(webview_t w,
  function WEBVIEW_API (line 134) | WEBVIEW_API void *webview_get_window(webview_t w) {
  function WEBVIEW_API (line 145) | WEBVIEW_API void *webview_get_native_handle(webview_t w,
  function WEBVIEW_API (line 170) | WEBVIEW_API webview_error_t webview_set_title(webview_t w, const char *t...
  function WEBVIEW_API (line 178) | WEBVIEW_API webview_error_t webview_set_size(webview_t w, int width, int...
  function WEBVIEW_API (line 185) | WEBVIEW_API webview_error_t webview_navigate(webview_t w, const char *ur...
  function WEBVIEW_API (line 193) | WEBVIEW_API webview_error_t webview_set_html(webview_t w, const char *ht...
  function WEBVIEW_API (line 201) | WEBVIEW_API webview_error_t webview_init(webview_t w, const char *js) {
  function WEBVIEW_API (line 209) | WEBVIEW_API webview_error_t webview_eval(webview_t w, const char *js) {
  function WEBVIEW_API (line 217) | WEBVIEW_API webview_error_t webview_bind(webview_t w, const char *name,
  function WEBVIEW_API (line 235) | WEBVIEW_API webview_error_t webview_unbind(webview_t w, const char *name) {
  function WEBVIEW_API (line 243) | WEBVIEW_API webview_error_t webview_return(webview_t w, const char *id,
  function WEBVIEW_API (line 253) | WEBVIEW_API const webview_version_info_t *webview_version(void) {

FILE: core/include/webview/detail/backends/cocoa_webkit.hh
  type webview (line 60) | namespace webview {
    type detail (line 61) | namespace detail {
      class user_script::impl (line 63) | class user_script::impl {
        method impl (line 65) | impl(id script) : m_script{objc::retain(script)} {}
        method impl (line 69) | impl(const impl &) = delete;
        method impl (line 70) | impl &operator=(const impl &) = delete;
        method impl (line 71) | impl(impl &&) = delete;
        method impl (line 72) | impl &operator=(impl &&) = delete;
        method id (line 74) | id get_native() const { return m_script; }
      type cocoa_webkit (line 84) | namespace cocoa_webkit {
        class cocoa_wkwebview_engine (line 89) | class cocoa_wkwebview_engine : public engine_base {
          method cocoa_wkwebview_engine (line 91) | cocoa_wkwebview_engine(bool debug, void *window)
          method cocoa_wkwebview_engine (line 98) | cocoa_wkwebview_engine(const cocoa_wkwebview_engine &) = delete;
          method cocoa_wkwebview_engine (line 99) | cocoa_wkwebview_engine &operator=(const cocoa_wkwebview_engine &...
          method cocoa_wkwebview_engine (line 100) | cocoa_wkwebview_engine(cocoa_wkwebview_engine &&) = delete;
          method cocoa_wkwebview_engine (line 101) | cocoa_wkwebview_engine &operator=(cocoa_wkwebview_engine &&) = d...
          method window_impl (line 149) | result<void *> window_impl() override {
          method widget_impl (line 156) | result<void *> widget_impl() override {
          method browser_controller_impl (line 163) | result<void *> browser_controller_impl() override {
          method noresult (line 170) | noresult terminate_impl() override {
          method noresult (line 175) | noresult run_impl() override {
          method noresult (line 180) | noresult dispatch_impl(std::function<void()> f) override {
          method noresult (line 190) | noresult set_title_impl(const std::string &title) override {
          method noresult (line 194) | noresult set_size_impl(int width, int height, webview_hint_t hin...
          method noresult (line 220) | noresult navigate_impl(const std::string &url) override {
          method noresult (line 228) | noresult set_html_impl(const std::string &html) override {
          method noresult (line 234) | noresult eval_impl(const std::string &js) override {
          method user_script (line 246) | user_script add_user_script_impl(const std::string &js) override {
          method remove_all_user_scripts_impl (line 259) | void remove_all_user_scripts_impl(
          method are_user_scripts_equal_impl (line 266) | bool are_user_scripts_equal_impl(const user_script &first,
          method id (line 274) | id create_app_delegate() {
          method id (line 301) | id create_script_message_handler() {
          method id (line 324) | static id create_webkit_ui_delegate() {
          method id (line 369) | static id create_window_delegate() {
          method cocoa_wkwebview_engine (line 388) | static cocoa_wkwebview_engine *get_associated_webview(id object) {
          method set_associated_webview (line 397) | static void set_associated_webview(id object, cocoa_wkwebview_en...
          method is_app_bundled (line 402) | static bool is_app_bundled() noexcept {
          method on_application_did_finish_launching (line 412) | void on_application_did_finish_launching(id /*delegate*/, id app) {
          method on_window_will_close (line 440) | void on_window_will_close(id /*delegate*/, id /*window*/) {
          method window_settings (line 447) | void window_settings(bool debug) {
          method set_up_widget (line 521) | void set_up_widget() {
          method stop_run_loop (line 530) | void stop_run_loop() {
          method get_and_set_is_first_instance (line 540) | static bool get_and_set_is_first_instance() noexcept {
          method window_init (line 548) | void window_init(void *window) {
          method window_init_proceed (line 574) | void window_init_proceed() {
          method noresult (line 586) | noresult window_show() {
          method run_event_loop_while (line 595) | void run_event_loop_while(std::function<bool()> fn) override {

FILE: core/include/webview/detail/backends/gtk_webkitgtk.hh
  type webview (line 78) | namespace webview {
    type detail (line 79) | namespace detail {
      class user_script::impl (line 81) | class user_script::impl {
        method impl (line 83) | impl(WebKitUserScript *script) : m_script{script} {
        method impl (line 89) | impl(const impl &) = delete;
        method impl (line 90) | impl &operator=(const impl &) = delete;
        method impl (line 91) | impl(impl &&) = delete;
        method impl (line 92) | impl &operator=(impl &&) = delete;
        method WebKitUserScript (line 94) | WebKitUserScript *get_native() const { return m_script; }
      class gtk_webkit_engine (line 100) | class gtk_webkit_engine : public engine_base {
        method gtk_webkit_engine (line 102) | gtk_webkit_engine(bool debug, void *window) : engine_base{!window} {
        method gtk_webkit_engine (line 108) | gtk_webkit_engine(const gtk_webkit_engine &) = delete;
        method gtk_webkit_engine (line 109) | gtk_webkit_engine &operator=(const gtk_webkit_engine &) = delete;
        method gtk_webkit_engine (line 110) | gtk_webkit_engine(gtk_webkit_engine &&) = delete;
        method gtk_webkit_engine (line 111) | gtk_webkit_engine &operator=(gtk_webkit_engine &&) = delete;
        method window_impl (line 135) | result<void *> window_impl() override {
        method widget_impl (line 142) | result<void *> widget_impl() override {
        method browser_controller_impl (line 149) | result<void *> browser_controller_impl() override {
        method noresult (line 156) | noresult run_impl() override {
        method noresult (line 164) | noresult terminate_impl() override {
        method noresult (line 168) | noresult dispatch_impl(std::function<void()> f) override {
        method noresult (line 178) | noresult set_title_impl(const std::string &title) override {
        method noresult (line 183) | noresult set_size_impl(int width, int height, webview_hint_t hints...
        method noresult (line 197) | noresult navigate_impl(const std::string &url) override {
        method noresult (line 202) | noresult set_html_impl(const std::string &html) override {
        method noresult (line 208) | noresult eval_impl(const std::string &js) override {
        method user_script (line 225) | user_script add_user_script_impl(const std::string &js) override {
        method remove_all_user_scripts_impl (line 237) | void remove_all_user_scripts_impl(
        method are_user_scripts_equal_impl (line 242) | bool are_user_scripts_equal_impl(const user_script &first,
        method window_init (line 274) | void window_init(void *window) {
        method window_settings (line 308) | void window_settings(bool debug) {
        method noresult (line 319) | noresult window_show() {
        method run_event_loop_while (line 334) | void run_event_loop_while(std::function<bool()> fn) override {

FILE: core/include/webview/detail/backends/win32_edge.hh
  type webview (line 83) | namespace webview {
    type detail (line 84) | namespace detail {
      class webview2_com_handler (line 88) | class webview2_com_handler
        method webview2_com_handler (line 97) | webview2_com_handler(HWND hwnd, msg_cb_t msgCb, webview2_com_handl...
        method webview2_com_handler (line 101) | webview2_com_handler(const webview2_com_handler &other) = delete;
        method webview2_com_handler (line 102) | webview2_com_handler &operator=(const webview2_com_handler &other)...
        method webview2_com_handler (line 103) | webview2_com_handler(webview2_com_handler &&other) = delete;
        method webview2_com_handler (line 104) | webview2_com_handler &operator=(webview2_com_handler &&other) = de...
        method AddRef (line 106) | AddRef() { return ++m_ref_count; }
        method Release (line 107) | Release() {
        method QueryInterface (line 114) | QueryInterface(REFIID riid, LPVOID *ppv) {
        method Invoke (line 140) | Invoke(HRESULT res, ICoreWebView2Environment *env) {
        method Invoke (line 150) | Invoke(HRESULT res,
        method Invoke (line 175) | Invoke(ICoreWebView2 * /*sender*/,
        method Invoke (line 187) | Invoke(ICoreWebView2 * /*sender*/,
        method set_attempt_handler (line 199) | void set_attempt_handler(std::function<HRESULT()> attempt_handler)...
        method try_create_environment (line 206) | void try_create_environment() noexcept {
      class webview2_user_script_added_handler (line 242) | class webview2_user_script_added_handler
        method webview2_user_script_added_handler (line 247) | webview2_user_script_added_handler(callback_fn cb) : m_cb{cb} {}
        method webview2_user_script_added_handler (line 250) | webview2_user_script_added_handler(
        method webview2_user_script_added_handler (line 252) | webview2_user_script_added_handler &
        method webview2_user_script_added_handler (line 254) | webview2_user_script_added_handler(
        method webview2_user_script_added_handler (line 256) | webview2_user_script_added_handler &
        method AddRef (line 259) | AddRef() { return ++m_ref_count; }
        method Release (line 260) | Release() {
        method QueryInterface (line 268) | QueryInterface(REFIID riid, LPVOID *ppv) {
        method Invoke (line 284) | Invoke(HRESULT res, LPCWSTR id) {
      class user_script::impl (line 294) | class user_script::impl {
        method impl (line 296) | impl(const std::wstring &id, const std::wstring &code)
        method impl (line 299) | impl(const impl &) = delete;
        method impl (line 300) | impl &operator=(const impl &) = delete;
        method impl (line 301) | impl(impl &&) = delete;
        method impl (line 302) | impl &operator=(impl &&) = delete;
      class win32_edge_engine (line 312) | class win32_edge_engine : public engine_base {
        method win32_edge_engine (line 314) | win32_edge_engine(bool debug, void *window) : engine_base{!window} {
        method win32_edge_engine (line 369) | win32_edge_engine(const win32_edge_engine &other) = delete;
        method win32_edge_engine (line 370) | win32_edge_engine &operator=(const win32_edge_engine &other) = del...
        method win32_edge_engine (line 371) | win32_edge_engine(win32_edge_engine &&other) = delete;
        method win32_edge_engine (line 372) | win32_edge_engine &operator=(win32_edge_engine &&other) = delete;
        method noresult (line 375) | noresult run_impl() override {
        method window_impl (line 383) | result<void *> window_impl() override {
        method widget_impl (line 389) | result<void *> widget_impl() override {
        method browser_controller_impl (line 395) | result<void *> browser_controller_impl() override {
        method noresult (line 401) | noresult terminate_impl() override {
        method noresult (line 405) | noresult dispatch_impl(dispatch_fn_t f) override {
        method noresult (line 410) | noresult set_title_impl(const std::string &title) override {
        method noresult (line 415) | noresult set_size_impl(int width, int height, webview_hint_t hints...
        method noresult (line 444) | noresult navigate_impl(const std::string &url) override {
        method noresult (line 450) | noresult eval_impl(const std::string &js) override {
        method noresult (line 458) | noresult set_html_impl(const std::string &html) override {
        method user_script (line 463) | user_script add_user_script_impl(const std::string &js) override {
        method remove_all_user_scripts_impl (line 494) | void
        method are_user_scripts_equal_impl (line 502) | bool are_user_scripts_equal_impl(const user_script &first,
        method window_init (line 510) | void window_init(void *window) {
        method window_settings (line 712) | void window_settings(bool debug) {
        method noresult (line 718) | noresult window_show() {
        method noresult (line 727) | noresult embed(HWND wnd, bool debug, msg_cb_t cb) {
        method resize_widget (line 808) | void resize_widget() {
        method resize_webview (line 818) | void resize_webview() {
        method focus_webview (line 827) | void focus_webview() {
        method is_webview2_available (line 833) | bool is_webview2_available() const noexcept {
        method on_dpi_changed (line 846) | void on_dpi_changed(int dpi) {
        method SIZE (line 855) | SIZE get_size() const {
        method SIZE (line 863) | SIZE get_scaled_size(int from_dpi, int to_dpi) const {
        method on_system_setting_change (line 868) | void on_system_setting_change(const wchar_t *area) {
        method run_event_loop_while (line 875) | void run_event_loop_while(std::function<bool()> fn) override {

FILE: core/include/webview/detail/basic_result.hh
  type webview (line 36) | namespace webview {
    type detail (line 37) | namespace detail {
      class basic_result (line 40) | class basic_result {
        method basic_result (line 46) | basic_result() : basic_result(value_type{}) {}
        method basic_result (line 48) | basic_result(const value_type &value) : m_value{value} {}
        method basic_result (line 49) | basic_result(value_type &&value) : m_value{std::forward<value_type...
        method basic_result (line 51) | basic_result(const error_type &error) : m_error{error} {}
        method basic_result (line 52) | basic_result(error_type &&error) : m_error{std::forward<error_type...
        method ok (line 54) | bool ok() const { return has_value() && !has_error(); }
        method has_value (line 55) | bool has_value() const { return m_value.has_value(); }
        method has_error (line 56) | bool has_error() const { return m_error.has_value(); }
        method ensure_ok (line 58) | void ensure_ok() {
        method value_type (line 64) | const value_type &value() const {
        method error_type (line 71) | const error_type &error() const {
      class basic_result<void, Error, Exception> (line 84) | class basic_result<void, Error, Exception> {
        method basic_result (line 90) | basic_result() = default;
        method basic_result (line 92) | basic_result(error_type &&error) : m_error{std::forward<error_type...
        method ok (line 94) | bool ok() const { return !has_error(); }
        method has_error (line 96) | bool has_error() const { return m_error.has_value(); }
        method ensure_ok (line 98) | void ensure_ok() {
        method error_type (line 104) | const error_type &error() const {

FILE: core/include/webview/detail/engine_base.hh
  type webview (line 43) | namespace webview {
    type detail (line 44) | namespace detail {
      class engine_base (line 46) | class engine_base {
        method engine_base (line 48) | engine_base(bool owns_window) : m_owns_window{owns_window} {}
        method noresult (line 52) | noresult navigate(const std::string &url) {
        class binding_ctx_t (line 60) | class binding_ctx_t {
          method binding_ctx_t (line 62) | binding_ctx_t(binding_t callback, void *arg)
          method call (line 64) | void call(std::string id, std::string args) const {
        method noresult (line 80) | noresult bind(const std::string &name, sync_binding_t fn) {
        method noresult (line 87) | noresult bind(const std::string &name, binding_t fn, void *arg) {
        method noresult (line 103) | noresult unbind(const std::string &name) {
        method noresult (line 119) | noresult resolve(const std::string &id, int status,
        method window (line 132) | result<void *> window() { return window_impl(); }
        method widget (line 133) | result<void *> widget() { return widget_impl(); }
        method browser_controller (line 134) | result<void *> browser_controller() { return browser_controller_im...
        method noresult (line 135) | noresult run() { return run_impl(); }
        method noresult (line 136) | noresult terminate() { return terminate_impl(); }
        method noresult (line 137) | noresult dispatch(std::function<void()> f) { return dispatch_impl(...
        method noresult (line 138) | noresult set_title(const std::string &title) { return set_title_im...
        method noresult (line 140) | noresult set_size(int width, int height, webview_hint_t hints) {
        method noresult (line 146) | noresult set_html(const std::string &html) { return set_html_impl(...
        method noresult (line 148) | noresult init(const std::string &js) {
        method noresult (line 153) | noresult eval(const std::string &js) { return eval_impl(js); }
        method user_script (line 169) | virtual user_script *add_user_script(const std::string &js) {
        method user_script (line 182) | virtual user_script *replace_user_script(const user_script &old_sc...
        method replace_bind_script (line 197) | void replace_bind_script() {
        method add_init_script (line 205) | void add_init_script(const std::string &post_fn) {
        method create_init_script (line 210) | std::string create_init_script(const std::string &post_fn) {
        method create_bind_script (line 280) | std::string create_bind_script() {
        method on_message (line 304) | virtual void on_message(const std::string &msg) {
        method on_window_created (line 316) | virtual void on_window_created() { inc_window_count(); }
        method on_window_destroyed (line 318) | virtual void on_window_destroyed(bool skip_termination = false) {
        method deplete_run_loop_event_queue (line 327) | void deplete_run_loop_event_queue() {
        method dispatch_size_default (line 336) | void dispatch_size_default() {
        method set_default_size_guard (line 347) | void set_default_size_guard(bool guarded) { m_is_size_set = guarde...
        method owns_window (line 349) | bool owns_window() const { return m_owns_window; }
        method inc_window_count (line 357) | static unsigned int inc_window_count() { return ++window_ref_count...
        method dec_window_count (line 359) | static unsigned int dec_window_count() {

FILE: core/include/webview/detail/exceptions.hh
  type webview (line 33) | namespace webview {
    type detail (line 34) | namespace detail {
      class bad_access (line 36) | class bad_access : public std::exception {}

FILE: core/include/webview/detail/json.hh
  type webview (line 35) | namespace webview {
    type detail (line 36) | namespace detail {
      function json_parse_c (line 38) | inline int json_parse_c(const char *s, size_t sz, const char *key, s...
      function is_json_special_char (line 181) | constexpr bool is_json_special_char(char c) {
      function is_ascii_control_char (line 186) | constexpr bool is_ascii_control_char(char c) {
      function json_escape (line 191) | inline std::string json_escape(const std::string &s, bool add_quotes...
      function json_unescape (line 252) | inline int json_unescape(const char *s, size_t n, char *out) {
      function json_parse (line 307) | inline std::string json_parse(const std::string &s, const std::strin...

FILE: core/include/webview/detail/native_library.hh
  type webview (line 44) | namespace webview {
    type detail (line 45) | namespace detail {
      class library_symbol (line 48) | class library_symbol {
        method library_symbol (line 52) | constexpr explicit library_symbol(const char *name) : m_name(name) {}
      class native_library (line 61) | class native_library {
        method native_library (line 63) | native_library() = default;
        method native_library (line 65) | explicit native_library(const std::string &name)
        method native_library (line 69) | explicit native_library(const std::wstring &name)
        method native_library (line 84) | native_library(const native_library &other) = delete;
        method native_library (line 85) | native_library &operator=(const native_library &other) = delete;
        method native_library (line 86) | native_library(native_library &&other) noexcept { *this = std::mov...
        method native_library (line 88) | native_library &operator=(native_library &&other) noexcept {
        method get (line 102) | typename Symbol::type get(const Symbol &symbol) const {
        method is_loaded (line 125) | bool is_loaded() const { return !!m_handle; }
        method detach (line 127) | void detach() { m_handle = nullptr; }
        method is_loaded (line 130) | static inline bool is_loaded(const std::string &name) {
        method mod_handle_t (line 149) | static inline mod_handle_t load_library(const std::string &name) {
        method mod_handle_t (line 158) | static inline mod_handle_t load_library(const std::wstring &name) {

FILE: core/include/webview/detail/optional.hh
  type webview (line 37) | namespace webview {
    type detail (line 38) | namespace detail {
      class optional (line 40) | class optional {
        method optional (line 43) | optional() = default;
        method optional (line 45) | optional(const T &other) noexcept : m_has_data{true} {
        method optional (line 49) | optional(T &&other) noexcept : m_has_data{true} {
        method optional (line 53) | optional(const optional<T> &other) noexcept { *this = other; }
        method optional (line 55) | optional &operator=(const optional<T> &other) noexcept {
        method optional (line 67) | optional(optional<T> &&other) noexcept { *this = std::move(other); }
        method optional (line 69) | optional &operator=(optional<T> &&other) noexcept {
        method T (line 88) | const T &get() const {
        method T (line 96) | T &get() {
        method has_value (line 104) | bool has_value() const { return m_has_data; }
      class optional<void> (line 112) | class optional<void> {}

FILE: core/include/webview/detail/platform/darwin/cocoa/NSApplication.hh
  type webview (line 38) | namespace webview {
    type detail (line 39) | namespace detail {
      type cocoa (line 40) | namespace cocoa {
        type NSApplicationActivationPolicy (line 42) | enum NSApplicationActivationPolicy : NSInteger {
        type NSEventMask (line 46) | enum NSEventMask : NSUInteger { NSEventMaskAny = NSUIntegerMax }
        type NSModalResponse (line 48) | enum NSModalResponse : NSInteger { NSModalResponseOK = 1 }
        type NSRunLoopMode (line 50) | namespace NSRunLoopMode {
          function id (line 51) | inline id NSDefaultRunLoopMode() {
        function NSApplication_set_delegate (line 56) | inline void NSApplication_set_delegate(id self, id delegate) {
        function NSApplication_run (line 60) | inline void NSApplication_run(id self) {
        function NSApplication_stop (line 64) | inline void NSApplication_stop(id self, id sender = nullptr) {
        function id (line 68) | inline id NSApplication_get_sharedApplication() {
        function NSApplication_sendEvent (line 73) | inline void NSApplication_sendEvent(id self, id event) {
        function id (line 77) | inline id NSApplication_nextEventMatchingMask(id self, NSEventMask...
        function NSApplication_setActivationPolicy (line 85) | inline void
        function NSApplication_activateIgnoringOtherApps (line 91) | inline void NSApplication_activateIgnoringOtherApps(id self, bool ...
        function NSApplication_postEvent (line 96) | inline void NSApplication_postEvent(id self, id event, bool at_sta...

FILE: core/include/webview/detail/platform/darwin/cocoa/NSBundle.hh
  type webview (line 37) | namespace webview {
    type detail (line 38) | namespace detail {
      type cocoa (line 39) | namespace cocoa {
        function id (line 41) | inline id NSBundle_get_mainBundle() {
        function id (line 46) | inline id NSBundle_get_bundlePath(id self) {

FILE: core/include/webview/detail/platform/darwin/cocoa/NSEvent.hh
  type webview (line 39) | namespace webview {
    type detail (line 40) | namespace detail {
      type cocoa (line 41) | namespace cocoa {
        type NSEventType (line 43) | enum NSEventType : NSUInteger {
        type NSEventModifierFlags (line 49) | enum NSEventModifierFlags : NSUInteger {}
        function id (line 51) | inline id NSEvent_otherEventWithType(NSEventType type, NSPoint loc...

FILE: core/include/webview/detail/platform/darwin/cocoa/NSInvocation.hh
  type webview (line 37) | namespace webview {
    type detail (line 38) | namespace detail {
      type cocoa (line 39) | namespace cocoa {
        function id (line 41) | inline id NSInvocation_invocationWithMethodSignature(id sig) {
        function NSInvocation_set_target (line 47) | inline void NSInvocation_set_target(id self, id target) {
        function NSInvocation_setArgument (line 51) | inline void NSInvocation_setArgument(id self, void *location, NSIn...
        function NSInvocation_invoke (line 56) | inline void NSInvocation_invoke(id self) {

FILE: core/include/webview/detail/platform/darwin/cocoa/NSMethodSignature.hh
  type webview (line 37) | namespace webview {
    type detail (line 38) | namespace detail {
      type cocoa (line 39) | namespace cocoa {
        function id (line 41) | inline id NSMethodSignature_signatureWithObjCTypes(const char *typ...

FILE: core/include/webview/detail/platform/darwin/cocoa/NSNotification.hh
  type webview (line 37) | namespace webview {
    type detail (line 38) | namespace detail {
      type cocoa (line 39) | namespace cocoa {
        function id (line 41) | inline id NSNotification_get_object(id self) {

FILE: core/include/webview/detail/platform/darwin/cocoa/NSNumber.hh
  type webview (line 37) | namespace webview {
    type detail (line 38) | namespace detail {
      type cocoa (line 39) | namespace cocoa {
        function id (line 41) | inline id NSNumber_numberWithBool(bool value) {

FILE: core/include/webview/detail/platform/darwin/cocoa/NSObject.hh
  type webview (line 37) | namespace webview {
    type detail (line 38) | namespace detail {
      type cocoa (line 39) | namespace cocoa {
        function NSObject_setValue_forKey (line 41) | inline void NSObject_setValue_forKey(id self, id value, id key) {

FILE: core/include/webview/detail/platform/darwin/cocoa/NSOpenPanel.hh
  type webview (line 37) | namespace webview {
    type detail (line 38) | namespace detail {
      type cocoa (line 39) | namespace cocoa {
        function id (line 41) | inline id NSOpenPanel_openPanel() {
        function NSOpenPanel_set_canChooseFiles (line 46) | inline void NSOpenPanel_set_canChooseFiles(id self, bool value) {
        function NSOpenPanel_set_canChooseDirectories (line 51) | inline void NSOpenPanel_set_canChooseDirectories(id self, bool val...
        function NSOpenPanel_set_allowsMultipleSelection (line 56) | inline void NSOpenPanel_set_allowsMultipleSelection(id self, bool ...
        function id (line 61) | inline id NSOpenPanel_get_URLs(id self) {

FILE: core/include/webview/detail/platform/darwin/cocoa/NSPoint.hh
  type webview (line 37) | namespace webview {
    type detail (line 38) | namespace detail {
      type cocoa (line 39) | namespace cocoa {
        function NSPoint (line 43) | constexpr inline NSPoint NSPointMake(CGFloat x, CGFloat y) {

FILE: core/include/webview/detail/platform/darwin/cocoa/NSRect.hh
  type webview (line 37) | namespace webview {
    type detail (line 38) | namespace detail {
      type cocoa (line 39) | namespace cocoa {
        function NSRect (line 43) | constexpr inline NSRect NSRectMake(CGFloat x, CGFloat y, CGFloat w...

FILE: core/include/webview/detail/platform/darwin/cocoa/NSSavePanel.hh
  type webview (line 38) | namespace webview {
    type detail (line 39) | namespace detail {
      type cocoa (line 40) | namespace cocoa {
        function NSModalResponse (line 42) | inline NSModalResponse NSSavePanel_runModal(id self) {

FILE: core/include/webview/detail/platform/darwin/cocoa/NSSize.hh
  type webview (line 37) | namespace webview {
    type detail (line 38) | namespace detail {
      type cocoa (line 39) | namespace cocoa {
        function NSSize (line 43) | constexpr inline NSSize NSSizeMake(CGFloat w, CGFloat h) {

FILE: core/include/webview/detail/platform/darwin/cocoa/NSString.hh
  type webview (line 39) | namespace webview {
    type detail (line 40) | namespace detail {
      type cocoa (line 41) | namespace cocoa {
        type NSStringEncoding (line 43) | enum NSStringEncoding : NSUInteger {
        function NSString_hasSuffix (line 48) | inline bool NSString_hasSuffix(id self, id suffix) {
        function id (line 53) | inline id NSString_alloc() {
        function id (line 58) | inline id NSString_initWithBytes(id self, const void *bytes, NSUIn...
        function id (line 65) | inline id NSString_stringWithUTF8String(const char *utf8_string) {
        function id (line 71) | inline id NSString_stringWithUTF8String(const std::string &utf8_st...

FILE: core/include/webview/detail/platform/darwin/cocoa/NSURL.hh
  type webview (line 40) | namespace webview {
    type detail (line 41) | namespace detail {
      type cocoa (line 42) | namespace cocoa {
        function id (line 44) | inline id NSURL_URLWithString(id string) {
        function id (line 49) | inline id NSURL_URLWithString(const char *string) {
        function id (line 53) | inline id NSURL_URLWithString(const std::string &string) {

FILE: core/include/webview/detail/platform/darwin/cocoa/NSURLRequest.hh
  type webview (line 37) | namespace webview {
    type detail (line 38) | namespace detail {
      type cocoa (line 39) | namespace cocoa {
        function id (line 41) | inline id NSURLRequest_requestWithURL(id url) {

FILE: core/include/webview/detail/platform/darwin/cocoa/NSValue.hh
  type webview (line 37) | namespace webview {
    type detail (line 38) | namespace detail {
      type cocoa (line 39) | namespace cocoa {
        function id (line 41) | inline id NSValue_valueWithPointer(const void *pointer) {
        function NSValue_getValue (line 46) | inline void NSValue_getValue(id self, void *value, NSUInteger size) {

FILE: core/include/webview/detail/platform/darwin/cocoa/NSView.hh
  type webview (line 38) | namespace webview {
    type detail (line 39) | namespace detail {
      type cocoa (line 40) | namespace cocoa {
        type NSAutoresizingMaskOptions (line 42) | enum NSAutoresizingMaskOptions : NSUInteger {
        function id (line 51) | inline id NSView_alloc() {
        function id (line 55) | inline id NSView_initWithFrame(id self, NSRect frame_rect) {
        function id (line 59) | inline id NSView_withFrame(NSRect frame_rect) {
        function NSView_set_autoresizesSubviews (line 63) | inline void NSView_set_autoresizesSubviews(id self, bool resizes) {
        function NSView_addSubview (line 68) | inline void NSView_addSubview(id self, id subview) {
        function NSRect (line 72) | inline NSRect NSView_get_bounds(id self) {
        function NSView_set_frame (line 76) | inline void NSView_set_frame(id self, NSRect frame) {
        function NSView_set_autoresizingMask (line 80) | inline void NSView_set_autoresizingMask(id self,

FILE: core/include/webview/detail/platform/darwin/cocoa/NSWindow.hh
  type webview (line 41) | namespace webview {
    type detail (line 42) | namespace detail {
      type cocoa (line 43) | namespace cocoa {
        type NSBackingStoreType (line 45) | enum NSBackingStoreType : NSUInteger { NSBackingStoreBuffered = 2 }
        type NSWindowStyleMask (line 47) | enum NSWindowStyleMask : NSUInteger {
        function id (line 54) | inline id NSWindow_alloc() {
        function id (line 59) | inline id NSWindow_initWithContentRect(id self, NSRect content_rect,
        function id (line 68) | inline id NSWindow_withContentRect(NSRect content_rect, NSWindowSt...
        function NSWindow_close (line 75) | inline void NSWindow_close(id self) {
        function NSRect (line 79) | inline NSRect NSWindow_get_frame(id self) {
        function NSWindow_setFrame (line 83) | inline void NSWindow_setFrame(id self, NSRect frame_rect, bool dis...
        function NSWindow_set_styleMask (line 90) | inline void NSWindow_set_styleMask(id self, NSWindowStyleMask styl...
        function NSWindow_set_title (line 94) | inline void NSWindow_set_title(id self, const std::string &title) {
        function NSWindow_makeKeyAndOrderFront (line 103) | inline void NSWindow_makeKeyAndOrderFront(id self, id sender = nul...
        function NSWindow_set_contentView (line 107) | inline void NSWindow_set_contentView(id self, id view) {
        function id (line 111) | inline id NSWindow_get_contentView(id self) {
        function NSWindow_set_delegate (line 115) | inline void NSWindow_set_delegate(id self, id delegate) {
        function NSWindow_center (line 119) | inline void NSWindow_center(id self) {
        function NSWindow_set_contentMinSize (line 123) | inline void NSWindow_set_contentMinSize(id self, NSSize size) {
        function NSWindow_set_contentMaxSize (line 127) | inline void NSWindow_set_contentMaxSize(id self, NSSize size) {

FILE: core/include/webview/detail/platform/darwin/cocoa/types.hh
  type webview (line 37) | namespace webview {
    type detail (line 38) | namespace detail {
      type cocoa (line 39) | namespace cocoa {

FILE: core/include/webview/detail/platform/darwin/objc/Class.hh
  type webview (line 39) | namespace webview {
    type detail (line 40) | namespace detail {
      type objc (line 41) | namespace objc {
        function id (line 43) | inline id Class_new(Class class_) {
        function Class (line 47) | inline Class get_class(const char *name) { return objc_getClass(na...

FILE: core/include/webview/detail/platform/darwin/objc/autoreleasepool.hh
  type webview (line 39) | namespace webview {
    type detail (line 40) | namespace detail {
      type objc (line 41) | namespace objc {
        class autoreleasepool (line 44) | class autoreleasepool {
          method autoreleasepool (line 46) | autoreleasepool()
          method autoreleasepool (line 55) | autoreleasepool(const autoreleasepool &) = delete;
          method autoreleasepool (line 56) | autoreleasepool &operator=(const autoreleasepool &) = delete;
          method autoreleasepool (line 57) | autoreleasepool(autoreleasepool &&) = delete;
          method autoreleasepool (line 58) | autoreleasepool &operator=(autoreleasepool &&) = delete;

FILE: core/include/webview/detail/platform/darwin/objc/invoke.hh
  type webview (line 37) | namespace webview {
    type detail (line 38) | namespace detail {
      type objc (line 39) | namespace objc {
        function Result (line 47) | Result invoke(Callable callable, Args... args) noexcept {
        function Result (line 53) | Result msg_send(Args... args) noexcept {
        function Result (line 59) | Result msg_send_stret(Args... args) noexcept {
        function SEL (line 67) | inline SEL selector(const char *name) { return sel_registerName(na...

FILE: core/include/webview/detail/platform/darwin/objc/memory.hh
  type webview (line 39) | namespace webview {
    type detail (line 40) | namespace detail {
      type objc (line 41) | namespace objc {
        function id (line 43) | inline id autorelease(id object) {
        function id (line 47) | inline id retain(id object) { return msg_send<id>(object, selector...
        function release (line 49) | inline void release(id object) { msg_send<void>(object, selector("...

FILE: core/include/webview/detail/platform/darwin/webkit/WKOpenPanelParameters.hh
  type webview (line 37) | namespace webview {
    type detail (line 38) | namespace detail {
      type webkit (line 39) | namespace webkit {
        function WKOpenPanelParameters_get_allowsMultipleSelection (line 41) | inline bool WKOpenPanelParameters_get_allowsMultipleSelection(id s...
        function WKOpenPanelParameters_get_allowsDirectories (line 46) | inline bool WKOpenPanelParameters_get_allowsDirectories(id self) {

FILE: core/include/webview/detail/platform/darwin/webkit/WKScriptMessage.hh
  type webview (line 37) | namespace webview {
    type detail (line 38) | namespace detail {
      type webkit (line 39) | namespace webkit {
        function id (line 41) | inline id WKScriptMessage_get_body(id self) {

FILE: core/include/webview/detail/platform/darwin/webkit/WKUserContentController.hh
  type webview (line 37) | namespace webview {
    type detail (line 38) | namespace detail {
      type webkit (line 39) | namespace webkit {
        function WKUserContentController_addScriptMessageHandler (line 41) | inline void WKUserContentController_addScriptMessageHandler(id sel...
        function WKUserContentController_addUserScript (line 47) | inline void WKUserContentController_addUserScript(id self, id user...
        function WKUserContentController_removeAllUserScripts (line 51) | inline void WKUserContentController_removeAllUserScripts(id self) {

FILE: core/include/webview/detail/platform/darwin/webkit/WKUserScript.hh
  type webview (line 37) | namespace webview {
    type detail (line 38) | namespace detail {
      type webkit (line 39) | namespace webkit {
        type WKUserScriptInjectionTime (line 41) | enum WKUserScriptInjectionTime : NSInteger {
        function id (line 45) | inline id WKUserScript_alloc() {
        function id (line 50) | inline id WKUserScript_initWithSource(id self, id source,
        function id (line 58) | inline id WKUserScript_withSource(id source,

FILE: core/include/webview/detail/platform/darwin/webkit/WKWebView.hh
  type webview (line 39) | namespace webview {
    type detail (line 40) | namespace detail {
      type webkit (line 41) | namespace webkit {
        function id (line 43) | inline id WKWebView_alloc() {
        function id (line 48) | inline id WKWebView_initWithFrame(id self, CGRect frame, id config...
        function id (line 54) | inline id WKWebView_withFrame(CGRect frame, id configuration) {
        function id (line 59) | inline id WKWebView_get_UIDelegate(id self) {
        function WKWebView_set_UIDelegate (line 63) | inline void WKWebView_set_UIDelegate(id self, id ui_delegate) {
        function id (line 67) | inline id WKWebView_loadHTMLString(id self, id string, id base_url) {
        function id (line 72) | inline id WKWebView_get_URL(id self) {
        function id (line 76) | inline id WKWebView_loadRequest(id self, id request) {
        function WKWebView_evaluateJavaScript (line 80) | inline void WKWebView_evaluateJavaScript(id self, id js_string,
        function WKWebView_set_inspectable (line 87) | inline void WKWebView_set_inspectable(id self, bool inspectable) {

FILE: core/include/webview/detail/platform/darwin/webkit/WKWebViewConfiguration.hh
  type webview (line 37) | namespace webview {
    type detail (line 38) | namespace detail {
      type webkit (line 39) | namespace webkit {
        function id (line 41) | inline id WKWebViewConfiguration_new() {
        function id (line 46) | inline id WKWebViewConfiguration_get_userContentController(id self) {
        function id (line 50) | inline id WKWebViewConfiguration_get_preferences(id self) {

FILE: core/include/webview/detail/platform/linux/gtk/compat.hh
  type webview (line 51) | namespace webview {
    type detail (line 52) | namespace detail {
      class gtk_compat (line 57) | class gtk_compat {
        method gboolean (line 59) | static gboolean init_check() {
        method GtkWidget (line 67) | static GtkWidget *window_new() {
        method window_set_child (line 75) | static void window_set_child(GtkWindow *window, GtkWidget *widget) {
        method window_remove_child (line 83) | static void window_remove_child(GtkWindow *window, GtkWidget *widg...
        method widget_set_visible (line 93) | static void widget_set_visible(GtkWidget *widget, bool visible) {
        method window_set_size (line 105) | static void window_set_size(GtkWindow *window, int width, int heig...
        method window_set_max_size (line 115) | static void window_set_max_size(GtkWindow *window, int width, int ...

FILE: core/include/webview/detail/platform/linux/webkitgtk/compat.hh
  type webview (line 60) | namespace webview {
    type detail (line 61) | namespace detail {
      class webkitgtk_compat (line 66) | class webkitgtk_compat {
        method connect_script_message_received (line 76) | static void
        method get_string_from_js_result (line 98) | static std::string get_string_from_js_result(JSCValue *r) {
        method get_string_from_js_result (line 106) | static std::string get_string_from_js_result(WebKitJavascriptResul...
        method user_content_manager_register_script_message_handler (line 126) | static void user_content_manager_register_script_message_handler(

FILE: core/include/webview/detail/platform/linux/webkitgtk/dmabuf.hh
  type webview (line 63) | namespace webview {
    type detail (line 64) | namespace detail {
      type webkit_dmabuf (line 70) | namespace webkit_dmabuf {
        function get_env (line 73) | static inline std::string get_env(const std::string &name) {
        function set_env (line 82) | static inline void set_env(const std::string &name, const std::str...
        function is_using_nvidia_driver (line 88) | static inline bool is_using_nvidia_driver() {
        function is_wayland_display (line 97) | static inline bool is_wayland_display() {
        function is_gdk_x11_backend (line 112) | static inline bool is_gdk_x11_backend() {
        function is_webkit_dmabuf_bugged (line 129) | static inline bool is_webkit_dmabuf_bugged() {
        function apply_webkit_dmabuf_workaround (line 154) | static inline void apply_webkit_dmabuf_workaround() {

FILE: core/include/webview/detail/platform/windows/com_init_wrapper.hh
  type webview (line 60) | namespace webview {
    type detail (line 61) | namespace detail {
      class com_init_wrapper (line 70) | class com_init_wrapper {
        method com_init_wrapper (line 72) | com_init_wrapper() = default;
        method com_init_wrapper (line 74) | com_init_wrapper(DWORD dwCoInit) {
        method com_init_wrapper (line 101) | com_init_wrapper(const com_init_wrapper &other) = delete;
        method com_init_wrapper (line 102) | com_init_wrapper &operator=(const com_init_wrapper &other) = delete;
        method com_init_wrapper (line 104) | com_init_wrapper(com_init_wrapper &&other) noexcept {
        method com_init_wrapper (line 108) | com_init_wrapper &operator=(com_init_wrapper &&other) noexcept {

FILE: core/include/webview/detail/platform/windows/dpi.hh
  type webview (line 59) | namespace webview {
    type detail (line 60) | namespace detail {
      function is_per_monitor_v2_awareness_available (line 62) | inline bool is_per_monitor_v2_awareness_available() {
      function enable_dpi_awareness (line 67) | inline bool enable_dpi_awareness() {
      function enable_non_client_dpi_scaling_if_needed (line 92) | inline bool enable_non_client_dpi_scaling_if_needed(HWND window) {
      function get_default_window_dpi (line 119) | constexpr int get_default_window_dpi() {
      function get_window_dpi (line 123) | inline int get_window_dpi(HWND window) {
      function scale_value_for_dpi (line 132) | constexpr int scale_value_for_dpi(int value, int from_dpi, int to_dp...
      function SIZE (line 136) | constexpr SIZE scale_size(int width, int height, int from_dpi, int t...
      function SIZE (line 141) | inline SIZE make_window_frame_size(HWND window, int width, int height,

FILE: core/include/webview/detail/platform/windows/dwmapi.hh
  type webview (line 43) | namespace webview {
    type detail (line 44) | namespace detail {
      type dwmapi_symbols (line 45) | namespace dwmapi_symbols {

FILE: core/include/webview/detail/platform/windows/iid.hh
  type webview (line 47) | namespace webview {
    type detail (line 48) | namespace detail {
      type cast_info_t (line 50) | struct cast_info_t {
      function To (line 60) | To *cast_if_equal_iid(From *from, REFIID riid, const cast_info_t<To>...

FILE: core/include/webview/detail/platform/windows/ntdll.hh
  type webview (line 43) | namespace webview {
    type detail (line 44) | namespace detail {
      type ntdll_symbols (line 45) | namespace ntdll_symbols {

FILE: core/include/webview/detail/platform/windows/reg_key.hh
  type webview (line 48) | namespace webview {
    type detail (line 49) | namespace detail {
      class reg_key (line 51) | class reg_key {
        method reg_key (line 53) | explicit reg_key(HKEY root_key, const wchar_t *sub_key, DWORD opti...
        method reg_key (line 63) | explicit reg_key(HKEY root_key, const std::wstring &sub_key, DWORD...
        method reg_key (line 74) | reg_key(const reg_key &other) = delete;
        method reg_key (line 75) | reg_key &operator=(const reg_key &other) = delete;
        method reg_key (line 76) | reg_key(reg_key &&other) = delete;
        method reg_key (line 77) | reg_key &operator=(reg_key &&other) = delete;
        method is_open (line 79) | bool is_open() const { return !!m_handle; }
        method get_handle (line 80) | bool get_handle() const { return m_handle; }
        method query_bytes (line 83) | void query_bytes(const wchar_t *name, Container &result) const {
        method query_string (line 103) | std::wstring query_string(const wchar_t *name) const {
        method query_uint (line 116) | unsigned int query_uint(const wchar_t *name,

FILE: core/include/webview/detail/platform/windows/shcore.hh
  type webview (line 43) | namespace webview {
    type detail (line 44) | namespace detail {
      type shcore_symbols (line 45) | namespace shcore_symbols {

FILE: core/include/webview/detail/platform/windows/theme.hh
  type webview (line 39) | namespace webview {
    type detail (line 40) | namespace detail {
      function is_dark_theme_enabled (line 42) | inline bool is_dark_theme_enabled() {
      function apply_window_theme (line 53) | inline void apply_window_theme(HWND window) {

FILE: core/include/webview/detail/platform/windows/user32.hh
  type webview (line 43) | namespace webview {
    type detail (line 44) | namespace detail {
      type user32_symbols (line 45) | namespace user32_symbols {
        type dpi_awareness (line 61) | enum class dpi_awareness : intptr_t {

FILE: core/include/webview/detail/platform/windows/version.hh
  type webview (line 51) | namespace webview {
    type detail (line 52) | namespace detail {
      function parse_version (line 57) | std::array<unsigned int, 4>
      function parse_version (line 88) | std::array<unsigned int, 4> parse_version(const T (&version)[Length]...
      function get_file_version_string (line 92) | inline std::wstring
      function compare_os_version (line 123) | inline int compare_os_version(unsigned int major, unsigned int minor,

FILE: core/include/webview/detail/platform/windows/webview2/loader.hh
  type webview (line 56) | namespace webview {
    type detail (line 57) | namespace detail {
      function get_last_native_path_component (line 82) | std::basic_string<T>
      type mswebview2 (line 92) | namespace mswebview2 {
        type webview2_runtime_type (line 123) | enum class webview2_runtime_type { installed = 0, embedded = 1 }
        type webview2_symbols (line 125) | namespace webview2_symbols {
        type webview2_symbols (line 141) | namespace webview2_symbols {
        class loader (line 157) | class loader {
          method HRESULT (line 159) | HRESULT create_environment_with_options(
          method HRESULT (line 183) | HRESULT
          type client_info_t (line 205) | struct client_info_t {
            method client_info_t (line 211) | client_info_t() = default;
            method client_info_t (line 213) | client_info_t(bool found, std::wstring dll_path, std::wstring ...
          method HRESULT (line 221) | HRESULT create_environment_with_options_impl(
          method HRESULT (line 244) | HRESULT
          method client_info_t (line 265) | client_info_t find_available_client(PCWSTR browser_dir) const {
            method client_info_t (line 211) | client_info_t() = default;
            method client_info_t (line 213) | client_info_t(bool found, std::wstring dll_path, std::wstring ...
          method make_client_dll_path (line 278) | std::wstring make_client_dll_path(const std::wstring &dir) const {
          method client_info_t (line 300) | client_info_t
            method client_info_t (line 211) | client_info_t() = default;
            method client_info_t (line 213) | client_info_t(bool found, std::wstring dll_path, std::wstring ...
          method client_info_t (line 325) | client_info_t find_embedded_client(unsigned int min_api_version,
            method client_info_t (line 211) | client_info_t() = default;
            method client_info_t (line 213) | client_info_t(bool found, std::wstring dll_path, std::wstring ...
        type cast_info (line 362) | namespace cast_info {

FILE: core/include/webview/detail/user_script.hh
  type webview (line 36) | namespace webview {
    type detail (line 37) | namespace detail {
      class user_script (line 39) | class user_script {
        class impl (line 41) | class impl
        method user_script (line 45) | user_script(const std::string &code, impl_ptr &&impl_)
        method user_script (line 48) | user_script(const user_script &other) = delete;
        method user_script (line 49) | user_script &operator=(const user_script &other) = delete;
        method user_script (line 50) | user_script(user_script &&other) noexcept { *this = std::move(othe...
        method user_script (line 52) | user_script &operator=(user_script &&other) noexcept {
        method impl (line 63) | impl &get_impl() { return *m_impl; }
        method impl (line 65) | const impl &get_impl() const { return *m_impl; }

FILE: core/include/webview/detail/utility/string.hh
  type webview (line 40) | namespace webview {
    type detail (line 41) | namespace detail {
      function widen_string (line 45) | inline std::wstring widen_string(const std::string &input) {
      function narrow_string (line 67) | inline std::string narrow_string(const std::wstring &input) {

FILE: core/include/webview/errors.h
  type webview_error_t (line 45) | typedef enum {

FILE: core/include/webview/errors.hh
  type webview (line 36) | namespace webview {
    class error_info (line 38) | class error_info {
      method error_info (line 40) | error_info(webview_error_t code, const std::string &message = {}) no...
      method error_info (line 42) | error_info() = default;
      method webview_error_t (line 44) | webview_error_t code() const { return m_code; }
    class exception (line 52) | class exception : public std::exception {
      method exception (line 54) | exception(webview_error_t code, const std::string &message,
      method exception (line 58) | exception(webview_error_t code, const std::string &message) noexcept
      method exception (line 61) | exception(const error_info &error, std::exception_ptr cause) noexcept
      method exception (line 66) | exception(const error_info &error) noexcept : m_error{error} {}
      method exception (line 68) | exception() = default;
      method error_info (line 70) | const error_info &error() const { return m_error; }
      method cause (line 71) | std::exception_ptr cause() const { return m_cause; }

FILE: core/include/webview/json_deprecated.hh
  type webview (line 34) | namespace webview {
    function WEBVIEW_DEPRECATED_PRIVATE (line 36) | WEBVIEW_DEPRECATED_PRIVATE
    function WEBVIEW_DEPRECATED_PRIVATE (line 42) | WEBVIEW_DEPRECATED_PRIVATE
    function WEBVIEW_DEPRECATED_PRIVATE (line 47) | WEBVIEW_DEPRECATED_PRIVATE
    function WEBVIEW_DEPRECATED_PRIVATE (line 52) | WEBVIEW_DEPRECATED_PRIVATE

FILE: core/include/webview/types.h
  type webview_version_t (line 30) | typedef struct {
  type webview_version_info_t (line 40) | typedef struct {
  type webview_native_handle_kind_t (line 56) | typedef enum {
  type webview_hint_t (line 70) | typedef enum {

FILE: core/include/webview/types.hh
  type webview (line 36) | namespace webview {

FILE: core/tests/src/functional_tests.cc
  function cb_assert_arg (line 35) | void cb_assert_arg(webview_t w, void *arg) {
  function cb_terminate (line 40) | void cb_terminate(webview_t w, void *arg) {
  type context_t (line 59) | struct context_t {
  type test_webview (line 263) | struct test_webview : webview::browser_engine {
    method test_webview (line 265) | test_webview(cb_t cb) : webview::browser_engine(true, nullptr), m_cb(c...
    method on_message (line 266) | void on_message(const std::string &msg) override { m_cb(this, i++, msg...

FILE: examples/basic.c
  function main (line 16) | int main(void) {

FILE: examples/basic.cc
  function main (line 9) | int main() {

FILE: examples/bind.c
  type start_routine_wrapper_arg_t (line 16) | typedef struct {
  function DWORD (line 23) | DWORD __stdcall start_routine_wrapper(void *wrapper_arg) {
  function thread_create (line 40) | int thread_create(void (*start_routine)(void *), void *arg) {
  function thread_sleep (line 68) | void thread_sleep(int seconds) {
  type context_t (line 76) | typedef struct {
  function count (line 113) | void count(const char *id, const char *req, void *arg) {
  type compute_thread_params_t (line 122) | typedef struct {
  function compute_thread_params_t (line 128) | compute_thread_params_t *
  function compute_thread_params_free (line 140) | void compute_thread_params_free(compute_thread_params_t *p) {
  function compute_thread_proc (line 146) | void compute_thread_proc(void *arg) {
  function compute (line 156) | void compute(const char *id, const char *req, void *arg) {
  function main (line 174) | int main(void) {

FILE: examples/bind.cc
  function main (line 45) | int main() {

FILE: scripts/amalgamate/amalgamate.py
  class Include (line 14) | class Include:
    method __eq__ (line 18) | def __eq__(self, other):
    method __lt__ (line 23) | def __lt__(self, other):
  class ProcessorContext (line 30) | class ProcessorContext:
  function process_file (line 42) | def process_file(context: ProcessorContext, input: os.PathLike, search_d...
  function replace_copyright (line 125) | def replace_copyright(context: ProcessorContext, match: re.Match[str]):
  function amalgamate (line 136) | def amalgamate(
  function reformat_file (line 172) | def reformat_file(file: os.PathLike, clang_format_exe: os.PathLike):
  function main (line 181) | def main(options):
  function parse_args (line 199) | def parse_args():

FILE: scripts/amalgamate/test/main.c
  function main (line 4) | int main(void) {

FILE: scripts/amalgamate/test/main.cc
  function main (line 3) | int main() {

FILE: test_driver/include/webview/test_driver.hh
  type webview (line 33) | namespace webview {
    type failure_info (line 35) | struct failure_info {
    type test_failure (line 41) | struct test_failure : public std::exception {
      method test_failure (line 42) | explicit test_failure(const failure_info &info) noexcept : m_info{in...
      method failure_info (line 44) | const failure_info &info() const noexcept { return m_info; }
    class test_reg (line 50) | class test_reg {
      method test_reg (line 52) | test_reg() = default;
      method test_reg (line 54) | test_reg(const char *name, std::function<void()> fn) noexcept
      method invoke (line 58) | void invoke() const { m_fn(); }
    type auto_test_reg (line 65) | struct auto_test_reg {
      method auto_test_reg (line 66) | explicit auto_test_reg(test_reg reg) noexcept {

FILE: test_driver/src/test_driver.cc
  type webview (line 32) | namespace webview {
  type failure_exit_codes (line 41) | struct failure_exit_codes {
    type type (line 42) | enum type {
  function cmd_help (line 51) | int cmd_help() {
  function cmd_list (line 56) | int cmd_list() {
  function cmd_run_test (line 69) | int cmd_run_test(const std::string &test_name) {
  function cmd_run_all_tests (line 95) | int cmd_run_all_tests() {
  function main (line 136) | int main(int argc, const char *argv[]) {
Condensed preview — 144 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (598K chars).
[
  {
    "path": ".clang-format",
    "chars": 3169,
    "preview": "---\nLanguage:        Cpp\n# BasedOnStyle:  LLVM\nAccessModifierOffset: -2\nAlignAfterOpenBracket: Align\nAlignConsecutiveAss"
  },
  {
    "path": ".clang-tidy",
    "chars": 2549,
    "preview": "---\n# We should aim to fix the code and re-enable most of the rules here.\n# The following were disabled due to false pos"
  },
  {
    "path": ".gitattributes",
    "chars": 24,
    "preview": "*.h linguist-language=c\n"
  },
  {
    "path": ".github/actions/cmake/action.yaml",
    "chars": 6689,
    "preview": "name: CMake build\ndescription: Build project using CMake\ninputs:\n  artifacts-name:\n    description: Artifacts name\n    r"
  },
  {
    "path": ".github/actions/setup-env/action.yaml",
    "chars": 1931,
    "preview": "name: Set up environment\ndescription: Sets up the environment by checking out code, installing required packages, etc.\ni"
  },
  {
    "path": ".github/issue_template.md",
    "chars": 810,
    "preview": "<!--\n\nThanks for filing an issue! If this is a question or feature request, just delete\neverything here and write out th"
  },
  {
    "path": ".github/workflows/build.yaml",
    "chars": 5203,
    "preview": "name: Build\non:\n  workflow_call:\n    inputs:\n      coverage:\n        type: boolean\n        description: Enable code cove"
  },
  {
    "path": ".github/workflows/build_matrix.csv",
    "chars": 11006,
    "preview": "job-type,os,image,arch,cxx-std,toolchain,toolchain-executable-suffix,generator,pr-only,checks,strict-clang-tidy,package,"
  },
  {
    "path": ".github/workflows/build_matrix_schema.json",
    "chars": 804,
    "preview": "{\n    \"apt\": \"string\",\n    \"arch\": \"string\",\n    \"checks\": \"boolean\",\n    \"comments\": \"string\",\n    \"cxx-std\": \"number\","
  },
  {
    "path": ".github/workflows/check.yaml",
    "chars": 5628,
    "preview": "name: Check\non:\n  workflow_call:\njobs:\n  format:\n    runs-on: ubuntu-22.04\n    steps:\n      - uses: actions/checkout@v4\n"
  },
  {
    "path": ".github/workflows/ci.yaml",
    "chars": 4866,
    "preview": "name: CI\non: [push, pull_request]\ndefaults:\n  run:\n    shell: bash\njobs:\n  init:\n    runs-on: ubuntu-22.04\n    outputs:\n"
  },
  {
    "path": ".github/workflows/csv.js",
    "chars": 2384,
    "preview": "/**\n * A simple CSV parser that should be \"good enough\" for basic needs.\n */\n\nconst fs = require(\"node:fs\");\n\nfunction p"
  },
  {
    "path": ".github/workflows/draft-release.yaml",
    "chars": 2372,
    "preview": "name: Draft Release\non:\n  workflow_dispatch:\ndefaults:\n  run:\n    shell: bash\nconcurrency:\n  group: ${{ github.ref }}\n  "
  },
  {
    "path": ".gitignore",
    "chars": 25,
    "preview": "# Build artifacts\n/build\n"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 3230,
    "preview": "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Change"
  },
  {
    "path": "CMakeLists.txt",
    "chars": 862,
    "preview": "cmake_minimum_required(VERSION 3.16)\n\ninclude(\"${CMAKE_CURRENT_SOURCE_DIR}/cmake/internal.cmake\")\nwebview_extract_versio"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 640,
    "preview": "# Contributing\n\nContributing to the webview project is always welcome! We are especially in need of MacOs developers. Ac"
  },
  {
    "path": "LICENSE",
    "chars": 1111,
    "preview": "MIT License\n\nCopyright (c) 2017 Serge Zaitsev\nCopyright (c) 2022 Steffen André Langnes\n\nPermission is hereby granted, fr"
  },
  {
    "path": "MIGRATION.md",
    "chars": 3035,
    "preview": "# Migration\n\n## v0.11.0 to v0.12.0\n\nSome CMake targets names have been replaced in order to match the exported/installed"
  },
  {
    "path": "README.md",
    "chars": 20972,
    "preview": "# webview\n\n<a href=\"https://discord.gg/24KMecn\" title=\"Join the chat at Discord\"><img src=\"https://assets-global.website"
  },
  {
    "path": "cmake/clang_format.cmake",
    "chars": 882,
    "preview": "file(TO_CMAKE_PATH \"${BINARY_DIR}\" BINARY_DIR)\nfile(TO_CMAKE_PATH \"${SOURCE_DIR}\" SOURCE_DIR)\n\nfile(GLOB_RECURSE TEMP_FI"
  },
  {
    "path": "cmake/extract_version.cmake",
    "chars": 273,
    "preview": "# Extracts the library's version number and prints it to stdout.\n\ninclude(\"${CMAKE_CURRENT_LIST_DIR}/internal.cmake\")\nwe"
  },
  {
    "path": "cmake/internal.cmake",
    "chars": 15524,
    "preview": "set(WEBVIEW_CURRENT_CMAKE_DIR \"${CMAKE_CURRENT_LIST_DIR}\")\ninclude(\"${WEBVIEW_CURRENT_CMAKE_DIR}/webview.cmake\")\n\n# Need"
  },
  {
    "path": "cmake/modules/FindMSWebView2.cmake",
    "chars": 710,
    "preview": "if(DEFINED MSWebView2_ROOT)\n    find_path(MSWebView2_INCLUDE_DIR WebView2.h\n        PATHS\n            \"${MSWebView2_ROOT"
  },
  {
    "path": "cmake/toolchains/arm64-windows-msvc.cmake",
    "chars": 173,
    "preview": "set(CMAKE_SYSTEM_NAME Windows)\nset(CMAKE_SYSTEM_PROCESSOR ARM64)\n\nset(CMAKE_C_COMPILER cl)\nset(CMAKE_CXX_COMPILER cl)\n\ns"
  },
  {
    "path": "cmake/toolchains/host-gnu.cmake",
    "chars": 134,
    "preview": "set(CMAKE_C_COMPILER \"gcc${WEBVIEW_TOOLCHAIN_EXECUTABLE_SUFFIX}\")\nset(CMAKE_CXX_COMPILER \"g++${WEBVIEW_TOOLCHAIN_EXECUTA"
  },
  {
    "path": "cmake/toolchains/host-llvm.cmake",
    "chars": 140,
    "preview": "set(CMAKE_C_COMPILER \"clang${WEBVIEW_TOOLCHAIN_EXECUTABLE_SUFFIX}\")\nset(CMAKE_CXX_COMPILER \"clang++${WEBVIEW_TOOLCHAIN_E"
  },
  {
    "path": "cmake/toolchains/i686-w64-mingw32.cmake",
    "chars": 498,
    "preview": "set(CMAKE_SYSTEM_NAME Windows)\nset(CMAKE_SYSTEM_PROCESSOR i686)\n\nset(CMAKE_SYSROOT /usr/i686-w64-mingw32)\nset(CMAKE_C_CO"
  },
  {
    "path": "cmake/toolchains/i686-windows-msvc.cmake",
    "chars": 171,
    "preview": "set(CMAKE_SYSTEM_NAME Windows)\nset(CMAKE_SYSTEM_PROCESSOR x86)\n\nset(CMAKE_C_COMPILER cl)\nset(CMAKE_CXX_COMPILER cl)\n\nset"
  },
  {
    "path": "cmake/toolchains/universal-macos-llvm.cmake",
    "chars": 234,
    "preview": "set(CMAKE_SYSTEM_NAME Darwin)\n\nset(CMAKE_C_COMPILER \"clang${WEBVIEW_TOOLCHAIN_EXECUTABLE_SUFFIX}\")\nset(CMAKE_CXX_COMPILE"
  },
  {
    "path": "cmake/toolchains/x86_64-msys2-gnu-ucrt64.cmake",
    "chars": 240,
    "preview": "set(CMAKE_SYSTEM_NAME Windows)\nset(CMAKE_SYSTEM_PROCESSOR x86_64)\n\nset(CMAKE_C_COMPILER \"gcc${WEBVIEW_TOOLCHAIN_EXECUTAB"
  },
  {
    "path": "cmake/toolchains/x86_64-msys2-llvm-clang64.cmake",
    "chars": 247,
    "preview": "set(CMAKE_SYSTEM_NAME Windows)\nset(CMAKE_SYSTEM_PROCESSOR x86_64)\n\nset(CMAKE_C_COMPILER \"clang${WEBVIEW_TOOLCHAIN_EXECUT"
  },
  {
    "path": "cmake/toolchains/x86_64-w64-mingw32.cmake",
    "chars": 510,
    "preview": "set(CMAKE_SYSTEM_NAME Windows)\nset(CMAKE_SYSTEM_PROCESSOR x86_64)\n\nset(CMAKE_SYSROOT /usr/x86_64-w64-mingw32)\nset(CMAKE_"
  },
  {
    "path": "cmake/toolchains/x86_64-windows-msvc.cmake",
    "chars": 171,
    "preview": "set(CMAKE_SYSTEM_NAME Windows)\nset(CMAKE_SYSTEM_PROCESSOR AMD64)\n\nset(CMAKE_C_COMPILER cl)\nset(CMAKE_CXX_COMPILER cl)\n\ns"
  },
  {
    "path": "cmake/webview-config.cmake.in",
    "chars": 275,
    "preview": "@PACKAGE_INIT@\n\ninclude(CMakeFindDependencyMacro)\ninclude(\"${CMAKE_CURRENT_LIST_DIR}/webview.cmake\")\nlist(APPEND CMAKE_M"
  },
  {
    "path": "cmake/webview.cmake",
    "chars": 4157,
    "preview": "macro(webview_options)\n    if(CMAKE_SYSTEM_NAME STREQUAL \"Windows\")\n        set(WEBVIEW_MSWEBVIEW2_VERSION \"1.0.1150.38\""
  },
  {
    "path": "compatibility/CMakeLists.txt",
    "chars": 65,
    "preview": "if(WEBVIEW_USE_COMPAT_MINGW)\n    add_subdirectory(mingw)\nendif()\n"
  },
  {
    "path": "compatibility/mingw/CMakeLists.txt",
    "chars": 612,
    "preview": "# Compatibility target for MinGW that can be used to work around missing\n# \"EventToken.h\" header (used by MS WebView2) w"
  },
  {
    "path": "compatibility/mingw/include/EventToken.h",
    "chars": 749,
    "preview": "#ifndef WEBVIEW_COMPAT_EVENTTOKEN_H\n#define WEBVIEW_COMPAT_EVENTTOKEN_H\n#ifdef _WIN32\n\n// This compatibility header prov"
  },
  {
    "path": "core/CMakeLists.txt",
    "chars": 3885,
    "preview": "# Core header library\nadd_library(webview_core_headers INTERFACE)\nadd_library(webview::core ALIAS webview_core_headers)\n"
  },
  {
    "path": "core/include/webview/api.h",
    "chars": 8777,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/backends.hh",
    "chars": 1565,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/c_api_impl.hh",
    "chars": 8160,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/backends/cocoa_webkit.hh",
    "chars": 22477,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/backends/gtk_webkitgtk.hh",
    "chars": 11649,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/backends/win32_edge.hh",
    "chars": 29456,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/basic_result.hh",
    "chars": 3327,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/engine_base.hh",
    "chars": 12281,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/exceptions.hh",
    "chars": 1562,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/json.hh",
    "chars": 9190,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/native_library.hh",
    "chars": 4757,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/optional.hh",
    "chars": 3531,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/darwin/cocoa/NSApplication.hh",
    "chars": 3831,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/darwin/cocoa/NSBundle.hh",
    "chars": 2036,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/darwin/cocoa/NSEvent.hh",
    "chars": 2740,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/darwin/cocoa/NSInvocation.hh",
    "chars": 2442,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/darwin/cocoa/NSMethodSignature.hh",
    "chars": 2013,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/darwin/cocoa/NSNotification.hh",
    "chars": 1895,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/darwin/cocoa/NSNumber.hh",
    "chars": 1992,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/darwin/cocoa/NSObject.hh",
    "chars": 1913,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/darwin/cocoa/NSOpenPanel.hh",
    "chars": 2624,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/darwin/cocoa/NSPoint.hh",
    "chars": 1893,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/darwin/cocoa/NSRect.hh",
    "chars": 1913,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/darwin/cocoa/NSSavePanel.hh",
    "chars": 1937,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/darwin/cocoa/NSSize.hh",
    "chars": 1885,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/darwin/cocoa/NSString.hh",
    "chars": 3110,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/darwin/cocoa/NSURL.hh",
    "chars": 2225,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/darwin/cocoa/NSURLRequest.hh",
    "chars": 1959,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/darwin/cocoa/NSValue.hh",
    "chars": 2105,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/darwin/cocoa/NSView.hh",
    "chars": 3129,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/darwin/cocoa/NSWindow.hh",
    "chars": 4911,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/darwin/cocoa/cocoa.hh",
    "chars": 2122,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/darwin/cocoa/types.hh",
    "chars": 1794,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/darwin/objc/Class.hh",
    "chars": 1913,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/darwin/objc/autoreleasepool.hh",
    "chars": 2317,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/darwin/objc/invoke.hh",
    "chars": 2756,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/darwin/objc/memory.hh",
    "chars": 1986,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/darwin/objc/objc.hh",
    "chars": 1761,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/darwin/webkit/WKOpenPanelParameters.hh",
    "chars": 2162,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/darwin/webkit/WKScriptMessage.hh",
    "chars": 1900,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/darwin/webkit/WKUserContentController.hh",
    "chars": 2384,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/darwin/webkit/WKUserScript.hh",
    "chars": 2732,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/darwin/webkit/WKWebView.hh",
    "chars": 3792,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/darwin/webkit/WKWebViewConfiguration.hh",
    "chars": 2258,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/darwin/webkit/webkit.hh",
    "chars": 1840,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/linux/gtk/compat.hh",
    "chars": 3830,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/linux/webkitgtk/compat.hh",
    "chars": 4657,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/linux/webkitgtk/dmabuf.hh",
    "chars": 4984,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/windows/com_init_wrapper.hh",
    "chars": 3763,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/windows/dpi.hh",
    "chars": 5254,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/windows/dwmapi.hh",
    "chars": 2391,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/windows/iid.hh",
    "chars": 2436,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/windows/ntdll.hh",
    "chars": 1970,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/windows/reg_key.hh",
    "chars": 4130,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/windows/shcore.hh",
    "chars": 2067,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/windows/theme.hh",
    "chars": 2792,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/windows/user32.hh",
    "chars": 3599,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/windows/version.hh",
    "chars": 5114,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/platform/windows/webview2/loader.hh",
    "chars": 13914,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/user_script.hh",
    "chars": 2432,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/detail/utility/string.hh",
    "chars": 3432,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/errors.h",
    "chars": 2521,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/errors.hh",
    "chars": 2758,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/json_deprecated.hh",
    "chars": 2154,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/macros.h",
    "chars": 3903,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/types.h",
    "chars": 2960,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/types.hh",
    "chars": 1697,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/version.h",
    "chars": 2313,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview/webview.h",
    "chars": 1281,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2017 Serge Zaitsev\n * Copyright (c) 2022 Steffen André Langnes\n *\n * Permission is"
  },
  {
    "path": "core/include/webview.h",
    "chars": 322,
    "preview": "/**\n * @file webview.h\n *\n * @deprecated This header file is deprecated. Use `webview/webview.h` instead.\n *\n * This fil"
  },
  {
    "path": "core/src/webview.cc",
    "chars": 29,
    "preview": "#include \"webview/webview.h\"\n"
  },
  {
    "path": "core/tests/CMakeLists.txt",
    "chars": 702,
    "preview": "include(${PROJECT_SOURCE_DIR}/test_driver/cmake/discovery.cmake)\n\nif(MSVC)\n    add_compile_options(/utf-8)\nendif()\n\nadd_"
  },
  {
    "path": "core/tests/src/functional_tests.cc",
    "chars": 9557,
    "preview": "#include \"webview/test_driver.hh\"\n\n#define WEBVIEW_VERSION_MAJOR 1\n#define WEBVIEW_VERSION_MINOR 2\n#define WEBVIEW_VERSI"
  },
  {
    "path": "core/tests/src/unit_tests.cc",
    "chars": 7561,
    "preview": "#include \"webview/test_driver.hh\"\n#include \"webview/webview.h\"\n\nTEST_CASE(\"Ensure that JSON parsing works\") {\n  auto J ="
  },
  {
    "path": "docs/CMakeLists.txt",
    "chars": 80,
    "preview": "add_subdirectory(api)\n\nadd_custom_target(webview_docs DEPENDS webview_api_docs)\n"
  },
  {
    "path": "docs/api/CMakeLists.txt",
    "chars": 2224,
    "preview": "webview_find_doxygen(${WEBVIEW_IS_CI})\n\nif(NOT Doxygen_FOUND)\n    message(WARNING \"Skipping docs as Doxygen was not foun"
  },
  {
    "path": "docs/api/Doxyfile.in",
    "chars": 115417,
    "preview": "# Doxyfile 1.9.1\n\n# This file describes the settings to be used by the documentation system\n# doxygen (www.doxygen.org) "
  },
  {
    "path": "examples/CMakeLists.txt",
    "chars": 1369,
    "preview": "find_package(Threads REQUIRED)\n\nset(COPYRIGHT \"Copyright [year], Your Name\")\nset(VENDOR \"Your Name\")\nset(DESCRIPTION \"Ex"
  },
  {
    "path": "examples/basic.c",
    "chars": 557,
    "preview": "#include \"webview/webview.h\"\n#include <stddef.h>\n\n#ifdef _WIN32\n#include <windows.h>\n#endif\n\n#ifdef _WIN32\nint WINAPI Wi"
  },
  {
    "path": "examples/basic.cc",
    "chars": 511,
    "preview": "#include \"webview/webview.h\"\n\n#include <iostream>\n\n#ifdef _WIN32\nint WINAPI WinMain(HINSTANCE /*hInst*/, HINSTANCE /*hPr"
  },
  {
    "path": "examples/bind.c",
    "chars": 5412,
    "preview": "#include \"webview/webview.h\"\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#ifdef _WIN32\n#include <windows"
  },
  {
    "path": "examples/bind.cc",
    "chars": 2564,
    "preview": "#include \"webview/webview.h\"\n\n#include <chrono>\n#include <iostream>\n#include <string>\n#include <thread>\n\nconstexpr const"
  },
  {
    "path": "examples/resources/macos/resources.cmake",
    "chars": 564,
    "preview": "set(MACOSX_BUNDLE_BUNDLE_NAME \"${PROJECT_NAME}\")\nset(MACOSX_BUNDLE_BUNDLE_VERSION \"${PROJECT_VERSION}\")\nset(MACOSX_BUNDL"
  },
  {
    "path": "examples/resources/windows/resources.cmake",
    "chars": 223,
    "preview": "configure_file(\"${CMAKE_CURRENT_LIST_DIR}/version.rc.in\" \"resources/windows/version.rc\" @ONLY)\nlist(APPEND SHARED_SOURCE"
  },
  {
    "path": "examples/resources/windows/resources.rc",
    "chars": 204,
    "preview": "#define IDI_APPLICATION 32512\n\n// An application icon can be specified with a low ID\n//100 ICON \"webview.ico\"\n\n// Window"
  },
  {
    "path": "examples/resources/windows/version.rc.in",
    "chars": 979,
    "preview": "#include <winver.h>\n#pragma code_page(65001)\nVS_VERSION_INFO VERSIONINFO\nFILEVERSION @PROJECT_VERSION_MAJOR@,@PROJECT_VE"
  },
  {
    "path": "gcovr.cfg",
    "chars": 187,
    "preview": "html-details = yes\noutput = build/coverage/\nfilter = ^core/include/\ngcov-exclude-directories = build/_deps/\ndelete-gcov-"
  },
  {
    "path": "gcovr.ci.cfg",
    "chars": 119,
    "preview": "filter = ^core/include/\ngcov-exclude-directories = build/_deps/\nexclude = build/_deps/\nmerge-mode-functions = separate\n"
  },
  {
    "path": "packaging/CMakeLists.txt",
    "chars": 2876,
    "preview": "set(CPACK_PACKAGE_NAME webview)\nset(CPACK_PACKAGE_VENDOR webview organization)\nset(CPACK_PACKAGE_VERSION ${WEBVIEW_VERSI"
  },
  {
    "path": "packaging/external_package.cmake.in",
    "chars": 4646,
    "preview": "set(WEBVIEW_ARCHIVE_SYSTEM_ARCH_FILE_NAME \"@WEBVIEW_ARCHIVE_SYSTEM_ARCH_FILE_NAME@\")\nset(WEBVIEW_ARCHIVE_UNIVERSAL_FILE_"
  },
  {
    "path": "packaging/test/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "packaging/test/CMakeLists.txt",
    "chars": 581,
    "preview": "cmake_minimum_required(VERSION 3.16)\nproject(example LANGUAGES C CXX)\n\n# Workaround for missing \"EventToken.h\" (used by "
  },
  {
    "path": "scripts/amalgamate/amalgamate.py",
    "chars": 8241,
    "preview": "from argparse import ArgumentParser\nfrom dataclasses import dataclass, field\nimport graphlib\nimport os\nimport pathlib\nim"
  },
  {
    "path": "scripts/amalgamate/test/.gitignore",
    "chars": 7,
    "preview": "build/\n"
  },
  {
    "path": "scripts/amalgamate/test/main.c",
    "chars": 149,
    "preview": "#include \"webview_amalgamation.h\"\n#include <stddef.h>\n\nint main(void) {\n  webview_t w = webview_create(0, NULL);\n  webvi"
  },
  {
    "path": "scripts/amalgamate/test/main.cc",
    "chars": 100,
    "preview": "#include \"webview_amalgamation.h\"\n\nint main() {\n  webview::webview w(false, nullptr);\n  return 0;\n}\n"
  },
  {
    "path": "scripts/amalgamate/test/webview.cc",
    "chars": 34,
    "preview": "#include \"webview_amalgamation.h\"\n"
  },
  {
    "path": "test_driver/CMakeLists.txt",
    "chars": 166,
    "preview": "add_library(webview_test_driver STATIC)\ntarget_sources(webview_test_driver PRIVATE src/test_driver.cc)\ntarget_include_di"
  },
  {
    "path": "test_driver/cmake/discovery.cmake",
    "chars": 2998,
    "preview": "set(WEBVIEW_TEST_DISCOVERY_DIR ${CMAKE_CURRENT_LIST_DIR})\n\nfunction(webview_discover_tests TARGET)\n    cmake_parse_argum"
  },
  {
    "path": "test_driver/cmake/generate_includes.cmake",
    "chars": 901,
    "preview": "file(WRITE \"${TEST_DRIVER_CONFIG_FILE}\"\n    \"set(TEST_DRIVER \\\"${TEST_DRIVER}\\\")\\n\"\n)\n\nfile(WRITE \"${TEST_INCLUDE_FILE}\""
  },
  {
    "path": "test_driver/include/webview/test_driver.hh",
    "chars": 4643,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2024 Steffen André Langnes\n *\n * Permission is hereby granted, free of charge, to "
  },
  {
    "path": "test_driver/src/test_driver.cc",
    "chars": 4863,
    "preview": "/*\n * MIT License\n *\n * Copyright (c) 2024 Steffen André Langnes\n *\n * Permission is hereby granted, free of charge, to "
  },
  {
    "path": "webview.i",
    "chars": 1241,
    "preview": "%module webview \n%{\n#include \"webview.h\"\n%}\n#define WEBVIEW_HINT_NONE 0\n#define WEBVIEW_HINT_MIN 1\n#define WEBVIEW_HINT_"
  }
]

// ... and 1 more files (download for full content)

About this extraction

This page contains the full source code of the webview/webview GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 144 files (555.0 KB), approximately 143.9k tokens, and a symbol index with 679 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!