From cc81f863c5014ddf2a3ec8b2f2a3096a618d72a9 Mon Sep 17 00:00:00 2001 From: wheaney <42350981+wheaney@users.noreply.github.com> Date: Sat, 22 Feb 2025 18:13:21 -0800 Subject: [PATCH] Drop display distance easing while moving the slider, update the UI (WIP), add a "zoom on focus" toggle --- gnome/src/virtualmonitorsactor.js | 28 +++++- ui/src/connecteddevice.py | 90 +++++++++++++++---- ui/src/gtk/connected-device.ui | 140 +++++++++++++++++++++--------- ui/src/gtk/no-device.ui | 12 --- ui/src/nodevice.py | 8 +- ui/src/window.py | 8 +- 6 files changed, 207 insertions(+), 79 deletions(-) diff --git a/gnome/src/virtualmonitorsactor.js b/gnome/src/virtualmonitorsactor.js index 834185a..d7b3327 100644 --- a/gnome/src/virtualmonitorsactor.js +++ b/gnome/src/virtualmonitorsactor.js @@ -366,6 +366,13 @@ export const VirtualMonitorEffect = GObject.registerClass({ GObject.ParamFlags.READWRITE, -1, 100, -1 ), + 'display-zoom-on-focus': GObject.ParamSpec.boolean( + 'display-zoom-on-focus', + 'Display zoom on focus', + 'Automatically move a display closer when it becomes focused.', + GObject.ParamFlags.READWRITE, + true + ), 'display-distance': GObject.ParamSpec.double( 'display-distance', 'Display Distance', @@ -444,6 +451,7 @@ export const VirtualMonitorEffect = GObject.registerClass({ super(params); this._current_display_distance = this._is_focused() ? this.display_distance : this.display_distance_default; + this.no_distance_ease = false; this.connect('notify::display-distance', this._update_display_distance.bind(this)); this.connect('notify::focused-monitor-index', this._update_display_distance.bind(this)); @@ -464,6 +472,13 @@ export const VirtualMonitorEffect = GObject.registerClass({ this._distance_ease_timeline.stop(); } + + if (this.no_distance_ease) { + this._current_display_distance = desired_distance; + this._update_display_position_uniforms(); + this.no_distance_ease = false; + return; + } // if we're the focused display, we'll double the timeline and wait for the first half to let other // displays ease out first @@ -792,6 +807,13 @@ export const VirtualMonitorsActor = GObject.registerClass({ 2.5, 1.0 ), + 'display-zoom-on-focus': GObject.ParamSpec.boolean( + 'display-zoom-on-focus', + 'Display zoom on focus', + 'Automatically move a display closer when it becomes focused.', + GObject.ParamFlags.READWRITE, + true + ), 'display-distance': GObject.ParamSpec.double( 'display-distance', 'Display Distance', @@ -976,7 +998,6 @@ export const VirtualMonitorsActor = GObject.registerClass({ 'monitor-placements', 'imu-snapshots', 'focused-monitor-index', - 'display-distance', 'lens-vector', 'look-ahead-override', 'disable-anti-aliasing', @@ -986,8 +1007,11 @@ export const VirtualMonitorsActor = GObject.registerClass({ })); const updateEffectDistanceDefault = (() => { + effect.no_distance_ease = Math.abs(this.display_distance - effect.display_distance) <= 0.05; + effect.display_distance = this.display_distance; effect.display_distance_default = this._display_distance_default(); }).bind(this); + this._property_connections.push(this.connect('notify::display-distance', updateEffectDistanceDefault)); this._property_connections.push(this.connect('notify::toggle-display-distance-start', updateEffectDistanceDefault)); this._property_connections.push(this.connect('notify::toggle-display-distance-end', updateEffectDistanceDefault)); @@ -1047,7 +1071,7 @@ export const VirtualMonitorsActor = GObject.registerClass({ } _display_distance_default() { - return Math.max(this.toggle_display_distance_start, this.toggle_display_distance_end); + return Math.max(this.display_distance, this.toggle_display_distance_start, this.toggle_display_distance_end); } _fov_details() { diff --git a/ui/src/connecteddevice.py b/ui/src/connecteddevice.py index f262a7e..7cd9a7e 100644 --- a/ui/src/connecteddevice.py +++ b/ui/src/connecteddevice.py @@ -23,6 +23,7 @@ class ConnectedDevice(Gtk.Box): device_label = Gtk.Template.Child() effect_enable_switch = Gtk.Template.Child() + display_zoom_on_focus_switch = Gtk.Template.Child() display_distance_scale = Gtk.Template.Child() display_distance_adjustment = Gtk.Template.Child() # display_size_scale = Gtk.Template.Child() @@ -37,8 +38,11 @@ class ConnectedDevice(Gtk.Box): add_virtual_display_menu = Gtk.Template.Child() add_virtual_display_button = Gtk.Template.Child() launch_display_settings_button = Gtk.Template.Child() - set_toggle_display_distance_start_button = Gtk.Template.Child() - set_toggle_display_distance_end_button = Gtk.Template.Child() + all_displays_distance_label = Gtk.Template.Child() + set_all_displays_distance_button = Gtk.Template.Child() + focused_display_distance_label = Gtk.Template.Child() + set_focused_display_distance_button = Gtk.Template.Child() + display_distance_presets_description = Gtk.Template.Child() reassign_toggle_xr_effect_shortcut_button = Gtk.Template.Child() toggle_xr_effect_shortcut_label = Gtk.Template.Child() reassign_recenter_display_shortcut_button = Gtk.Template.Child() @@ -68,6 +72,7 @@ class ConnectedDevice(Gtk.Box): self.init_template() self.active = True self.all_enabled_state_inputs = [ + self.display_zoom_on_focus_switch, self.display_distance_scale, # self.display_size_scale, # self.follow_mode_switch, @@ -75,8 +80,8 @@ class ConnectedDevice(Gtk.Box): # self.curved_display_switch, self.add_virtual_display_menu, self.add_virtual_display_button, - self.set_toggle_display_distance_start_button, - self.set_toggle_display_distance_end_button, + self.set_all_displays_distance_button, + self.set_focused_display_distance_button, self.movement_look_ahead_scale, self.monitor_wrapping_scheme_menu, self.monitor_spacing_scale, @@ -105,6 +110,7 @@ class ConnectedDevice(Gtk.Box): self.settings.bind('viewport-offset-y', self.viewport_offset_y_adjustment, 'value', Gio.SettingsBindFlags.DEFAULT) self.settings.connect('changed::monitor-wrapping-scheme', self._handle_monitor_wrapping_scheme_setting_changed) self.desktop_settings.bind('text-scaling-factor', self.text_scaling_adjustment, 'value', Gio.SettingsBindFlags.DEFAULT) + self.display_zoom_on_focus_switch.connect('notify::active', self._handle_zoom_on_focus_switch_changed) self.monitor_wrapping_scheme_menu.connect('changed', self._handle_monitor_wrapping_scheme_menu_changed) self._handle_monitor_wrapping_scheme_setting_changed(self.settings, self.settings.get_string('monitor-wrapping-scheme')) @@ -115,12 +121,15 @@ class ConnectedDevice(Gtk.Box): [self.reassign_toggle_follow_shortcut_button, self.toggle_follow_shortcut_label] ]) - self.bind_set_distance_toggle([ - self.set_toggle_display_distance_start_button, - self.set_toggle_display_distance_end_button - ]) + self.set_all_displays_distance_button.connect('clicked', self._on_set_all_displays_distance) + self.set_focused_display_distance_button.connect('clicked', self.on_set_focused_display_distance) + self._set_all_displays_distance(self.settings.get_double('toggle-display-distance-end')) + self._set_focused_display_distance(self.settings.get_double('toggle-display-distance-start')) + self.display_distance_adjustment.connect('value-changed', self._on_display_distance_update) + self._on_display_distance_update(self.display_distance_adjustment) + self.add_virtual_display_menu.set_active_id('1080p') - self.add_virtual_display_button.connect('clicked', self.on_add_virtual_display) + self.add_virtual_display_button.connect('clicked', self._on_add_virtual_display) self.launch_display_settings_button.connect('clicked', self._launch_display_settings) self.state_manager = StateManager.get_instance() @@ -147,6 +156,9 @@ class ConnectedDevice(Gtk.Box): self.virtual_display_manager.connect('notify::displays', self._on_virtual_displays_update) self._on_virtual_displays_update(self.virtual_display_manager, None) + self.display_distance_presets_description.set_markup( + _("These presets are used unless manually overridden by the slider above.")) + self.connect("destroy", self._on_widget_destroy) self.virtual_displays_by_pid = {} @@ -157,6 +169,16 @@ class ConnectedDevice(Gtk.Box): if appinfo.get_id() == 'gnome-display-panel.desktop': self._settings_displays_app_info = appinfo break + + def _handle_zoom_on_focus_switch_changed(self, widget, param): + display_distance = self.settings.get_double('display-distance') + toggle_display_distance_end = self.settings.get_double('toggle-display-distance-end') + toggle_display_distance_start = self.settings.get_double('toggle-display-distance-start') + is_zoom_on_focus_already_enabled = display_distance < toggle_display_distance_end + if widget.get_active() and not is_zoom_on_focus_already_enabled: + self.settings.set_double('display-distance', toggle_display_distance_start) + elif not widget.get_active() and is_zoom_on_focus_already_enabled: + self.settings.set_double('display-distance', toggle_display_distance_end) def _handle_monitor_wrapping_scheme_setting_changed(self, settings, val): self.monitor_wrapping_scheme_menu.set_active_id(val) @@ -219,13 +241,51 @@ class ConnectedDevice(Gtk.Box): def set_device_name(self, name): self.device_label.set_markup(f"{name}") - - def bind_set_distance_toggle(self, widgets): - for widget in widgets: - widget.connect('clicked', lambda *args, widget=widget: on_set_display_distance_toggle(widget)) - reload_display_distance_toggle_button(widget) - def on_add_virtual_display(self, *args): + def _on_display_distance_update(self, adjustment): + display_distance = adjustment.get_value() + toggle_display_distance_end = self.settings.get_double('toggle-display-distance-end') + self.set_all_displays_distance_button.set_label(f"Use {display_distance}") + self.set_all_displays_distance_button.set_visible(display_distance != toggle_display_distance_end) + + toggle_display_distance_start = self.settings.get_double('toggle-display-distance-start') + self.set_focused_display_distance_button.set_label(f"Use {display_distance}") + self.set_focused_display_distance_button.set_visible(display_distance != toggle_display_distance_start) + + should_zoom_on_focus_be_enabled = display_distance < toggle_display_distance_end + if self.display_zoom_on_focus_switch.get_active() != should_zoom_on_focus_be_enabled: + self.display_zoom_on_focus_switch.set_active(should_zoom_on_focus_be_enabled) + + def _set_focused_display_distance(self, distance): + self.focused_display_distance_label.set_markup(f"Focused display: {distance}") + self.settings.set_double('toggle-display-distance-start', distance) + self.set_focused_display_distance_button.set_visible(False) + + def _set_all_displays_distance(self, distance): + self.all_displays_distance_label.set_markup(f"All displays: {distance}") + self.settings.set_double('toggle-display-distance-end', distance) + self.set_all_displays_distance_button.set_visible(False) + self.display_zoom_on_focus_switch.set_active(False) + + def _on_set_all_displays_distance(self, *args): + distance = self.settings.get_double('display-distance') + focused_display_distance = self.settings.get_double('toggle-display-distance-start') + all_displays_distance = self.settings.get_double('toggle-display-distance-end') + if (distance < focused_display_distance): + self._set_focused_display_distance(distance) + + self._set_all_displays_distance(distance) + + def on_set_focused_display_distance(self, *args): + distance = self.settings.get_double('display-distance') + focused_display_distance = self.settings.get_double('toggle-display-distance-start') + all_displays_distance = self.settings.get_double('toggle-display-distance-end') + if (distance > all_displays_distance): + self._set_all_displays_distance(distance) + + self._set_focused_display_distance(distance) + + def _on_add_virtual_display(self, *args): resolution = self.add_virtual_display_menu.get_active_id() logger.info(f"Adding virtual display {resolution}") diff --git a/ui/src/gtk/connected-device.ui b/ui/src/gtk/connected-device.ui index 98389a7..60ed974 100644 --- a/ui/src/gtk/connected-device.ui +++ b/ui/src/gtk/connected-device.ui @@ -50,6 +50,18 @@ + + + Display zoom on focus + Automatically move a display closer when you look at it. Adjust using the "Display distances" slider below. + + + + 3 + + + + Virtual displays @@ -69,7 +81,7 @@ - center + 3 @@ -89,7 +101,7 @@ add-virtual-display list-add-symbolic - center + 3 @@ -104,53 +116,97 @@ Adjustments - Display distance - Closer appears larger, further appears smaller. Controls depth when in widescreen mode. - - - 3 - true - 0 - 2 - 350 - false - - - 0.2 - 2.5 - 0.01 - 1.05 - - - - 0.2 - 1.0 - 2.5 - - - - - - - - Display toggle distances - Use the buttons to capture the current display distance for use with the keyboard shortcut. - 2 + Display distances + Set how close you want displays to appear. - 30 - 150 - 30 + vertical + 3 - - toggle-display-distance-start + 3 + 20 + 15 + true + 0 + 2 + 350 + false + + + 0.2 + 2.5 + 0.01 + 1.05 + + + + closer + fullscreen + farther + - - toggle-display-distance-end + + 15 + + + + 3 + 5 + + + + + 25 + 1 + 15 + + + vertical + 6 + + + + 3 + + + + + 0 + set-all-displays-distance + 3 + + 20 + 20 + + + + + + + vertical + 6 + + + + 3 + + + + + 0 + set-all-displays-distance + 3 + + 20 + 20 + + + + @@ -167,7 +223,7 @@ 30 150 30 - center + 3 diff --git a/ui/src/gtk/no-device.ui b/ui/src/gtk/no-device.ui index c7d6cad..9cbfa96 100644 --- a/ui/src/gtk/no-device.ui +++ b/ui/src/gtk/no-device.ui @@ -29,18 +29,6 @@ - - - Start in widescreen mode - Widescreen mode is not supported for all glasses. - 2 - - - 3 - - - - diff --git a/ui/src/nodevice.py b/ui/src/nodevice.py index b36c656..878889f 100644 --- a/ui/src/nodevice.py +++ b/ui/src/nodevice.py @@ -10,7 +10,7 @@ class NoDevice(Gtk.Box): __gtype_name__ = "NoDevice" effect_enable_switch = Gtk.Template.Child() - widescreen_mode_switch = Gtk.Template.Child() + # widescreen_mode_switch = Gtk.Template.Child() def __init__(self): super(Gtk.Box, self).__init__() @@ -23,7 +23,7 @@ class NoDevice(Gtk.Box): self.config_manager.connect('notify::breezy-desktop-enabled', self._handle_enabled_config) self.effect_enable_switch.connect('notify::active', self._handle_switch_enabled_state) - self.settings.bind('widescreen-mode', self.widescreen_mode_switch, 'active', Gio.SettingsBindFlags.DEFAULT) + # self.settings.bind('widescreen-mode', self.widescreen_mode_switch, 'active', Gio.SettingsBindFlags.DEFAULT) self._handle_enabled_config(self.config_manager, None) @@ -41,5 +41,5 @@ class NoDevice(Gtk.Box): self.config_manager.set_property('breezy-desktop-enabled', requesting_enabled) - def _on_widget_destroy(self, widget): - self.settings.unbind('widescreen-mode', self.widescreen_mode_switch, 'active') + # def _on_widget_destroy(self, widget): + # self.settings.unbind('widescreen-mode', self.widescreen_mode_switch, 'active') diff --git a/ui/src/window.py b/ui/src/window.py index 375fa96..330e743 100644 --- a/ui/src/window.py +++ b/ui/src/window.py @@ -85,13 +85,13 @@ class BreezydesktopWindow(Gtk.ApplicationWindow): for child in self.main_content: self.main_content.remove(child) - if not self._skip_verification and not verify_installation(): + if self.settings.get_boolean('debug-no-device'): + self.main_content.append(self.connected_device) + self.connected_device.set_device_name('Fake device') + elif not self._skip_verification and not verify_installation(): self.main_content.append(self.failed_verification) elif not ExtensionsManager.get_instance().is_installed(): self.main_content.append(self.no_extension) - elif self.settings.get_boolean('debug-no-device'): - self.main_content.append(self.connected_device) - self.connected_device.set_device_name('Fake device') elif not self.state_manager.driver_running: self.main_content.append(self.no_driver) elif not self.state_manager.license_present: