Add follow mode support
This commit is contained in:
parent
204ae71dd9
commit
e50a3f1c2b
|
|
@ -2,3 +2,4 @@
|
|||
/build/
|
||||
__pycache__
|
||||
*.zip
|
||||
gschemas.compiled
|
||||
|
|
|
|||
|
|
@ -155,6 +155,7 @@ export default class BreezyDesktopExtension extends Extension {
|
|||
|
||||
this._add_settings_keybinding('recenter-display-shortcut', this._recenter_display.bind(this));
|
||||
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));
|
||||
} catch (e) {
|
||||
console.error('Error enabling XR effect', e);
|
||||
this._effect_disable();
|
||||
|
|
@ -187,13 +188,21 @@ export default class BreezyDesktopExtension extends Extension {
|
|||
});
|
||||
}
|
||||
|
||||
_recenter_display() {
|
||||
_write_control(key, value) {
|
||||
const file = Gio.file_new_for_path('/dev/shm/xr_driver_control');
|
||||
const stream = file.replace(null, false, Gio.FileCreateFlags.NONE, null);
|
||||
stream.write('recenter_screen=true', null);
|
||||
stream.write(`${key}=${value}`, null);
|
||||
stream.close(null);
|
||||
}
|
||||
|
||||
_recenter_display() {
|
||||
this._write_control('recenter_screen', 'true');
|
||||
}
|
||||
|
||||
_toggle_follow_mode() {
|
||||
this._write_control('toggle_breezy_desktop_smooth_follow', 'true');
|
||||
}
|
||||
|
||||
_effect_disable() {
|
||||
this._is_effect_running = false;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# stolen from dconf-editor:
|
||||
# https://gitlab.gnome.org/GNOME/dconf-editor/-/blob/master/build-aux/start-dconf-editor.sh
|
||||
|
||||
IFS=: read -ra host_data_dirs < <(flatpak-spawn --host sh -c 'echo "$XDG_DATA_DIRS"')
|
||||
|
||||
# To avoid potentially muddying up $XDG_DATA_DIRS too much, we link the schema paths
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
[Desktop Entry]
|
||||
Name=breezydesktop
|
||||
Name=Breezy Desktop
|
||||
Exec=start-breezy-desktop
|
||||
Icon=com.xronlinux.BreezyDesktop
|
||||
Terminal=false
|
||||
|
|
|
|||
|
|
@ -28,6 +28,15 @@
|
|||
Shortcut to change the display distance.
|
||||
</description>
|
||||
</key>
|
||||
<key name="toggle-follow-shortcut" type="as">
|
||||
<default>
|
||||
<![CDATA[['<Control><Super>0']]]>
|
||||
</default>
|
||||
<summary>Toggle follow mode</summary>
|
||||
<description>
|
||||
Shortcut to toggle follow mode.
|
||||
</description>
|
||||
</key>
|
||||
<key name="display-distance" type="d">
|
||||
<default>
|
||||
1.05
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
from gi.repository import Gio, Gtk
|
||||
from gi.repository import Gio, Gtk, GObject
|
||||
from .settingsmanager import SettingsManager
|
||||
from .shortcutdialog import bind_shortcut_settings
|
||||
from .statemanager import StateManager
|
||||
from .xrdriveripc import XRDriverIPC
|
||||
|
||||
@Gtk.Template(resource_path='/com/xronlinux/BreezyDesktop/gtk/connected-device.ui')
|
||||
class ConnectedDevice(Gtk.Box):
|
||||
|
|
@ -8,6 +10,7 @@ class ConnectedDevice(Gtk.Box):
|
|||
|
||||
effect_enable_switch = Gtk.Template.Child()
|
||||
display_distance_scale = Gtk.Template.Child()
|
||||
follow_mode_switch = Gtk.Template.Child()
|
||||
device_label = Gtk.Template.Child()
|
||||
set_toggle_display_distance_start_button = Gtk.Template.Child()
|
||||
set_toggle_display_distance_end_button = Gtk.Template.Child()
|
||||
|
|
@ -15,18 +18,22 @@ class ConnectedDevice(Gtk.Box):
|
|||
recenter_display_shortcut_label = Gtk.Template.Child()
|
||||
reassign_toggle_display_distance_shortcut_button = Gtk.Template.Child()
|
||||
toggle_display_distance_shortcut_label = Gtk.Template.Child()
|
||||
reassign_toggle_follow_shortcut_button = Gtk.Template.Child()
|
||||
toggle_follow_shortcut_label = Gtk.Template.Child()
|
||||
|
||||
def __init__(self):
|
||||
super(Gtk.Box, self).__init__()
|
||||
self.init_template()
|
||||
self.settings = SettingsManager.get_instance().settings
|
||||
self.ipc = XRDriverIPC.get_instance()
|
||||
|
||||
self.settings.bind('display-distance', self.display_distance_scale, 'value', Gio.SettingsBindFlags.DEFAULT)
|
||||
self.settings.bind('effect-enable', self.effect_enable_switch, 'active', Gio.SettingsBindFlags.DEFAULT)
|
||||
|
||||
bind_shortcut_settings(self.get_parent(), [
|
||||
[self.reassign_recenter_display_shortcut_button, self.recenter_display_shortcut_label],
|
||||
[self.reassign_toggle_display_distance_shortcut_button, self.toggle_display_distance_shortcut_label]
|
||||
[self.reassign_toggle_display_distance_shortcut_button, self.toggle_display_distance_shortcut_label],
|
||||
[self.reassign_toggle_follow_shortcut_button, self.toggle_follow_shortcut_label]
|
||||
])
|
||||
|
||||
self.bind_set_distance_toggle([
|
||||
|
|
@ -34,6 +41,20 @@ class ConnectedDevice(Gtk.Box):
|
|||
self.set_toggle_display_distance_end_button
|
||||
])
|
||||
|
||||
self.state_manager = StateManager.get_instance()
|
||||
self.state_manager.bind_property('follow-mode', self.follow_mode_switch, 'active', GObject.BindingFlags.DEFAULT)
|
||||
|
||||
self.follow_mode_switch.set_active(self.state_manager.follow_mode)
|
||||
self.follow_mode_switch.connect('notify::active', self._request_follow_mode)
|
||||
|
||||
def _request_follow_mode(self, switch, param):
|
||||
if (self.state_manager.follow_mode == switch.get_active()):
|
||||
return
|
||||
|
||||
self.ipc.write_control_flags({
|
||||
'enable_breezy_desktop_smooth_follow': switch.get_active()
|
||||
})
|
||||
|
||||
def set_device_name(self, name):
|
||||
self.device_label.set_markup(f"<b>{name}</b>")
|
||||
|
||||
|
|
|
|||
|
|
@ -65,6 +65,17 @@
|
|||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title" translatable="true">Follow enabled</property>
|
||||
<property name="subtitle" translatable="true">Keep the virtual display near the center of your view</property>
|
||||
<child>
|
||||
<object class="GtkSwitch" id="follow_mode_switch">
|
||||
<property name="valign">3</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
|
|
@ -155,6 +166,35 @@
|
|||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="AdwActionRow">
|
||||
<property name="title" translatable="true">Toggle follow mode shortcut</property>
|
||||
<property name="subtitle" translatable="true">Quickly toggle follow mode</property>
|
||||
<property name="valign">2</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="spacing">30</property>
|
||||
<property name="margin-start">30</property>
|
||||
<child>
|
||||
<object class="GtkShortcutLabel" id="toggle_follow_shortcut_label">
|
||||
<property name="valign">3</property>
|
||||
<property name="accelerator"></property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="reassign_toggle_follow_shortcut_button">
|
||||
<style>
|
||||
<class name="row-button"/>
|
||||
</style>
|
||||
<property name="name">toggle-follow-shortcut</property>
|
||||
<property name="valign">3</property>
|
||||
<property name="label" translatable="true">Change</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -11,7 +11,11 @@ class Logger:
|
|||
|
||||
class StateManager(GObject.GObject):
|
||||
__gsignals__ = {
|
||||
'device_update': (GObject.SIGNAL_RUN_FIRST, None, (str,))
|
||||
'device-update': (GObject.SIGNAL_RUN_FIRST, None, (str,))
|
||||
}
|
||||
|
||||
__gproperties__ = {
|
||||
'follow-mode': (bool, 'Follow Mode', 'Whether the follow mode is enabled', False, GObject.ParamFlags.READWRITE)
|
||||
}
|
||||
|
||||
_instance = None
|
||||
|
|
@ -32,7 +36,7 @@ class StateManager(GObject.GObject):
|
|||
|
||||
def __init__(self):
|
||||
GObject.GObject.__init__(self)
|
||||
self.ipc = XRDriverIPC(logger = Logger(), user="wayne", user_home="/home/wayne")
|
||||
self.ipc = XRDriverIPC.get_instance()
|
||||
self.connected_device_name = None
|
||||
|
||||
self.start()
|
||||
|
|
@ -49,6 +53,16 @@ class StateManager(GObject.GObject):
|
|||
new_device_name = StateManager.device_name(self.state)
|
||||
if self.connected_device_name != new_device_name:
|
||||
self.connected_device_name = new_device_name
|
||||
self.emit('device_update', self.connected_device_name)
|
||||
self.emit('device-update', self.connected_device_name)
|
||||
|
||||
self.set_property('follow-mode', self.state.get('breezy_desktop_smooth_follow_enabled'))
|
||||
|
||||
if self.running: threading.Timer(1.0, self._refresh_state).start()
|
||||
|
||||
def do_set_property(self, prop, value):
|
||||
if prop.name == 'follow-mode':
|
||||
self.follow_mode = value
|
||||
|
||||
def do_get_property(self, prop):
|
||||
if prop.name == 'follow-mode':
|
||||
return self.follow_mode
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ class BreezydesktopWindow(Gtk.ApplicationWindow):
|
|||
super().__init__(**kwargs)
|
||||
|
||||
state_manager = StateManager.get_instance()
|
||||
state_manager.connect('device_update', self._handle_device_update)
|
||||
state_manager.connect('device-update', self._handle_device_update)
|
||||
|
||||
self.connected_device = ConnectedDevice()
|
||||
self.no_device = NoDevice()
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ CONTROL_FLAGS_FILE_PATH = '/dev/shm/xr_driver_control'
|
|||
# read-only file that the driver writes (but never reads) to with its current state
|
||||
DRIVER_STATE_FILE_PATH = '/dev/shm/xr_driver_state'
|
||||
|
||||
CONTROL_FLAGS = ['recenter_screen', 'recalibrate', 'sbs_mode', 'refresh_device_license']
|
||||
CONTROL_FLAGS = ['recenter_screen', 'recalibrate', 'sbs_mode', 'refresh_device_license', 'enable_breezy_desktop_smooth_follow']
|
||||
SBS_MODE_VALUES = ['unset', 'enable', 'disable']
|
||||
MANAGED_EXTERNAL_MODES = ['virtual_display', 'sideview', 'none']
|
||||
VR_LITE_OUTPUT_MODES = ['mouse', 'joystick']
|
||||
|
|
@ -58,8 +58,24 @@ CONFIG_ENTRIES = {
|
|||
'sideview_smooth_follow_enabled': [parse_boolean, False]
|
||||
}
|
||||
|
||||
class Logger:
|
||||
def info(self, message):
|
||||
print(message)
|
||||
|
||||
def error(self, message):
|
||||
print(message)
|
||||
|
||||
class XRDriverIPC:
|
||||
def __init__(self, logger, user=None, user_home=None):
|
||||
_instance = None
|
||||
|
||||
@staticmethod
|
||||
def get_instance():
|
||||
if not XRDriverIPC._instance:
|
||||
XRDriverIPC._instance = XRDriverIPC()
|
||||
|
||||
return XRDriverIPC._instance
|
||||
|
||||
def __init__(self, logger=Logger(), user=None, user_home=None):
|
||||
self.breezy_installed = False
|
||||
self.breezy_installing = False
|
||||
self.user = user if user else pwd.getpwuid( os.getuid() )[0]
|
||||
|
|
@ -218,6 +234,7 @@ class XRDriverIPC:
|
|||
state['sbs_mode_supported'] = False
|
||||
state['firmware_update_recommended'] = False
|
||||
state['device_license'] = {}
|
||||
state['breezy_desktop_smooth_follow_enabled'] = False
|
||||
|
||||
try:
|
||||
with open(DRIVER_STATE_FILE_PATH, 'r') as f:
|
||||
|
|
@ -232,7 +249,7 @@ class XRDriverIPC:
|
|||
state[key] = parse_int(value, 0)
|
||||
elif key in ['calibration_setup', 'calibration_state', 'connected_device_brand', 'connected_device_model']:
|
||||
state[key] = value
|
||||
elif key in ['sbs_mode_enabled', 'sbs_mode_supported', 'firmware_update_recommended']:
|
||||
elif key in ['sbs_mode_enabled', 'sbs_mode_supported', 'firmware_update_recommended', 'breezy_desktop_smooth_follow_enabled']:
|
||||
state[key] = parse_boolean(value, False)
|
||||
elif key == 'device_license':
|
||||
state[key] = json.loads(value)
|
||||
|
|
|
|||
Loading…
Reference in New Issue