Merge branch 'async_requests'

This commit is contained in:
wheaney 2024-07-24 11:21:54 -07:00
commit 4c3f70eb17
2 changed files with 60 additions and 14 deletions

View File

@ -86,9 +86,18 @@ function getMonitorConfig(displayConfigProxy, callback) {
}
// triggers callback with true result if an an async monitor config change was triggered, false if no config change needed
function performOptimalModeCheck(displayConfigProxy, connectorName, headsetAsPrimary, useHighestRefreshRate, callback) {
function performOptimalModeCheck(displayConfigProxy, connectorName, headsetAsPrimary, useHighestRefreshRate,
callback, allowConfigUpdateFn) {
Globals.logger.log_debug(`monitormanager.js performOptimalModeCheck for ${connectorName}`);
displayConfigProxy.GetCurrentStateRemote((result, error) => {
if (!allowConfigUpdateFn()) {
// other requests are in progress, this monitor state may be stale, do nothing
Globals.logger.log_debug('MonitorManager performOptimalModeCheck: allowConfigUpdate is false');
callback(false, null);
return;
}
if (error) {
callback(null, `GetCurrentState failed: ${error}`);
} else {
@ -240,6 +249,10 @@ export const MonitorManager = GObject.registerClass({
this._monitorProperties = null;
this._changeHookFn = null;
this._needsConfigCheck = this.use_optimal_monitor_config;
// help prevent certain actions from taking place multiple times in the event of rapid monitor updates
this._asyncRequestsInFlight = 0;
this._configCheckRequestsCount = 0;
}
enable() {
@ -279,36 +292,59 @@ export const MonitorManager = GObject.registerClass({
return this._monitorProperties;
}
// returns true if a check is needed, caller should wait for the next change hook call
// returns true if an async check is needed, caller should wait for the next change hook call
needsOptimalModeCheck(monitorConnector) {
Globals.logger.log_debug(`MonitorManager checkOptimalMode: ${monitorConnector}`);
Globals.logger.log_debug(`MonitorManager needsOptimalModeCheck: ${monitorConnector}`);
if (this._displayConfigProxy == null) {
Globals.logger.log('MonitorManager checkOptimalMode: _displayConfigProxy not set!');
Globals.logger.log('MonitorManager needsOptimalModeCheck: _displayConfigProxy not set!');
return false;
}
if (this._needsConfigCheck) {
const isCheckingConfig = this._needsConfigCheck;
if (this._needsConfigCheck && this._asyncRequestsInFlight === 0) {
this._asyncRequestsInFlight++;
const configCheckCountSnapshot = this._configCheckRequestsCount;
const allowConfigUpdateFn = (() => {
// allow updates to the config if this is the only in-flight request and no more requests
// were made while we were waiting for the previous request to complete
return this._asyncRequestsInFlight === 1 && this._configCheckRequestsCount === configCheckCountSnapshot;
}).bind(this);
performOptimalModeCheck(this._displayConfigProxy, monitorConnector, this.headset_as_primary, this.use_highest_refresh_rate, ((configChanged, error) => {
this._needsConfigCheck = false;
if (--this._asyncRequestsInFlight > 0) {
Globals.logger.log_debug(`MonitorManager needsOptimalModeCheck: ${this._asyncRequestsInFlight} async requests still pending, skipping change hook`);
return;
} else if (this._configCheckRequestsCount !== configCheckCountSnapshot) {
Globals.logger.log_debug('MonitorManager needsOptimalModeCheck: config checks requested while in-flight, skipping change hook');
return;
}
if (error) {
Globals.logger.log(`Failed to switch to optimal mode for monitor ${monitorConnector}: ${error}`);
// tell the extension to proceed, this should result in another config check
this._changeHookFn();
} else {
this._needsConfigCheck = false;
if (configChanged) {
Globals.logger.log(`Switched to optimal mode for monitor ${monitorConnector}`);
} else if (!!this._changeHookFn) {
Globals.logger.log_debug('MonitorManager checkOptimalMode: no config change');
Globals.logger.log_debug('MonitorManager needsOptimalModeCheck: no config change');
// no config change means this won't be triggered automatically, so trigger it manually
this._changeHookFn();
} else {
Globals.logger.log('MonitorManager checkOptimalMode: can\'t trigger change hook, no hook set!');
Globals.logger.log('MonitorManager needsOptimalModeCheck: can\'t trigger change hook, no hook set!');
}
}
}).bind(this));
}).bind(this), allowConfigUpdateFn);
} else if (!this._needsConfigCheck) {
Globals.logger.log_debug('MonitorManager needsOptimalModeCheck: skipping config check');
} else {
Globals.logger.log_debug('MonitorManager checkOptimalMode: skipping config check');
Globals.logger.log_debug(`MonitorManager needsOptimalModeCheck: skipping due to async requests ${this._asyncRequestsInFlight}`);
}
return this._needsConfigCheck;
return isCheckingConfig;
}
_on_monitors_change() {
@ -316,11 +352,17 @@ export const MonitorManager = GObject.registerClass({
if (this._displayConfigProxy == null) {
return;
}
this._needsConfigCheck = this.use_optimal_monitor_config;
if (this.use_optimal_monitor_config) {
this._needsConfigCheck = true;
this._configCheckRequestsCount++;
}
this._asyncRequestsInFlight++;
getMonitorConfig(this._displayConfigProxy, ((result, error) => {
if (error) {
Globals.logger.log(error);
return;
}
const monitorProperties = [];
for (let i = 0; i < result.length; i++) {
const [monitorName, connectorName, vendor, product, serial, refreshRate] = result[i];
@ -340,7 +382,11 @@ export const MonitorManager = GObject.registerClass({
}
this._monitorProperties = monitorProperties;
if (!!this._changeHookFn) {
this._changeHookFn();
if (--this._asyncRequestsInFlight === 0) {
this._changeHookFn();
} else {
Globals.logger.log_debug(`MonitorManager _on_monitors_change: ${this._asyncRequestsInFlight} requests still pending, skipping change hook`);
}
} else {
Globals.logger.log('MonitorManager _on_monitors_change: can\'t trigger change hook, no hook set!');
}

@ -1 +1 @@
Subproject commit 95c2fbfae235d7637b10f24c1f75bcc7d1de8142
Subproject commit b0080ca844e057d31aae0e70aa6d026059ea304f