Remove wine support for Cef

This commit is contained in:
Natsumi
2025-08-01 00:50:08 +12:00
parent 7eaa9b55c8
commit 3c21d88efa
23 changed files with 650 additions and 1066 deletions

View File

@@ -223,10 +223,5 @@ namespace VRCX
using var client = MainForm.Instance.Browser.GetDevToolsClient();
_ = client.Network.SetUserAgentOverrideAsync(Program.Version);
}
public override bool IsRunningUnderWine()
{
return Wine.GetIfWine();
}
}
}

View File

@@ -65,21 +65,16 @@ namespace VRCX
{
return CultureInfo.CurrentCulture.ToString();
}
public override string CustomVrScript()
{
var filePath = Path.Join(Program.AppDataDirectory, "customvr.js");
if (File.Exists(filePath))
return File.ReadAllText(filePath);
return string.Empty;
}
public override bool IsRunningUnderWine()
{
return Wine.GetIfWine();
}
public override List<KeyValuePair<string, string>> GetExecuteVrFeedFunctionQueue()
{
throw new NotImplementedException("GetExecuteVrFeedFunctionQueue is not implemented in AppApiVrCef.");

View File

@@ -24,21 +24,10 @@ namespace VRCX
var isGameRunning = false;
var isSteamVRRunning = false;
var isHmdAfk = false;
if (ProcessMonitor.Instance.IsProcessRunning("VRChat"))
isGameRunning = true;
if (Wine.GetIfWine())
{
var wineTmpPath = Path.Join(Program.AppDataDirectory, "wine.tmp");
if (File.Exists(wineTmpPath))
{
var wineTmp = File.ReadAllText(wineTmpPath);
if (wineTmp.Contains("isGameRunning=true"))
isGameRunning = true;
}
}
if (ProcessMonitor.Instance.IsProcessRunning("vrserver"))
isSteamVRRunning = true;
@@ -49,7 +38,7 @@ namespace VRCX
if (MainForm.Instance?.Browser != null && !MainForm.Instance.Browser.IsLoading && MainForm.Instance.Browser.CanExecuteJavascriptInMainFrame)
MainForm.Instance.Browser.ExecuteScriptAsync("$app.store.game.updateIsGameRunning", isGameRunning, isSteamVRRunning, isHmdAfk);
}
public override bool IsGameRunning()
{
// unused
@@ -61,7 +50,7 @@ namespace VRCX
// unused
return ProcessMonitor.Instance.IsProcessRunning("vrserver");
}
public override int QuitGame()
{
var processes = Process.GetProcessesByName("vrchat");

View File

@@ -14,7 +14,7 @@ namespace VRCX
public abstract void SetZoom(double zoomLevel);
public abstract Task<double> GetZoom();
public abstract void DesktopNotification(string BoldText, string Text = "", string Image = "");
public abstract void RestartApplication(bool isUpgrade);
public abstract bool CheckForUpdateExe();
public abstract void ExecuteAppFunction(string function, string json);
@@ -28,7 +28,6 @@ namespace VRCX
public abstract void CopyImageToClipboard(string path);
public abstract void FlashWindow();
public abstract void SetUserAgent();
public abstract bool IsRunningUnderWine();
// Folders
public abstract string GetVRChatAppDataLocation();
@@ -48,7 +47,7 @@ namespace VRCX
public abstract Task<string> OpenFileSelectorDialog(string defaultPath = "", string defaultExt = "",
string defaultFilter = "All files (*.*)|*.*");
// GameHandler
public abstract void OnProcessStateChanged(MonitoredProcess monitoredProcess);
public abstract void CheckGameRunning();
@@ -57,7 +56,7 @@ namespace VRCX
public abstract int QuitGame();
public abstract bool StartGame(string arguments);
public abstract bool StartGameFromPath(string path, string arguments);
// RegistryPlayerPrefs
public abstract object GetVRChatRegistryKey(string key);
public abstract string GetVRChatRegistryKeyString(string key);
@@ -68,7 +67,7 @@ namespace VRCX
public abstract bool HasVRChatRegistryFolder();
public abstract void DeleteVRChatRegistryFolder();
public abstract string ReadVrcRegJsonFile(string filepath);
// Screenshot
public abstract string AddScreenshotMetadata(string path, string metadataString, string worldId, bool changeFilename = false);
}

