aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2022-05-04 21:50:32 +0200
committerLibravatar Kristóf Marussy <kristof@marussy.com>2022-05-16 00:55:03 +0200
commitefc32118b6b079462255890a7cb7c2e09ae9d473 (patch)
tree7bf13f27316c5db78fc6ea38e9a550f9a97452e4
parentbuild: integration testing support (diff)
downloadsophie-efc32118b6b079462255890a7cb7c2e09ae9d473.tar.gz
sophie-efc32118b6b079462255890a7cb7c2e09ae9d473.tar.zst
sophie-efc32118b6b079462255890a7cb7c2e09ae9d473.zip
feat: use wayland when available
Auto-detect wayland in the yarn watch script. We use a shell script wrapper to launch sophie with wayland-specific arguments whenever appropriate. Because of this, the electron binary that ships with sophie has been renamed to sophie-bin. Signed-off-by: Kristóf Marussy <kristof@marussy.com>
-rw-r--r--.electron-builder.config.cjs98
-rw-r--r--build-helpers/detect_wayland.sh16
-rw-r--r--package.json2
-rw-r--r--scripts/watch.js26
4 files changed, 114 insertions, 28 deletions
diff --git a/.electron-builder.config.cjs b/.electron-builder.config.cjs
index efd9ef7..3eef91c 100644
--- a/.electron-builder.config.cjs
+++ b/.electron-builder.config.cjs
@@ -1,29 +1,8 @@
1const { readFile, rename, writeFile } = require('node:fs/promises');
2const path = require('node:path');
3
1const { Arch } = require('electron-builder'); 4const { Arch } = require('electron-builder');
2const { flipFuses, FuseV1Options, FuseVersion } = require('@electron/fuses'); 5const { flipFuses, FuseV1Options, FuseVersion } = require('@electron/fuses');
3const { join } = require('path');
4
5/**
6 * @type {import('electron-builder').Configuration}
7 * @see https://www.electron.build/configuration/configuration
8 */
9const config = {
10 directories: {
11 output: 'dist',
12 buildResources: 'buildResources',
13 },
14 files: [
15 'packages/main/dist/**',
16 'packages/preload/dist/**',
17 'packages/renderer/dist/**',
18 'packages/service-preload/dist/**',
19 'locales/**',
20 // Do not ship with source maps.
21 '!**/*.map',
22 ],
23 afterPack(context) {
24 return burnFuses(context);
25 },
26};
27 6
28/** 7/**
29 * Hardens the shipped electron binary by burning some electron fuses. 8 * Hardens the shipped electron binary by burning some electron fuses.
@@ -46,7 +25,7 @@ async function burnFuses(context) {
46 darwin: '.app', 25 darwin: '.app',
47 win32: '.exe', 26 win32: '.exe',
48 }[context.electronPlatformName] || ''; 27 }[context.electronPlatformName] || '';
49 const electronBinaryPath = join( 28 const electronBinaryPath = path.join(
50 context.appOutDir, 29 context.appOutDir,
51 `${context.packager.appInfo.productFilename}${ext}`, 30 `${context.packager.appInfo.productFilename}${ext}`,
52 ); 31 );
@@ -66,4 +45,73 @@ async function burnFuses(context) {
66 return flipFuses(electronBinaryPath, fuseConfig); 45 return flipFuses(electronBinaryPath, fuseConfig);
67} 46}
68 47
48/**
49 * Adds a wrapper scripts that detects in wayland is in use and enabled it in chromium.
50 *
51 * The script in `build-heleprs/detect_wayland.sh` uses the `WAYLAND_DISPLAY` environmental
52 * variable to detect whether wayland is in use.
53 *
54 * If wayland is in use, the script enables the wayland ozone backed for chromium
55 * and pipewire screen sharing. Otherwise, the x11 ozone backend will be used.
56 *
57 * @param {import('electron-builder').AfterPackContext} context The `electron-builder` context.
58 * @return {Promise<void>} The promise to add the wrapper script.
59 * @see https://stackoverflow.com/a/45537237
60 */
61async function enableWaylandAutoDetection(context) {
62 const { appOutDir, packager: { appInfo: { productName, productFilename } } } = context;
63 const electronBinaryPath = path.join(appOutDir, productFilename);
64 const newFilename = `${productFilename}-bin`;
65 const newElectronBinaryPath = path.join(appOutDir, newFilename);
66 await rename(electronBinaryPath, newElectronBinaryPath);
67 const wrapperScriptPath = path.join(__dirname, 'build-helpers/detect_wayland.sh');
68 const wrapperScriptTempate = await readFile(wrapperScriptPath, 'utf8');
69 const replacements = new Map([
70 ['PRODUCT_NAME', productName],
71 ['REAL_BINARY_NAME', newFilename],
72 ]);
73 const wrapperScript = wrapperScriptTempate.replaceAll(
74 /\{\{([^}]+)\}\}/g,
75 (_match, /** @type {string} */ variable) => {
76 const replacement = replacements.get(variable);
77 if (replacement === undefined) {
78 throw new Error(`Unknown variable: ${variable}`);
79 }
80 return replacement;
81 },
82 );
83 await writeFile(electronBinaryPath, wrapperScript, {
84 encoding: 'utf8',
85 mode: 0o755,
86 });
87}
88
89/**
90 * @type {import('electron-builder').Configuration}
91 * @see https://www.electron.build/configuration/configuration
92 */
93const config = {
94 directories: {
95 output: 'dist',
96 buildResources: 'buildResources',
97 },
98 files: [
99 'packages/main/dist/**',
100 'packages/preload/dist/**',
101 'packages/renderer/dist/**',
102 'packages/service-preload/dist/**',
103 'locales/**',
104 // Do not ship with source maps.
105 '!**/*.map',
106 ],
107 afterPack(context) {
108 return burnFuses(context);
109 },
110 async afterSign(context) {
111 if (context.electronPlatformName === 'linux') {
112 await enableWaylandAutoDetection(context);
113 }
114 }
115};
116
69module.exports = config; 117module.exports = config;
diff --git a/build-helpers/detect_wayland.sh b/build-helpers/detect_wayland.sh
new file mode 100644
index 0000000..e82a383
--- /dev/null
+++ b/build-helpers/detect_wayland.sh
@@ -0,0 +1,16 @@
1#!/usr/bin/env sh
2if [ ! -L "$0" ]; then
3 electron_dir="$(dirname "$0")"
4else
5 if command -v readlink >/dev/null; then
6 electron_dir="$(dirname "$(readlink -f "$0")")"
7 else
8 electron_dir="/opt/{{PRODUCT_NAME}}"
9 fi
10fi
11electron_path="${electron_dir}/{{REAL_BINARY_NAME}}"
12if [ -n "${WAYLAND_DISPLAY+1}" ]; then
13 exec "${electron_path}" --enable-features=WaylandWindowDecorations,WebRTCPipeWireCapturer --ozone-platform=wayland "$@"
14else
15 exec "${electron_path}" --ozone-platform=x11 "$@"
16fi
diff --git a/package.json b/package.json
index 2e60130..9c864cc 100644
--- a/package.json
+++ b/package.json
@@ -23,7 +23,7 @@
23 "test": "node --experimental-vm-modules --no-warnings $(yarn bin jest)", 23 "test": "node --experimental-vm-modules --no-warnings $(yarn bin jest)",
24 "test:ci": "yarn test --ci --coverage --reporters=default --reporters=jest-junit", 24 "test:ci": "yarn test --ci --coverage --reporters=default --reporters=jest-junit",
25 "test:integ": "electron scripts/electronJest.cjs --user-data-dir=userDataDir/integ --config=jest.integ.config.cjs --runInBand", 25 "test:integ": "electron scripts/electronJest.cjs --user-data-dir=userDataDir/integ --config=jest.integ.config.cjs --runInBand",
26 "test:integ:xvfb": "cross-env DISABLE_GPU=true xvfb-run -s \"-screen 0 1920x1080x24\" electron scripts/electronJest.cjs --user-data-dir=userDataDir/integ --config=jest.integ.config.cjs --runInBand", 26 "test:integ:xvfb": "cross-env DISABLE_GPU=true xvfb-run -s \"-screen 0 1920x1080x24\" electron scripts/electronJest.cjs --user-data-dir=userDataDir/integ --disable-features=WebRTCPipeWireCapturer --ozone-platform=x11 --config=jest.integ.config.cjs --runInBand",
27 "test:integ:ci": "cross-env DISABLE_GPU=true yarn test:integ --ci --coverage --reporters=default --reporters=jest-junit", 27 "test:integ:ci": "cross-env DISABLE_GPU=true yarn test:integ --ci --coverage --reporters=default --reporters=jest-junit",
28 "test:integ:xvfb:ci": "yarn test:integ:xvfb --ci --coverage --reporters=default --reporters=jest-junit", 28 "test:integ:xvfb:ci": "yarn test:integ:xvfb --ci --coverage --reporters=default --reporters=jest-junit",
29 "build": "node scripts/build.js", 29 "build": "node scripts/build.js",
diff --git a/scripts/watch.js b/scripts/watch.js
index eeee6e4..5db0d30 100644
--- a/scripts/watch.js
+++ b/scripts/watch.js
@@ -1,4 +1,5 @@
1import { spawn } from 'node:child_process'; 1import { spawn } from 'node:child_process';
2import os from 'node:os';
2import path from 'node:path'; 3import path from 'node:path';
3 4
4import { watch } from 'chokidar'; 5import { watch } from 'chokidar';
@@ -31,7 +32,7 @@ const userDataDir = path.join(thisDir, '../userDataDir/development');
31 32
32/** @type {RegExp[]} */ 33/** @type {RegExp[]} */
33const stderrIgnorePatterns = [ 34const stderrIgnorePatterns = [
34 // warning about devtools extension 35 // Warning about devtools extension
35 // https://github.com/cawa-93/vite-electron-builder/issues/492 36 // https://github.com/cawa-93/vite-electron-builder/issues/492
36 // https://github.com/MarshallOfSound/electron-devtools-installer/issues/143 37 // https://github.com/MarshallOfSound/electron-devtools-installer/issues/143
37 /ExtensionLoadWarning/, 38 /ExtensionLoadWarning/,
@@ -44,6 +45,8 @@ const stderrIgnorePatterns = [
44 // Does not seem to occur in production 45 // Does not seem to occur in production
45 // https://github.com/electron/electron/issues/32133#issuecomment-1079916988 46 // https://github.com/electron/electron/issues/32133#issuecomment-1079916988
46 /(sandbox_bundle\.js script failed to run|object null is not iterable).+ node:electron\/js2c\/sandbox_bundle \(160\)$/, 47 /(sandbox_bundle\.js script failed to run|object null is not iterable).+ node:electron\/js2c\/sandbox_bundle \(160\)$/,
48 // Warning when GPU-accelerated video decoding is not available (some wayland configs)
49 /Passthrough is not supported, GL is/,
47]; 50];
48 51
49/** 52/**
@@ -134,6 +137,20 @@ function setupMainPackageWatcher(viteDevServer) {
134 const portOrDefault = port || 3000; 137 const portOrDefault = port || 3000;
135 process.env.VITE_DEV_SERVER_URL = `${protocol}//${hostOrDefault}:${portOrDefault}/`; 138 process.env.VITE_DEV_SERVER_URL = `${protocol}//${hostOrDefault}:${portOrDefault}/`;
136 139
140 /** @type {string[]} */
141 let extraArgs = [];
142
143 if (['aix', 'freebsd', 'linux', 'openbsd', 'sunos'].includes(os.platform())) {
144 // Use wayland display server if available.
145 extraArgs =
146 'WAYLAND_DISPLAY' in process.env
147 ? [
148 '--enable-features=WaylandWindowDecorations,WebRTCPipeWireCapturer',
149 '--ozone-platform=wayland',
150 ]
151 : ['--ozone-platform=x11'];
152 }
153
137 /** @type {import('child_process').ChildProcessByStdio<null, null, import('stream').Readable> 154 /** @type {import('child_process').ChildProcessByStdio<null, null, import('stream').Readable>
138 | undefined} */ 155 | undefined} */
139 let childProcess; 156 let childProcess;
@@ -144,7 +161,12 @@ function setupMainPackageWatcher(viteDevServer) {
144 function spawnProcess() { 161 function spawnProcess() {
145 childProcess = spawn( 162 childProcess = spawn(
146 String(electronPath), 163 String(electronPath),
147 ['.', `--user-data-dir=${userDataDir}`, ...process.argv.slice(2)], 164 [
165 '.',
166 `--user-data-dir=${userDataDir}`,
167 ...extraArgs,
168 ...process.argv.slice(2),
169 ],
148 { 170 {
149 stdio: ['inherit', 'inherit', 'pipe'], 171 stdio: ['inherit', 'inherit', 'pipe'],
150 }, 172 },