Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,29 @@ jobs:
WEBKIT_DISABLE_DMABUF_RENDERER: "1"
WEBKIT_DISABLE_SANDBOX_THIS_IS_DANGEROUS: "1"
LIBGL_ALWAYS_SOFTWARE: "1"

windows-e2e:
name: Windows host + E2E
runs-on: windows-latest
env:
NO_WX: "1"
steps:
- uses: actions/checkout@v4
- uses: erlef/setup-beam@v1
with:
otp-version: "26"
elixir-version: "1.18"
- name: Checkout desktop (path dep)
uses: actions/checkout@v4
with:
repository: elixir-desktop/desktop
path: desktop
- name: Build host
shell: pwsh
run: .\scripts\build_windows.ps1
- run: mix deps.get
- name: E2E
shell: pwsh
run: mix test
env:
DESKTOP_WEBVIEW_BINARY: ${{ github.workspace }}\priv\native\windows\DesktopWebView.exe
24 changes: 23 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,26 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

# windows: add when native/windows host exists — attach DesktopWebView-windows-* to the same draft release
windows:
name: Windows x64 artifact
runs-on: windows-latest
steps:
- uses: actions/checkout@v4
- name: Build host
shell: pwsh
run: .\scripts\build_windows.ps1
- name: Pack
shell: pwsh
run: |
New-Item -ItemType Directory -Force -Path dist | Out-Null
Copy-Item priv\native\windows\DesktopWebView.exe dist\DesktopWebView-windows-x64.exe
$hash = (Get-FileHash -Algorithm SHA256 dist\DesktopWebView-windows-x64.exe).Hash.ToLower()
Set-Content -NoNewline -Path dist\DesktopWebView-windows-x64.exe.sha256 -Value "$hash DesktopWebView-windows-x64.exe"
- uses: softprops/action-gh-release@v2
with:
draft: true
files: |
dist/DesktopWebView-windows-x64.exe
dist/DesktopWebView-windows-x64.exe.sha256
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ desktop_webview-*.tar
native/macos/.build/
native/macos/Package.resolved
native/linux/build/
native/windows/build/
priv/native/macos/DesktopWebView
priv/native/linux/DesktopWebView
priv/native/windows/DesktopWebView.exe
.DS_Store
*.swp
59 changes: 30 additions & 29 deletions docs/status/windows.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,36 @@

States: `done` | `partial` | `todo` | `n/a`

Host not implemented yet. Follow [docs/porting.md](../porting.md).
Binary delivery via GitHub Releases (not Hex `priv/`).
C++ / Win32 / WebView2 host under [`native/windows/`](../../native/windows/).
Local/CI binary: `priv/native/windows/DesktopWebView.exe`.
Release asset: `DesktopWebView-windows-x64.exe` (GitHub Releases; not Hex `priv/`).

