Drop display distance easing while moving the slider, update the UI (WIP), add a "zoom on focus" toggle

This commit is contained in:
wheaney 2025-02-22 18:13:21 -08:00
parent b77ede606d
commit cc81f863c5
6 changed files with 207 additions and 79 deletions

View File

@ -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() {

View File

@ -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(
_("<span size=\"small\">These presets are used unless manually overridden by the slider above.</span>"))
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"<b>{name}</b>")
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: <b>{distance}</b>")
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: <b>{distance}</b>")
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}")

View File

@ -50,6 +50,18 @@
</child>
</object>
</child>
<child>
<object class="AdwActionRow">
<property name="title" translatable="yes"><!-- feature switch -->Display zoom on focus</property>
<property name="subtitle" translatable="yes">Automatically move a display closer when you look at it. Adjust using the "Display distances" slider below.
</property>
<child>
<object class="GtkSwitch" id="display_zoom_on_focus_switch">
<property name="valign">3</property>
</object>
</child>
</object>
</child>
<child>
<object class="AdwActionRow">
<property name="title" translatable="yes"><!-- adjustment slider -->Virtual displays</property>
@ -69,7 +81,7 @@
</child>
<child>
<object class="GtkBox">
<property name="valign">center</property>
<property name="valign">3</property>
<style>
<class name="flat"/>
</style>
@ -89,7 +101,7 @@
<object class="GtkButton" id="add_virtual_display_button">
<property name="name">add-virtual-display</property>
<property name="icon-name">list-add-symbolic</property>
<property name="valign">center</property>
<property name="valign">3</property>
<style>
<class name="flat"/>
</style>
@ -104,53 +116,97 @@
<property name="title" translatable="yes"><!-- Section containing sliders for adjusting the XR effect -->Adjustments</property>
<child>
<object class="AdwActionRow" id="display_distance_row">
<property name="title" translatable="yes"><!-- adjustment slider -->Display distance</property>
<property name="subtitle" translatable="yes">Closer appears larger, further appears smaller. Controls depth when in widescreen mode.</property>
<child>
<object class="GtkScale" id="display_distance_scale">
<property name="valign">3</property>
<property name="draw-value">true</property>
<property name="value-pos">0</property>
<property name="digits">2</property>
<property name="width-request">350</property>
<property name="has-origin">false</property>
<property name="adjustment">
<object class="GtkAdjustment" id="display_distance_adjustment">
<property name="lower">0.2</property>
<property name="upper">2.5</property>
<property name="step-increment">0.01</property>
<property name="value">1.05</property>
</object>
</property>
<marks>
<mark value="0.2" position="bottom">0.2</mark>
<mark value="1.0" position="bottom">1.0</mark>
<mark value="2.5" position="bottom">2.5</mark>
</marks>
</object>
</child>
</object>
</child>
<child>
<object class="AdwActionRow">
<property name="title" translatable="yes"><!-- adjustment slider -->Display toggle distances</property>
<property name="subtitle" translatable="yes">Use the buttons to capture the current display distance for use with the keyboard shortcut.</property>
<property name="valign">2</property>
<property name="title" translatable="yes"><!-- adjustment slider -->Display distances</property>
<property name="subtitle" translatable="yes">Set how close you want displays to appear.</property>
<child>
<object class="GtkBox">
<property name="spacing">30</property>
<property name="width-request">150</property>
<property name="margin-start">30</property>
<property name="orientation">vertical</property>
<property name="valign">3</property>
<child>
<object class="GtkButton" id="set_toggle_display_distance_start_button">
<property name="name">toggle-display-distance-start</property>
<object class="GtkScale" id="display_distance_scale">
<property name="valign">3</property>
<property name="margin-top">20</property>
<property name="margin-bottom">15</property>
<property name="draw-value">true</property>
<property name="value-pos">0</property>
<property name="digits">2</property>
<property name="width-request">350</property>
<property name="has-origin">false</property>
<property name="adjustment">
<object class="GtkAdjustment" id="display_distance_adjustment">
<property name="lower">0.2</property>
<property name="upper">2.5</property>
<property name="step-increment">0.01</property>
<property name="value">1.05</property>
</object>
</property>
<marks>
<mark value="0.2" position="bottom">closer</mark>
<mark value="1.0" position="bottom">fullscreen</mark>
<mark value="2.5" position="bottom">farther</mark>
</marks>
</object>
</child>
<child>
<object class="GtkButton" id="set_toggle_display_distance_end_button">
<property name="name">toggle-display-distance-end</property>
<object class="GtkSeparator">
<property name="margin-bottom">15</property>
</object>
</child>
<child>
<object class="GtkLabel" id="display_distance_presets_description">
<property name="valign">3</property>
<property name="margin-bottom">5</property>
</object>
</child>
<child>
<object class="GtkBox">
<property name="spacing">25</property>
<property name="homogeneous">1</property>
<property name="margin-bottom">15</property>
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="focused_display_distance_label">
<property name="label" translatable="yes"></property>
<property name="valign">3</property>
</object>
</child>
<child>
<object class="GtkButton" id="set_focused_display_distance_button">
<property name="visible">0</property>
<property name="name">set-all-displays-distance</property>
<property name="valign">3</property>
<property name="label"></property>
<property name="margin-start">20</property>
<property name="margin-end">20</property>
</object>
</child>
</object>
</child>
<child>
<object class="GtkBox">
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="all_displays_distance_label">
<property name="label" translatable="yes"></property>
<property name="valign">3</property>
</object>
</child>
<child>
<object class="GtkButton" id="set_all_displays_distance_button">
<property name="visible">0</property>
<property name="name">set-all-displays-distance</property>
<property name="valign">3</property>
<property name="label"></property>
<property name="margin-start">20</property>
<property name="margin-end">20</property>
</object>
</child>
</object>
</child>
</object>
</child>
</object>
@ -167,7 +223,7 @@
<property name="spacing">30</property>
<property name="width-request">150</property>
<property name="margin-start">30</property>
<property name="valign">center</property>
<property name="valign">3</property>
<style>
<class name="flat"/>
</style>

View File

@ -29,18 +29,6 @@
</child>
</object>
</child>
<child>
<object class="AdwActionRow" id="widescreen_mode_row">
<property name="title" translatable="yes"><!-- feature switch -->Start in widescreen mode</property>
<property name="subtitle" translatable="yes">Widescreen mode is not supported for all glasses.</property>
<property name="valign">2</property>
<child>
<object class="GtkSwitch" id="widescreen_mode_switch">
<property name="valign">3</property>
</object>
</child>
</object>
</child>
</object>
</child>
</template>

View File

@ -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')

View File

@ -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: