Prevent display sleep while on a call
This commit is contained in:
parent
34fd945f83
commit
0e3d12c457
3 changed files with 152 additions and 0 deletions
40
app/PreventDisplaySleepService.ts
Normal file
40
app/PreventDisplaySleepService.ts
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
// Copyright 2021 Signal Messenger, LLC
|
||||||
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
import type { PowerSaveBlocker } from 'electron';
|
||||||
|
import * as log from '../ts/logging/log';
|
||||||
|
|
||||||
|
export class PreventDisplaySleepService {
|
||||||
|
private blockerId: undefined | number;
|
||||||
|
|
||||||
|
constructor(private powerSaveBlocker: PowerSaveBlocker) {}
|
||||||
|
|
||||||
|
setEnabled(isEnabled: boolean): void {
|
||||||
|
log.info(
|
||||||
|
`Prevent display sleep service: ${
|
||||||
|
isEnabled ? 'preventing' : 'allowing'
|
||||||
|
} display sleep`
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isEnabled) {
|
||||||
|
this.enable();
|
||||||
|
} else {
|
||||||
|
this.disable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private enable(): void {
|
||||||
|
if (this.blockerId !== undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.blockerId = this.powerSaveBlocker.start('prevent-display-sleep');
|
||||||
|
}
|
||||||
|
|
||||||
|
private disable(): void {
|
||||||
|
if (this.blockerId === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.powerSaveBlocker.stop(this.blockerId);
|
||||||
|
delete this.blockerId;
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ import {
|
||||||
dialog,
|
dialog,
|
||||||
ipcMain as ipc,
|
ipcMain as ipc,
|
||||||
Menu,
|
Menu,
|
||||||
|
powerSaveBlocker,
|
||||||
protocol as electronProtocol,
|
protocol as electronProtocol,
|
||||||
screen,
|
screen,
|
||||||
shell,
|
shell,
|
||||||
|
@ -54,6 +55,7 @@ import * as attachments from './attachments';
|
||||||
import * as attachmentChannel from './attachment_channel';
|
import * as attachmentChannel from './attachment_channel';
|
||||||
import * as bounce from '../ts/services/bounce';
|
import * as bounce from '../ts/services/bounce';
|
||||||
import * as updater from '../ts/updater/index';
|
import * as updater from '../ts/updater/index';
|
||||||
|
import { PreventDisplaySleepService } from './PreventDisplaySleepService';
|
||||||
import { SystemTrayService } from './SystemTrayService';
|
import { SystemTrayService } from './SystemTrayService';
|
||||||
import { SystemTraySettingCache } from './SystemTraySettingCache';
|
import { SystemTraySettingCache } from './SystemTraySettingCache';
|
||||||
import {
|
import {
|
||||||
|
@ -120,6 +122,10 @@ const enableCI = config.get<boolean>('enableCI');
|
||||||
const sql = new MainSQL();
|
const sql = new MainSQL();
|
||||||
const heicConverter = getHeicConverter();
|
const heicConverter = getHeicConverter();
|
||||||
|
|
||||||
|
const preventDisplaySleepService = new PreventDisplaySleepService(
|
||||||
|
powerSaveBlocker
|
||||||
|
);
|
||||||
|
|
||||||
let systemTrayService: SystemTrayService | undefined;
|
let systemTrayService: SystemTrayService | undefined;
|
||||||
const systemTraySettingCache = new SystemTraySettingCache(
|
const systemTraySettingCache = new SystemTraySettingCache(
|
||||||
sql,
|
sql,
|
||||||
|
@ -761,6 +767,8 @@ ipc.on('title-bar-double-click', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
ipc.on('set-is-call-active', (_event, isCallActive) => {
|
ipc.on('set-is-call-active', (_event, isCallActive) => {
|
||||||
|
preventDisplaySleepService.setEnabled(isCallActive);
|
||||||
|
|
||||||
if (!mainWindow) {
|
if (!mainWindow) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
104
ts/test-node/app/PreventDisplaySleepService_test.ts
Normal file
104
ts/test-node/app/PreventDisplaySleepService_test.ts
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
// Copyright 2021 Signal Messenger, LLC
|
||||||
|
// SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
|
import { assert } from 'chai';
|
||||||
|
import * as sinon from 'sinon';
|
||||||
|
import type { PowerSaveBlocker } from 'electron';
|
||||||
|
|
||||||
|
import { PreventDisplaySleepService } from '../../../app/PreventDisplaySleepService';
|
||||||
|
|
||||||
|
describe('PreventDisplaySleepService', () => {
|
||||||
|
class FakePowerSaveBlocker implements PowerSaveBlocker {
|
||||||
|
private nextId = 0;
|
||||||
|
private idsStarted = new Set<number>();
|
||||||
|
|
||||||
|
isStarted(id: number): boolean {
|
||||||
|
return this.idsStarted.has(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
start(type: 'prevent-app-suspension' | 'prevent-display-sleep'): number {
|
||||||
|
assert.strictEqual(type, 'prevent-display-sleep');
|
||||||
|
|
||||||
|
const result = this.nextId;
|
||||||
|
this.nextId += 1;
|
||||||
|
this.idsStarted.add(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
stop(id: number): void {
|
||||||
|
assert(this.idsStarted.has(id), `${id} was never started`);
|
||||||
|
this.idsStarted.delete(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is only for testing.
|
||||||
|
_idCount(): number {
|
||||||
|
return this.idsStarted.size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let sandbox: sinon.SinonSandbox;
|
||||||
|
let powerSaveBlocker: FakePowerSaveBlocker;
|
||||||
|
let service: PreventDisplaySleepService;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
sandbox = sinon.createSandbox();
|
||||||
|
powerSaveBlocker = new FakePowerSaveBlocker();
|
||||||
|
service = new PreventDisplaySleepService(powerSaveBlocker);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
sandbox.restore();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does nothing if disabling when it was already disabled', () => {
|
||||||
|
const startStub = sandbox.stub(powerSaveBlocker, 'start');
|
||||||
|
const stopStub = sandbox.stub(powerSaveBlocker, 'stop');
|
||||||
|
|
||||||
|
service.setEnabled(false);
|
||||||
|
|
||||||
|
assert.strictEqual(powerSaveBlocker._idCount(), 0);
|
||||||
|
sinon.assert.notCalled(startStub);
|
||||||
|
sinon.assert.notCalled(stopStub);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can start power blocking', () => {
|
||||||
|
service.setEnabled(true);
|
||||||
|
|
||||||
|
assert.strictEqual(powerSaveBlocker._idCount(), 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('only starts power blocking once', () => {
|
||||||
|
service.setEnabled(true);
|
||||||
|
service.setEnabled(true);
|
||||||
|
service.setEnabled(true);
|
||||||
|
|
||||||
|
assert.strictEqual(powerSaveBlocker._idCount(), 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can start and stop power blocking', () => {
|
||||||
|
const startSpy = sandbox.spy(powerSaveBlocker, 'start');
|
||||||
|
const stopStub = sandbox.spy(powerSaveBlocker, 'stop');
|
||||||
|
|
||||||
|
service.setEnabled(true);
|
||||||
|
service.setEnabled(false);
|
||||||
|
|
||||||
|
assert.strictEqual(powerSaveBlocker._idCount(), 0);
|
||||||
|
sinon.assert.calledOnce(startSpy);
|
||||||
|
sinon.assert.calledOnce(stopStub);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can toggle power blocking several times', () => {
|
||||||
|
const startSpy = sandbox.spy(powerSaveBlocker, 'start');
|
||||||
|
const stopStub = sandbox.spy(powerSaveBlocker, 'stop');
|
||||||
|
|
||||||
|
service.setEnabled(true);
|
||||||
|
service.setEnabled(false);
|
||||||
|
service.setEnabled(true);
|
||||||
|
service.setEnabled(false);
|
||||||
|
service.setEnabled(true);
|
||||||
|
|
||||||
|
assert.strictEqual(powerSaveBlocker._idCount(), 1);
|
||||||
|
sinon.assert.calledThrice(startSpy);
|
||||||
|
sinon.assert.calledTwice(stopStub);
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in a new issue