| Feature | Status | Notes |
|---------|--------|-------|
| TCP listen + `listening <port>` | todo | |
| `initialize` + capabilities | todo | |
| `--edw-no-beam` / argv strip | todo | |
| Ini + defaults | todo | |
| Lifetime reconnect | todo | |
| Lifetime coupled | todo | |
| Window open/show/hide/title/min size | todo | |
| Multi-window (ids) | todo | |
| Close veto → Elixir | todo | |
| Raise / iconize / shown / active | todo | |
| Webview loadURL / reload / current URL | todo | |
| Webview rebuild | todo | |
| New window → external open | todo | |
| Context menu disable | todo | |
| Menubar from DOM | todo | |
| Tray / status item | todo | |
| Apple menu | n/a | |
| Notifications | todo | |
| Icons from path / PNG | todo | |
| OS events (reopen, open url/file) | todo | |
| Locale / os_description | todo | |
| Permission policy hybrid | todo | |
| Microphone in webview | todo | |
| Camera in webview | todo | |
| Test RPC channel | todo | |
| Release artifact download | todo | |
| Ad-hoc / CI signing | todo | |
| TCP listen + `listening <port>` | done | E2E launcher discovery |
| `initialize` + capabilities | done | E2E setup |
| `--edw-no-beam` / argv strip | done | E2E |
| Ini + defaults | done | Same semantics as Linux/macOS |
| Lifetime reconnect | done | Packaged mode (keep listening) |
| Lifetime coupled | done | Exit on disconnect; `--edw-no-beam` exits |
| Window open/show/hide/title/min size | done | E2E window test |
| Multi-window (ids) | done | E2E |
| Close veto → Elixir | done | `WM_CLOSE` → `event.window.close_requested` |
| Raise / iconize / shown / active | done | Raise covered by E2E |
| Webview loadURL / reload / current URL | done | E2E |
| Webview rebuild | done | E2E |
| New window → external open | done | `ShellExecute` + event |
| Context menu disable | done | WebView2 settings |
| Menubar from DOM | done | E2E menu create |
| Tray / status item | done | `Shell_NotifyIcon`; E2E tray create |
| Apple menu | n/a | Successful no-op |
| Notifications | done | Balloon via tray when present; E2E |
| Icons from path / PNG | partial | Path/ICO via `LoadImage`; PNG→HICON deferred |
| OS events (reopen, open url/file) | partial | `system.open_url` done; OS reopen/file events not wired |
| Locale / os_description | done | E2E |
| Permission policy hybrid | done | E2E simulate + policy |
| Microphone in webview | done | Permission RPC + WebView2 kinds |
| Camera in webview | done | Permission RPC + WebView2 kinds |
| Test RPC channel | done | E2E |
| Release artifact download | todo | Elixir fetch/cache still pending |
| Ad-hoc / CI signing | todo | Authenticode via desktop_deployment later |
69 changes: 69 additions & 0 deletions native/windows/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
cmake_minimum_required(VERSION 3.16)
project(DesktopWebView LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

include(FetchContent)

FetchContent_Declare(
nlohmann_json
URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
)
FetchContent_MakeAvailable(nlohmann_json)

set(WEBVIEW2_VERSION "1.0.2903.40")
FetchContent_Declare(
microsoft_webview2
URL "https://www.nuget.org/api/v2/package/Microsoft.Web.WebView2/${WEBVIEW2_VERSION}"
DOWNLOAD_EXTRACT_TIMESTAMP TRUE
)
FetchContent_MakeAvailable(microsoft_webview2)

set(WEBVIEW2_ROOT "${microsoft_webview2_SOURCE_DIR}")
set(WEBVIEW2_INCLUDE "${WEBVIEW2_ROOT}/build/native/include")
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(WEBVIEW2_LIB_DIR "${WEBVIEW2_ROOT}/build/native/x64")
else()
set(WEBVIEW2_LIB_DIR "${WEBVIEW2_ROOT}/build/native/x86")
endif()

add_executable(DesktopWebView
src/main.cpp
src/config.cpp
src/json_util.cpp
src/rpc_server.cpp
src/web_window.cpp
src/host_controller.cpp
)

target_include_directories(DesktopWebView PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src
${WEBVIEW2_INCLUDE}
)

target_compile_definitions(DesktopWebView PRIVATE
UNICODE
_UNICODE
NOMINMAX
)

target_link_libraries(DesktopWebView PRIVATE
nlohmann_json::nlohmann_json
"${WEBVIEW2_LIB_DIR}/WebView2LoaderStatic.lib"
ws2_32
ole32
oleaut32
uuid
shell32
user32
gdi32
comctl32
advapi32
shlwapi
version
)

install(TARGETS DesktopWebView RUNTIME DESTINATION bin)
61 changes: 49 additions & 12 deletions native/windows/README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,55 @@
# Windows host (WebView2)

Not implemented yet. This directory will hold the Microsoft Edge WebView2 host.
C++17 + **Win32** + **WebView2** executable `DesktopWebView.exe`.

## Specs
## Prerequisites

- Visual Studio 2022 with MSVC x64 toolchain (`vcvars64.bat`)
- CMake 3.16+
- [Microsoft Edge WebView2 Evergreen Runtime](https://developer.microsoft.com/microsoft-edge/webview2/)
(the host prints a clear stderr error if the runtime is missing)

CMake fetches `Microsoft.Web.WebView2` and `nlohmann/json` during configure.

## Build

```powershell
# from repo root (x64 Developer PowerShell, or let the script call vcvars64)
.\scripts\build_windows.ps1
```

Output is copied to `priv\native\windows\DesktopWebView.exe` for local/CI use.
Release artifact name: `DesktopWebView-windows-x64.exe` (see [packaging.md](../../docs/packaging.md)).

## Run (dev / E2E)

- [Porting guide](../../docs/porting.md) — checklist, toolchain, E2E gate
- [Protocol](../../docs/protocol.md) — JSON-RPC + behavioral semantics
- [Packaging](../../docs/packaging.md) — Windows layout and release artifact names
- [Status](../../docs/status/windows.md) — feature matrix
```powershell
.\priv\native\windows\DesktopWebView.exe --edw-no-beam --edw-test-rpc --edw-port=0
# prints: listening <port>
```

## Contract (summary)
```powershell
$env:DESKTOP_WEBVIEW_BINARY = "$PWD\priv\native\windows\DesktopWebView.exe"
mix test.e2e
```

## Structure

| Path | Role |
|------|------|
| `CMakeLists.txt` | CMake project + WebView2 / JSON deps |
| `src/` | Host sources (config, RPC, windows, dispatch) |

Do not add a native unit-test suite; exercise the binary from Elixir E2E (`mix test.e2e`).

`menu.set_apple` is a successful no-op on Windows.

Microphone / camera: hybrid permission RPC applies; packaged apps may also need
Windows privacy capability declarations (see [packaging.md](../../docs/packaging.md)).

## Specs

- Native process listens on TCP; Elixir connects
- JSON-RPC 2.0 over 4-byte length-prefixed frames
- `--edw-*` host flags; remaining argv forwarded to BEAM
- Binary: `DesktopWebView-windows-x64.exe` via GitHub Releases (not Hex `priv/`)
- `menu.set_apple` → successful no-op
- [Porting guide](../../docs/porting.md)
- [Protocol](../../docs/protocol.md)
- [Packaging](../../docs/packaging.md)
- [Status](../../docs/status/windows.md)
Loading
Loading