mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-10-21 05:01:26 -07:00
- Stop stripping HYPRLAND_INSTANCE_SIGNATURE in applyX11EnvOverrides so the overlay can use hyprctl to lift Hyprland's fullscreen input block - Fixes the overlay becoming unclickable over fullscreen mpv with mpv.backend: x11 - Update launcher and backend tests, add changelog fragment
104 lines
4.3 KiB
TypeScript
104 lines
4.3 KiB
TypeScript
/*
|
|
Shared XWayland/X11 backend forcing for mpv and the Electron app.
|
|
|
|
On Wayland sessions the SubMiner overlay can only be reliably kept above mpv when
|
|
BOTH processes run under XWayland: the Wayland protocol forbids clients from
|
|
controlling window stacking, so Electron's `setAlwaysOnTop`/`moveTop` become
|
|
no-ops under a native Wayland surface. Hyprland and Sway are the exception — they
|
|
are supported natively via compositor-specific window placement — so all forcing
|
|
here is gated to "Linux + Wayland session + NOT Hyprland/Sway".
|
|
|
|
This module is shared between the `launcher/` bundle and the Electron `src/` build
|
|
so the gate and the mpv backend args stay in one place.
|
|
*/
|
|
|
|
/**
|
|
* mpv args that pin the *windowing* stack to X11/XWayland, in Vulkan-then-OpenGL order.
|
|
* mpv walks the list and skips contexts that do not match the configured `--gpu-api`,
|
|
* so this works for both a Vulkan and an OpenGL config.
|
|
*
|
|
* Deliberately does NOT set `--vo`/`--gpu-api`: forcing `--vo=gpu --gpu-api=opengl` here
|
|
* used to drop configs off `vo=gpu-next` onto the legacy renderer, where user shaders
|
|
* written for gpu-next (e.g. ArtCNN, `//!COMPONENTS 4` LUMA hooks) abort mpv with
|
|
* `copy_image: Assertion '*offset + count < sizeof(dst)' failed` as soon as their
|
|
* upscale-only `//!WHEN` condition turns on, i.e. on the first fullscreen toggle.
|
|
*/
|
|
export const MPV_X11_BACKEND_ARGS = ['--gpu-context=x11vk,x11egl,x11'] as const;
|
|
|
|
export type LinuxDesktopEnv = {
|
|
xdgCurrentDesktop: string;
|
|
xdgSessionDesktop: string;
|
|
hasWayland: boolean;
|
|
};
|
|
|
|
export function getLinuxDesktopEnv(env: NodeJS.ProcessEnv = process.env): LinuxDesktopEnv {
|
|
const xdgCurrentDesktop = (env.XDG_CURRENT_DESKTOP || '').toLowerCase();
|
|
const xdgSessionDesktop = (env.XDG_SESSION_DESKTOP || '').toLowerCase();
|
|
const xdgSessionType = (env.XDG_SESSION_TYPE || '').toLowerCase();
|
|
return {
|
|
xdgCurrentDesktop,
|
|
xdgSessionDesktop,
|
|
hasWayland: Boolean(env.WAYLAND_DISPLAY) || xdgSessionType === 'wayland',
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Compositors that SubMiner supports natively on Wayland (no XWayland forcing).
|
|
* Detected via their socket env vars or the XDG desktop identifiers.
|
|
*/
|
|
export function isSupportedWaylandCompositor(env: NodeJS.ProcessEnv = process.env): boolean {
|
|
const desktop = getLinuxDesktopEnv(env);
|
|
return (
|
|
Boolean(env.HYPRLAND_INSTANCE_SIGNATURE || env.SWAYSOCK) ||
|
|
desktop.xdgCurrentDesktop.includes('hyprland') ||
|
|
desktop.xdgCurrentDesktop.includes('sway') ||
|
|
desktop.xdgSessionDesktop.includes('hyprland') ||
|
|
desktop.xdgSessionDesktop.includes('sway')
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Should this Linux session be pushed onto XWayland/X11? True for a Wayland session
|
|
* that is not one of the natively-supported compositors and has an X11 display
|
|
* available for the fallback. This is the "auto" decision shared by the Electron app
|
|
* and SubMiner-managed mpv launches.
|
|
*/
|
|
export function shouldForceX11WaylandSession(env: NodeJS.ProcessEnv = process.env): boolean {
|
|
if (process.platform !== 'linux') return false;
|
|
if (!env.DISPLAY?.trim()) return false;
|
|
if (!getLinuxDesktopEnv(env).hasWayland) return false;
|
|
return !isSupportedWaylandCompositor(env);
|
|
}
|
|
|
|
/**
|
|
* Launcher-facing decision that also honors an explicit `--backend` choice:
|
|
* - `x11` forces the X11 stack whenever an X11 display exists,
|
|
* - `auto` defers to {@link shouldForceX11WaylandSession}.
|
|
*/
|
|
export function shouldForceX11MpvBackend(
|
|
backend: string,
|
|
env: NodeJS.ProcessEnv = process.env,
|
|
): boolean {
|
|
if (process.platform !== 'linux' || !env.DISPLAY?.trim()) {
|
|
return false;
|
|
}
|
|
if (backend === 'x11') return true;
|
|
return backend === 'auto' && shouldForceX11WaylandSession(env);
|
|
}
|
|
|
|
/**
|
|
* Strip Wayland/compositor hints and pin the session type to X11 on the given env
|
|
* object (mutates in place and returns it) so a child mpv process picks XWayland.
|
|
*
|
|
* HYPRLAND_INSTANCE_SIGNATURE is kept: the overlay app inherits this env through the
|
|
* mpv plugin, and Hyprland still manages its XWayland windows. Without hyprctl access
|
|
* the overlay cannot lift Hyprland's fullscreen input block, so it stays visible but
|
|
* unclickable over fullscreen mpv.
|
|
*/
|
|
export function applyX11EnvOverrides(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv {
|
|
delete env.WAYLAND_DISPLAY;
|
|
delete env.SWAYSOCK;
|
|
env.XDG_SESSION_TYPE = 'x11';
|
|
return env;
|
|
}
|