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
5 changes: 5 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.git
**/bin
**/node_modules
**/obj
publish
7 changes: 4 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -226,8 +226,9 @@ _pkginfo.txt
# but keep track of directories ending in .cache
!?*.[Cc]ache/

# Others
ClientBin/
# Others
/publish/
ClientBin/
~$*
*~
*.dbmdl
Expand Down Expand Up @@ -357,4 +358,4 @@ MigrationBackup/
.store/

# mac-created file to track user view preferences for a directory
.DS_Store
.DS_Store
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,39 @@ pnpm run build

## Usage

### Run MTGO with Docker

On a Wayland desktop, start MTGO with:

```sh
docker compose up mtgo-wayland
```

The `mtgo-wayland` service uses the [`videreproject/mtgo:wayland`](https://hub.docker.com/r/videreproject/mtgo) image. On its first run, it downloads and installs MTGO, then stores the Wine prefix and bootstrapper in the `mtgo-wine-data` volume for later runs.

To follow the service logs or stop the container, use:

```sh
docker compose logs -f mtgo-wayland
docker compose down
```

The service mounts the Wayland socket from the current desktop session. Docker reads its directory from `XDG_RUNTIME_DIR` and uses `wayland-0` when `WAYLAND_DISPLAY` is unset, so start it from a session where `XDG_RUNTIME_DIR` is set. It also mounts the host X11 socket for XWayland fallback and disables WPF hardware acceleration to avoid rendering MTGO windows black under Wine.

### Run Tracker with MTGO under Wine

The `tracker-wayland` service builds on `videreproject/mtgosdk:wayland`. Its image installs both the Visual C++ 2015–2022 runtime and Microsoft's x64 Evergreen WebView2 Runtime for the Tracker's embedded web UI.

To run the Tracker through wine, first build the Windows executable on the host, then build and start the service:

```sh
pnpm run publish
docker compose build tracker-wayland
docker compose up tracker-wayland
```

The service starts both MTGO and the Tracker in the same container and Wine prefix so MTGOSDK can discover the MTGO process. It dalso isables Tracker's installer and starts WebView2 with GPU acceleration disabled, and generates a loopback certificate for Tracker's HTTPS server for local development. Data for the Tracker is persisted in the `tracker-wine-data` volume and is shared in the Wine environment.

### Development mode

To run the Tracker in development mode (with hot reload for the client and debug configuration):
Expand Down
50 changes: 50 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
services:
mtgo-wayland:
image: videreproject/mtgo:wayland
init: true
stdin_open: true
tty: true
devices:
- /dev/dri:/dev/dri
environment:
DISPLAY: ${DISPLAY:-}
WAYLAND_DISPLAY: ${WAYLAND_DISPLAY:-wayland-0}
XDG_RUNTIME_DIR: /tmp/runtime-dir
WINEDEBUG: -all
command:
- /bin/bash
- /workspace/docker/run-mtgo-wayland.sh
volumes:
- .:/workspace
- mtgo-wine-data:/home/wine/.wine
- ${XDG_RUNTIME_DIR:?XDG_RUNTIME_DIR must be set}/${WAYLAND_DISPLAY:-wayland-0}:/tmp/runtime-dir/${WAYLAND_DISPLAY:-wayland-0}
- /tmp/.X11-unix:/tmp/.X11-unix

tracker-wayland:
build:
context: .
dockerfile: docker/tracker-wine.Dockerfile
image: videreproject/tracker:wayland-dev
init: true
stdin_open: true
tty: true
devices:
- /dev/dri:/dev/dri
environment:
DISPLAY: ${DISPLAY:-}
WAYLAND_DISPLAY: ${WAYLAND_DISPLAY:-wayland-0}
XDG_RUNTIME_DIR: /tmp/runtime-dir
WINEDEBUG: -all
TRACKER_DISABLE_INSTALLER: "1"
TRACKER_WINE_COMPAT: "1"
APP_THEME: Dark
WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS: --disable-gpu
volumes:
- .:/workspace
- tracker-wine-data:/home/wine/.wine
- ${XDG_RUNTIME_DIR:?XDG_RUNTIME_DIR must be set}/${WAYLAND_DISPLAY:-wayland-0}:/tmp/runtime-dir/${WAYLAND_DISPLAY:-wayland-0}
- /tmp/.X11-unix:/tmp/.X11-unix

volumes:
mtgo-wine-data:
tracker-wine-data:
22 changes: 22 additions & 0 deletions docker/run-mtgo-wayland.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/bin/bash
set -euo pipefail

bootstrap=/home/wine/mtgo_setup.exe
persisted_bootstrap=/home/wine/.wine/mtgo_setup.exe

if [[ ! -f "$bootstrap" && -f "$persisted_bootstrap" ]]; then
cp "$persisted_bootstrap" "$bootstrap"
fi

if [[ ! -f "$bootstrap" ]]; then
install-mtgo.sh
cp "$bootstrap" "$persisted_bootstrap"
fi

# MTGO's WPF surface can render black through Wine's accelerated composition.
# Force WPF software rendering in this Wine prefix.
wine reg add 'HKCU\Software\Microsoft\Avalon.Graphics' \
/v DisableHWAcceleration /t REG_DWORD /d 1 /f >/dev/null

mtgo
exec wineserver -w
69 changes: 69 additions & 0 deletions docker/run-tracker-wine.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#!/bin/bash
set -euo pipefail

tracker_exe='/workspace/publish/Videre Tracker.exe'
tracker_certificate=/opt/tracker/localhost.pfx
skip_mtgo=false
if [[ "${TRACKER_SKIP_MTGO:-0}" =~ ^(1|true|yes|on)$ ]]; then
skip_mtgo=true
fi

if [[ "$skip_mtgo" == false ]]; then
bootstrap=/home/wine/mtgo_setup.exe
persisted_bootstrap=/home/wine/.wine/mtgo_setup.exe

if [[ ! -f "$bootstrap" && -f "$persisted_bootstrap" ]]; then
cp "$persisted_bootstrap" "$bootstrap"
fi

if [[ ! -f "$bootstrap" ]]; then
install-mtgo.sh
cp "$bootstrap" "$persisted_bootstrap"
fi
fi

if [[ ! -f "$tracker_exe" ]]; then
echo "Tracker executable not found at: $tracker_exe" >&2
echo "Run 'pnpm run publish' on the host before starting tracker-wayland." >&2
exit 1
fi

# The published app explicitly enables HTTPS.
# Point Kestrel at the loopback-only certificate since Wine has no ASP.NET dev cert.
export ASPNETCORE_Kestrel__Certificates__Default__Path
ASPNETCORE_Kestrel__Certificates__Default__Path="$(winepath -w "$tracker_certificate")"
export ASPNETCORE_Kestrel__Certificates__Default__Password=tracker-localhost

# Wine's accelerated WPF composition currently renders MTGO as a black surface.
# We instead have WPF fall back to software rendering for compatibility with Wine.
wine reg add 'HKCU\Software\Microsoft\Avalon.Graphics' \
/v DisableHWAcceleration /t REG_DWORD /d 1 /f >/dev/null

#
# WebView2 currently attempts DirectComposition when it inherits a modern
# Windows version under Wine. Wine bug 58921 documents that WebView2 renders
# when only msedgewebview2.exe is reported as Windows 8.
#
# See https://bugs.winehq.org/show_bug.cgi?id=58921 for details.
#
wine reg add 'HKCU\Software\Wine\AppDefaults\msedgewebview2.exe' \
/v Version /t REG_SZ /d win8 /f >/dev/null

if [[ "$skip_mtgo" == true ]]; then
echo "Skipping MTGO launch (TRACKER_SKIP_MTGO is enabled)."
else
# The ClickOnce bootstrapper detaches after starting MTGO.
mtgo
fi

echo "Launching Videre Tracker..."
wine "$tracker_exe" &
tracker_pid=$!

if wait "$tracker_pid"; then
tracker_status=0
else
tracker_status=$?
fi
wineserver -w
exit "$tracker_status"
62 changes: 62 additions & 0 deletions docker/tracker-wine.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
FROM videreproject/mtgosdk:wayland AS tracker-prereqs

ARG WEBVIEW2_RUNTIME_URL=https://go.microsoft.com/fwlink/?linkid=2124701

USER root
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
xauth \
libegl1 \
libgl1 \
libgles2 \
libgl1-mesa-dri \
&& rm -rf /var/lib/apt/lists/*

USER wine

# Tracker's native WebView2 loader uses the current Visual C++ runtime family.
RUN xvfb-run -a winetricks -q --force vcrun2022

# The current runtime rejects Wine's Windows 7 default, so configure this
# Tracker-specific prefix as Windows 10 before running Microsoft's installer.
RUN xvfb-run -a winetricks -q win10

FROM tracker-prereqs

ARG WEBVIEW2_RUNTIME_URL=https://go.microsoft.com/fwlink/?linkid=2124701

# Install the current x64 Evergreen standalone WebView2 Runtime into the Wine
# prefix. The Microsoft fwlink resolves to the current signed installer.
RUN curl --fail --location --retry 3 \
--output /tmp/MicrosoftEdgeWebView2RuntimeInstallerX64.exe \
"${WEBVIEW2_RUNTIME_URL}" \
&& xvfb-run -a wine /tmp/MicrosoftEdgeWebView2RuntimeInstallerX64.exe \
/silent /install \
&& wineserver -k \
&& find "/home/wine/.wine/drive_c/Program Files (x86)/Microsoft/EdgeWebView/Application" \
-mindepth 2 -maxdepth 2 -name msedgewebview2.exe -print -quit \
| grep -q . \
&& rm /tmp/MicrosoftEdgeWebView2RuntimeInstallerX64.exe

USER root
COPY --chmod=755 docker/run-tracker-wine.sh /usr/local/bin/run-tracker-wine

# Kestrel needs an explicit certificate because Wine does not provide the
# ASP.NET Core development certificate that UseHttps() normally discovers.
# This certificate is only used by Tracker's loopback server.
RUN mkdir -p /opt/tracker \
&& openssl req -x509 -newkey rsa:2048 -sha256 -nodes -days 3650 \
-subj "/CN=localhost" \
-addext "subjectAltName=DNS:localhost,IP:127.0.0.1,IP:::1" \
-keyout /tmp/tracker-localhost.key \
-out /tmp/tracker-localhost.crt \
&& openssl pkcs12 -export \
-out /opt/tracker/localhost.pfx \
-inkey /tmp/tracker-localhost.key \
-in /tmp/tracker-localhost.crt \
-passout pass:tracker-localhost \
&& chmod 0444 /opt/tracker/localhost.pfx \
&& rm /tmp/tracker-localhost.key /tmp/tracker-localhost.crt
USER wine

CMD ["run-tracker-wine"]
2 changes: 1 addition & 1 deletion src/client/src/layout/LayoutContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ export default function Layout() {
const currentBreadcrumbHref = isApiDocsPage ? getApiUrl("/docs") : undefined;

return (
<ThemeProvider defaultTheme="system" storageKey="vite-ui-theme">
<ThemeProvider defaultTheme="dark" storageKey="vite-ui-theme">
<EventsProvider>
<CardTooltipProvider>
<SidebarProvider>
Expand Down
Loading