View File

@@ -13,7 +13,6 @@ public abstract partial class AppApiVr
public abstract double GetUptime();
public abstract string CurrentCulture();
public abstract string CustomVrScript();
public abstract bool IsRunningUnderWine();
public abstract List<KeyValuePair<string, string>> GetExecuteVrFeedFunctionQueue();
public abstract List<KeyValuePair<string, string>> GetExecuteVrOverlayFunctionQueue();
}

View File

@@ -147,12 +147,5 @@ namespace VRCX
public override void SetUserAgent()
{
}
public override bool IsRunningUnderWine()
{
return false;
}
}
}

View File

@@ -93,10 +93,5 @@ namespace VRCX
return string.Empty;
}
public override bool IsRunningUnderWine()
{
return false;
}
}
}

View File

@@ -72,10 +72,6 @@ namespace VRCX
private static void InstallUpdate()
{
var setupArguments = string.Empty;
#if !LINUX
if (Wine.GetIfWine())
setupArguments += "/SKIP_SHORTCUT=true";
#endif
try
{

View File

@@ -1,17 +0,0 @@
### Download and run AppImage from [Releases](https://github.com/vrcx-team/VRCX/releases)
If you're using Fedora, you may need to reboot after installing .NET for [DOTNET_ROOT](https://src.fedoraproject.org/rpms/dotnet9.0/blob/rawhide/f/dotnet.sh.in#_3) environment variable to take affect.
---
### Legacy Wine guide
VRCX on Linux was made possible by these people:
@RinLovesYou, @galister, @BenjaminZehowlt, @regalialong
Run `curl -sSf https://raw.githubusercontent.com/vrcx-team/VRCX/master/Linux/install-vrcx.sh | bash`
It'll preconfigure you a Wine bottle with VRCX.
You will require Wine >= 9.0 due to CEF and winetricks for corefonts.

View File

@@ -1,2 +0,0 @@
### twemoji-color-font
- [https://github.com/13rac1/twemoji-color-font](https://github.com/13rac1/twemoji-color-font)

Binary file not shown.

View File

@@ -1,105 +0,0 @@
#!/usr/bin/env bash
steamapps=$HOME/.local/share/Steam/steamapps/compatdata
stable="https://api0.vrcx.app/releases/stable/latest/download"
nightly="https://api0.vrcx.app/releases/nightly/latest/download"
download_url=$stable
XDG_DATA_HOME=${XDG_DATA_HOME:=$HOME/.local/share}
export WINEPREFIX="$XDG_DATA_HOME"/vrcx
export WINEARCH=win64
set -e
set -u
# Ensure Wine version >= 9.0
wine_version=$(wine --version | grep -Po '(?<=wine-)([0-9.]+)')
if [ "${1-}" != "force" ] && awk "BEGIN {exit !($wine_version < 9.0)}"; then
echo "Your Wine version: $wine_version"
echo "Please upgrade your Wine version to 9.0 or higher."
echo "If you want to try anyway, run: install-vrcx.sh force"
exit 1
fi
if ! [ -x "$(command -v winetricks)" ]; then
echo "You don't have winetricks installed or 'command -v winetricks' doesn't recongize it, you will want it for corefonts."
exit 1
fi
if [[ ! -d $WINEPREFIX ]]; then
echo "Creating Wine prefix."
logs=$(winecfg /v win10 2>&1)
if [ "$?" -ne "0" ]; then
echo "*********** Error while creating Wine prefix ***********"
echo "$logs"
echo "*********** Error while creating Wine prefix ***********"
exit 1
fi
fi
if [[ ! -d $steamapps ]] && [[ -d $HOME/.var/app/com.valvesoftware.Steam/.local/share/Steam/steamapps/compatdata ]]; then
echo "Flatpak Steam detected."
steamapps=$HOME/.var/app/com.valvesoftware.Steam/.local/share/Steam/steamapps/compatdata
fi
vrc_appdata=$steamapps/438100/pfx/drive_c/users/steamuser/AppData/LocalLow/VRChat/VRChat
vrc_dst=$WINEPREFIX/drive_c/users/$USER/AppData/LocalLow/VRChat/VRChat
if [[ ! -d $vrc_appdata ]]; then
echo "No VRC installation detected."
echo "If you want to use VRC on this computer, please install it now and start it once."
echo "Otherwise, you will lose out on some features, like Game Log"
read -p "Press enter to continue"
fi
if [[ -d $vrc_appdata ]] && [[ ! -d $vrc_dst ]]; then
echo "Link VRChat AppData into Wine Prefix"
mkdir -p $(dirname $vrc_dst)
ln -s $vrc_appdata $vrc_dst
fi
winetricks --force -q corefonts # Workaround for https://bugs.winehq.org/show_bug.cgi?id=32342
echo "Download VRCX"
INSTALL_LOCATION="$WINEPREFIX/drive_c/Program Files/VRCX"
if [[ ! -d $INSTALL_LOCATION ]]; then
mkdir -p "$INSTALL_LOCATION"
else
rm -rf "${INSTALL_LOCATION:?}/"*
fi
cd "$INSTALL_LOCATION"
curl -L $download_url -o vrcx_setup.exe
WINEPREFIX=$WINEPREFIX wine vrcx_setup.exe /S /SKIP_SHORTCUT=true
rm vrcx_setup.exe
# Install twemoji font as Segoe UI is proprietary and not included in wine
echo "Download twemoji font."
curl -L https://raw.githubusercontent.com/vrcx-team/VRCX/master/Linux/fonts/seguiemj.ttf -o seguiemj.ttf
echo "Install twemoji font."
cp seguiemj.ttf "$WINEPREFIX/drive_c/windows/Fonts"
WINEPREFIX=$WINEPREFIX wine reg add 'HKLM\Software\Microsoft\Windows NT\CurrentVersion\Fonts' /v 'seguiemj' /t REG_SZ /d 'seguiemj.ttf' /f
rm seguiemj.ttf
curl -L https://raw.githubusercontent.com/vrcx-team/VRCX/master/Linux/vrcx.sh -o $WINEPREFIX/drive_c/vrcx.sh
chmod +x $WINEPREFIX/drive_c/vrcx.sh
curl -L https://raw.githubusercontent.com/vrcx-team/VRCX/master/Linux/winediscordipcbridge.exe -o $WINEPREFIX/drive_c/winediscordipcbridge.exe
echo "Install VRCX.png to $XDG_DATA_HOME/icons"
curl -L https://raw.githubusercontent.com/vrcx-team/VRCX/master/VRCX.png -o "$XDG_DATA_HOME/icons/VRCX.png"
echo "Install vrcx.exe.desktop to $XDG_DATA_HOME/applications"
echo "[Desktop Entry]
Type=Application
Name=VRCX
Categories=Utility;
Exec=$WINEPREFIX/drive_c/vrcx.sh
Icon=VRCX
" > $XDG_DATA_HOME/applications/vrcx.exe.desktop
echo "Done! Check your menu for VRCX."

View File

@@ -1,40 +0,0 @@
#!/usr/bin/env bash
export WINEPREFIX=~/.local/share/vrcx
# Function to launch winediscordipcbridge
launch_ipcbridge() {
wine ~/.local/share/vrcx/drive_c/winediscordipcbridge.exe &
IPCBRIDGE_PID=$!
}
# Launch winediscordipcbridge
launch_ipcbridge
# Launch VRCX
wine "$WINEPREFIX/drive_c/Program Files/VRCX/VRCX.exe" &
VRCX_PID=$!
while kill -0 $VRCX_PID 2>/dev/null; do
# Check if VRChat is running
if ps -A | grep -i "VRChat.exe" > /dev/null; then
isGameRunning=true
else
isGameRunning=false
fi
echo "isGameRunning=$isGameRunning" > "$WINEPREFIX/drive_c/users/$USER/AppData/Roaming/VRCX/wine.tmp"
# Check if winediscordipcbridge is running
if ! kill -0 $IPCBRIDGE_PID 2>/dev/null; then
echo "winediscordipcbridge.exe not running, restarting..."
launch_ipcbridge
fi
sleep 1
done
# Cleanup after VRCX exits
echo "isGameRunning=false" > "$WINEPREFIX/drive_c/users/$USER/AppData/Roaming/VRCX/wine.tmp"
# Kill winediscordipcbridge if it's still running
kill $IPCBRIDGE_PID 2>/dev/null

Binary file not shown.

1322
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -32,33 +32,32 @@
"homepage": "https://github.com/vrcx-team/VRCX#readme",
"devDependencies": {
"@electron/rebuild": "^4.0.1",
"@eslint/js": "^9.31.0",
"@eslint/js": "^9.32.0",
"@fontsource/noto-sans-jp": "^5.2.6",
"@fontsource/noto-sans-kr": "^5.2.6",
"@fontsource/noto-sans-sc": "^5.2.6",
"@fontsource/noto-sans-tc": "^5.2.6",
"@infolektuell/noto-color-emoji": "^0.2.0",
"@prettier/plugin-pug": "^3.4.0",
"@types/jest": "^30.0.0",
"@types/node": "^24.0.13",
"@types/node": "^24.1.0",
"animate.css": "^4.1.1",
"concurrently": "^9.2.0",
"copy-webpack-plugin": "^13.0.0",
"cross-env": "^7.0.3",
"cross-env": "^10.0.0",
"css-loader": "^7.1.2",
"dayjs": "^1.11.13",
"echarts": "^5.6.0",
"electron": "^37.2.1",
"echarts": "^6.0.0",
"electron": "^37.2.5",
"electron-builder": "^26.0.12",
"element-ui": "^2.15.14",
"esbuild-jest": "^0.5.0",
"esbuild-loader": "^4.3.0",
"eslint": "^9.31.0",
"eslint-config-prettier": "^10.1.5",
"eslint": "^9.32.0",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-vue": "^9.33.0",
"globals": "^16.3.0",
"html-webpack-plugin": "^5.6.3",
"jest": "^30.0.4",
"jest": "^30.0.5",
"mini-css-extract-plugin": "^2.9.2",
"noty": "^3.2.0-beta-deprecated",
"pinia": "^2.3.1",
@@ -77,7 +76,7 @@
"vue-loader": "^15.11.1",
"vue-markdown": "^2.2.4",
"vue-marquee-text-component": "^1.2.0",
"webpack": "^5.100.1",
"webpack": "^5.101.0",
"webpack-cli": "^6.0.1",
"webpack-dev-server": "^5.2.2",
"worker-timers": "^8.0.23",
@@ -171,4 +170,4 @@
"hazardous": "^0.3.0",
"node-api-dotnet": "^0.9.12"
}
}
}

View File

@@ -92,14 +92,6 @@
store.auth.autoLoginAfterMounted();
store.vrcx.checkAutoBackupRestoreVrcRegistry();
store.game.checkVRChatDebugLogging();
try {
if (await AppApi.IsRunningUnderWine()) {
store.vrcx.isRunningUnderWine = true;
store.vrcx.applyWineEmojis();
}
} catch (err) {
console.error(err, 'Failed to check if running under Wine');
}
});
return {

View File

@@ -3,10 +3,9 @@
import '@fontsource/noto-sans-jp';
import '@fontsource/noto-sans-sc';
import '@fontsource/noto-sans-tc';
import '@infolektuell/noto-color-emoji';
// @ts-ignore
import pugTemplate from './vr.pug';
import Vue, { onMounted, reactive, toRefs } from 'vue';
import Vue, { onMounted, reactive, toRefs, nextTick } from 'vue';
import Noty from 'noty';
import * as workerTimers from 'worker-timers';
import MarqueeText from 'vue-marquee-text-component';
@@ -23,7 +22,7 @@
template: pugTemplate,
components: {
'marquee-text': MarqueeText,
'location': VrLocation
location: VrLocation
},
setup() {
const vrState = reactive({
@@ -70,10 +69,7 @@
});
onMounted(async () => {
if (WINDOWS) {
vrState.isRunningUnderWine = await AppApiVr.IsRunningUnderWine();
await applyWineEmojis();
} else {
if (LINUX) {
updateVrElectronLoop();
}
if (vrState.appType === '1') {
@@ -82,29 +78,32 @@
}
setDatetimeFormat();
window.$app.configUpdate = configUpdate;
window.$app.updateOnlineFriendCount = updateOnlineFriendCount;
window.$app.nowPlayingUpdate = nowPlayingUpdate;
window.$app.lastLocationUpdate = lastLocationUpdate;
window.$app.wristFeedUpdate = wristFeedUpdate;
window.$app.refreshCustomScript = refreshCustomScript;
window.$app.playNoty = playNoty;
window.$app.statusClass = statusClass;
window.$app.notyClear = notyClear;
window.$app.addEntryHudFeed = addEntryHudFeed;
window.$app.updateHudFeedTag = updateHudFeedTag;
window.$app.updateHudTimeout = updateHudTimeout;
window.$app.setDatetimeFormat = setDatetimeFormat;
window.$app.setAppLanguage = setAppLanguage;
window.$app.trackingResultToClass = trackingResultToClass;
window.$app.updateFeedLength = updateFeedLength;
window.$app.updateStatsLoop = updateStatsLoop;
window.$app.updateVrElectronLoop = updateVrElectronLoop;
window.$app.cleanHudFeedLoop = cleanHudFeedLoop;
window.$app.cleanHudFeed = cleanHudFeed;
window.$app.applyWineEmojis = applyWineEmojis;
nextTick(() => {
window.$app.configUpdate = configUpdate;
window.$app.updateOnlineFriendCount = updateOnlineFriendCount;
window.$app.nowPlayingUpdate = nowPlayingUpdate;
window.$app.lastLocationUpdate = lastLocationUpdate;
window.$app.wristFeedUpdate = wristFeedUpdate;
window.$app.refreshCustomScript = refreshCustomScript;
window.$app.playNoty = playNoty;
window.$app.statusClass = statusClass;
window.$app.notyClear = notyClear;
window.$app.addEntryHudFeed = addEntryHudFeed;
window.$app.updateHudFeedTag = updateHudFeedTag;
window.$app.updateHudTimeout = updateHudTimeout;
window.$app.setDatetimeFormat = setDatetimeFormat;
window.$app.setAppLanguage = setAppLanguage;
window.$app.trackingResultToClass = trackingResultToClass;
window.$app.updateFeedLength = updateFeedLength;
window.$app.updateStatsLoop = updateStatsLoop;
window.$app.updateVrElectronLoop = updateVrElectronLoop;
window.$app.cleanHudFeedLoop = cleanHudFeedLoop;
window.$app.cleanHudFeed = cleanHudFeed;
window.$app.vrState = vrState;
window.$app.vrState = vrState;
AppApiVr.VrInit();
});
});
function configUpdate(json) {
@@ -621,19 +620,6 @@
}
}
async function applyWineEmojis() {
if (document.contains(document.getElementById('app-emoji-font'))) {
document.getElementById('app-emoji-font').remove();
}
if (vrState.isRunningUnderWine) {
const $appEmojiFont = document.createElement('link');
$appEmojiFont.setAttribute('id', 'app-emoji-font');
$appEmojiFont.rel = 'stylesheet';
$appEmojiFont.href = 'emoji.font.css';
document.head.appendChild($appEmojiFont);
}
}
function trackingResultToClass(deviceStatus) {
switch (deviceStatus) {
case 'Uninitialized':

View File

@@ -1,40 +0,0 @@
body,
input,
textarea,
select,
button {
font-family: 'Noto Sans JP', 'Noto Sans KR', 'Noto Sans TC', 'Noto Sans SC',
'Noto Color Emoji', 'Meiryo UI', 'Malgun Gothic', 'Segoe UI', sans-serif;
}
body {
--md-sys-typescale-headline-medium-font: 'Google Sans', 'Noto Sans',
'Noto Sans TC', 'Noto Sans JP', 'Noto Sans SC', 'Noto Color Emoji',
'Roboto', sans-serif;
--md-sys-typescale-headline-small-font: 'Google Sans', 'Noto Sans',
'Noto Sans TC', 'Noto Sans JP', 'Noto Sans SC', 'Noto Color Emoji',
'Roboto', sans-serif;
--md-sys-typescale-title-medium-font: 'Google Sans', 'Noto Sans',
'Noto Sans TC', 'Noto Sans JP', 'Noto Sans SC', 'Noto Color Emoji',
'Roboto', sans-serif;
--md-sys-typescale-label-large-font: 'Google Sans', 'Noto Sans',
'Noto Sans TC', 'Noto Sans JP', 'Noto Sans SC', 'Noto Color Emoji',
'Roboto', sans-serif;
--md-sys-typescale-label-medium-font: 'Google Sans', 'Noto Sans',
'Noto Sans TC', 'Noto Sans JP', 'Noto Sans SC', 'Noto Color Emoji',
'Roboto', sans-serif;
--md-sys-typescale-body-large-font: 'Google Sans', 'Noto Sans',
'Noto Sans TC', 'Noto Sans JP', 'Noto Sans SC', 'Noto Color Emoji',
'Roboto', sans-serif;
--md-sys-typescale-body-medium-font: 'Google Sans', 'Noto Sans',
'Noto Sans TC', 'Noto Sans JP', 'Noto Sans SC', 'Noto Color Emoji',
'Roboto', sans-serif;
--md-sys-typescale-body-small-font: 'Google Sans', 'Noto Sans',
'Noto Sans TC', 'Noto Sans JP', 'Noto Sans SC', 'Noto Color Emoji',
'Roboto', sans-serif;
}
:root {
--font: 'Poppins', 'Noto Sans JP', 'Noto Sans KR', 'Noto Sans TC',
'Noto Sans SC', 'Noto Color Emoji', sans-serif;
}

1
src/bootstrap.js vendored
View File

@@ -2,7 +2,6 @@ import '@fontsource/noto-sans-kr';
import '@fontsource/noto-sans-jp';
import '@fontsource/noto-sans-sc';
import '@fontsource/noto-sans-tc';
import '@infolektuell/noto-color-emoji';
import Vue from 'vue';
import { PiniaVuePlugin } from 'pinia';

View File

@@ -119,10 +119,7 @@ export const useUpdateLoopStore = defineStore('UpdateLoop', () => {
state.nextAutoStateChange = 3;
userStore.updateAutoStateChange();
}
if (
(vrcxStore.isRunningUnderWine || LINUX) &&
--state.nextGetLogCheck <= 0
) {
if (LINUX && --state.nextGetLogCheck <= 0) {
state.nextGetLogCheck = 0.5;
const logLines = await LogWatcher.GetLogLines();
if (logLines) {
@@ -131,10 +128,7 @@ export const useUpdateLoopStore = defineStore('UpdateLoop', () => {
});
}
}
if (
(vrcxStore.isRunningUnderWine || LINUX) &&
--state.nextGameRunningCheck <= 0
) {
if (LINUX && --state.nextGameRunningCheck <= 0) {
if (WINDOWS) {
state.nextGameRunningCheck = 3;
AppApi.CheckGameRunning();

View File

@@ -203,19 +203,6 @@ export const useVrcxStore = defineStore('Vrcx', () => {
}
});
async function applyWineEmojis() {
if (document.contains(document.getElementById('app-emoji-font'))) {
document.getElementById('app-emoji-font').remove();
}
if (state.isRunningUnderWine) {
const $appEmojiFont = document.createElement('link');
$appEmojiFont.setAttribute('id', 'app-emoji-font');
$appEmojiFont.rel = 'stylesheet';
$appEmojiFont.href = 'emoji.font.css';
document.head.appendChild($appEmojiFont);
}
}
function showConsole() {
AppApi.ShowDevTools();
if (
@@ -771,7 +758,6 @@ export const useVrcxStore = defineStore('Vrcx', () => {
clearVRCXCacheFrequency,
maxTableSize,
showConsole,
applyWineEmojis,
clearVRCXCache,
startupLaunchCommand,
eventVrcxMessage,

View File

@@ -13,14 +13,7 @@ module.exports = (env, argv) => {
const isProduction = argv.mode === 'production';
return {
entry: {
vendor: [
'element-ui',
'noty',
'vue',
'vue-i18n',
'worker-timers',
`${scssBasePath}emoji.font.scss`
],
vendor: ['element-ui', 'noty', 'vue', 'vue-i18n', 'worker-timers'],
app: {
import: ['./src/app.js', './src/app.scss'],
dependOn: 'vendor'