Fix monitor spacing and layout issues, issue where cursor occasionally appears underneath menus

This commit is contained in:
wheaney 2025-02-13 13:11:08 -08:00
parent 44feff832c
commit 6b5c0dc307
4 changed files with 84 additions and 66 deletions

View File

@ -44,10 +44,6 @@ export class CursorManager {
this._stopCloningMouse();
}
moveAboveSiblings() {
if (this._cursorRoot) this._mainActor.set_child_above_sibling(this._cursorRoot, null);
}
// After this:
// * real cursor is disabled
// * cloning is "on"
@ -179,6 +175,9 @@ export class CursorManager {
return;
if (inBounds) {
if (this._cursorRoot && this._mainActor.get_last_child() !== this._cursorRoot)
this._mainActor.set_child_above_sibling(this._cursorRoot, null);
if (this._systemCursorShown) this._hideSystemCursor();
this._cursorRoot.set_position(xMouse, yMouse);
} else if (!this._systemCursorShown && !inBounds) {

View File

@ -134,41 +134,7 @@ export const DeviceDataStream = GObject.registerClass({
// Refresh the data from the IPC file. if keepalive_only is true, we'll only check and update breezy_desktop_running if it
// hasn't been checked within KEEPALIVE_REFRESH_INTERVAL_SEC.
refresh_data(keepalive_only = false) {
if (this.debug_no_device) {
this.was_debug_no_device = true;
if (!this.device_data) {
this.device_data = {
version: 1.0,
enabled: true,
imuResetState: false,
displayRes: [1920.0, 1080.0],
sbsEnabled: false,
displayFov: 46.0,
lookAheadCfg: [0.0, 0.0, 0.0, 0.0]
}
}
if (!keepalive_only) {
this._counter = ((this._counter ?? -1)+1)%COUNTER_MAX;
const imuDataFirst = nextDebugIMUQuaternion(this._counter);
const imuData = [
...imuDataFirst,
...imuDataFirst,
...imuDataFirst,
2.0, 1.0, 0.0, 0.0
]
const imuDateMs = Date.now();
this.device_data.imuData = imuData;
this.device_data.imuDateMs = imuDateMs;
this.imu_snapshots = {
imu_data: imuData,
timestamp_ms: imuDateMs
};
}
this.breezy_desktop_running = true;
return;
} else if (this.was_debug_no_device) {
if (!this.debug_no_device && this.was_debug_no_device) {
this.was_debug_no_device = false;
this.device_data = null;
this.breezy_desktop_running = false;
@ -252,6 +218,40 @@ export const DeviceDataStream = GObject.registerClass({
} else {
this.breezy_desktop_running = false;
}
} else if (this.debug_no_device) {
this.was_debug_no_device = true;
if (!this.device_data) {
this.device_data = {
version: 1.0,
enabled: true,
imuResetState: false,
displayRes: [1920.0, 1080.0],
sbsEnabled: false,
displayFov: 46.0,
lookAheadCfg: [0.0, 0.0, 0.0, 0.0]
}
}
if (!keepalive_only) {
this._counter = ((this._counter ?? -1)+1)%COUNTER_MAX;
const imuDataFirst = nextDebugIMUQuaternion(this._counter);
const imuData = [
...imuDataFirst,
...imuDataFirst,
...imuDataFirst,
2.0, 1.0, 0.0, 0.0
]
const imuDateMs = Date.now();
this.device_data.imuData = imuData;
this.device_data.imuDateMs = imuDateMs;
this.imu_snapshots = {
imu_data: imuData,
timestamp_ms: imuDateMs
};
}
this.breezy_desktop_running = true;
return;
}
}
});

View File

@ -68,7 +68,6 @@ export default class BreezyDesktopExtension extends Extension {
this._actor_added_connection = null;
this._actor_removed_connection = null;
this._data_stream_connection = null;
this._stage_redraw_connection = null;
if (!Globals.logger) {
Globals.logger = new Logger({
@ -368,7 +367,6 @@ export default class BreezyDesktopExtension extends Extension {
_handle_sibling_update() {
Globals.logger.log_debug('BreezyDesktopExtension _handle_sibling_update()');
this._cursor_manager.moveAboveSiblings();
global.stage.set_child_above_sibling(this._overlay, null);
}
@ -586,18 +584,13 @@ export default class BreezyDesktopExtension extends Extension {
Main.wm.removeKeybinding('toggle-display-distance-shortcut');
Main.wm.removeKeybinding('toggle-follow-shortcut');
Meta.enable_unredirect_for_display(global.display);
if (this._stage_redraw_connection) {
global.stage.disconnect(this._stage_redraw_connection);
this._stage_redraw_connection = null;
}
if (this._actor_added_connection) {
global.stage.disconnect(this._actor_added_connection);
Main.layoutManager.uiGroup.disconnect(this._actor_added_connection);
this._actor_added_connection = null;
}
if (this._actor_removed_connection) {
global.stage.disconnect(this._actor_removed_connection);
Main.layoutManager.uiGroup.disconnect(this._actor_removed_connection);
this._actor_removed_connection = null;
}
if (this._distance_binding) {

View File

@ -68,33 +68,60 @@ function degreesToRadians(degrees) {
/***
* @returns {Object} - containing `begin`, `center`, and `end` radians for rotating the given monitor
*/
function monitorWrap(cachedMonitorWrap, radiusPixels, monitorSpacingPixels, monitorBeginPixel, monitorLengthPixels) {
let closestWrap = cachedMonitorWrap.reduce((previous, current) => {
return (!previous || Math.abs(current.pixel - monitorBeginPixel) < Math.abs(previous.pixel - monitorBeginPixel)) ? current : previous;
}, undefined);
function monitorWrap(cachedMonitorRadians, radiusPixels, monitorSpacingPixels, monitorBeginPixel, monitorLengthPixels) {
let closestWrapPixel = monitorBeginPixel;
let closestWrap = cachedMonitorRadians[monitorBeginPixel];
if (closestWrap === undefined) {
closestWrapPixel = Object.keys(cachedMonitorRadians).reduce((previousPixel, currentPixel) => {
if (previousPixel === undefined) return currentPixel;
const currentDelta = currentPixel - monitorBeginPixel;
const previousDelta = previousPixel - monitorBeginPixel;
// always prefer an exact monitor width match
if (previousDelta % monitorLengthPixels !== 0) {
if (currentDelta % monitorLengthPixels === 0) return currentPixel;
// prefer placing a monitor to the right or below, even if there's a closer placement to the left or above
if (previousDelta < 0 && currentDelta > 0) return currentPixel;
// otherwise, just prefer the closest one
if (Math.abs(currentDelta) < Math.abs(previousDelta)) return currentPixel;
}
return previousPixel;
}, undefined);
closestWrap = cachedMonitorRadians[closestWrapPixel];
}
const spacingRadians = Math.asin(monitorSpacingPixels / 2 / radiusPixels) * 2;
if (closestWrap.pixel !== monitorBeginPixel) {
if (closestWrapPixel !== monitorBeginPixel) {
// there's a gap between the cached wrap value and this one
const gapPixels = monitorBeginPixel - closestWrap.pixel;
const gapPixels = monitorBeginPixel - closestWrapPixel;
const gapHalfRadians = Math.asin(gapPixels / 2 / radiusPixels);
const gapRadians = gapHalfRadians * 2;
const appliedSpacingRadians = Math.trunc(gapPixels / monitorLengthPixels) * spacingRadians;
// use Math.floor so if it's negative (this monitor is to the left of or above the closest) it will always
// compenstate for the spacing that's needed at the right/bottom
const appliedSpacingRadians = Math.floor(gapPixels / monitorLengthPixels) * spacingRadians;
// update the closestWrap value and cache it
closestWrap = { pixel: monitorBeginPixel, radians: closestWrap.radians + gapRadians + appliedSpacingRadians };
cachedMonitorWrap.push(closestWrap);
closestWrap = closestWrap + gapRadians + appliedSpacingRadians;
closestWrapPixel = monitorBeginPixel;
cachedMonitorRadians[closestWrapPixel] = closestWrap;
}
const monitorHalfRadians = Math.asin(monitorLengthPixels / 2 / radiusPixels);
const centerRadians = closestWrap.radians + monitorHalfRadians;
const centerRadians = closestWrap + monitorHalfRadians;
const endRadians = centerRadians + monitorHalfRadians;
// since we're computing the end values for this monitor, cache them too in case they line up with a future monitor
cachedMonitorWrap.push({ pixel: monitorBeginPixel + monitorLengthPixels, radians: endRadians + spacingRadians });
const nextMonitorPixel = monitorBeginPixel + monitorLengthPixels;
if (cachedMonitorRadians[nextMonitorPixel] === undefined)
cachedMonitorRadians[nextMonitorPixel] = endRadians + spacingRadians;
return {
begin: closestWrap.radians,
begin: closestWrap,
center: centerRadians,
end: endRadians
}
@ -119,7 +146,7 @@ function monitorsToPlacements(fovDetails, monitorDetailsList, monitorWrappingSch
const centerRadius = fovDetails.heightPixels / 2 / Math.sin(fovVerticalRadians / 2);
const monitorPlacements = [];
const cachedMonitorWrap = [];
const cachedMonitorRadians = {};
if (monitorWrappingScheme === 'horizontal') {
// monitors wrap around us horizontally
@ -129,9 +156,9 @@ function monitorsToPlacements(fovDetails, monitorDetailsList, monitorWrappingSch
const edgeRadius = fovDetails.widthPixels / 2 / Math.sin(fovHorizontalRadians / 2);
const monitorSpacingPixels = monitorSpacing * fovDetails.widthPixels;
cachedMonitorWrap.push({ pixel: 0, radians: -fovHorizontalRadians / 2 });
cachedMonitorRadians[0] = -fovHorizontalRadians / 2;
monitorDetailsList.forEach(monitorDetails => {
const monitorWrapDetails = monitorWrap(cachedMonitorWrap, edgeRadius, monitorSpacingPixels, monitorDetails.x, monitorDetails.width);
const monitorWrapDetails = monitorWrap(cachedMonitorRadians, edgeRadius, monitorSpacingPixels, monitorDetails.x, monitorDetails.width);
const monitorCenterRadius = Math.sqrt(Math.pow(edgeRadius, 2) - Math.pow(monitorDetails.width / 2, 2));
const upTopPixels = monitorDetails.y + (monitorDetails.y / fovDetails.heightPixels) * monitorSpacingPixels;
const upCenterPixels = upTopPixels + monitorDetails.height / 2 - fovDetails.heightPixels / 2;
@ -178,9 +205,9 @@ function monitorsToPlacements(fovDetails, monitorDetailsList, monitorWrappingSch
const edgeRadius = fovDetails.heightPixels / 2 / Math.sin(fovVerticalRadians / 2);
const monitorSpacingPixels = monitorSpacing * fovDetails.heightPixels;
cachedMonitorWrap.push({ pixel: 0, radians: -fovVerticalRadians / 2 });
cachedMonitorRadians[0] = -fovVerticalRadians / 2;
monitorDetailsList.forEach(monitorDetails => {
const monitorWrapDetails = monitorWrap(cachedMonitorWrap, edgeRadius, monitorSpacingPixels, monitorDetails.y, monitorDetails.height);
const monitorWrapDetails = monitorWrap(cachedMonitorRadians, edgeRadius, monitorSpacingPixels, monitorDetails.y, monitorDetails.height);
const monitorCenterRadius = Math.sqrt(Math.pow(edgeRadius, 2) - Math.pow(monitorDetails.height / 2, 2));
const westPixels = monitorDetails.x + (monitorDetails.x / fovDetails.widthPixels) * monitorSpacingPixels;
const westCenterPixels = westPixels + monitorDetails.width / 2 - fovDetails.widthPixels / 2;
@ -252,7 +279,6 @@ function monitorsToPlacements(fovDetails, monitorDetailsList, monitorWrappingSch
});
});
}
Globals.logger.log_debug(`\t\t\tCached monitor wrap: ${JSON.stringify(cachedMonitorWrap)}`);
return monitorPlacements;
}