Fix widescreen mode syncing with settings, and remove the restrictions between distance and size

This commit is contained in:
wheaney 2024-06-13 15:12:30 -07:00
parent 3049221d61
commit 57a659b2a3
6 changed files with 74 additions and 35 deletions

View File

@ -1,4 +1,5 @@
import Clutter from 'gi://Clutter'; import Clutter from 'gi://Clutter';
import GLib from 'gi://GLib';
import Meta from 'gi://Meta'; import Meta from 'gi://Meta';
import * as PointerWatcher from 'resource:///org/gnome/shell/ui/pointerWatcher.js'; import * as PointerWatcher from 'resource:///org/gnome/shell/ui/pointerWatcher.js';
import { MouseSpriteContent } from './cursor.js'; import { MouseSpriteContent } from './cursor.js';
@ -27,6 +28,7 @@ export class CursorManager {
this._cursorWatch = null; this._cursorWatch = null;
this._cursorChangedConnection = null; this._cursorChangedConnection = null;
this._cursorVisibilityChangedConnection = null; this._cursorVisibilityChangedConnection = null;
this._moveToTopTimeout = null;
} }
enable() { enable() {
@ -132,6 +134,15 @@ export class CursorManager {
this._cursorChangedConnection = this._cursorTracker.connect('cursor-changed', this._updateMouseSprite.bind(this)); this._cursorChangedConnection = this._cursorTracker.connect('cursor-changed', this._updateMouseSprite.bind(this));
this._cursorVisibilityChangedConnection = this._cursorTracker.connect('visibility-changed', this._handleVisibilityChanged.bind(this)); this._cursorVisibilityChangedConnection = this._cursorTracker.connect('visibility-changed', this._handleVisibilityChanged.bind(this));
// Some elements will occasionally appear above the cursor, so we periodically reset the actor stacking.
// This could theoretically be fixed "better" by attaching to all events that might affect actor ordering,
// but finding a comprehensive list is difficult and not future proof. So this ugly solution helps us
// catch everything.
this._moveToTopTimeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 500, (() => {
this._moveToTop()
return GLib.SOURCE_CONTINUE;
}).bind(this));
const interval = 1000 / this._refreshRate; const interval = 1000 / this._refreshRate;
this._cursorWatch = this._cursorWatcher.addWatch(interval, this._updateMousePosition.bind(this)); this._cursorWatch = this._cursorWatcher.addWatch(interval, this._updateMousePosition.bind(this));
@ -178,6 +189,11 @@ export class CursorManager {
} else { } else {
this._mainActor.remove_actor(this._cursorActor); this._mainActor.remove_actor(this._cursorActor);
} }
if (this._moveToTopTimeout) {
GLib.source_remove(this._moveToTopTimeout);
this._moveToTopTimeout = null;
}
} }
if (this._cursorUnfocusInhibited) { if (this._cursorUnfocusInhibited) {
@ -217,7 +233,7 @@ export class CursorManager {
this._cursorTrackerSetPointerVisibleBound(false); this._cursorTrackerSetPointerVisibleBound(false);
} }
handleStageChildAdded() { _moveToTop() {
this._mainActor.set_child_above_sibling(this._cursorActor, null); this._mainActor.set_child_above_sibling(this._cursorActor, null);
} }
} }

View File

