diff --git a/app/main.ts b/app/main.ts index f0c15eba8..d0d197622 100644 --- a/app/main.ts +++ b/app/main.ts @@ -2630,13 +2630,16 @@ ipc.handle('show-save-dialog', async (_event, { defaultPath }) => { return { canceled: false, filePath: finalFilePath }; }); -ipc.handle('getScreenCaptureSources', async () => { - return desktopCapturer.getSources({ - fetchWindowIcons: true, - thumbnailSize: { height: 102, width: 184 }, - types: ['window', 'screen'], - }); -}); +ipc.handle( + 'getScreenCaptureSources', + async (_event, types: Array<'screen' | 'window'> = ['screen', 'window']) => { + return desktopCapturer.getSources({ + fetchWindowIcons: true, + thumbnailSize: { height: 102, width: 184 }, + types, + }); + } +); ipc.handle('executeMenuRole', async ({ sender }, untypedRole) => { const role = untypedRole as MenuItemConstructorOptions['role']; diff --git a/ts/services/calling.ts b/ts/services/calling.ts index e828f3ef9..c316c0676 100644 --- a/ts/services/calling.ts +++ b/ts/services/calling.ts @@ -95,6 +95,7 @@ import { import { callingMessageToProto } from '../util/callingMessageToProto'; import { getSendOptions } from '../util/getSendOptions'; import { requestMicrophonePermissions } from '../util/requestMicrophonePermissions'; +import OS from '../util/os/osMain'; import { SignalService as Proto } from '../protobuf'; import dataInterface from '../sql/Client'; import { @@ -1329,8 +1330,20 @@ export class CallingClass { } async getPresentingSources(): Promise> { + // There's a Linux Wayland Electron bug where requesting desktopCapturer. + // getSources() with types as ['screen', 'window'] (the default) pops 2 + // OS permissions dialogs in an unusable state (Dialog 1 for Share Window + // is the foreground and ignores input; Dialog 2 for Share Screen is background + // and requires input. As a workaround, request both sources sequentially. + // https://github.com/signalapp/Signal-Desktop/issues/5350#issuecomment-1688614149 const sources: ReadonlyArray = - await ipcRenderer.invoke('getScreenCaptureSources'); + OS.isLinux() && OS.isWaylandEnabled() + ? ( + await ipcRenderer.invoke('getScreenCaptureSources', ['screen']) + ).concat( + await ipcRenderer.invoke('getScreenCaptureSources', ['window']) + ) + : await ipcRenderer.invoke('getScreenCaptureSources'); const presentableSources: Array = []; diff --git a/ts/util/os/osMain.ts b/ts/util/os/osMain.ts index e4c1be65f..0612f6176 100644 --- a/ts/util/os/osMain.ts +++ b/ts/util/os/osMain.ts @@ -19,9 +19,14 @@ function getLinuxName(): string | undefined { return match[1]; } +function isWaylandEnabled(): boolean { + return Boolean(process.env.WAYLAND_DISPLAY); +} + const OS = { ...getOSFunctions(os.release()), getLinuxName, + isWaylandEnabled, }; export default OS;