feat: improve wayland compatability

This commit is contained in:
Johannes Millan 2025-06-19 15:05:47 +02:00
parent 5dafeabee1
commit 0848f6015d
5 changed files with 69 additions and 1 deletions

View file

@ -464,3 +464,19 @@ You can specify a custom folder for saving your data by starting the application
```bash
superproductivity --user-data-dir=/path/to/my/data
```
### Linux/Wayland Compatibility
If you're experiencing issues running Super Productivity on Wayland (such as rendering problems, VSync errors, or GLib-GObject warnings), you can force the application to use X11 mode by starting it with the `--force-x11` parameter:
```bash
superproductivity --force-x11
```
This will automatically apply compatibility fixes including:
- Forcing the Ozone platform to use X11 instead of Wayland
- Disabling GPU VSync to prevent GetVSyncParametersIfAvailable() errors
- Setting the appropriate environment variables for X11 compatibility
The application will automatically detect Wayland sessions and apply these fixes, but you can use this flag if automatic detection doesn't work properly.

View file

@ -86,8 +86,13 @@ export const createWindow = ({
nodeIntegration: false,
// make remote module work with those two settings
contextIsolation: true,
// Additional settings for better Linux/Wayland compatibility
enableBlinkFeatures: 'OverlayScrollbar',
},
icon: ICONS_FOLDER + '/icon_256x256.png',
// Wayland compatibility: disable transparent/frameless features that can cause issues
transparent: false,
frame: true,
});
// see: https://pratikpc.medium.com/bypassing-cors-with-electron-ab7eaf331605

View file

@ -32,6 +32,7 @@ let customUrl: string;
let isDisableTray = false;
let forceDarkTray = false;
let wasUserDataDirSet = false;
let forceX11 = false;
if (IS_DEV) {
log('Starting in DEV Mode!!!');
@ -59,6 +60,31 @@ export const startApp = (): void => {
// https://github.com/electron/electron/issues/46538#issuecomment-2808806722
app.commandLine.appendSwitch('gtk-version', '3');
// Wayland compatibility fixes
// Force X11 backend on Wayland to avoid rendering issues
if (process.platform === 'linux') {
// Check if running on Wayland or if X11 is forced
const isWayland =
process.env.WAYLAND_DISPLAY || process.env.XDG_SESSION_TYPE === 'wayland';
if (isWayland || forceX11) {
log('Applying X11/Wayland compatibility fixes');
// Force Ozone platform to X11
app.commandLine.appendSwitch('ozone-platform', 'x11');
// Disable GPU vsync to fix GetVSyncParametersIfAvailable() errors
app.commandLine.appendSwitch('disable-gpu-vsync');
// Additional flags to improve compatibility
app.commandLine.appendSwitch('disable-features', 'UseOzonePlatform');
app.commandLine.appendSwitch('enable-features', 'UseSkiaRenderer');
// Set GDK backend to X11
process.env.GDK_BACKEND = 'x11';
}
}
// NOTE: needs to be executed before everything else
process.argv.forEach((val) => {
if (val && val.includes('--disable-tray')) {
@ -86,6 +112,11 @@ export const startApp = (): void => {
if (val && val.includes('--dev-tools')) {
isShowDevTools = true;
}
if (val && val.includes('--force-x11')) {
forceX11 = true;
log('Forcing X11 mode');
}
});
// TODO remove at one point in the future and only leave the directory setting part

View file

@ -196,6 +196,10 @@ export class SyncWrapperService {
} else if (error instanceof CanNotMigrateMajorDownError) {
alert(this._translateService.instant(T.F.SYNC.A.REMOTE_MODEL_VERSION_NEWER));
return 'HANDLED_ERROR';
} else if (error?.message === 'Sync already in progress') {
// Silently ignore concurrent sync attempts
console.log('Sync already in progress, skipping concurrent sync attempt');
return 'HANDLED_ERROR';
} else {
const errStr = getSyncErrorStr(error);
this._snackService.open({

View file

@ -51,6 +51,8 @@ export class Pfapi<const MD extends ModelCfgs> {
isEncrypt: false,
});
private _isSyncInProgress = false;
public readonly wasDataMigratedInitiallyPromise: Promise<void>;
public readonly tmpBackupService: TmpBackupService<AllSyncModels<MD>>;
@ -131,6 +133,15 @@ export class Pfapi<const MD extends ModelCfgs> {
}
private async _wrapSyncAction<T>(logPrefix: string, fn: () => Promise<T>): Promise<T> {
// Check if sync is already in progress
if (this._isSyncInProgress) {
pfLog(2, `${logPrefix} SKIPPED - sync already in progress`);
throw new Error('Sync already in progress');
}
// Set sync in progress flag
this._isSyncInProgress = true;
// Lock the database during sync to prevent concurrent modifications
this.db.lock();
@ -149,8 +160,9 @@ export class Pfapi<const MD extends ModelCfgs> {
this.ev.emit('syncStatusChange', 'ERROR');
throw e;
} finally {
// Always unlock the database, even on error
// Always unlock the database and clear sync flag, even on error
this.db.unlock();
this._isSyncInProgress = false;
}
}