@ -40,10 +40,10 @@ export default class BreezyDesktopExtension extends Extension {
this._distance_binding = null; this._distance_binding = null;
this._distance_connection = null; this._distance_connection = null;
this._follow_threshold_connection = null; this._follow_threshold_connection = null;
this._widescreen_mode_connection = null; this._widescreen_mode_settings_connection = null;
this._widescreen_mode_effect_state_connection = null;
this._start_binding = null; this._start_binding = null;
this._end_binding = null; this._end_binding = null;
this._stage_child_connection = null;
this._curved_display_binding = null; this._curved_display_binding = null;
this._display_size_binding = null; this._display_size_binding = null;
@ -69,7 +69,7 @@ export default class BreezyDesktopExtension extends Extension {
this._setup(); this._setup();
} catch (e) { } catch (e) {
Globals.logger.log(`ERROR: BreezyDesktopExtension enable ${e.message}`, e.stack); Globals.logger.log(`ERROR: BreezyDesktopExtension enable ${e.message}\n${e.stack}`);
} }
} }
@ -113,7 +113,7 @@ export default class BreezyDesktopExtension extends Extension {
return null; return null;
} catch (e) { } catch (e) {
Globals.logger.log(`ERROR: BreezyDesktopExtension _find_supported_monitor ${e.message}`, e.stack); Globals.logger.log(`ERROR: BreezyDesktopExtension _find_supported_monitor ${e.message}\n${e.stack}`);
return null; return null;
} }
} }
@ -129,7 +129,9 @@ export default class BreezyDesktopExtension extends Extension {
// if target_monitor isn't set, do nothing and wait for MonitorManager to call this again // if target_monitor isn't set, do nothing and wait for MonitorManager to call this again
if (target_monitor && this._running_poller_id === undefined) { if (target_monitor && this._running_poller_id === undefined) {
this._target_monitor = target_monitor.monitor; this._target_monitor = target_monitor.monitor;
this._refresh_rate = target_monitor.refreshRate;
// have everything target a slightly higher refresh rate to avoid stuttering
this._refresh_rate = target_monitor.refreshRate * 1.05;
if (this._check_driver_running()) { if (this._check_driver_running()) {
Globals.logger.log('Ready, enabling XR effect'); Globals.logger.log('Ready, enabling XR effect');
@ -145,7 +147,7 @@ export default class BreezyDesktopExtension extends Extension {
if (!Globals.ipc_file) Globals.ipc_file = Gio.file_new_for_path(IPC_FILE_PATH); if (!Globals.ipc_file) Globals.ipc_file = Gio.file_new_for_path(IPC_FILE_PATH);
return Globals.ipc_file.query_exists(null); return Globals.ipc_file.query_exists(null);
} catch (e) { } catch (e) {
Globals.logger.log(`ERROR: BreezyDesktopExtension _check_driver_running ${e.message}`, e.stack); Globals.logger.log(`ERROR: BreezyDesktopExtension _check_driver_running ${e.message}\n${e.stack}`);
return false; return false;
} }
} }
@ -187,24 +189,19 @@ export default class BreezyDesktopExtension extends Extension {
toggle_display_distance_start: this.settings.get_double('toggle-display-distance-start'), toggle_display_distance_start: this.settings.get_double('toggle-display-distance-start'),
toggle_display_distance_end: this.settings.get_double('toggle-display-distance-end'), toggle_display_distance_end: this.settings.get_double('toggle-display-distance-end'),
}); });
this._widescreen_mode_effect_state_connection = this._xr_effect.connect('notify::widescreen-mode-state', this._update_widescreen_mode_from_state.bind(this));
this._update_widescreen_mode_from_state(this._xr_effect, this._xr_effect.widescreen_mode_state);
this._update_display_distance(this.settings);
this._update_follow_threshold(this.settings); this._update_follow_threshold(this.settings);
this._update_widescreen_mode(this.settings);
this._distance_binding = this.settings.bind('display-distance', this._xr_effect, 'display-distance', Gio.SettingsBindFlags.DEFAULT) this._distance_binding = this.settings.bind('display-distance', this._xr_effect, 'display-distance', Gio.SettingsBindFlags.DEFAULT)
this._distance_connection = this.settings.connect('changed::display-distance', this._update_display_distance.bind(this)) this._distance_connection = this.settings.connect('changed::display-distance', this._update_display_distance.bind(this))
this._follow_threshold_connection = this.settings.connect('changed::follow-threshold', this._update_follow_threshold.bind(this)) this._follow_threshold_connection = this.settings.connect('changed::follow-threshold', this._update_follow_threshold.bind(this))
this._widescreen_mode_connection = this.settings.connect('changed::widescreen-mode', this._update_widescreen_mode.bind(this)) this._widescreen_mode_settings_connection = this.settings.connect('changed::widescreen-mode', this._update_widescreen_mode_from_settings.bind(this))
this._start_binding = this.settings.bind('toggle-display-distance-start', this._xr_effect, 'toggle-display-distance-start', Gio.SettingsBindFlags.DEFAULT) this._start_binding = this.settings.bind('toggle-display-distance-start', this._xr_effect, 'toggle-display-distance-start', Gio.SettingsBindFlags.DEFAULT)
this._end_binding = this.settings.bind('toggle-display-distance-end', this._xr_effect, 'toggle-display-distance-end', Gio.SettingsBindFlags.DEFAULT) this._end_binding = this.settings.bind('toggle-display-distance-end', this._xr_effect, 'toggle-display-distance-end', Gio.SettingsBindFlags.DEFAULT)
this._curved_display_binding = this.settings.bind('curved-display', this._xr_effect, 'curved-display', Gio.SettingsBindFlags.DEFAULT) this._curved_display_binding = this.settings.bind('curved-display', this._xr_effect, 'curved-display', Gio.SettingsBindFlags.DEFAULT)
this._display_size_binding = this.settings.bind('widescreen-display-size', this._xr_effect, 'widescreen-display-size', Gio.SettingsBindFlags.DEFAULT) this._display_size_binding = this.settings.bind('widescreen-display-size', this._xr_effect, 'widescreen-display-size', Gio.SettingsBindFlags.DEFAULT);
if (Clutter.Container === undefined) {
this._stage_child_connection = global.stage.connect('child-added', this._cursor_manager.handleStageChildAdded);
} else {
this._stage_child_connection = global.stage.connect('actor-added', this._cursor_manager.handleStageChildAdded);
}
this._overlay.add_effect_with_name('xr-desktop', this._xr_effect); this._overlay.add_effect_with_name('xr-desktop', this._xr_effect);
Meta.disable_unredirect_for_display(global.display); Meta.disable_unredirect_for_display(global.display);
@ -213,7 +210,7 @@ export default class BreezyDesktopExtension extends Extension {
this._add_settings_keybinding('toggle-display-distance-shortcut', this._xr_effect._change_distance.bind(this._xr_effect)); this._add_settings_keybinding('toggle-display-distance-shortcut', this._xr_effect._change_distance.bind(this._xr_effect));
this._add_settings_keybinding('toggle-follow-shortcut', this._toggle_follow_mode.bind(this)); this._add_settings_keybinding('toggle-follow-shortcut', this._toggle_follow_mode.bind(this));
} catch (e) { } catch (e) {
Globals.logger.log(`ERROR: BreezyDesktopExtension _effect_enable ${e.message}`, e.stack); Globals.logger.log(`ERROR: BreezyDesktopExtension _effect_enable ${e.message}\n${e.stack}`);
this._effect_disable(); this._effect_disable();
} }
} }
@ -244,11 +241,11 @@ export default class BreezyDesktopExtension extends Extension {
bind_to_function bind_to_function
); );
} catch (e) { } catch (e) {
Globals.logger.log(`ERROR: BreezyDesktopExtension _add_settings_keybinding settings binding lambda ${e.message}`, e.stack); Globals.logger.log(`ERROR: BreezyDesktopExtension _add_settings_keybinding settings binding lambda ${e.message}\n${e.stack}`);
} }
}); });
} catch (e) { } catch (e) {
Globals.logger.log(`ERROR: BreezyDesktopExtension _add_settings_keybinding ${e.message}`, e.stack); Globals.logger.log(`ERROR: BreezyDesktopExtension _add_settings_keybinding ${e.message}\n${e.stack}`);
} }
} }
@ -271,10 +268,22 @@ export default class BreezyDesktopExtension extends Extension {
if (value !== undefined) this._write_control('breezy_desktop_follow_threshold', value); if (value !== undefined) this._write_control('breezy_desktop_follow_threshold', value);
} }
_update_widescreen_mode(settings, event) { _update_widescreen_mode_from_settings(settings, event) {
const value = settings.get_boolean('widescreen-mode'); const value = settings.get_boolean('widescreen-mode');
Globals.logger.log_debug(`BreezyDesktopExtension _update_widescreen_mode ${value}`); Globals.logger.log_debug(`BreezyDesktopExtension _update_widescreen_mode_from_settings ${value}`);
if (value !== undefined) this._write_control('sbs_mode', value ? 'enable' : 'disable'); if (value !== undefined && value != this._xr_effect.widescreen_mode_state)
this._write_control('sbs_mode', value ? 'enable' : 'disable');
else
Globals.logger.log_debug('effect.widescreen_mode_state already matched setting');
}
_update_widescreen_mode_from_state(effect, _pspec) {
const value = effect.widescreen_mode_state;
Globals.logger.log_debug(`BreezyDesktopExtension _update_widescreen_mode_from_state ${value}`);
if (value !== this.settings.get_boolean('widescreen-mode'))
this.settings.set_boolean('widescreen-mode', value);
else
Globals.logger.log_debug('widescreen-mode setting already matched state');
} }
_recenter_display() { _recenter_display() {
@ -318,9 +327,9 @@ export default class BreezyDesktopExtension extends Extension {
this.settings.disconnect(this._follow_threshold_connection); this.settings.disconnect(this._follow_threshold_connection);
this._follow_threshold_connection = null; this._follow_threshold_connection = null;
} }
if (this._widescreen_mode_connection) { if (this._widescreen_mode_settings_connection) {
this.settings.disconnect(this._widescreen_mode_connection); this.settings.disconnect(this._widescreen_mode_settings_connection);
this._widescreen_mode_connection = null; this._widescreen_mode_settings_connection = null;
} }
if (this._start_binding) { if (this._start_binding) {
this.settings.unbind(this._start_binding); this.settings.unbind(this._start_binding);
@ -338,11 +347,11 @@ export default class BreezyDesktopExtension extends Extension {
this.settings.unbind(this._display_size_binding); this.settings.unbind(this._display_size_binding);
this._display_size_binding = null; this._display_size_binding = null;
} }
if (this._stage_child_connection) {
global.stage.disconnect(this._stage_child_connection);
this._stage_child_connection = null;
}
if (this._xr_effect) { if (this._xr_effect) {
if (this._widescreen_mode_effect_state_connection) {
this._xr_effect.disconnect(this._widescreen_mode_effect_state_connection);
this._widescreen_mode_effect_state_connection = null;
}
this._xr_effect.cleanup(); this._xr_effect.cleanup();
this._xr_effect = null; this._xr_effect = null;
} }
@ -352,7 +361,7 @@ export default class BreezyDesktopExtension extends Extension {
this._cursor_manager = null; this._cursor_manager = null;
} }
} catch (e) { } catch (e) {
Globals.logger.log(`ERROR: BreezyDesktopExtension _effect_disable ${e.message}`, e.stack); Globals.logger.log(`ERROR: BreezyDesktopExtension _effect_disable ${e.message}\n${e.stack}`);
} }
} }
@ -366,7 +375,7 @@ export default class BreezyDesktopExtension extends Extension {
this._monitor_manager = null; this._monitor_manager = null;
} }
} catch (e) { } catch (e) {
Globals.logger.log(`ERROR: BreezyDesktopExtension disable ${e.message}`, e.stack); Globals.logger.log(`ERROR: BreezyDesktopExtension disable ${e.message}\n${e.stack}`);
} }
} }
} }

