Update optimal config logic to shift other monitors that would be affected by a change in screen resolution

This commit is contained in:
wheaney 2024-07-29 13:49:39 -07:00
parent 0238cd7790
commit 1b14468d86
2 changed files with 61 additions and 12 deletions

View File

@ -101,8 +101,7 @@ export default class BreezyDesktopExtension extends Extension {
return GLib.SOURCE_REMOVE;
}
const is_driver_running = this._check_driver_running();
if (is_driver_running && target_monitor) {
if (this._check_driver_running() && target_monitor) {
// Don't enable the effect yet if monitor updates are needed.
// _setup will be triggered again since a !ready result means it will trigger monitor changes,
// so we can remove this timeout_add no matter what.
@ -221,7 +220,7 @@ export default class BreezyDesktopExtension extends Extension {
_needs_widescreen_monitor_update() {
Globals.logger.log_debug('BreezyDesktopExtension _needs_widescreen_monitor_update');
const state = this._read_state(['sbs_mode_enabled']);
const state = this._read_state();
const sbs_enabled = state['sbs_mode_enabled'] === 'true';
const widescreen_setting_enabled = this.settings.get_boolean('widescreen-mode');
if (widescreen_setting_enabled !== sbs_enabled) {
@ -249,6 +248,8 @@ export default class BreezyDesktopExtension extends Extension {
this._overlay.opacity = 255;
this._overlay.set_position(targetMonitor.x, targetMonitor.y);
this._overlay.set_size(targetMonitor.width, targetMonitor.height);
Globals.logger.log_debug(`BreezyDesktopExtension _effect_enable overlay size: \
${targetMonitor.width}x${targetMonitor.height} at ${targetMonitor.x},${targetMonitor.y}`);
const overlayContent = new Clutter.Actor({clip_to_allocation: true});
const uiClone = new Clutter.Clone({ source: Main.layoutManager.uiGroup, clip_to_allocation: true });
@ -349,7 +350,7 @@ export default class BreezyDesktopExtension extends Extension {
}
}
_read_state(keys) {
_read_state() {
const state = {};
try {
const file = Gio.file_new_for_path('/dev/shm/xr_driver_state');
@ -364,7 +365,7 @@ export default class BreezyDesktopExtension extends Extension {
const lines = contents.split('\n');
for (const line of lines) {
const [k, v] = line.split('=');
if (keys.includes(k)) state[k] = v;
state[k] = v;
}
}
}
@ -388,10 +389,25 @@ export default class BreezyDesktopExtension extends Extension {
// requests sbs_mode change and monitors to ensure the state reflects the setting
_request_sbs_mode_change(value) {
Globals.logger.log_debug(`BreezyDesktopExtension _request_sbs_mode_change ${value}`);
this._write_control('sbs_mode', value ? 'enable' : 'disable');
if (!this._sbs_mode_update_timeout) {
var attempts = 0;
this._sbs_mode_update_timeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 3000, (() => {
const state = this._read_state();
const sbs_enabled = state['sbs_mode_enabled'] === 'true';
if (sbs_enabled === value) {
Globals.logger.log_debug('BreezyDesktopExtension _request_sbs_mode_change - successfully updated');
this._sbs_mode_update_timeout = undefined;
if (this.settings.get_boolean('fast-sbs-mode-switching')) {
// setup and polling were halted if this is enabled, so we have to re-trigger setup
this._setup();
}
return GLib.SOURCE_REMOVE;
}
if (attempts++ < 3) {
this._write_control('sbs_mode', value ? 'enable' : 'disable');
return GLib.SOURCE_CONTINUE;

View File

@ -107,7 +107,7 @@ function performOptimalModeCheck(displayConfigProxy, connectorName, headsetAsPri
// iterate over all monitors at least once, collecting the best fit mode for our monitor, and mode information
// for each monitor
let ourMonitor = undefined;
let monitorToModeIdMap = {};
let monitorToCurrentModeMap = {};
let bestFitMode = undefined;
const skipScaleUpdate = !!properties['global-scale-required'];
for (let monitor of monitors) {
@ -128,7 +128,7 @@ function performOptimalModeCheck(displayConfigProxy, connectorName, headsetAsPri
for (let mode of modes) {
const [modeId, width, height, refreshRate, preferredScale, supportedScales, modeProperites] = mode;
const isCurrent = !!modeProperites['is-current'];
if (isCurrent) monitorToModeIdMap[connector] = modeId;
if (isCurrent) monitorToCurrentModeMap[connector] = mode;
if (isOurMonitor && (!bestFitMode || (
width >= bestFitMode.width &&
@ -144,8 +144,7 @@ function performOptimalModeCheck(displayConfigProxy, connectorName, headsetAsPri
width,
height,
refreshRate,
bestScale,
isCurrent
bestScale
};
}
}
@ -154,6 +153,14 @@ function performOptimalModeCheck(displayConfigProxy, connectorName, headsetAsPri
if (!!ourMonitor) {
let anyMonitorsChanged = false;
if (!!bestFitMode) {
// this will hold how much the width of the monitor has changed,
// and what range of y values is affected
let deltaX = 0;
let rangeY = [0, 0];
// sort logicalMonitors by x ascending, so we can tell if any are affected by a width change
logicalMonitors.sort((a, b) => a[0] - b[0]);
// map from original logical monitors schema to a(iiduba(ssa{sv})) for ApplyMonitorsConfig call
const updatedLogicalMonitors = logicalMonitors.map((logicalMonitor) => {
const [x, y, scale, transform, primary, monitors, logMonProperties] = logicalMonitor;
@ -164,8 +171,29 @@ function performOptimalModeCheck(displayConfigProxy, connectorName, headsetAsPri
// there can only be one primary monitor, so we need to set all other monitors to not primary and glasses to primary,
// if headsetAsPrimary is true
anyMonitorsChanged |= headsetAsPrimary && ((hasOurMonitor && !primary) || (!hasOurMonitor && primary));
// we need to figure out if the deltaX applies to this logical monitor,
// i.e. if it is within the same row as our monitor and to the right of it
let thisDeltaX = deltaX;
if (thisDeltaX !== 0) {
// find the monitor with the largest height
const maxMonitorHeight = monitors.reduce((maxHeight, monitor) => {
const monitorConnector = monitor[0];
const currentMode = monitorToCurrentModeMap[monitorConnector];
const currentHeight = currentMode[2];
return Math.max(maxHeight, currentHeight);
}, 0);
if (y >= rangeY[1] || y + maxMonitorHeight <= rangeY[0]) {
// monitors outside the y range are not affected by the width change
thisDeltaX = 0;
} else {
anyMonitorsChanged = true;
}
}
return [
x,
x + thisDeltaX,
y,
newScale,
transform,
@ -173,10 +201,15 @@ function performOptimalModeCheck(displayConfigProxy, connectorName, headsetAsPri
monitors.map((monitor) => {
const monitorConnector = monitor[0];
const isOurMonitor = monitorConnector === connectorName;
anyMonitorsChanged |= isOurMonitor && !bestFitMode.isCurrent;
const [currentModeId, currentWidth, currentHeight] = monitorToCurrentModeMap[monitorConnector];
if (isOurMonitor) {
deltaX = bestFitMode.width - currentWidth;
rangeY = [y, y + currentHeight];
}
anyMonitorsChanged |= isOurMonitor && bestFitMode.modeId !== currentModeId;
return [
monitorConnector,
isOurMonitor ? bestFitMode.modeId : monitorToModeIdMap[monitorConnector],
isOurMonitor ? bestFitMode.modeId : currentModeId,
{} // properties
];
})