From 554e0a607c278f5d7e921b581a47320a2290bef1 Mon Sep 17 00:00:00 2001 From: wheaney <42350981+wheaney@users.noreply.github.com> Date: Mon, 6 May 2024 22:57:35 -0700 Subject: [PATCH] Add shortcut dialog support back in --- ui/src/breezydesktop.gresource.xml | 7 +- ui/src/connecteddevice.py | 32 +++++- .../connected-device.ui} | 2 +- ui/src/{nodevice.ui => gtk/no-device.ui} | 0 ui/src/gtk/shortcut-dialog.ui | 43 +++++++ ui/src/{ => gtk}/window.ui | 11 ++ ui/src/meson.build | 7 +- ui/src/nodevice.py | 2 +- ...{SettingsManager.py => settingsmanager.py} | 0 ui/src/shortcutdialog.py | 107 ++++++++++++++++++ ui/src/{StateManager.py => statemanager.py} | 2 +- ui/src/window.py | 7 +- ui/src/{XRDriverIPC.py => xrdriveripc.py} | 0 13 files changed, 204 insertions(+), 16 deletions(-) rename ui/src/{connecteddevice.ui => gtk/connected-device.ui} (98%) rename ui/src/{nodevice.ui => gtk/no-device.ui} (100%) create mode 100644 ui/src/gtk/shortcut-dialog.ui rename ui/src/{ => gtk}/window.ui (76%) rename ui/src/{SettingsManager.py => settingsmanager.py} (100%) create mode 100644 ui/src/shortcutdialog.py rename ui/src/{StateManager.py => statemanager.py} (97%) rename ui/src/{XRDriverIPC.py => xrdriveripc.py} (100%) diff --git a/ui/src/breezydesktop.gresource.xml b/ui/src/breezydesktop.gresource.xml index bdca624..540448f 100644 --- a/ui/src/breezydesktop.gresource.xml +++ b/ui/src/breezydesktop.gresource.xml @@ -1,9 +1,10 @@ - connecteddevice.ui - nodevice.ui - window.ui + gtk/connected-device.ui + gtk/no-device.ui + gtk/shortcut-dialog.ui + gtk/window.ui gtk/help-overlay.ui diff --git a/ui/src/connecteddevice.py b/ui/src/connecteddevice.py index d56afdd..23abb92 100644 --- a/ui/src/connecteddevice.py +++ b/ui/src/connecteddevice.py @@ -1,7 +1,8 @@ -from gi.repository import Adw, Gio, Gtk -from .SettingsManager import SettingsManager +from gi.repository import Gio, Gtk +from .settingsmanager import SettingsManager +from .shortcutdialog import bind_shortcut_settings -@Gtk.Template(resource_path='/com/xronlinux/BreezyDesktop/connecteddevice.ui') +@Gtk.Template(resource_path='/com/xronlinux/BreezyDesktop/gtk/connected-device.ui') class ConnectedDevice(Gtk.Box): __gtype_name__ = "ConnectedDevice" @@ -21,5 +22,30 @@ class ConnectedDevice(Gtk.Box): 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.reassign_toggle_display_distance_shortcut_button + ]) + + self.bind_set_distance_toggle([ + self.set_toggle_display_distance_start_button, + self.set_toggle_display_distance_end_button + ]) + 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 reload_display_distance_toggle_button(widget): + distance = SettingsManager.get_instance().settings.get_double(widget.get_name()) + if distance: widget.set_label(str(distance)) + +def on_set_display_distance_toggle(widget): + settings = SettingsManager.get_instance().settings + distance = settings.get_double('display-distance') + settings.set_double(widget.get_name(), distance) + reload_display_distance_toggle_button(widget) \ No newline at end of file diff --git a/ui/src/connecteddevice.ui b/ui/src/gtk/connected-device.ui similarity index 98% rename from ui/src/connecteddevice.ui rename to ui/src/gtk/connected-device.ui index 52b7a5c..d831291 100644 --- a/ui/src/connecteddevice.ui +++ b/ui/src/gtk/connected-device.ui @@ -105,7 +105,7 @@ - Distance start and end + Display distance start and end Use the buttons to capture the current display distance as start and end points. 2 diff --git a/ui/src/nodevice.ui b/ui/src/gtk/no-device.ui similarity index 100% rename from ui/src/nodevice.ui rename to ui/src/gtk/no-device.ui diff --git a/ui/src/gtk/shortcut-dialog.ui b/ui/src/gtk/shortcut-dialog.ui new file mode 100644 index 0000000..8435a9b --- /dev/null +++ b/ui/src/gtk/shortcut-dialog.ui @@ -0,0 +1,43 @@ + + + + + \ No newline at end of file diff --git a/ui/src/window.ui b/ui/src/gtk/window.ui similarity index 76% rename from ui/src/window.ui rename to ui/src/gtk/window.ui index ec426d3..5566b30 100644 --- a/ui/src/window.ui +++ b/ui/src/gtk/window.ui @@ -6,6 +6,17 @@ 300 + + + Breezy Desktop + 1 + end + 5 + + + True diff --git a/ui/src/meson.build b/ui/src/meson.build index 73f2fc1..160465e 100644 --- a/ui/src/meson.build +++ b/ui/src/meson.build @@ -31,10 +31,11 @@ breezydesktop_sources = [ 'connecteddevice.py', 'main.py', 'nodevice.py', - 'SettingsManager.py', - 'StateManager.py', + 'settingsmanager.py', + 'shortcutdialog.py', + 'statemanager.py', 'window.py', - 'XRDriverIPC.py' + 'xrdriveripc.py' ] install_data(breezydesktop_sources, install_dir: moduledir) diff --git a/ui/src/nodevice.py b/ui/src/nodevice.py index 6f9d434..7006584 100644 --- a/ui/src/nodevice.py +++ b/ui/src/nodevice.py @@ -1,5 +1,5 @@ from gi.repository import Adw, Gtk -@Gtk.Template(resource_path='/com/xronlinux/BreezyDesktop/nodevice.ui') +@Gtk.Template(resource_path='/com/xronlinux/BreezyDesktop/gtk/no-device.ui') class NoDevice(Gtk.Box): __gtype_name__ = "NoDevice" diff --git a/ui/src/SettingsManager.py b/ui/src/settingsmanager.py similarity index 100% rename from ui/src/SettingsManager.py rename to ui/src/settingsmanager.py diff --git a/ui/src/shortcutdialog.py b/ui/src/shortcutdialog.py new file mode 100644 index 0000000..0def848 --- /dev/null +++ b/ui/src/shortcutdialog.py @@ -0,0 +1,107 @@ +from gi.repository import Gtk, Gdk + +from .settingsmanager import SettingsManager + +# ported from https://github.com/velitasali/gnome-shell-extension-awesome-tiles +@Gtk.Template(resource_path='/com/xronlinux/BreezyDesktop/gtk/shortcut-dialog.ui') +class ShortcutDialog(Gtk.Dialog): + __gtype_name__ = 'ShortcutDialog' + + event_controller = Gtk.Template.Child() + + def __init__(self, settings_key): + super(Gtk.Dialog, self).__init__() + self.init_template() + + self.settings_key = settings_key + self.key_pressed_connect_id = self.event_controller.connect('key-pressed', self._on_key_pressed) + + def _on_key_pressed(self, widget, keyval, keycode, state): + mask = state & Gtk.accelerator_get_default_mod_mask() + mask &= ~Gdk.ModifierType.LOCK_MASK + + done = True + if mask == 0 and keyval == Gdk.KEY_Escape: + self.visible = False + elif keyval == Gdk.KEY_BackSpace: + SettingsManager.get_instance().settings.set_strv(self.settings_key, []) + self.close() + elif is_binding_valid(mask, keycode, keyval) and is_accel_valid(state, keyval): + binding = Gtk.accelerator_name_with_keycode( + None, + keyval, + keycode, + state + ) + label = Gtk.accelerator_get_label(keyval, state) + + # hacky way to store the label, causes warnings from the WM + SettingsManager.get_instance().settings.set_strv(self.settings_key, [binding, label]) + + self.close() + else: + done = False + + if done and self.key_pressed_connect_id: + self.event_controller.disconnect(self.key_pressed_connect_id) + self.key_pressed_connect_id = None + + return Gdk.EVENT_STOP + +def is_binding_valid(mask, keycode, keyval): + if mask == 0 or mask == Gdk.ModifierType.SHIFT_MASK and keycode != 0: + if keyval >= Gdk.KEY_a and keyval <= Gdk.KEY_z or \ + keyval >= Gdk.KEY_A and keyval <= Gdk.KEY_Z or \ + keyval >= Gdk.KEY_0 and keyval <= Gdk.KEY_9 or \ + keyval >= Gdk.KEY_kana_fullstop and keyval <= Gdk.KEY_semivoicedsound or \ + keyval >= Gdk.KEY_Arabic_comma and keyval <= Gdk.KEY_Arabic_sukun or \ + keyval >= Gdk.KEY_Serbian_dje and keyval <= Gdk.KEY_Cyrillic_HARDSIGN or \ + keyval >= Gdk.KEY_Greek_ALPHAaccent and keyval <= Gdk.KEY_Greek_omega or \ + keyval >= Gdk.KEY_hebrew_doublelowline and keyval <= Gdk.KEY_hebrew_taf or \ + keyval >= Gdk.KEY_Thai_kokai and keyval <= Gdk.KEY_Thai_lekkao or \ + keyval >= Gdk.KEY_Hangul_Kiyeog and keyval <= Gdk.KEY_Hangul_J_YeorinHieuh or \ + keyval == Gdk.KEY_space and mask == 0 or \ + is_keyval_forbidden(keyval): + return False + return True + +def is_keyval_forbidden(keyval): + forbidden_keyvals = [ + Gdk.KEY_Home, + Gdk.KEY_Left, + Gdk.KEY_Up, + Gdk.KEY_Right, + Gdk.KEY_Down, + Gdk.KEY_Page_Up, + Gdk.KEY_Page_Down, + Gdk.KEY_End, + Gdk.KEY_Tab, + Gdk.KEY_KP_Enter, + Gdk.KEY_Return, + Gdk.KEY_Mode_switch + ] + return keyval in forbidden_keyvals + +def is_accel_valid(mask, keyval): + return Gtk.accelerator_valid(keyval, mask) or (keyval == Gdk.KEY_Tab and mask != 0) + +def bind_shortcut_settings(window, widgets): + for widget in widgets: + SettingsManager.get_instance().settings.connect('changed::' + widget.get_name(), + lambda *args, widget=widget: reload_shortcut_widget(widget)) + widget.connect('clicked', lambda *args, widget=widget: on_assign_shortcut(window, widget)) + + reload_shortcut_widgets(widgets) + +def on_assign_shortcut(window, widget): + dialog = ShortcutDialog(widget.get_name()) + dialog.set_transient_for(widget.get_ancestor(Gtk.Window)) + dialog.present() + +def reload_shortcut_widget(widget): + shortcut = SettingsManager.get_instance().settings.get_strv(widget.get_name()) + widget.set_label(shortcut[1] if len(shortcut) > 1 else 'Disabled') + +def reload_shortcut_widgets(widgets): + for widget in widgets: + reload_shortcut_widget(widget) \ No newline at end of file diff --git a/ui/src/StateManager.py b/ui/src/statemanager.py similarity index 97% rename from ui/src/StateManager.py rename to ui/src/statemanager.py index 427200a..a96a893 100644 --- a/ui/src/StateManager.py +++ b/ui/src/statemanager.py @@ -1,6 +1,6 @@ import threading from gi.repository import GObject -from .XRDriverIPC import XRDriverIPC +from .xrdriveripc import XRDriverIPC class Logger: def info(self, message): diff --git a/ui/src/window.py b/ui/src/window.py index b0d580e..190f8bc 100644 --- a/ui/src/window.py +++ b/ui/src/window.py @@ -18,11 +18,11 @@ # SPDX-License-Identifier: GPL-3.0-or-later from gi.repository import Gtk -from .StateManager import StateManager +from .statemanager import StateManager from .connecteddevice import ConnectedDevice from .nodevice import NoDevice -@Gtk.Template(resource_path='/com/xronlinux/BreezyDesktop/window.ui') +@Gtk.Template(resource_path='/com/xronlinux/BreezyDesktop/gtk/window.ui') class BreezydesktopWindow(Gtk.ApplicationWindow): __gtype_name__ = 'BreezydesktopWindow' @@ -45,5 +45,4 @@ class BreezydesktopWindow(Gtk.ApplicationWindow): self.connected_device.set_device_name(connected_device_name) else: self.connected_device.set_visible(False) - self.no_device.set_visible(True) - + self.no_device.set_visible(True) \ No newline at end of file diff --git a/ui/src/XRDriverIPC.py b/ui/src/xrdriveripc.py similarity index 100% rename from ui/src/XRDriverIPC.py rename to ui/src/xrdriveripc.py