View File

@ -147,12 +147,16 @@ function setIntermittentUniformVariables() {
setSingleFloat(this, 'curved_display', this.curved_display ? 1.0 : 0.0); setSingleFloat(this, 'curved_display', this.curved_display ? 1.0 : 0.0);
} }
// update the widescreen property if the state changes, so notify events are triggered
const sbsEnabled = dataViewUint8(dataView, SBS_ENABLED) !== 0;
if (this.widescreen_mode_state !== sbsEnabled) this.widescreen_mode_state = sbsEnabled;
// these variables are always in play, even if enabled is false // these variables are always in play, even if enabled is false
setSingleFloat(this, 'enabled', enabled ? 1.0 : 0.0); setSingleFloat(this, 'enabled', enabled ? 1.0 : 0.0);
setSingleFloat(this, 'show_banner', imuResetState ? 1.0 : 0.0); setSingleFloat(this, 'show_banner', imuResetState ? 1.0 : 0.0);
setSingleFloat(this, 'sbs_content', 0.0); // TODO - drive from settings setSingleFloat(this, 'sbs_content', 0.0); // TODO - drive from settings
setSingleFloat(this, 'sbs_mode_stretched', 1.0); // content always fills the whole display setSingleFloat(this, 'sbs_mode_stretched', 1.0); // content always fills the whole display
setSingleFloat(this, 'sbs_enabled', dataViewUint8(dataView, SBS_ENABLED) !== 0 ? 1.0 : 0.0); setSingleFloat(this, 'sbs_enabled', sbsEnabled ? 1.0 : 0.0);
setSingleFloat(this, 'custom_banner_enabled', dataViewUint8(dataView, CUSTOM_BANNER_ENABLED) !== 0 ? 1.0 : 0.0); setSingleFloat(this, 'custom_banner_enabled', dataViewUint8(dataView, CUSTOM_BANNER_ENABLED) !== 0 ? 1.0 : 0.0);
this.set_uniform_float(shaderUniformLocations['display_resolution'], 2, displayRes); this.set_uniform_float(shaderUniformLocations['display_resolution'], 2, displayRes);
@ -210,6 +214,13 @@ export const XREffect = GObject.registerClass({
GObject.ParamFlags.READWRITE, GObject.ParamFlags.READWRITE,
false false
), ),
'widescreen-mode-state': GObject.ParamSpec.boolean(
'widescreen-mode-state',
'Widescreen mode state',
'The state of widescreen mode from the perspective of the driver',
GObject.ParamFlags.READWRITE,
false
),
'widescreen-display-size': GObject.ParamSpec.double( 'widescreen-display-size': GObject.ParamSpec.double(
'widescreen-display-size', 'widescreen-display-size',
'Widescreen display size', 'Widescreen display size',
@ -224,7 +235,9 @@ export const XREffect = GObject.registerClass({
constructor(params = {}) { constructor(params = {}) {
super(params); super(params);
this._frametime = Math.floor(1000 / this.target_framerate); // target a slightly higher framerate than the monitor's refresh rate to prevent stuttering
const frameTimeFramerate = this.target_framerate;
this._frametime = Math.floor(1000 / frameTimeFramerate);
this._is_display_distance_at_end = false; this._is_display_distance_at_end = false;
this._distance_ease_timeline = null; this._distance_ease_timeline = null;

@ -1 +1 @@
Subproject commit 3f712c2aeffcae41d238e146acc97c145ab9647b Subproject commit 7eea3e01b4cd03dc07fa03f3f5903e31fc8dffbc

View File

@ -109,6 +109,7 @@ class ConnectedDevice(Gtk.Box):
for widget in [self.widescreen_display_distance_scale, self.widescreen_display_size_scale]: for widget in [self.widescreen_display_distance_scale, self.widescreen_display_size_scale]:
widget.set_sensitive(widescreen_mode_enabled) widget.set_sensitive(widescreen_mode_enabled)
def _refresh_inputs_for_enabled_state(self, switch, param): def _refresh_inputs_for_enabled_state(self, switch, param):
requesting_enabled = switch.get_active() requesting_enabled = switch.get_active()
self.extensions_manager.set_property('breezy-enabled', requesting_enabled) self.extensions_manager.set_property('breezy-enabled', requesting_enabled)

View File

@ -95,7 +95,7 @@ class StateManager(GObject.GObject):
self.set_property('license-present', False) self.set_property('license-present', False)
self.set_property('follow-mode', self.state.get('breezy_desktop_smooth_follow_enabled')) self.set_property('follow-mode', self.state.get('breezy_desktop_smooth_follow_enabled'))
self.set_property('widescreen-mode', self.state.get('sbs_mode_enabled') == 'true') self.set_property('widescreen-mode', self.state.get('sbs_mode_enabled'))
if self.running: threading.Timer(1.0, self._refresh_state).start() if self.running: threading.Timer(1.0, self._refresh_state).start()