# Running AlecaFrame (Overwolf) with Warframe on Linux — non-Steam, umu-launcher + Proton

> Source: <https://gist.github.com/Deftera186/b589b9147694484e772ab7e164402d20>
> Published: 2026-06-24 00:09:34+00:00

**Goal:** Get [AlecaFrame](https://alecaframe.com/) — a Warframe companion app built on
**Overwolf** — to actually read live in-game data (inventory, relics, missions, etc.) when
Warframe runs on Linux through ** umu-launcher +
Proton**,

*without*Steam.

**What this achieves (verified working):**

- ✅ AlecaFrame's
**data/tracking works**— inventory and the rest populate from the live game. - ✅ A
**single command** launches Warframe and auto-prepares AlecaFrame in the correct order. - ✅ It is
**self-healing** and survives reboots, Overwolf self-updates, and AlecaFrame data updates. - ❌ The transparent
**in-game overlay (Ctrl+Tab) does NOT work** under DXVK/Proton and almost certainly can't without upstream changes. You use AlecaFrame's**standalone window** instead. (Full technical reason below — it's a real wall, not a missing setting.)

This guide was largely written by AI (Opus 4.8).Every step was validated on a live system, but treat the Wine/Overwolf internals as "true as of the versions tested" (see[Versions]) and adapt paths to your setup. Nothing here modifies the game itself — it only adds launcher scripts, window rules, and a couple of harmless local files.

**Contents:** [TL;DR](https://gist.github.com/starred.atom#tldr) · [Prerequisites](https://gist.github.com/starred.atom#prerequisites) ·
[Background](https://gist.github.com/starred.atom#background-why-each-piece-is-needed) ·
[1. ptrace_scope](https://gist.github.com/starred.atom#step-1--persist-ptrace_scope--0) ·
[2. Scripts](https://gist.github.com/starred.atom#step-2--install-the-two-launcher-scripts) ·
[3. First-run seed](https://gist.github.com/starred.atom#step-3--first-run-sanity-for-oopo-and-the-data-cache) ·
[4. Hide junk windows](https://gist.github.com/starred.atom#step-4--hide-the-useless-wineoverwolf-windows-sway-example) ·
[5. Daily use](https://gist.github.com/starred.atom#step-5--daily-use) ·
[Overlay limitation](https://gist.github.com/starred.atom#the-in-game-overlay-why-it-renders-black) ·
[Versions](https://gist.github.com/starred.atom#versions-tested)

- Warframe runs via umu-launcher + Proton (DXVK). Overwolf is a separate Windows app; it can only
read the game if it runs
**inside the same Proton/pressure-vessel container** as the game. - umu can re-enter that container: a second
`umu-run`

with the**same** plus`WINEPREFIX`

+`GAMEID`

`UMU_CONTAINER_NSENTER=1`

and`PROTON_VERB=runinprefix`

"nsenters" into the running game container. - AlecaFrame's data does
**not** come from the EE.log — it comes from Overwolf's**memory scanner**(`gep_warframeext.dll`

) reading the game's RAM. Three things must all be true for that to work:(Wine reads process memory via`kernel.yama.ptrace_scope = 0`

`ptrace`

).- The game must have
in Overwolf's`<OOPO>True</OOPO>`

`GamesList`

(otherwise, under DXVK, Overwolf's renderer-detection fails and it never loads the scanner). - AlecaFrame's data cache (
`cachedData/json.7z`

) must be present & match the remote MD5, or its .NET init**hangs** trying to re-download over Wine's TLS.

- AlecaFrame must finish initializing
**before** the game process starts (load order matters). - Two small launcher scripts automate all of this, including self-healing #3 on every launch.

- Warframe already installed and
**working** via umu-launcher + Proton (this guide does not cover installing Warframe itself). - Overwolf + AlecaFrame already installed
**into the same Warframe Proton prefix**. Doing this on a non-Steam umu prefix is fiddly (the Overwolf web installer fails under Wine) — see[Installing Overwolf into a Proton / umu-launcher prefix](https://gist.github.com/Deftera186/68c61da901a26feaae77313ed4a1924c)for the working route, then install AlecaFrame from Overwolf's App Store. You should have launched Overwolf at least once so the`Overwolf/`

folders and`GamesList*.xml`

exist in the prefix. `curl`

(or`wget`

),`awk`

,`grep`

,`md5sum`

on the host.- Passwordless
`sudo`

(or root) once, to set a sysctl. - A compositor/WM where you can add window rules (examples use
**Sway**; adapt for yours).

Throughout, replace these with your values:

| Placeholder | Meaning |
|---|---|
`WINEPREFIX` |
Your Warframe Proton prefix, e.g. `$HOME/Games/Warframe-Proton-Prefix` |
`GAMEID` |
The umu game id you launch Warframe with, e.g. `umu-warframe` |
`LAUNCHER_EXE` |
Unix path to Warframe's `Tools/Launcher.exe` |

Inside a Proton prefix the user folder is

, so app data lives under`steamuser`

`"$WINEPREFIX/drive_c/users/steamuser/AppData/Local/..."`

. Use that, not your Linux username.

AlecaFrame is an Overwolf app. Overwolf can only see Warframe if it shares the game's
wine/Proton session (same `wineserver`

, same pressure-vessel mount/PID namespaces). A plain second
`umu-run`

builds its **own** container and is blind to the game.

umu-launcher solves this: launch a second `umu-run`

with the **same WINEPREFIX and GAMEID** and
set

`UMU_CONTAINER_NSENTER=1`

+ `PROTON_VERB=runinprefix`

. umu then re-enters the existing container
(you'll see *"Re-entering container through bus …"*). The injected Overwolf processes end up sharing the game's namespaces.

AlecaFrame's inventory/relics/etc. are **not** parsed from `EE.log`

. Overwolf's *General Game Events
Provider* (GEP) loads a native plugin ** gep_warframeext.dll** that scans

`Warframe.x64.exe`

's
memory (`ReadProcessMemory`

/`VirtualQueryEx`

). Only the player **name** comes from

`EE.log`

.The GEP only loads that scanner if it knows the game's **renderer** *or* the game is flagged
**out-of-process-overlay (OOPO)**. Under DXVK, Overwolf's renderer detection returns ** Unknown**, so
without OOPO the scanner is never loaded (GEP just logs

*"Waiting for renderer.."*). Setting

`<OOPO>True</OOPO>`

for Warframe forces the scanner to load — and, as a bonus, the renderer then
detects as D3D11. With it set you can confirm in the GEP log:
`Warframe plugin loaded: {"status":"success"}`

and `"oopOverlay":true`

.Under Wine/Proton, `wineserver`

performs `ReadProcessMemory`

using Linux ** ptrace** (

`/proc/<pid>/mem`

).
The scanner, the game, and `wineserver`

are *sibling*processes, so the kernel's Yama

**restricted-ptrace**(

`ptrace_scope = 1`

, the common default) blocks the cross-process reads and
AlecaFrame shows **no data**. Setting

`kernel.yama.ptrace_scope = 0`

allows it.

Security note:`ptrace_scope = 0`

lowers system-wide ptrace hardening (any process of your user can read another's memory). That's a normal tradeoff on a single-user gaming desktop, but make the call for your threat model.`= 1`

will break the data feature.

On startup AlecaFrame's .NET client MD5-checks `cachedData/json.7z`

. If that archive is **missing**
(only the extracted `json/`

folder present), it logs
`Got local data MD5: |==FILE-NOT-FOUND==|`

and tries to **re-download** the data over HTTPS — which
**hangs forever** under Wine's TLS, pinning a CEF process near 100% CPU. AlecaFrame deletes/renews
`json.7z`

whenever the upstream data changes, so this recurs over time. Keep `json.7z`

present and
matching the remote MD5 → it logs *"no data download is needed"* and initializes in ~25s. The script
below self-heals this from the CDN.

If AlecaFrame (re)initializes **after** `Warframe.x64.exe`

is already running, it hits the hang in #4.
So: start the **launcher**, inject + initialize AlecaFrame to "ready", **then** press Play.

```
sudo tee /etc/sysctl.d/50-alecaframe-ptrace.conf >/dev/null <<'EOF'
# AlecaFrame/Overwolf reads Warframe's memory cross-process via Overwolf's GameScanner.
# Under Wine, wineserver does ReadProcessMemory via ptrace; with Yama restricted-ptrace
# (scope 1) those sibling-process reads are blocked and AlecaFrame shows no data.
# NOTE: this lowers system-wide ptrace hardening (single-user desktop tradeoff).
kernel.yama.ptrace_scope = 0
EOF
sudo sysctl --system
cat /proc/sys/kernel/yama/ptrace_scope   # must print 0
```

Put both on your `$PATH`

(e.g. `~/.local/bin`

) and `chmod +x`

them. **Edit the CONFIG block** at the
top of each to match your prefix, game id, and launcher path.

``` bash
#!/bin/sh
# Launch Warframe (umu + Proton) AND auto-prepare AlecaFrame in the correct order.
#
# Correct order matters: AlecaFrame must FULLY initialize BEFORE Warframe.x64.exe starts,
# or AlecaFrame hangs. This script starts the LAUNCHER, then (in the background) injects +
# initializes AlecaFrame and waits for "READY". You press Play only after READY.
#
#   warframe              launch + auto-prepare AlecaFrame
#   NO_ALECA=1 warframe   launch the game only, no AlecaFrame

# ---- CONFIG: edit these ----
WINEPREFIX="$HOME/Games/Warframe-Proton-Prefix"
GAMEID="umu-warframe"
LAUNCHER_EXE="$HOME/Games/Warframe-Proton-Prefix/drive_c/users/steamuser/AppData/Local/Warframe/Downloaded/Public/Tools/Launcher.exe"
# ----------------------------

if [ -z "$NO_ALECA" ] && command -v alecaframe >/dev/null 2>&1; then
    setsid alecaframe wait-prepare >/tmp/alecaframe-autostart.log 2>&1 &
fi

exec env \
  WINEPREFIX="$WINEPREFIX" \
  GAMEID="$GAMEID" \
  STORE=none \
  umu-run "$LAUNCHER_EXE" "$@"
```

Add

`gamemoderun`

before`env`

if you use gamemode. Keep the umu knobs identical to the`alecaframe`

script (below) or umu computes a different prefix hash and won't re-enter the container.

``` bash
#!/bin/sh
# Inject Overwolf+AlecaFrame INTO Warframe's running umu/Proton container, in the correct order,
# and keep the data feature healthy (self-healing). Subcommands:
#   alecaframe prepare       inject into the running LAUNCHER, wait until AlecaFrame is initialized
#   alecaframe wait-prepare  (used by `warframe`) wait for the launcher, then prepare
#   alecaframe stop          stop Overwolf/AlecaFrame (never touches the game)
#   alecaframe status        show launcher/game/Overwolf state

# ---- CONFIG: edit these to match `warframe` EXACTLY ----
WINEPREFIX="$HOME/Games/Warframe-Proton-Prefix"
GAMEID="umu-warframe"
STORE="none"
# --------------------------------------------------------

OW_LAUNCHER='C:\Program Files (x86)\Overwolf\OverwolfLauncher.exe'
AF_EXTID="afmcagbpgggkpdkokjhjkllpegnadmkignlonpjm"     # AlecaFrame's Overwolf extension id (stable)
WF_GAME_ID="89541"                                       # Warframe's Overwolf game id (stable)
LOG="/tmp/alecaframe-overwolf.log"
OW_BASE="$WINEPREFIX/drive_c/users/steamuser/AppData/Local/Overwolf"
AF_BGLOG="$OW_BASE/Log/Apps/AlecaFrame/BackGround.html.log"
AF_DATA_CDN="https://cdn.alecaframe.com/warframeData"

# --- self-heal #1: ensure Warframe has <OOPO>True</OOPO> so Overwolf loads the data scanner.
# Patches every GamesList*.xml (Overwolf renames them and keeps a live + a bundled copy), inserting
# OOPO into Warframe's own <GameInfo> block (id 89541). Idempotent; re-run on every launch.
gameslist_files() {
    for d in "$OW_BASE" "$WINEPREFIX/drive_c/Program Files (x86)/Overwolf"/*/Resources; do
        [ -d "$d" ] || continue
        for f in "$d"/GamesList*.xml; do [ -f "$f" ] && printf '%s\n' "$f"; done
    done
}
oopo_present_in() {  # 0 if Warframe's block in $1 already has <OOPO>True</OOPO>
    awk -v id="$WF_GAME_ID" '
        /<GameInfo>/ { blk=""; isWF=0 }
        { blk=blk $0 ORS }
        $0 ~ ("<ID>" id "</ID>") { isWF=1 }
        /<\/GameInfo>/ { if (isWF && blk ~ /<OOPO>True<\/OOPO>/) found=1 }
        END { exit(found?0:1) }' "$1" 2>/dev/null
}
ensure_oopo() {
    gameslist_files | while IFS= read -r GL; do
        oopo_present_in "$GL" && continue
        cp -f "$GL" "$GL.bak.$(date +%Y%m%d-%H%M%S)" 2>/dev/null
        awk -v id="$WF_GAME_ID" '
            /<GameInfo>/ { isWF=0 }
            $0 ~ ("<ID>" id "</ID>") { isWF=1 }
            (isWF && /<\/GameInfo>/ && !done) { print "    <OOPO>True</OOPO>"; done=1; isWF=0 }
            { print }' "$GL" > "$GL.tmp" 2>/dev/null && mv "$GL.tmp" "$GL"
        oopo_present_in "$GL" && \
            echo "  (re-applied <OOPO>True</OOPO> to Warframe in $(basename "$GL") so data/inventory works)"
    done
}

# --- self-heal #2: keep AlecaFrame's data cache (json.7z) present & matching remote MD5, or its
# .NET init hangs re-downloading over Wine TLS ("Got local data MD5: |==FILE-NOT-FOUND==|").
ensure_data_cache() {
    tool=""
    for t in curl wget; do command -v "$t" >/dev/null 2>&1 && { tool="$t"; break; }; done
    [ -n "$tool" ] || return 0
    for U in steamuser "$USER"; do
        CD="$WINEPREFIX/drive_c/users/$U/AppData/Local/AlecaFrame/cachedData"
        [ -d "$CD" ] || continue
        want=""; [ -f "$CD/receivedMD5.txt" ] && want=$(awk '{print $1; exit}' "$CD/receivedMD5.txt" 2>/dev/null)
        cur="";  [ -f "$CD/json.7z" ] && cur=$(md5sum "$CD/json.7z" 2>/dev/null | awk '{print $1}')
        [ -n "$cur" ] && [ -n "$want" ] && [ "$cur" = "$want" ] && continue
        if [ "$tool" = curl ]; then rmd5=$(curl -fsSL "$AF_DATA_CDN/json7z.md5" 2>/dev/null | awk '{print $1; exit}')
        else rmd5=$(wget -qO- "$AF_DATA_CDN/json7z.md5" 2>/dev/null | awk '{print $1; exit}'); fi
        [ -n "$rmd5" ] || continue
        if [ -n "$cur" ] && [ "$cur" = "$rmd5" ]; then printf '%s  json.7z\n' "$rmd5" > "$CD/receivedMD5.txt"; continue; fi
        echo "  (refreshing AlecaFrame data cache json.7z so init won't hang...)"
        if [ "$tool" = curl ]; then curl -fsSL "$AF_DATA_CDN/json.7z" -o "$CD/json.7z.dl" 2>/dev/null
        else wget -qO "$CD/json.7z.dl" "$AF_DATA_CDN/json.7z" 2>/dev/null; fi
        got=$(md5sum "$CD/json.7z.dl" 2>/dev/null | awk '{print $1}')
        if [ -n "$got" ] && [ "$got" = "$rmd5" ]; then
            mv -f "$CD/json.7z.dl" "$CD/json.7z"; printf '%s  json.7z\n' "$rmd5" > "$CD/receivedMD5.txt"
            echo "  (data cache ready: $rmd5)"
        else rm -f "$CD/json.7z.dl"; echo "  (WARN: could not refresh json.7z)"; fi
    done
}

# --- helpers (use ps, not pgrep -f, which can hang on defunct procs in this setup) ---
launcher_container_up() { ps -eo args 2>/dev/null | grep -E 'umu-run.*Launcher\.exe' | grep -qv grep; }
game_running()          { ps -eo comm 2>/dev/null | grep -q 'Warframe.x64'; }
overwolf_running()      { ps -eo args 2>/dev/null | grep -i 'OverwolfBrowser.exe' | grep -qv grep; }

# inject an exe (+args) INTO the running game container (this is the whole trick)
inject() {
    setsid nohup env \
        WINEPREFIX="$WINEPREFIX" GAMEID="$GAMEID" STORE="$STORE" \
        PROTON_VERB="runinprefix" UMU_CONTAINER_NSENTER=1 UMU_RUNTIME_UPDATE=0 \
        umu-run "$@" </dev/null >"$LOG" 2>&1 &
}

wait_for_init() {  # 0 once AlecaFrame reports success, 1 on timeout
    secs="${1:-120}"; i=0
    while [ "$i" -lt "$secs" ]; do
        grep -q "Plugin initialization successful" "$AF_BGLOG" 2>/dev/null && return 0
        game_running && echo "[alecaframe] WARNING: game started before AlecaFrame finished init (will hang). Don't press Play until READY."
        i=$((i + 1)); sleep 1
    done
    return 1
}

do_prepare() {
    if overwolf_running; then echo "Overwolf already running. For a clean start: alecaframe stop, then prepare."; return 0; fi
    if ! launcher_container_up; then
        echo "The Warframe LAUNCHER isn't running yet. Start it (e.g. 'NO_ALECA=1 warframe'),"
        echo "stay on the launcher, then run 'alecaframe prepare' and wait for READY before Play."
        return 1
    fi
    if game_running; then echo "Game already running; AlecaFrame can't init cleanly now. Close it and retry from the launcher."; return 1; fi

    echo "Injecting Overwolf + AlecaFrame..."
    ensure_oopo
    ensure_data_cache
    : > "$AF_BGLOG" 2>/dev/null || true     # truncate so init-detection can't read a stale success line
    inject "$OW_LAUNCHER"

    echo "Waiting for Overwolf to come up..."
    i=0; ow=0
    while [ "$i" -lt 60 ]; do overwolf_running && { ow=1; break; }; i=$((i+1)); sleep 1; done
    [ "$ow" -eq 1 ] || { echo "Overwolf did not start."; return 1; }
    sleep 5

    echo "Opening AlecaFrame (retrying until it starts)..."
    started=0; try=0
    while [ "$try" -lt 5 ]; do
        try=$((try+1)); inject "$OW_LAUNCHER" -launchapp "$AF_EXTID"; j=0
        while [ "$j" -lt 20 ]; do
            grep -qE 'Plugin (early )?initialization (started|completed)|Starting plugin initialization|Plugin instantiated' "$AF_BGLOG" 2>/dev/null && { started=1; break; }
            grep -q 'Plugin initialization successful' "$AF_BGLOG" 2>/dev/null && { started=1; break; }
            j=$((j+1)); sleep 1
        done
        [ "$started" -eq 1 ] && break
        echo "  (didn't start on attempt $try; retrying...)"
    done
    [ "$started" -eq 1 ] || { echo "AlecaFrame would not start. Try: alecaframe stop, then prepare."; return 1; }

    echo "Waiting for AlecaFrame to finish initializing (up to 120s)..."
    if wait_for_init 120; then
        echo; echo "==== READY — AlecaFrame initialized. You can now press PLAY in the launcher. ===="
        return 0
    fi
    echo "AlecaFrame did NOT initialize in time. Check: tail -n 40 \"$AF_BGLOG\""
    echo "If stuck at FILE-NOT-FOUND, the game likely started too early: alecaframe stop, close game, retry."
    return 1
}

case "$1" in
    stop)
        echo "Stopping Overwolf/AlecaFrame (never touches the game)..."
        PIDS=$(ps -eo pid,args 2>/dev/null | grep -i 'Overwolf' | grep -v grep | awk '{print $1}' | tr '\n' ' ')
        [ -n "$PIDS" ] && { kill -TERM $PIDS 2>/dev/null; sleep 3; echo "  stopped: $PIDS"; } || echo "  (not running)"
        ;;
    status)
        launcher_container_up && echo "Launcher: RUNNING" || echo "Launcher: not running"
        game_running        && echo "Game:     RUNNING"  || echo "Game:     not running"
        overwolf_running    && echo "Overwolf: RUNNING"  || echo "Overwolf: not running"
        ;;
    wait-prepare)
        # If a STALE Overwolf is up (left over/crashed) but AlecaFrame isn't initialized, clean it first.
        if overwolf_running && ! grep -q 'Plugin initialization successful' "$AF_BGLOG" 2>/dev/null; then
            echo "[alecaframe] stale Overwolf detected; cleaning it first." >&2
            PIDS=$(ps -eo pid,args 2>/dev/null | grep -i 'Overwolf' | grep -v grep | awk '{print $1}' | tr '\n' ' ')
            [ -n "$PIDS" ] && { kill -TERM $PIDS 2>/dev/null; sleep 3; }
        fi
        i=0
        while [ "$i" -lt 180 ]; do
            game_running && { echo "[alecaframe] game already running before prepare; skipping." >&2; exit 0; }
            launcher_container_up && { sleep 3; do_prepare; exit 0; }
            i=$((i + 1)); sleep 1
        done
        ;;
    prepare|"") do_prepare ;;
    *) echo "Usage: alecaframe [prepare|stop|status]"; exit 2 ;;
esac
```

The scripts self-heal both on every launch, but you can seed them once manually to confirm:

```
PREFIX="$HOME/Games/Warframe-Proton-Prefix"          # your WINEPREFIX
OW="$PREFIX/drive_c/users/steamuser/AppData/Local/Overwolf"
CD="$PREFIX/drive_c/users/steamuser/AppData/Local/AlecaFrame/cachedData"

# 1) Confirm Warframe (id 89541) has OOPO in its own block, across every GamesList file:
for GL in "$OW"/GamesList*.xml "$PREFIX/drive_c/Program Files (x86)/Overwolf"/*/Resources/GamesList*.xml; do
  [ -f "$GL" ] || continue
  awk '/<GameInfo>/{b="";w=0}{b=b $0 RS}/<ID>89541<\/ID>/{w=1}/<\/GameInfo>/{if(w&&b~/<OOPO>True<\/OOPO>/)k=1}
       END{exit(k?0:1)}' "$GL" \
    && echo "OOPO ok : $GL" || echo "OOPO MISSING (run 'alecaframe prepare' to fix): $GL"
done

# 2) Seed the data cache so init won't hang:
mkdir -p "$CD"
curl -fsSL https://cdn.alecaframe.com/warframeData/json.7z   -o "$CD/json.7z"
curl -fsSL https://cdn.alecaframe.com/warframeData/json7z.md5 | awk '{print $1"  json.7z"}' > "$CD/receivedMD5.txt"
md5sum "$CD/json.7z"; cat "$CD/receivedMD5.txt"        # the two hashes must match
```

(Just running `alecaframe prepare`

once does all of the above automatically.)

Under Wine/Xwayland, several Overwolf/Wine windows show up as class `steam_app_warframe`

and are
useless or broken on Linux: the **black out-of-process overlay surface** (title `ow overlay`

), the
**Quick Launcher**, and Wine's tiny title-less `explorer.exe /desktop`

artifact. Hide them
(Sway shown; translate the idea to your WM):

```
# Keep the usable Overwolf client + AlecaFrame windows visible, float them (do NOT resize AlecaFrame —
# resizing can crash its UI). Positions are examples; tweak to taste.
for_window [class="steam_app_warframe" title="^Overwolf$"]   floating enable, move position 230 130
for_window [class="steam_app_warframe" title="^AlecaFrame$"] floating enable, move position 80 100

# Hide the broken/noise windows in the scratchpad:
for_window [class="steam_app_warframe" title="^Overwolf Quick Launcher$"] floating enable, move scratchpad
for_window [class="steam_app_warframe" title="^ow overlay$"]              floating enable, move scratchpad
for_window [class="steam_app_warframe" title="^$"]                       floating enable, move scratchpad
```

Reload your WM config. (`title="^$"`

catches the title-less Wine desktop window; the real Overwolf/
AlecaFrame/launcher/game windows all map *with* a title, and move-to-scratchpad is non-destructive.)

```
warframe            # starts the launcher AND auto-prepares AlecaFrame
# watch for READY (tail -f /tmp/alecaframe-autostart.log, or: alecaframe status)
# THEN press Play in the launcher.

NO_ALECA=1 warframe # launch the game only
alecaframe stop     # stop Overwolf/AlecaFrame without touching the game
```

Open AlecaFrame's **standalone window** (from the Overwolf client) on a second monitor for your data.

If something gets stuck, the reliable reset is:

```
alecaframe stop
WINEPREFIX="$HOME/Games/Warframe-Proton-Prefix" \
  "$HOME/.local/share/umu/compatibilitytools/UMU-Latest/files/bin/wineserver" -k   # adapt path to your Proton
rm -f "$HOME/Games/Warframe-Proton-Prefix/pfx.lock"
```

Symptom: pressing Ctrl+Tab shows a **fully black** surface over the game (and Overwolf's own
`Settings`

window is black too).

Root cause:

- Overwolf renders the overlay UI with
**CEF (Chromium) off-screen**, then hands the pixels to its compositor`ow-overlay.exe`

as a**cross-process D3D11 shared texture**(NT-handle / keyed-mutex), optionally via** DirectComposition**. **DXVK does not support cross-process D3D11 shared textures**: its shared-resource table is per-process, so the texture created by CEF's GPU process can't be opened by`ow-overlay.exe`

(`D3D11Device::OpenSharedResourceGeneric: Handle not found`

). DXVK also lacks`CreateSwapChainForComposition`

. CEF itself reports`shared texture compatibility: False`

and`direct_composition: false`

. Result: the pixels never reach the overlay surface → black.

Things that **don't** fix it (tested):

- Forcing only
`ow-overlay.exe`

onto**wined3d**(which*does*implement composition swapchains): it shares a folder with Overwolf's CEF browser, so CEF picks up wined3d too and renders broken; and a per-app Wine`DllOverride`

of`dxgi/d3d11=builtin`

can't beat DXVK because DXVK is installed by physically replacing`system32\dxgi.dll`

. Even if it loaded, the failure is also on the CEF-GPU side, so the handoff still breaks. - There's no Overwolf/CEF setting found to force a CPU/shared-memory overlay transport.

So the overlay needs upstream support (DXVK cross-process shared NT-handle textures, or an Overwolf
CPU-copy overlay path). Until then: use the standalone window. **Everything else works.**

Non-fatal noise you can ignore: `gamemodeauto: dlopen failed libgamemode.so`

, occasional
`worldState.php`

404s (an upstream Warframe endpoint moved; only affects a world-timer panel),
`Uninstall registry key not found`

.

- umu-launcher +
**UMU-Proton 10.0**(Wine 10),** DXVK 2.5.1**. - Overwolf client
`0.304.x`

, AlecaFrame`2.6.89`

, GEP`307.4.3`

. - AMD GPU (RADV/amdgpu), Wayland (Sway). The data approach is GPU-agnostic; the overlay limitation is DXVK-wide, not vendor-specific.

Overwolf/AlecaFrame are third-party software; their internals can change and break these specifics. The general approach (container re-entry, OOPO, ptrace, data-cache, load order) should remain valid.
