diff --git a/gnome/src/cursormanager.js b/gnome/src/cursormanager.js index 51965bd..477432f 100644 --- a/gnome/src/cursormanager.js +++ b/gnome/src/cursormanager.js @@ -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) { diff --git a/gnome/src/devicedatastream.js b/gnome/src/devicedatastream.js index 03cd97f..1882a04 100644 --- a/gnome/src/devicedatastream.js +++ b/gnome/src/devicedatastream.js @@ -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; } } }); \ No newline at end of file diff --git a/gnome/src/extension.js b/gnome/src/extension.js index ea8bd5c..f2136ab 100644 --- a/gnome/src/extension.js +++ b/gnome/src/extension.js @@ -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) { diff --git a/gnome/src/virtualmonitorsactor.js b/gnome/src/virtualmonitorsactor.js index 119c558..992eb4a 100644 --- a/gnome/src/virtualmonitorsactor.js +++ b/gnome/src/virtualmonitorsactor.js @@ -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; }