From 7421cdba8f75bc3e0c3f229c6f0bf840219dca53 Mon Sep 17 00:00:00 2001 From: Colin Powell Date: Wed, 3 Apr 2024 12:59:14 -0400 Subject: [PATCH] [gnome] Update extensions for v46 --- gnome/.commands.json | 34 + .../BingWallpaper@ineffable-gmail.com/blur.js | 27 +- .../carousel.js | 5 +- .../extension.js | 14 +- .../locale/pt_BR/LC_MESSAGES/BingWallpaper.mo | Bin 5809 -> 7709 bytes .../metadata.json | 5 +- .../prefs.js | 307 ++-- .../schemas/gschemas.compiled | Bin 2432 -> 2432 bytes ...shell.extensions.bingwallpaper.gschema.xml | 2 +- .../ui/Settings4.ui | 1451 ---------------- .../ui/carousel4.ui | 4 +- .../ui/prefsadw.ui | 438 +++++ .../utils.js | 32 +- .../Options_UI.glade | 1493 +++++++++++++++++ .../convenience.js | 86 + .../display_module.js | 40 + .../extension.js | 1034 ++++++++++++ .../images/Icon_Info.png | Bin 0 -> 4260 bytes .../images/Icon_Performance.svg | 45 + .../images/Icon_Quality.svg | 45 + .../images/icon_default.svg | 99 ++ .../images/icon_defaultSel.svg | 99 ++ .../images/icon_recording.svg | 99 ++ .../images/icon_recordingSel.svg | 99 ++ ...EasyScreenCast@iacopodeenosee.gmail.com.mo | Bin 0 -> 8718 bytes ...EasyScreenCast@iacopodeenosee.gmail.com.mo | Bin 0 -> 9663 bytes ...EasyScreenCast@iacopodeenosee.gmail.com.mo | Bin 0 -> 7022 bytes ...EasyScreenCast@iacopodeenosee.gmail.com.mo | Bin 0 -> 5999 bytes ...EasyScreenCast@iacopodeenosee.gmail.com.mo | Bin 0 -> 8742 bytes ...EasyScreenCast@iacopodeenosee.gmail.com.mo | Bin 0 -> 7775 bytes ...EasyScreenCast@iacopodeenosee.gmail.com.mo | Bin 0 -> 8787 bytes ...EasyScreenCast@iacopodeenosee.gmail.com.mo | Bin 0 -> 9806 bytes ...EasyScreenCast@iacopodeenosee.gmail.com.mo | Bin 0 -> 6537 bytes ...EasyScreenCast@iacopodeenosee.gmail.com.mo | Bin 0 -> 8481 bytes ...EasyScreenCast@iacopodeenosee.gmail.com.mo | Bin 0 -> 8909 bytes ...EasyScreenCast@iacopodeenosee.gmail.com.mo | Bin 0 -> 9068 bytes .../metadata.json | 13 + .../prefs.css | 7 + .../prefs.js | 1184 +++++++++++++ .../schemas/gschemas.compiled | Bin 0 -> 2580 bytes ...hell.extensions.easyscreencast.gschema.xml | 200 +++ .../selection.js | 534 ++++++ .../settings.js | 192 +++ .../stylesheet.css | 36 + .../timer.js | 259 +++ .../utilaudio.js | 321 ++++ .../utilexecmd.js | 266 +++ .../utilgsp.js | 737 ++++++++ .../utilnotify.js | 147 ++ .../utilrecorder.js | 216 +++ .../utilwebcam.js | 315 ++++ .../Vitals@CoreCoding.com/extension.js | 155 +- .../helpers/subprocess.js | 54 + .../icons/{ => gnome}/battery-symbolic.svg | 0 .../icons/gnome/cpu-symbolic.svg | 1 + .../icons/gnome/fan-symbolic.svg | 1 + .../icons/gnome/gpu-symbolic.svg | 15 + .../icons/gnome/memory-symbolic.svg | 1 + .../icons/gnome/network-download-symbolic.svg | 1 + .../icons/gnome/network-symbolic.svg | 1 + .../icons/gnome/network-upload-symbolic.svg | 1 + .../icons/gnome/storage-symbolic.svg | 1 + .../icons/gnome/system-symbolic.svg | 1 + .../icons/gnome/temperature-symbolic.svg | 1 + .../icons/gnome/voltage-symbolic.svg | 1 + .../icons/original/battery-symbolic.svg | 8 + .../icons/{ => original}/cpu-symbolic.svg | 0 .../icons/{ => original}/fan-symbolic.svg | 0 .../icons/original/gpu-symbolic.svg | 15 + .../icons/{ => original}/memory-symbolic.svg | 0 .../network-download-symbolic.svg | 0 .../icons/{ => original}/network-symbolic.svg | 0 .../network-upload-symbolic.svg | 0 .../icons/{ => original}/storage-symbolic.svg | 0 .../icons/{ => original}/system-symbolic.svg | 0 .../{ => original}/temperature-symbolic.svg | 0 .../icons/{ => original}/voltage-symbolic.svg | 0 .../locale/be/LC_MESSAGES/vitals.mo | Bin 0 -> 10985 bytes .../locale/de/LC_MESSAGES/vitals.mo | Bin 8159 -> 11776 bytes .../locale/pt_BR/LC_MESSAGES/vitals.mo | Bin 7407 -> 8396 bytes .../Vitals@CoreCoding.com/menuItem.js | 6 +- .../Vitals@CoreCoding.com/metadata.json | 8 +- .../extensions/Vitals@CoreCoding.com/prefs.js | 7 +- .../extensions/Vitals@CoreCoding.com/prefs.ui | 1048 +++++++----- .../schemas/gschemas.compiled | Bin 1780 -> 1972 bytes ....gnome.shell.extensions.vitals.gschema.xml | 15 + .../Vitals@CoreCoding.com/sensors.js | 252 +++ .../Vitals@CoreCoding.com/values.js | 19 +- .../metadata.json | 6 +- .../extension.js | 28 - .../metadata.json | 15 - .../components/appfolders.js | 8 +- .../components/applications.js | 24 +- .../components/dash_to_dock.js | 420 +++-- .../components/lockscreen.js | 9 +- .../components/overview.js | 20 +- .../blur-my-shell@aunetx/components/panel.js | 32 +- .../components/screenshot.js | 8 +- .../components/window_list.js | 12 +- .../blur-my-shell@aunetx/conveniences/keys.js | 2 + .../blur-my-shell@aunetx/dbus/services.js | 3 + .../effects/blur_effect.glsl | 114 ++ .../effects/blur_effect.js | 236 +++ .../blur-my-shell@aunetx/extension.js | 124 +- .../af/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 0 -> 11393 bytes ...ur-my-shell.mo => blur-my-shell@aunetx.mo} | Bin 12893 -> 13175 bytes ...ur-my-shell.mo => blur-my-shell@aunetx.mo} | Bin .../be/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 0 -> 326 bytes ...ur-my-shell.mo => blur-my-shell@aunetx.mo} | Bin .../locale/ca/LC_MESSAGES/blur-my-shell.mo | Bin 1402 -> 0 bytes .../ca/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 0 -> 1770 bytes ...ur-my-shell.mo => blur-my-shell@aunetx.mo} | Bin 11360 -> 12299 bytes ...ur-my-shell.mo => blur-my-shell@aunetx.mo} | Bin 11858 -> 12116 bytes ...ur-my-shell.mo => blur-my-shell@aunetx.mo} | Bin ...ur-my-shell.mo => blur-my-shell@aunetx.mo} | Bin 11744 -> 12631 bytes ...ur-my-shell.mo => blur-my-shell@aunetx.mo} | Bin 11908 -> 12878 bytes ...ur-my-shell.mo => blur-my-shell@aunetx.mo} | Bin .../hi/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 0 -> 19509 bytes ...ur-my-shell.mo => blur-my-shell@aunetx.mo} | Bin 11464 -> 12140 bytes .../id/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 0 -> 11597 bytes ...ur-my-shell.mo => blur-my-shell@aunetx.mo} | Bin 11739 -> 12696 bytes ...ur-my-shell.mo => blur-my-shell@aunetx.mo} | Bin ...ur-my-shell.mo => blur-my-shell@aunetx.mo} | Bin .../locale/nb_NO/LC_MESSAGES/blur-my-shell.mo | Bin 3908 -> 0 bytes .../nb_NO/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 0 -> 11317 bytes ...ur-my-shell.mo => blur-my-shell@aunetx.mo} | Bin 11469 -> 12435 bytes ...ur-my-shell.mo => blur-my-shell@aunetx.mo} | Bin ...ur-my-shell.mo => blur-my-shell@aunetx.mo} | Bin 11370 -> 11603 bytes ...ur-my-shell.mo => blur-my-shell@aunetx.mo} | Bin 11087 -> 11684 bytes ...ur-my-shell.mo => blur-my-shell@aunetx.mo} | Bin 11531 -> 12431 bytes .../ro/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 0 -> 1762 bytes ...ur-my-shell.mo => blur-my-shell@aunetx.mo} | Bin 14926 -> 16241 bytes ...ur-my-shell.mo => blur-my-shell@aunetx.mo} | Bin ...ur-my-shell.mo => blur-my-shell@aunetx.mo} | Bin 11310 -> 11545 bytes ...ur-my-shell.mo => blur-my-shell@aunetx.mo} | Bin 19778 -> 20639 bytes ...ur-my-shell.mo => blur-my-shell@aunetx.mo} | Bin 11767 -> 12264 bytes ...ur-my-shell.mo => blur-my-shell@aunetx.mo} | Bin 14402 -> 14777 bytes .../locale/vi/LC_MESSAGES/blur-my-shell.mo | Bin 7854 -> 0 bytes .../vi/LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 0 -> 8849 bytes .../LC_MESSAGES/blur-my-shell@aunetx.mo | Bin 0 -> 10828 bytes .../LC_MESSAGES/blur-my-shell@aunetx.mo} | Bin 10394 -> 10391 bytes .../blur-my-shell@aunetx/metadata.json | 12 +- .../blur-my-shell@aunetx/preferences/dash.js | 12 + .../blur-my-shell@aunetx/preferences/panel.js | 5 + .../preferences/window_row.js | 9 +- .../schemas/gschemas.compiled | Bin 8160 -> 8296 bytes ...shell.extensions.blur-my-shell.gschema.xml | 65 +- .../blur-my-shell@aunetx/stylesheet.css | 400 +++-- .../blur-my-shell@aunetx/ui/applications.ui | 2 +- .../blur-my-shell@aunetx/ui/dash.ui | 46 + .../blur-my-shell@aunetx/ui/panel.ui | 23 +- .../blur-my-shell@aunetx/ui/window-row.ui | 4 + .../forge@jmmaranan.com/config/windows.json | 10 +- .../lib/extension/indicator.js | 8 + .../forge@jmmaranan.com/lib/extension/tree.js | 48 +- .../lib/extension/window.js | 232 ++- .../forge@jmmaranan.com/lib/prefs/settings.js | 14 + .../locale/it/LC_MESSAGES/forge.mo | Bin 3563 -> 5667 bytes .../locale/pt_BR/LC_MESSAGES/forge.mo | Bin 3066 -> 4264 bytes .../forge@jmmaranan.com/metadata.json | 5 +- .../forge@jmmaranan.com/stylesheet.css | 8 + .../gjsosk@vishram1123.com/extension.js | 690 +++++--- .../gjsosk@vishram1123.com/keycodes.json | 274 +-- .../gjsosk@vishram1123.com/prefs.js | 61 +- .../schemas/gschemas.compiled | Bin 1536 -> 1592 bytes ....gnome.shell.extensions.gjsosk.gschema.xml | 3 + .../gjsosk@vishram1123.com/stylesheet.css | 189 ++- .../hicolor/scalable/actions/alt-dark.svg | 51 + .../ui/icons/hicolor/scalable/actions/alt.svg | 69 + .../actions/app-icon-design-symbolic.svg | 49 + .../scalable/actions/backspace-dark.svg | 1 + .../hicolor/scalable/actions/backspace.svg | 36 + .../scalable/actions/capslock-dark.svg | 1 + .../hicolor/scalable/actions/capslock.svg | 1 + .../hicolor/scalable/actions/ctrl-dark.svg | 1 + .../icons/hicolor/scalable/actions/ctrl.svg | 1 + .../hicolor/scalable/actions/delete-dark.svg | 36 + .../icons/hicolor/scalable/actions/delete.svg | 36 + .../hicolor/scalable/actions/down-dark.svg | 1 + .../icons/hicolor/scalable/actions/down.svg | 1 + .../hicolor/scalable/actions/enter-dark.svg | 1 + .../icons/hicolor/scalable/actions/enter.svg | 1 + .../hicolor/scalable/actions/left-dark.svg | 1 + .../icons/hicolor/scalable/actions/left.svg | 1 + .../hicolor/scalable/actions/right-dark.svg | 1 + .../icons/hicolor/scalable/actions/right.svg | 1 + .../hicolor/scalable/actions/shift-dark.svg | 1 + .../icons/hicolor/scalable/actions/shift.svg | 1 + .../hicolor/scalable/actions/space-dark.svg | 1 + .../icons/hicolor/scalable/actions/space.svg | 1 + .../hicolor/scalable/actions/super-dark.svg | 37 + .../icons/hicolor/scalable/actions/super.svg | 37 + .../hicolor/scalable/actions/tab-dark.svg | 1 + .../ui/icons/hicolor/scalable/actions/tab.svg | 1 + .../hicolor/scalable/actions/up-dark.svg | 1 + .../ui/icons/hicolor/scalable/actions/up.svg | 1 + .../gsconnect@andyholmes.github.io/config.js | 8 +- .../gsconnect-preferences | 0 .../org.gnome.Shell.Extensions.GSConnect.mo | Bin 0 -> 19433 bytes .../metadata.json | 17 +- .../nautilus-gsconnect.py | 42 +- ...gnome.Shell.Extensions.GSConnect.gresource | Bin 65132 -> 60052 bytes .../service/components/input.js | 61 +- .../service/components/pulseaudio.js | 7 +- .../service/core.js | 4 - .../service/daemon.js | 0 .../service/device.js | 4 - .../service/nativeMessagingHost.js | 0 .../service/utils/setup.js | 8 +- .../shell/notification.js | 159 +- .../extension.js | 162 +- .../metadata.json | 5 +- .../screen-rotate@shyzus.github.io/prefs.js | 41 +- .../screen-rotate@shyzus.github.io/rotator.js | 7 +- .../schemas/gschemas.compiled | Bin 576 -> 684 bytes ...shell.extensions.screen-rotate.gschema.xml | 9 +- .../CHANGELOG.md | 278 +++ .../LICENSE | 674 ++++++++ .../extension.js | 35 + .../icons/threshold-active-symbolic.svg | 47 + .../icons/threshold-active.svg | 47 + .../icons/threshold-app-symbolic.svg | 47 + .../icons/threshold-error-symbolic.svg | 4 + .../icons/threshold-error.svg | 39 + .../icons/threshold-inactive-symbolic.svg | 45 + .../icons/threshold-inactive.svg | 45 + .../icons/threshold-unknown-symbolic.svg | 45 + .../icons/threshold-unknown.svg | 45 + .../libs/driver.js | 857 ++++++++++ .../libs/indicator.js | 431 +++++ ...ad-battery-threshold@marcosdalvarez.org.mo | Bin 0 -> 4711 bytes ...ad-battery-threshold@marcosdalvarez.org.mo | Bin 0 -> 5001 bytes ...ad-battery-threshold@marcosdalvarez.org.mo | Bin 0 -> 4921 bytes ...ad-battery-threshold@marcosdalvarez.org.mo | Bin 0 -> 4783 bytes ...ad-battery-threshold@marcosdalvarez.org.mo | Bin 0 -> 4155 bytes ...ad-battery-threshold@marcosdalvarez.org.mo | Bin 0 -> 5301 bytes ...ad-battery-threshold@marcosdalvarez.org.mo | Bin 0 -> 2282 bytes ...ad-battery-threshold@marcosdalvarez.org.mo | Bin 0 -> 4816 bytes ...ad-battery-threshold@marcosdalvarez.org.mo | Bin 0 -> 4803 bytes ...ad-battery-threshold@marcosdalvarez.org.mo | Bin 0 -> 6240 bytes .../metadata.json | 14 + .../preferences/about.js | 55 + .../preferences/general.js | 75 + .../preferences/thinkpad.js | 119 ++ .../preferences/utils.js | 20 + .../prefs.js | 23 + .../schemas/gschemas.compiled | Bin 0 -> 792 bytes ...l.extensions.battery-threshold.gschema.xml | 50 + .../ui/about.ui | 101 ++ .../ui/general.ui | 84 + .../ui/thinkpad.ui | 148 ++ 251 files changed, 15759 insertions(+), 3153 deletions(-) create mode 100644 gnome/.commands.json delete mode 100644 gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/ui/Settings4.ui create mode 100644 gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/ui/prefsadw.ui create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/Options_UI.glade create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/convenience.js create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/display_module.js create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/extension.js create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/images/Icon_Info.png create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/images/Icon_Performance.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/images/Icon_Quality.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/images/icon_default.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/images/icon_defaultSel.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/images/icon_recording.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/images/icon_recordingSel.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/locale/ca/LC_MESSAGES/EasyScreenCast@iacopodeenosee.gmail.com.mo create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/locale/cs/LC_MESSAGES/EasyScreenCast@iacopodeenosee.gmail.com.mo create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/locale/de/LC_MESSAGES/EasyScreenCast@iacopodeenosee.gmail.com.mo create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/locale/es/LC_MESSAGES/EasyScreenCast@iacopodeenosee.gmail.com.mo create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/locale/fr/LC_MESSAGES/EasyScreenCast@iacopodeenosee.gmail.com.mo create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/locale/it/LC_MESSAGES/EasyScreenCast@iacopodeenosee.gmail.com.mo create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/locale/ja/LC_MESSAGES/EasyScreenCast@iacopodeenosee.gmail.com.mo create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/locale/pt_BR/LC_MESSAGES/EasyScreenCast@iacopodeenosee.gmail.com.mo create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/locale/ru/LC_MESSAGES/EasyScreenCast@iacopodeenosee.gmail.com.mo create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/locale/uk/LC_MESSAGES/EasyScreenCast@iacopodeenosee.gmail.com.mo create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/locale/vi/LC_MESSAGES/EasyScreenCast@iacopodeenosee.gmail.com.mo create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/locale/zh/LC_MESSAGES/EasyScreenCast@iacopodeenosee.gmail.com.mo create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/metadata.json create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/prefs.css create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/prefs.js create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/schemas/gschemas.compiled create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/schemas/org.gnome.shell.extensions.easyscreencast.gschema.xml create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/selection.js create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/settings.js create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/stylesheet.css create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/timer.js create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/utilaudio.js create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/utilexecmd.js create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/utilgsp.js create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/utilnotify.js create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/utilrecorder.js create mode 100644 gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/utilwebcam.js create mode 100644 gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/helpers/subprocess.js rename gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/{ => gnome}/battery-symbolic.svg (100%) create mode 100644 gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/cpu-symbolic.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/fan-symbolic.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/gpu-symbolic.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/memory-symbolic.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/network-download-symbolic.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/network-symbolic.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/network-upload-symbolic.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/storage-symbolic.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/system-symbolic.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/temperature-symbolic.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/voltage-symbolic.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/original/battery-symbolic.svg rename gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/{ => original}/cpu-symbolic.svg (100%) rename gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/{ => original}/fan-symbolic.svg (100%) create mode 100644 gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/original/gpu-symbolic.svg rename gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/{ => original}/memory-symbolic.svg (100%) rename gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/{ => original}/network-download-symbolic.svg (100%) rename gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/{ => original}/network-symbolic.svg (100%) rename gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/{ => original}/network-upload-symbolic.svg (100%) rename gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/{ => original}/storage-symbolic.svg (100%) rename gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/{ => original}/system-symbolic.svg (100%) rename gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/{ => original}/temperature-symbolic.svg (100%) rename gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/{ => original}/voltage-symbolic.svg (100%) create mode 100644 gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/be/LC_MESSAGES/vitals.mo delete mode 100644 gnome/.local/share/gnome-shell/extensions/block-caribou-36@lxylxy123456.ercli.dev/extension.js delete mode 100644 gnome/.local/share/gnome-shell/extensions/block-caribou-36@lxylxy123456.ercli.dev/metadata.json create mode 100644 gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/blur_effect.glsl create mode 100644 gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/blur_effect.js create mode 100644 gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/af/LC_MESSAGES/blur-my-shell@aunetx.mo rename gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ar/LC_MESSAGES/{blur-my-shell.mo => blur-my-shell@aunetx.mo} (73%) rename gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/az/LC_MESSAGES/{blur-my-shell.mo => blur-my-shell@aunetx.mo} (100%) create mode 100644 gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/be/LC_MESSAGES/blur-my-shell@aunetx.mo rename gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/bg/LC_MESSAGES/{blur-my-shell.mo => blur-my-shell@aunetx.mo} (100%) delete mode 100644 gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ca/LC_MESSAGES/blur-my-shell.mo create mode 100644 gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ca/LC_MESSAGES/blur-my-shell@aunetx.mo rename gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/cs/LC_MESSAGES/{blur-my-shell.mo => blur-my-shell@aunetx.mo} (52%) rename gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/de/LC_MESSAGES/{blur-my-shell.mo => blur-my-shell@aunetx.mo} (71%) rename gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/el/LC_MESSAGES/{blur-my-shell.mo => blur-my-shell@aunetx.mo} (100%) rename gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/es/LC_MESSAGES/{blur-my-shell.mo => blur-my-shell@aunetx.mo} (53%) rename gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/fr/LC_MESSAGES/{blur-my-shell.mo => blur-my-shell@aunetx.mo} (54%) rename gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/he/LC_MESSAGES/{blur-my-shell.mo => blur-my-shell@aunetx.mo} (100%) create mode 100644 gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/hi/LC_MESSAGES/blur-my-shell@aunetx.mo rename gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/hu/LC_MESSAGES/{blur-my-shell.mo => blur-my-shell@aunetx.mo} (53%) create mode 100644 gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/id/LC_MESSAGES/blur-my-shell@aunetx.mo rename gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/it/LC_MESSAGES/{blur-my-shell.mo => blur-my-shell@aunetx.mo} (53%) rename gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ka/LC_MESSAGES/{blur-my-shell.mo => blur-my-shell@aunetx.mo} (100%) rename gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ko/LC_MESSAGES/{blur-my-shell.mo => blur-my-shell@aunetx.mo} (100%) delete mode 100644 gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/nb_NO/LC_MESSAGES/blur-my-shell.mo create mode 100644 gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/nb_NO/LC_MESSAGES/blur-my-shell@aunetx.mo rename gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/nl/LC_MESSAGES/{blur-my-shell.mo => blur-my-shell@aunetx.mo} (52%) rename gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/nn/LC_MESSAGES/{blur-my-shell.mo => blur-my-shell@aunetx.mo} (100%) rename gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/pl/LC_MESSAGES/{blur-my-shell.mo => blur-my-shell@aunetx.mo} (70%) rename gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/pt/LC_MESSAGES/{blur-my-shell.mo => blur-my-shell@aunetx.mo} (52%) rename gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/pt_BR/LC_MESSAGES/{blur-my-shell.mo => blur-my-shell@aunetx.mo} (53%) create mode 100644 gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ro/LC_MESSAGES/blur-my-shell@aunetx.mo rename gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ru/LC_MESSAGES/{blur-my-shell.mo => blur-my-shell@aunetx.mo} (55%) rename gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/sl/LC_MESSAGES/{blur-my-shell.mo => blur-my-shell@aunetx.mo} (100%) rename gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/sv/LC_MESSAGES/{blur-my-shell.mo => blur-my-shell@aunetx.mo} (69%) rename gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ta/LC_MESSAGES/{blur-my-shell.mo => blur-my-shell@aunetx.mo} (57%) rename gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/tr/LC_MESSAGES/{blur-my-shell.mo => blur-my-shell@aunetx.mo} (55%) rename gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/uk/LC_MESSAGES/{blur-my-shell.mo => blur-my-shell@aunetx.mo} (73%) delete mode 100644 gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/vi/LC_MESSAGES/blur-my-shell.mo create mode 100644 gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/vi/LC_MESSAGES/blur-my-shell@aunetx.mo create mode 100644 gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/zh_Hans/LC_MESSAGES/blur-my-shell@aunetx.mo rename gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/{zh_Hans/LC_MESSAGES/blur-my-shell.mo => zh_TW/LC_MESSAGES/blur-my-shell@aunetx.mo} (53%) create mode 100644 gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/alt-dark.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/alt.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/app-icon-design-symbolic.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/backspace-dark.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/backspace.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/capslock-dark.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/capslock.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/ctrl-dark.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/ctrl.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/delete-dark.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/delete.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/down-dark.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/down.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/enter-dark.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/enter.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/left-dark.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/left.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/right-dark.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/right.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/shift-dark.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/shift.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/space-dark.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/space.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/super-dark.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/super.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/tab-dark.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/tab.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/up-dark.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/up.svg mode change 100755 => 100644 gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/gsconnect-preferences create mode 100644 gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/locale/he/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo mode change 100755 => 100644 gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/service/daemon.js mode change 100755 => 100644 gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/service/nativeMessagingHost.js create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/CHANGELOG.md create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/LICENSE create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/extension.js create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-active-symbolic.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-active.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-app-symbolic.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-error-symbolic.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-error.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-inactive-symbolic.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-inactive.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-unknown-symbolic.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-unknown.svg create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/libs/driver.js create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/libs/indicator.js create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/locale/cs/LC_MESSAGES/thinkpad-battery-threshold@marcosdalvarez.org.mo create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/locale/de/LC_MESSAGES/thinkpad-battery-threshold@marcosdalvarez.org.mo create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/locale/es/LC_MESSAGES/thinkpad-battery-threshold@marcosdalvarez.org.mo create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/locale/fr/LC_MESSAGES/thinkpad-battery-threshold@marcosdalvarez.org.mo create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/locale/it/LC_MESSAGES/thinkpad-battery-threshold@marcosdalvarez.org.mo create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/locale/ja/LC_MESSAGES/thinkpad-battery-threshold@marcosdalvarez.org.mo create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/locale/nb_NO/LC_MESSAGES/thinkpad-battery-threshold@marcosdalvarez.org.mo create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/locale/pt/LC_MESSAGES/thinkpad-battery-threshold@marcosdalvarez.org.mo create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/locale/pt_BR/LC_MESSAGES/thinkpad-battery-threshold@marcosdalvarez.org.mo create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/locale/ru/LC_MESSAGES/thinkpad-battery-threshold@marcosdalvarez.org.mo create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/metadata.json create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/preferences/about.js create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/preferences/general.js create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/preferences/thinkpad.js create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/preferences/utils.js create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/prefs.js create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/schemas/gschemas.compiled create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/schemas/org.gnome.shell.extensions.battery-threshold.gschema.xml create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/ui/about.ui create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/ui/general.ui create mode 100644 gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/ui/thinkpad.ui diff --git a/gnome/.commands.json b/gnome/.commands.json new file mode 100644 index 0000000..e93f560 --- /dev/null +++ b/gnome/.commands.json @@ -0,0 +1,34 @@ +[ + { + "title": "Record", + "command": "record", + "icon": "utilities-terminal" + }, + { + "title": "File Manager 3", + "command": "nautilus", + "icon": "folder" + }, + { + "type": "separator" + }, + { + "title": "Web Browser", + "command": "firefox", + "icon": "web-browser" + }, + { + "type": "separator" + }, + { + "title": "SSH Connections", + "type": "submenu", + "submenu": [ + { + "title": "Connect to Server (SSH)", + "command": "gnome-terminal -- bash -c 'ssh root@10.144.1.2 -p 8022'", + "icon": "utilities-terminal" + } + ] + } +] diff --git a/gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/blur.js b/gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/blur.js index e063be6..95c7b77 100644 --- a/gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/blur.js +++ b/gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/blur.js @@ -37,7 +37,7 @@ function log(msg) { } // we patch UnlockDialog._updateBackgroundEffects() -function _updateBackgroundEffects_BWP(monitorIndex) { +export function _updateBackgroundEffects_BWP(monitorIndex) { // GNOME shell 3.36.4 and above log("_updateBackgroundEffects_BWP() called for shell >= 3.36.4"); const themeContext = St.ThemeContext.get_for_stage(global.stage); @@ -68,18 +68,26 @@ function _updateBackgroundEffects_BWP(monitorIndex) { // we patch both UnlockDialog._showClock() and UnlockDialog._showPrompt() to let us // adjustable blur in a Windows-like way (this ensures login prompt is readable) -function _showClock_BWP() { +export function _showClock_BWP() { promptActive = false; this._showClock_GNOME(); // pass to default GNOME function this._updateBackgroundEffects(); } -function _showPrompt_BWP() { +export function _showPrompt_BWP() { promptActive = true; this._showPrompt_GNOME(); // pass to default GNOME function this._updateBackgroundEffects(); } +export function _clampValue(value) { + // valid values are 0 to 100 + if (value > 100) + value = 100; + if (value < 0 ) + value = 0; + return value; +} export default class Blur { constructor() { this.enabled = false; @@ -87,24 +95,15 @@ export default class Blur { } set_blur_strength(value) { - BWP_BLUR_SIGMA = this._clampValue(value); + BWP_BLUR_SIGMA = _clampValue(value); log("lockscreen blur strength set to "+BWP_BLUR_SIGMA); } set_blur_brightness(value) { - BWP_BLUR_BRIGHTNESS = this._clampValue(value); + BWP_BLUR_BRIGHTNESS = _clampValue(value); log("lockscreen brightness set to " + BWP_BLUR_BRIGHTNESS); } - // valid values are 0 to 100 - _clampValue(value) { - if (value > 100) - value = 100; - if (value < 0 ) - value = 0; - return value; - } - _switch(enabled) { if (enabled && !this.enabled) { this._enable(); diff --git a/gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/carousel.js b/gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/carousel.js index c673b14..f522ee7 100644 --- a/gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/carousel.js +++ b/gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/carousel.js @@ -107,8 +107,8 @@ export default class Carousel { deleteButton.connect('clicked', (widget) => { this.log('Delete requested for '+filename); Utils.deleteImage(filename); - //Utils.cleanupImageList(this.settings); // hide image instead - Utils.hideImage(this.settings, [image]); + Utils.setImageHiddenStatus(this.settings, image.urlbase, true); + Utils.cleanupImageList(this.settings); // hide image instead widget.get_parent().get_parent().set_visible(false); // bit of a hack if (this.callbackfunc) this.callbackfunc(); @@ -169,6 +169,7 @@ export default class Carousel { this.flowBox.remove(widget.get_parent()); this.flowBox.set_max_children_per_line(2); this._create_gallery(); + }); let item = buildable.get_object('flowBoxPlaceholder'); diff --git a/gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/extension.js b/gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/extension.js index e286d0f..493e2c8 100644 --- a/gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/extension.js +++ b/gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/extension.js @@ -561,6 +561,7 @@ class BingWallpaperIndicator extends Button { _randomModeChanged() { let randomEnabled = this._settings.get_boolean('random-mode-enabled'); + Utils.validate_interval(this._settings); [this.toggleShuffleOnlyFaves, this.toggleShuffleOnlyUHD /*, this.toggleShuffleOnlyUnhidden*/] .forEach( x => { x.setSensitive(randomEnabled); @@ -588,8 +589,14 @@ class BingWallpaperIndicator extends Button { _trashImage() { log('trash image '+this.imageURL+' status was '+this.hidden_status); this.hidden_status = !this.hidden_status; - Utils.setImageHiddenStatus(this._settings, [this.imageURL], this.hidden_status); - this._setTrashIcon(this.hidden_status?ICON_UNTRASH_BUTTON:ICON_TRASH_BUTTON); + Utils.setImageHiddenStatus(this._settings, this.imageURL, this.hidden_status); + this._setTrashIcon(this.hidden_status?this.ICON_UNTRASH_BUTTON:this.ICON_TRASH_BUTTON); + if (this._settings.get_boolean('trash-deletes-images')) { + log('image to be deleted: '+this.filename); + Utils.deleteImage(this.filename); + Utils.validate_imagename(this._settings); + } + } _setFavouriteIcon(icon_name) { @@ -715,7 +722,7 @@ class BingWallpaperIndicator extends Button { if (seconds == null) { let diff = -Math.floor(GLib.DateTime.new_now_local().difference(this.shuffledue)/1000000); log('shuffle ('+this.shuffledue.format_iso8601()+') diff = '+diff); - if (diff > 0) { + if (diff > 30) { // on occasions the above will be 1 second seconds = diff; // if not specified, we should maintain the existing shuffle timeout (i.e. we just restored from saved state) } else if (this._settings.get_string('random-interval-mode') != 'custom') { @@ -842,6 +849,7 @@ class BingWallpaperIndicator extends Button { // special values, 'current' is most recent (default mode), 'random' picks one at random, anything else should be filename if (force_shuffle) { + log('forcing shuffle of image') image = this._shuffleImage(); if (this._settings.get_boolean('random-mode-enabled')) this._restartShuffleTimeout(); diff --git a/gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/locale/pt_BR/LC_MESSAGES/BingWallpaper.mo b/gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/locale/pt_BR/LC_MESSAGES/BingWallpaper.mo index 23eded600ae27369ba12e206d012d416e8984164..618d39716bf8241d29da7b3f5632f599fbcde759 100644 GIT binary patch literal 7709 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 Wj_3HWq&9UK<_d+8$bg(BsQwRt?X;Ev literal 5809 zcmb`KTZ|-C8OIL@iX$kXf)~`Yi{hf&Jva8^?CwC%&g?L8ZcNXxiwVKgU8lQ?sjk!1 zshZi@7=jN5Uo=W2!N&~=W{JcELQG72YKRXeDi0c8G|>k&CL|;xG0_KqUsd(=%+5wk zv@q)|-?%1fB#x1bzh+KOP5f1)m0Q0iOe9{};g9!PmhLg1-gD zo~6e#vR1BxG)!HAr{>tYR*94cuMPec!=@mz~B-i4<=DPYb&4cT?KC|bA zG!W1u>{>~vyViS-@r zn;jcukqxHRY2P!k_TeRa=CJRYC^|g7-U+?#C9a*Au5P-n^?Ex@JGwSgUs>E(pIdxH zFR$qHwY9a{^7q+er9huZ7r$^1SZgCgb)P#|* zo*otRr&UeIHr;l~rnX7Kd)I7ci49b(;j&cKwoRCZaeLr@wOUm(rn%WpTownq5oL)E z;}rYCbZ6h2By4xm*m}=XZv%}r%e8t<*H%|%^?XchwC~s`()MCLo%f9$Jr{*W*OIo4 z)6gcNnvuQF6WgBYS&VDt;hHr&;>*=HBDsIj9A(vUtyR0Y*`#K zfoX&hcFVGnYlpFr1**)W$E>08U(}ROLCT_Et596jK$P6jNuFkq{*TvC}&cyQ` zCfU^Uw70|drfv1c+M-UKZbo6R;YUsq5+3rC}>Ej-)X#sS*AZYXybD>e^Ho z5Li7J21SX4aUe^Q^@YJV9g-Zi=$f0l-b}2G)slgXTo@0TmcnMo*hrr>FguEPn{3)t z%+qFzBFK#<>pKo^B({yYYDuCR#w{n_3;U{+F;B^EVyQzSEE!bGc6%7J;+fYLvv&d^ zCp^k$Gw!0y%$tXzk4VKF)jpEy&_URhXIKf7gn|TA%1Y`ql~$6FGO9-gmEaX3rB+$D zraPrqSv_kL6?;_AB<2#G+r+zrrgSfTY-Vj_X<=z@X!3Yw|9PiLLL6{f zUQ_bS`TR`DC6CdujECC2{;P5x=!Z6Hiw|wgt?BuiNS=jSb>w0DI2#-+vHyeQkWY3U;wS1@KM+4FO~?6`>8zWpAF&wiV^!TX602(PFA1c*?GK0? zVhe@nAuRZb%htCXH7hH$XyH!HBw^Iyg&W+{#|?L}DHV?xdu>J3vynNVgjNwibPdjL zBPQmXqLsuqwMy|Ad6#$07(ZRkg`sj%3qeRTAG|;dl=k)<)4CQ@6O)jZh+|MxQQ?@O zV6cTDxjs^>`$ltemEs6f>6%M6 zW*$1TeUeK)PK<qT?{YOWZ4jRhMf zyqJ%am4&3a$C470>rosRmWTwBP4Zfl#O1nanCpRfQxBHYl3n3dMw3PQUoWFXYi&S% zc$s-*Fw2o)=Y`6vr8mX;((h$kj3~|px!Ehy)JhYfNvIsoizW-uWc_bJg`AYbXX_<( z8j(~+=+IxNde-HjIH=8RA}b9Wh>QC#ZNYe)@R^}3+aZ>S!jn@Gh14C8D=x^M3$+Ci zXWgRM3%w@dX^TAPgpksZ3ff;vsgu0%7YHHB+JT$>S1vMZf9<1Dx-lvId0ipI*MovGD`rUk^7>gdfm%$y5WAtAB=79Oq zZp&!#t1StI#4Nb?yKGwqpy+L)r63rh&xUDX)*wwXHm`aSh^n47d>W?kp7Is(R~!k9 zDMVp$n@h$1WwavAXn#$sg(4;V2s3H_m4p(lm8T0!wh5J5%jM { + shuffleIntervals.append(_(x.title)); + }); + + shuffleInterval.set_model(shuffleIntervals); + shuffleInterval.set_selected(Utils.randomIntervals.map( e => e.value).indexOf(settings.get_string('random-interval-mode'))); + // add wallpaper folder open and change buttons + const openBtn = new Gtk.Button( { + child: new Adw.ButtonContent({ + icon_name: 'folder-pictures-symbolic', + label: _('Open folder'), + },), + valign: Gtk.Align.CENTER, + halign: Gtk.Align.CENTER, + }); + const changeBtn = new Gtk.Button( { + child: new Adw.ButtonContent({ + icon_name: 'folder-download-symbolic', + label: _('Change folder'), + },), + valign: Gtk.Align.CENTER, + halign: Gtk.Align.CENTER, + }); + + folderRow.add_suffix(openBtn); + folderRow.add_suffix(changeBtn); + + blurAdjustment.set_value(settings.get_int('lockscreen-blur-strength')); + brightnessAdjustment.set_value(settings.get_int('lockscreen-blur-brightness')); + + const defaultBtn = new Gtk.Button( { + child: new Adw.ButtonContent({ + icon_name: 'emblem-default-symbolic', + label: _('Default'), + },), + valign: Gtk.Align.CENTER, + halign: Gtk.Align.CENTER, + }); + const noBlurBtn = new Gtk.Button( { + child: new Adw.ButtonContent({ + icon_name: 'emblem-default-symbolic', + label: _('No blur, slight dim'), + },), + valign: Gtk.Align.CENTER, + halign: Gtk.Align.CENTER, + }); + const slightBlurBtn = new Gtk.Button( { + child: new Adw.ButtonContent({ + icon_name: 'emblem-default-symbolic', + label: _('Slight blur & dim'), + },), + valign: Gtk.Align.CENTER, + halign: Gtk.Align.CENTER, + }); + + // add to presets row + blurPresets.add_suffix(defaultBtn); + blurPresets.add_suffix(noBlurBtn); + blurPresets.add_suffix(slightBlurBtn); + + randomIntervalEntry.set_value(settings.get_int('random-interval')); + + // these buttons either export or import saved JSON data + const buttonImportData = new Gtk.Button( { + child: new Adw.ButtonContent({ + icon_name: 'document-send-symbolic', + label: _('Import'), + },), + valign: Gtk.Align.CENTER, + halign: Gtk.Align.CENTER, + }); + const buttonExportData = new Gtk.Button( { + child: new Adw.ButtonContent({ + icon_name: 'document-save-symbolic', + label: _('Export'), + },), + valign: Gtk.Align.CENTER, + halign: Gtk.Align.CENTER, + }); + + json_actionrow.add_suffix(buttonImportData); + json_actionrow.add_suffix(buttonExportData); + + version_button.set_label(this.metadata.version.toString()); + try { httpSession = new Soup.Session(); httpSession.user_agent = 'User-Agent: Mozilla/5.0 (X11; GNOME Shell/' + Config.PACKAGE_VERSION + '; Linux x86_64; +https://github.com/neffo/bing-wallpaper-gnome-extension ) BingWallpaper Gnome Extension/' + this.metadata.version; @@ -98,43 +186,42 @@ export default class BingWallpaperExtensionPreferences extends ExtensionPreferen catch (e) { log("Error creating httpSession: " + e); } - + const icon_image = buildable.get_object('icon_image'); + // check that these are valid (can be edited through dconf-editor) Utils.validate_resolution(settings); Utils.validate_icon(settings, this.path, icon_image); + Utils.validate_interval(settings); // Indicator & notifications settings.bind('hide', hideSwitch, 'active', Gio.SettingsBindFlags.DEFAULT); settings.bind('notify', notifySwitch, 'active', Gio.SettingsBindFlags.DEFAULT); - - // add markets to dropdown list (aka a GtkComboText) - Utils.icon_list.forEach((iconname, index) => { - iconEntry.append(iconname, iconname); - }); - - // user selectable indicator icons - settings.bind('icon-name', iconEntry, 'active_id', Gio.SettingsBindFlags.DEFAULT); settings.connect('changed::icon-name', () => { Utils.validate_icon(settings, this.path, icon_image); + iconEntry.set_value(1 + Utils.icon_list.indexOf(settings.get_string('icon-name'))); + }); + + iconEntry.connect('output', () => { + settings.set_string('icon-name', Utils.icon_list[iconEntry.get_value()-1]); }); - iconEntry.set_active_id(settings.get_string('icon-name')); // connect switches to settings changes settings.bind('set-background', bgSwitch, 'active', Gio.SettingsBindFlags.DEFAULT); settings.bind('debug-logging', debugSwitch, 'active', Gio.SettingsBindFlags.DEFAULT); settings.bind('revert-to-current-image', revertSwitch, 'active', Gio.SettingsBindFlags.DEFAULT); - settings.bind('override-unsafe-wayland', unsafeSwitch, 'active', Gio.SettingsBindFlags.DEFAULT); + //settings.bind('override-unsafe-wayland', unsafeSwitch, 'active', Gio.SettingsBindFlags.DEFAULT); settings.bind('random-interval', randomIntervalEntry, 'value', Gio.SettingsBindFlags.DEFAULT); - settings.bind('always-export-bing-json', switchAlwaysExport, 'active', Gio.SettingsBindFlags.DEFAULT); + settings.bind('trash-deletes-images', trash_purge_switch, 'active', Gio.SettingsBindFlags.DEFAULT); + settings.bind('always-export-bing-json', always_export_switch, 'active', Gio.SettingsBindFlags.DEFAULT); // button opens Nautilus at our image folder - folderOpenBtn.connect('clicked', (widget) => { + openBtn.connect('clicked', (widget) => { Utils.openImageFolder(settings); }); - + // we populate the tab (gtk4+, gnome 40+), this was previously a button to open a new window in gtk3 carousel = new Carousel(settings, null, null, carouselFlowBox, this.dir.get_path()); // auto load carousel - + // this is intended for migrating image folders between computers (or even sharing) or backups // we export the Bing JSON data to the image directory, so this folder becomes portable buttonImportData.connect('clicked', () => { @@ -144,104 +231,66 @@ export default class BingWallpaperExtensionPreferences extends ExtensionPreferen Utils.exportBingJSON(settings); }); - //download folder - fileChooserBtn.set_label(Utils.getWallpaperDir(settings)); - - fileChooserBtn.connect('clicked', (widget) => { - let parent = widget.get_root(); - let curWallpaperDir = Gio.File.new_for_path(Utils.getWallpaperDir(settings)); - fileChooser.set_current_folder(curWallpaperDir.get_parent()); - fileChooser.set_action(Gtk.FileChooserAction.SELECT_FOLDER); - fileChooser.set_transient_for(parent); - fileChooser.set_accept_label(_('Select folder')); - fileChooser.show(); + // change wallpaper button + const dirChooser = new Gtk.FileDialog( { + accept_label: "Select", + modal: true, + title: _("Select wallpaper download folder"), }); - fileChooser.connect('response', (widget, response) => { - if (response !== Gtk.ResponseType.ACCEPT) { - return; - } - let fileURI = fileChooser.get_file().get_path().replace('file://', ''); - fileChooserBtn.set_label(fileURI); - Utils.moveImagesToNewFolder(settings, Utils.getWallpaperDir(settings), fileURI); - Utils.setWallpaperDir(settings, fileURI); - }); + changeBtn.connect('clicked', (widget) => { + dirChooser.set_initial_folder(Gio.File.new_for_path(Utils.getWallpaperDir(settings))); + dirChooser.select_folder(window, null, (self, res) => { + let new_path = self.select_folder_finish(res).get_uri().replace('file://', ''); + log(new_path); + Utils.moveImagesToNewFolder(settings, Utils.getWallpaperDir(settings), new_path); + Utils.setWallpaperDir(settings, new_path); + }); - // in Gtk 4 instead we use a DropDown, but we need to treat it a bit special - let market_grid = buildable.get_object('market_grid'); - marketEntry = Gtk.DropDown.new_from_strings(Utils.marketName); - marketEntry.set_selected(Utils.markets.indexOf(settings.get_string('market'))); - market_grid.attach(marketEntry, 1, 0, 1, 2); - marketEntry.connect('notify::selected-item', () => { - let id = marketEntry.get_selected(); - settings.set_string('market', Utils.markets[id]); }); - settings.connect('changed::market', () => { - marketEntry.set_selected(Utils.markets.indexOf(settings.get_string('market'))); - }); - - settings.connect('changed::download-folder', () => { - fileChooserBtn.set_label(Utils.getWallpaperDir(settings)); - }); - - // Resolution + const resolutionModel = new Gtk.StringList(); Utils.resolutions.forEach((res) => { // add res to dropdown list (aka a GtkComboText) - resolutionEntry.append(res, res); + resolutionModel.append(res); }); + resolutionEntry.set_model(resolutionModel); - settings.bind('resolution', resolutionEntry, 'active_id', Gio.SettingsBindFlags.DEFAULT); + settings.connect('changed::resolution', () => { + resolutionEntry.set_selected(Utils.resolutions.map( e => e.value).indexOf(settings.get_string('resolution'))); + }); settings.connect('changed::resolution', () => { Utils.validate_resolution(settings); }); // shuffle modes - settings.bind('random-mode-enabled', switchEnableShuffle, 'active', Gio.SettingsBindFlags.DEFAULT); - Utils.randomIntervals.forEach((x) => { - entryShuffleMode.append(x.value, _(x.title)); - }); - settings.bind('random-interval-mode', entryShuffleMode, 'active_id', Gio.SettingsBindFlags.DEFAULT); + settings.bind('random-mode-enabled', shuffleSwitch, 'active', Gio.SettingsBindFlags.DEFAULT); + /*settings.bind('random-interval-mode', entryShuffleMode, 'active_id', Gio.SettingsBindFlags.DEFAULT);*/ - // selected image can no longer be changed through a dropdown (didn't scale) - settings.bind('selected-image', historyEntry, 'label', Gio.SettingsBindFlags.DEFAULT); - settings.connect('changed::selected-image', () => { - Utils.validate_imagename(settings); + settings.connect('changed::random-interval-mode', () => { + shuffleInterval.set_selected(Utils.randomIntervals.map( e => e.value).indexOf(settings.get_string('random-interval-mode'))); }); - - // background styles (e.g. zoom or span) - Utils.backgroundStyle.forEach((style) => { - styleEntry.append(style, style); - }); - desktop_settings.bind('picture-options', styleEntry, 'active_id', Gio.SettingsBindFlags.DEFAULT); - + // GDM3 lockscreen blur override settings.bind('override-lockscreen-blur', overrideSwitch, 'active', Gio.SettingsBindFlags.DEFAULT); settings.bind('lockscreen-blur-strength', strengthEntry, 'value', Gio.SettingsBindFlags.DEFAULT); settings.bind('lockscreen-blur-brightness', brightnessEntry, 'value', Gio.SettingsBindFlags.DEFAULT); // add a couple of preset buttons - buttonGDMdefault.connect('clicked', (widget) => { + defaultBtn.connect('clicked', (widget) => { Utils.set_blur_preset(settings, Utils.PRESET_GNOME_DEFAULT); }); - buttonnoblur.connect('clicked', (widget) => { + noBlurBtn.connect('clicked', (widget) => { Utils.set_blur_preset(settings, Utils.PRESET_NO_BLUR); }); - buttonslightblur.connect('clicked', (widget) => { + slightBlurBtn.connect('clicked', (widget) => { Utils.set_blur_preset(settings, Utils.PRESET_SLIGHT_BLUR); }); - - // fetch + + // fetch change log (on about page) + if (httpSession) Utils.fetch_change_log(this.metadata.version.toString(), change_log, httpSession); - - const page = new Adw.PreferencesPage(); - const group = new Adw.PreferencesGroup(); - - group.add(box); - page.add(group); - - window.add(page); } } diff --git a/gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/schemas/gschemas.compiled b/gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/schemas/gschemas.compiled index 77f335cdc4d35f582d719ad2abaf7a9ab30ff7d5..bdd63d2234bd5eb535e55dd7d2fa231a16092d50 100644 GIT binary patch delta 14 VcmZn=ZV=w^frXKA^GB9`762y11qc8D delta 14 VcmZn=ZV=w^frXJ_^GB9`762x`1qT2C diff --git a/gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/schemas/org.gnome.shell.extensions.bingwallpaper.gschema.xml b/gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/schemas/org.gnome.shell.extensions.bingwallpaper.gschema.xml index c457c1d..b01c105 100644 --- a/gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/schemas/org.gnome.shell.extensions.bingwallpaper.gschema.xml +++ b/gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/schemas/org.gnome.shell.extensions.bingwallpaper.gschema.xml @@ -211,7 +211,7 @@ - false + true Trash deletes images or just marks as bad diff --git a/gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/ui/Settings4.ui b/gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/ui/Settings4.ui deleted file mode 100644 index 073a3bf..0000000 --- a/gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/ui/Settings4.ui +++ /dev/null @@ -1,1451 +0,0 @@ - - - - - - 50 - 1 - 10 - - - 100 - 5 - 10 - - - 7 - 1 - 2 - - - 300 - 604800 - 300 - 3600 - - - Bing Wallpaper pictures folder - 0 - select-folder - 1 - - - - 120 - - - 0 - 0 - 0 - 500 - - - - - 0 - 12 - 12 - 12 - 12 - vertical - 12 - 0 - - - 0 - - - 0 - none - - - 0 - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - Hide the indicator - 1 - - 0 - 0 - - - - - - end - 1 - - 1 - 0 - - - - - - - - - - 0 - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - Indicator icon - 1 - - 0 - 0 - 2 - - - - - - 0 - end - - 1 - 1 - 1 - - - - - - 32 - 32 - 0 - end - 1 - ../icons/bing-symbolic.svg - icon_image_black_bg - - 1 - 0 - 1 - - - - - - - - - - 0 - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - Enable desktop notifications - 1 - - 0 - 0 - - - - - - end - 1 - - 1 - 0 - - - - - - - - - - - - - - - - - 0 - - - 0 - none - - - - - 0 - 12 - 12 - 12 - 12 - - - 0 - Set background image - - 0 - 0 - - - - - - end - 1 - - 1 - 0 - - - - - - - - - - 0 - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - start - 1 - Background style option - - 0 - 0 - - - - - - - 1 - 0 - 1 - - - - - - - - - - 0 - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - Download folder - - 0 - 0 - - - - - - True - False - end - false - Bing Wallpaper pictures folder - - 1 - 0 - - - - - - Open folder - True - True - - 2 - 0 - - - - - - - - - - - - - - - - - 0 - - - 0 - none - - - 0 - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - start - 1 - Selected image - - 0 - 0 - - - - - - - 1 - 0 - 1 - - - - - - - - - - 0 - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - start - 1 - Shuffle enabled - - 0 - 0 - - - - - - end - 1 - - 1 - 0 - - - - - - - - - - 0 - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - start - 1 - Shuffle mode - - 0 - 0 - - - - - - - 1 - 0 - 1 - - - - - - - - - - - - - - - - - 0 - - - 0 - none - - - 0 - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - start - 1 - Bing locale - 1 - - 0 - 0 - - - - - - 0 - start - 0 - - - - 0 - 1 - - - - - - - - - - - - - - - - - - - 0 - Settings - - - - - - - 1 - - - 0 - 12 - 12 - 12 - 12 - vertical - 12 - - - 0 - 0 - - - 0 - none - - - 0 - - - 0 - 12 - 12 - 12 - 12 - 32 - - - end - - 1 - 0 - - - - - - 0 - start - 1 - Dynamically switches blur on GDM3 lock screen - - - 0 - 1 - - - - - - 0 - start - 1 - Enable dynamic lockscreen blur - 1 - - 0 - 0 - - - - - - - - - - - - - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - start - 1 - Blur can improve readability - - - 0 - 1 - - - - - - 0 - start - 1 - Background blur intensity - - 0 - 0 - - - - - - adjustment_blur - 1 - - 1 - 0 - - - - - - - - - - - - - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - start - 1 - Can improve contrast of login prompt - - - 0 - 1 - - - - - - 0 - start - 1 - Background brightness - - 0 - 0 - - - - - - adjustment_brightness - 1 - - 1 - 0 - - - - - - - - - - - - - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - start - 1 - Presets - 1 - - 0 - 0 - - - - - - No blur, slight dim - 1 - - 1 - 3 - - - - - - GNOME default - 1 - - 1 - 2 - - - - - - Slight blur, slight dim - 1 - - 1 - 4 - - - - - - - - - - - - - - - - - - - - - - 0 - Lock Screen - - - - - - - 2 - - - 0 - 12 - 12 - 12 - 12 - vertical - 12 - - - 0 - 0 - - - 0 - none - - - 0 - - - 0 - 12 - 12 - 12 - 12 - 32 - - - end - - 1 - 0 - - - - - - 0 - start - 1 - Enable logging to system journal - - - 0 - 1 - - - - - - 0 - start - 1 - Debug logging - 1 - - 0 - 0 - - - - - - - - - - - - - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - start - 1 - Switch to new images when available (unless on random mode) - - - 0 - 1 - - - - - - 0 - start - 1 - Always show new images - 1 - - 0 - 0 - - - - - - end - - 1 - 0 - - - - - - - - - - - - - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - start - 1 - Some newer features may be unstable on Wayland - - - 0 - 1 - - - - - - 0 - start - 1 - Enable all features on Wayland - 1 - - 0 - 0 - - - - - - end - - 1 - 0 - - - - - - - - - - - - - 0 - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - start - 1 - Screen resolution - 1 - - 0 - 0 - - - - - - 0 - start - Override automatic resolution selection - - - 0 - 1 - - - - - - - 1 - 0 - 2 - - - - - - - - - - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - start - 1 - Manually adjust random interval (seconds) - - - 0 - 1 - - - - - - 0 - start - 1 - Random interval - - 0 - 0 - - - - - - adjustment_random_interval - 1 - - 1 - 0 - - - - - - - - - - - - - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - start - 1 - Import Bing Wallpaper data - 1 - - 0 - 0 - - - - - - 0 - start - 1 - Import previously exported JSON data from wallpaper directory - - - 0 - 1 - - - - - - Import - 1 - - 1 - 1 - - - - - - - - - - - - - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - start - 1 - Export Bing Wallpaper data - 1 - - 0 - 0 - - - - - - 0 - start - 1 - Export JSON data to wallpaper dir for backup or data migration - - - 0 - 1 - - - - - - Export - 1 - - 1 - 1 - - - - - - - - - - - - - - - 0 - 12 - 12 - 12 - 12 - 32 - - - 0 - start - 1 - Always export Bing data - 1 - - 0 - 0 - - - - - - 0 - start - 1 - Export Bing JSON whenever data changes - - - - 0 - 1 - - - - - - end - - 1 - 1 - - - - - - - - - - - - - - - - - - - - - - 0 - Debug options - - - - - - - 3 - - - 0 - vertical - - - - 0 - 500 - 0 - 0 - - - 0 - center - 1 - 2 - 2 - 2 - 2 - - - - - - - - - 0 - Gallery - - - - - - - 4 - - - 0 - - - 1 - 0 - vertical - 5 - - - - 0 - Bing Wallpaper - - - - - - - - 0 - New wallpaper images everyday from Bing - center - 1 - - - - - 0 - center - - - - 0 - end - GNOME shell extension version - - - - - 0 - start - ... - - - - - - - https://github.com/neffo/bing-wallpaper-gnome-extension - 0 - 1 - center - https://github.com/neffo/bing-wallpaper-gnome-extension - - - - - 0 - center - vertical - 5 - - - 0 - Maintained by Michael Carroll - - - - - 0 - ineffable@gmail.com - 1 - - - - - 0 - 36 - Show your support to the author on <a href="https://flattr.com/@neffo">Flattr</a> or <a href="https://github.com/sponsors/neffo">Github Sponsors</a>. - 1 - - - - - 0 - 36 - - 1 - - Changes since last version - 1 - - - - - 0 - 36 - Based on NASA APOD GNOME shell extension by Elia Argentieri - center - 1 - - - - - - - - - - 0 - 0 - <span size="small">This program comes with ABSOLUTELY NO WARRANTY. -See the <a href="https://www.gnu.org/licenses/gpl-3.0.html">GNU General Public License, version 3 or later</a> for details.</span> - 1 - center - 1 - - - - - - - 0 - About - - - - - - diff --git a/gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/ui/carousel4.ui b/gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/ui/carousel4.ui index 4be8a98..c322874 100644 --- a/gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/ui/carousel4.ui +++ b/gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/ui/carousel4.ui @@ -56,7 +56,7 @@ Author: Michael Carroll 320 - 180 + 120 0 1 1 @@ -186,7 +186,7 @@ Author: Michael Carroll 120 0 preferences-desktop-wallpaper-symbolic - 3 + 2 0 0 diff --git a/gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/ui/prefsadw.ui b/gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/ui/prefsadw.ui new file mode 100644 index 0000000..538035c --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/ui/prefsadw.ui @@ -0,0 +1,438 @@ + + + + + + + emblem-photos-symbolic + Settings + + + Indicator + + + Hide Indicator + Whether to hide the panel indicator + + + + + Desktop notifications + Enable notifications on new images + + + + + Indicator icon + Select from alternate tray icons + + + 1 + 5 + 1 + + + + + + + + + + 64 + 64 + 0 + end + 1 + ../icons/bing-symbolic.svg + icon_image_black_bg + + + + + + + + + Wallpaper + + + Set wallpaper + Whether to set wallpaper automatically + + + + + Shuffle wallpaper + Randomly select wallpaper from collection + + + + + Shuffle interval + How frequently to shuffle wallpapers + + + + + + + Downloads + + + Download folder + Open or change wallpaper downloads folder + + + + + + + applications-system-symbolic + Lock screen + + + Lockscreen blur + + + Dynamic lockscreen blur + Whether to enable dynamic blur mode on lock screen + + + + + Blur strength + Blur strength when login prompt is not visible + + + 0 + 50 + 10 + 1 + + + + + + + Wallpaper brightness + Dim wallpaper when login prompt is not visible + + + 0 + 100 + 10 + 1 + + + + + + + + + + + + Presets + + + + + + + document-open-recent-symbolic + Gallery + + + 0 + 500 + 0 + 0 + + + + + 0 + center + 1 + 2 + 2 + 2 + 2 + + + + + + + + + preferences-other-symbolic + Debug + + + Debug options + + + Debug logging + Enable logging to system journal + + + + + Always show new images + Switch to new images when available (unless on random mode) + + + + + Purge on trash + Trashing an image will remove it from database + + + + + Screen resolution + Override automatic resolution selection + + + + + Random interval + Custom shuffle interval when enabled + + + 300 + 604800 + 300 + 3600 + + + + + + + + + + + + Always export Bing data + Export Bing JSON when image data changes + + + + + Bing JSON data + Custom shuffle interval when enabled + + + + + + + user-info-symbolic + About + + + + + + 128 + presentation + + + + + + True + center + Bing Wallpaper + + + + + + 0 + New wallpaper images everyday from Bing + center + 1 + + + + + + True + center + Maintained by Michael Carroll + + + + + + + + + Version + + + center + True + + + + + + + + Release notes + + + True + left + + + + + + + + + + + vertical + + + + + + GNOME extensions page + True + True + extension_page_linkbutton + + + https://extensions.gnome.org/extension/1262/bing-wallpaper-changer/ + + + + + adw-external-link-symbolic + presentation + + + + + + + Source code + True + True + source_code_linkbutton + + + https://github.com/neffo/bing-wallpaper-gnome-extension + + + + + adw-external-link-symbolic + presentation + + + + + + + Report an issue + True + True + bug_report_linkbutton + + + https://github.com/neffo/bing-wallpaper-gnome-extension/issues + + + + + adw-external-link-symbolic + presentation + + + + + + + Contributors + True + True + contributors_linkbutton + + + https://github.com/neffo/bing-wallpaper-gnome-extension/graphs/contributors + + + + + adw-external-link-symbolic + presentation + + + + + + + License + + + True + left + This extension is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + + + + + + + + + + + + + Change folder + true + Select new wallpaper download folder + + + + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/utils.js b/gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/utils.js index 6f2ff22..1ebe159 100644 --- a/gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/utils.js +++ b/gnome/.local/share/gnome-shell/extensions/BingWallpaper@ineffable-gmail.com/utils.js @@ -12,9 +12,9 @@ import GLib from 'gi://GLib'; import Soup from 'gi://Soup'; import GdkPixbuf from 'gi://GdkPixbuf'; -export var PRESET_GNOME_DEFAULT = { blur: 60, dim: 55 }; // as at GNOME 40 -export var PRESET_NO_BLUR = { blur: 0, dim: 60 }; -export var PRESET_SLIGHT_BLUR = { blur: 2, dim: 60 }; +export var PRESET_GNOME_DEFAULT = { blur: 45, dim: 65 }; // as at GNOME 40 +export var PRESET_NO_BLUR = { blur: 0, dim: 65 }; +export var PRESET_SLIGHT_BLUR = { blur: 2, dim: 30 }; export var BING_SCHEMA = 'org.gnome.shell.extensions.bingwallpaper'; export var DESKTOP_SCHEMA = 'org.gnome.desktop.background'; @@ -52,7 +52,8 @@ export var backgroundStyle = ['none', 'wallpaper', 'centered', 'scaled', 'stretc export var randomIntervals = [ {value: 'hourly', title: ('on the hour')}, {value: 'daily', title: ('every day at midnight')}, - {value: 'weekly', title: ('every Sunday at midnight')} ]; + {value: 'weekly', title: ('Sunday at midnight')}, + { value: 'custom', title: ('User defined interval')} ]; export var BingImageURL = 'https://www.bing.com/HPImageArchive.aspx'; export var BingParams = { format: 'js', idx: '0' , n: '8' , mbl: '1' , mkt: '' } ; @@ -67,7 +68,7 @@ export function validate_icon(settings, extension_path, icon_image = null) { // if called from prefs if (icon_image) { BingLog('set icon to: ' + extension_path + '/icons/' + icon_name + '.svg'); - let pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(extension_path + '/icons/' + icon_name + '.svg', 32, 32); + let pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(extension_path + '/icons/' + icon_name + '.svg', 64, 64); icon_image.set_from_pixbuf(pixbuf); } } @@ -78,6 +79,12 @@ export function validate_resolution(settings) { settings.reset('resolution'); } +export function validate_interval(settings) { + let index = randomIntervals.map( e => e.value).indexOf(settings.get_string('random-interval-mode')); + if (index == -1) // if not a valid interval + settings.reset('random-interval-mode'); +} + // FIXME: needs work export function validate_imagename(settings) { let filename = settings.get_string('selected-image'); @@ -188,16 +195,15 @@ export function setImageList(settings, imageList) { } } -export function setImageHiddenStatus(settings, hide_image_list, hide_status) { +export function setImageHiddenStatus(settings, hide_image, hide_status) { // get current image list let image_list = getImageList(settings); + log ('image count = '+image_list.length+', hide_image = '+hide_image); image_list.forEach( (x, i) => { - hide_image_list.forEach(u => { - if (u.includes(x.urlbase)) { - // mark as hidden - x.hidden = hide_status; - } - }); + if (hide_image.includes(x.urlbase)) { + // mark as hidden + x.hidden = hide_status; + } }); // export image list back to settings setImageList(settings, image_list); @@ -294,6 +300,8 @@ export function getImageByIndex(imageList, index) { } export function cleanupImageList(settings) { + if (settings.get_boolean('trash-deletes-images') == false) + return; let curList = imageListSortByDate(getImageList(settings)); let cutOff = GLib.DateTime.new_now_utc().add_days(-8); // 8 days ago let newList = []; diff --git a/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/Options_UI.glade b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/Options_UI.glade new file mode 100644 index 0000000..6ee3bb3 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/Options_UI.glade @@ -0,0 +1,1493 @@ + + + + + 5 + + + center + stk_Main + + + + + 800 + slide-left-right + + + page0 + Options + + + borderless + + + options-grid + 18 + 15 + + + end + 4 + 1 + Recording status indicators + right + + 0 + 0 + + + + + + end + 1 + Show alerts and notifications + + 0 + 1 + + + + + + 1 + start + 1 + + 1 + 1 + + + + + + end + 1 + Show a border around the area being recorded + + 0 + 2 + + + + + + 1 + start + 1 + + 1 + 2 + + + + + + end + 1 + Enable keyboard shortcut + + 0 + 3 + + + + + + + + 1 + liststore_KeyShortcut + 0 + 0 + + + + + + + 1 + 4 + + + + + + + Both [ESC + Default] + ESC only + Default only + Not any + + + 1 + 0 + + + + + + These words will be replaced + _fpath = the absolute path of the screencast video file. +_dirpath = the absolute path of destination folder for the screencast video file. +_fname = the name of the screencast video file. + end + 1 + Command post-recording + + 0 + 9 + + + + + + 1 + These words will be replaced + _fpath = the absolute path of the screencast video file. +_dirpath = the absolute path of destination folder for the screencast video file. +_fname = the name of the screencast video file. + 1 + + 1 + 9 + + + + + + end + 1 + Execute command after recording + + 0 + 8 + + + + + + 1 + start + 0 + + 1 + 8 + + + + + + 1 + start + 1 + + 1 + 5 + + + + + + end + 1 + Draw cursor on screencast + + 0 + 5 + + + + + + 1 + end + 1 + Active shortcut + + 0 + 4 + + + + + + 1 + start + 1 + + 1 + 3 + + + + + + end + 1 + Execute command before recording + + 0 + 6 + + + + + + 1 + start + 0 + + 1 + 6 + + + + + + These words will be replaced +_dirpath = the absolute path of destination folder for the screencast video file. + end + 1 + Command pre-recording + + 0 + 7 + + + + + + 1 + These words will be replaced +_dirpath = the absolute path of destination folder for the screencast video file. + 1 + + 1 + 7 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + page1 + Quality + + + borderless + + + vertical + + + 18 + 15 + + + end + 1 + Custom GStreamer Pipeline + + 0 + 0 + + + + + + 1 + start + 1 + + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + 800 + slide-up-down + + + pg_Preset + PagePreset + + + start + vertical + + + center + border-box + + + start + true + 100 + + + + + end + true + 100 + + + + + + + center + 1 + 1 + 18 + 5 + 0 + 0 + bottom + + + + + center + 1 + No GSP description + + 1 + word-char + end + + + + + + + + + pg_Custom + PageCustom + + + vertical + + + center + 18 + 15 + + + end + 1 + Frames Per Second + + 0 + 0 + + + + + + 1 + start + 1 + 0 + 1 + + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + 10 + 0.10000000149011612 + + + 1 + + + 1 + 5 + 5 + 1 + 1 + word-char + 0 + + + + + + + GStreamer Pipeline + + + + + + + center + vertical + + + start + The extension does NOT handle the webcam and audio when you use a custom gstreamer pipeline. + + 1 + + + + + + + + + + + 1 + Official doc + 1 + 1 + http://gstreamer.freedesktop.org/documentation/plugins.html + 1 + + + + + 1 + Wiki #1 + 1 + 1 + http://processors.wiki.ti.com/index.php/Example_GStreamer_Pipelines + + + + + 1 + Wiki #2 + 1 + 1 + http://wiki.oz9aec.net/index.php/Gstreamer_Cheat_Sheet + + + + + + + + + + + + + + + + + + + + + + + + page2 + WebCam + + + borderless + + + vertical + + + center + No webcam device selected + center + + + + + + + + + center + center + 0 + - + center + end + 1 + + + + + + + + center + 1 + stk_Webcam + + + + + 1 + 1 + 800 + slide-up-down + + + pg_quality_webcam + Quality + + + 1 + True + + + 1 + 1 + 1 + liststore_QualityWebCam + 1 + horizontal + + + + + + + + + + + + pg_size_webcam + Size + + + 18 + 15 + + + end + 1 + Type of unit of measure + + 0 + 0 + + + + + + end + 1 + Width + + 0 + 1 + + + + + + end + 1 + Height + + 0 + 2 + + + + + + 1 + start + 1 + 1 + + 1 + 1 + + + + + + 1 + start + 1 + 1 + + 1 + 2 + + + + + + start + 1 + + Percentage + Pixel + + + 1 + 0 + + + + + + + + + + + + + + + + + + + pg_position_webcam + Position + + + 18 + 15 + + + end + 1 + Put the webcam in the corner + + 0 + 0 + + + + + + start + 1 + + Right-Bottom + Left-Bottom + Right-Top + Left-Top + + + 1 + 0 + + + + + + end + 1 + Margin X + + 0 + 1 + + + + + + 1 + start + 1 + 1 + + 1 + 1 + + + + + + end + 1 + Margin Y + + 0 + 2 + + + + + + 1 + start + 0 + 1 + + 1 + 2 + + + + + + end + 1 + Alpha channel + + 0 + 3 + + + + + + 1 + start + 1 + 0,00 + 0.05 + 2 + 1 + + 1 + 3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + page3 + File + + + borderless + + + 18 + 15 + + + Select the folder where the file is saved, if not specific a folder the file will be saved in the $XDG_VIDEOS_DIR if it exists, or the home directory otherwise. + end + 1 + Destination folder + + 0 + 3 + + + + + + The filename which may contain some escape sequences - %d and %t will be replaced by the start date and time of the recording. + end + 1 + File name template + + 0 + 2 + + + + + + 1 + 1 + The filename which may contain some escape sequences - %d and %t will be replaced by the start date and time of the recording. + 1 + + 1 + 2 + + + + + + True + False + Select the folder where the file is saved, if not specific a folder the file will be saved in the $XDG_VIDEOS_DIR if it exists, or the home directory otherwise. + + 1 + 3 + + + + + + end + 1 + File container + + 0 + 0 + + + + + + end + 1 + File resolution + + 0 + 1 + + + + + + + WebM [VP8 encoder + vorbis] + WebM [VP9 encoder + vorbis] + MP4 [x264 encoder + mp3] + Mkv [x264 encoder + flac] + Ogg [Theora encoder + opus] + MP4_AAC [x264 encoder + aac] + + + 1 + 0 + + + + + + vertical + + + 1 + center + 1 + stk_FileResolution + + + + + 10 + 0 + 800 + slide-up-down + 1 + + + native + Native + + + Native area resolution + + + + + + + + + + preset + Preset + + + 5 + 18 + 15 + + + end + 1 + Preset helper + + 0 + 0 + + + + + + start + 1 + + VGA [480p] [4:3] + FWVGA [480p] [16:9] + SVGA [600p] [4:3] + SMPTE [720p] [4:3] + HD [720p] [16:9] + XGA [768p] [4:3] + HD ready [768p] [16:9] + SXGA [1024p] [5:4] + Full HD [1080p] [16:9] + UXGA [1200p] [4:3] + QHD [1440p] [16:9] + QSXGA [2048p] [5:4] + 4K [2160p] [16:9] + + + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + custom + Custom + + + vertical + + + 5 + 18 + 15 + + + end + 1 + Width + + 0 + 0 + + + + + + 1 + start + 1 + + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + 1 + 1 + 1 + + + + + 5 + 18 + 15 + + + end + 1 + Height + + 0 + 0 + + + + + + 1 + start + 1 + + 1 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + 1 + 1 + 1 + + + + + 1 + keep original aspect ratio + 1 + center + 5 + + + + + + + + + + 1 + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + page5 + Support + + + borderless + + + vertical + + + 5 + 18 + 15 + + + This option enable more debug message, to view these run this command into a terminal: +$ journalctl --since=today --no-pager | grep js +$ dbus-monitor "interface=org.gnome.Shell.Screencast" + end + 1 + Enable verbose debug + + 0 + 0 + + + + + + 1 + This option enable more debug message, to view these run this command into a terminal: +$ journalctl /usr/bin/gnome-session --since=today | grep js +$ dbus-monitor "interface=org.gnome.Shell.Screencast" + start + 1 + + 1 + 0 + + + + + + start + 5 + 0 + + extension + last Gstreamer pipeline + gnome shell + + + 1 + 1 + + + + + + This option enable more debug message, to view these run this command into a terminal: +$ journalctl --since=today --no-pager | grep js +$ dbus-monitor "interface=org.gnome.Shell.Screencast" + end + 1 + Display the log of + + 0 + 1 + + + + + + + + + + + + + + + + + + + + + + + 1 + 1 + True + + + 1 + 0 + 1 + + + + + + + 5 + 5 + + + + + center + Restore default options + 1 + 1 + + + + + + + + + + + + + + page4 + Info + + + borderless + + + vertical + + + 100 + + + + + EasyScreenCast + + + + + + + + + + center + 10 + 1 + N/A + 1 + + + + + + + + center + 15 + 15 + This extension simplifies the use of the +screen recorder included in gnome shell + center + middle + + + + + + + + This software is licensed under GPL v3 + 1 + 1 + https://github.com/EasyScreenCast/EasyScreenCast/blob/master/COPYING + + + + + Credits + 1 + 1 + https://github.com/EasyScreenCast/EasyScreenCast/graphs/contributors + + + + + How to contribute? + + + + + With a translation + 1 + 1 + https://github.com/EasyScreenCast/EasyScreenCast#translation + + + + + Reporting bugs + 1 + 1 + https://github.com/EasyScreenCast/EasyScreenCast/issues + + + + + Add code + 1 + 1 + https://github.com/EasyScreenCast/EasyScreenCast/pulls + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/convenience.js b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/convenience.js new file mode 100644 index 0000000..33c9f99 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/convenience.js @@ -0,0 +1,86 @@ +/* + Copyright (c) 2011-2012, Giovanni Campagna + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the GNOME nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +'use strict'; + +import Gio from 'gi://Gio'; + +var debugEnabled = false; + +/** + * @param {boolean} d Enable/Disable debug logging + */ +function setDebugEnabled(d) { + debugEnabled = d; +} + +/** + * @param {string} msg the message to log + * @class + */ +function TalkativeLog(msg) { + if (debugEnabled) + log(`[ESC]${msg}`); +} + +/** + * Gets the full (semantic) version of this extension. + * + *

Note: The actual value is added during build time. + * + * @returns {string} the version + */ +function getFullVersion() { + return '1.9.0'; // FULL_VERSION +} + +/** + * Loads an icon from the extension's subdirectory "images". + * + * @param {Gio.File} extensionDir dir of the extension + * @param {string} name filename of the image + * @returns {Gio.FileIcon} the icon + */ +function loadIcon(extensionDir, name) { + return new Gio.FileIcon({ + file: Gio.File.new_for_path( + getImagePath(extensionDir, name) + ), + }); +} + +/** + * Gets the path to the image from the extension's subdirectory "images". + * + * @param {Gio.File} extensionDir dir of the extension + * @param {string} name filename of the image + * @returns {string} the path + */ +function getImagePath(extensionDir, name) { + return extensionDir.get_child(`images/${name}`).get_path(); +} + +export {TalkativeLog, getFullVersion, setDebugEnabled, loadIcon, getImagePath}; diff --git a/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/display_module.js b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/display_module.js new file mode 100644 index 0000000..1f1702b --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/display_module.js @@ -0,0 +1,40 @@ +'use strict'; + +/** + * @type {{_display(): Meta_Display, number_of_displays(): int}} + */ +var DisplayApi = { + /** + * Returns the Wayland display or screen + * + * @returns {Meta.Display} + */ + _display() { + return global.display || global.screen; + }, + + /** + * @returns {int} + * @public + */ + number_displays() { + return this._display().get_n_monitors(); + }, + + /** + * @param {number} displayIndex the monitor number + * @returns {Meta.Rectangle} + */ + display_geometry_for_index(displayIndex) { + return this._display().get_monitor_geometry(displayIndex); + }, + + /** + * @param {Meta.Cursor} cursor the new cursor to set + */ + set_cursor(cursor) { + this._display().set_cursor(cursor); + }, +}; + +export {DisplayApi}; diff --git a/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/extension.js b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/extension.js new file mode 100644 index 0000000..c151057 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/extension.js @@ -0,0 +1,1034 @@ +/* + Copyright (C) 2013 Borsato Ivano + + The JavaScript code in this page is free software: you can + redistribute it and/or modify it under the terms of the GNU + General Public License (GNU GPL) as published by the Free Software + Foundation, either version 3 of the License, or (at your option) + any later version. The code is distributed WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU GPL for more details. +*/ + + +'use strict'; + +import GObject from 'gi://GObject'; +import St from 'gi://St'; +import Meta from 'gi://Meta'; +import Shell from 'gi://Shell'; +// https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/panelMenu.js +import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js'; +import Clutter from 'gi://Clutter'; +import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; +import * as Slider from 'resource:///org/gnome/shell/ui/slider.js'; +import * as Main from 'resource:///org/gnome/shell/ui/main.js'; + +import {Extension, gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js'; + +import * as Lib from './convenience.js'; +import * as Settings from './settings.js'; +import * as Time from './timer.js'; +import * as UtilRecorder from './utilrecorder.js'; +import * as UtilAudio from './utilaudio.js'; +import * as UtilWebcam from './utilwebcam.js'; +import * as UtilNotify from './utilnotify.js'; +import * as Selection from './selection.js'; +import * as UtilExeCmd from './utilexecmd.js'; + +var Indicator; +let timerD = null; +let timerC = null; + +let isActive = false; +let pathFile = ''; + +let keybindingConfigured = false; + +/** + * @type {EasyScreenCastIndicator} + */ +const EasyScreenCastIndicator = GObject.registerClass({ + GTypeName: 'EasyScreenCast_Indicator', +}, class EasyScreenCastIndicator extends PanelMenu.Button { + constructor(extension) { + super(null, 'EasyScreenCast_Indicator'); + + this._extension = extension; + this._settings = new Settings.Settings(this._extension.getSettings()); + Lib.setDebugEnabled(this._settings.getOption('b', Settings.VERBOSE_DEBUG_SETTING_KEY)); + this._settings._settings.connect( + `changed::${Settings.VERBOSE_DEBUG_SETTING_KEY}`, + () => { + Lib.setDebugEnabled(this._settings.getOption('b', Settings.VERBOSE_DEBUG_SETTING_KEY)); + } + ); + + this.CtrlAudio = new UtilAudio.MixerAudio(); + this.CtrlWebcam = new UtilWebcam.HelperWebcam(_('Unspecified webcam')); + + this.CtrlNotify = new UtilNotify.NotifyManager(); + this.CtrlExe = new UtilExeCmd.ExecuteStuff(this); + + // load indicator icons + this._icons = { + on: Lib.loadIcon(this._extension.dir, 'icon_recording.svg'), + onSel: Lib.loadIcon(this._extension.dir, 'icon_recordingSel.svg'), + off: Lib.loadIcon(this._extension.dir, 'icon_default.svg'), + offSel: Lib.loadIcon(this._extension.dir, 'icon_defaultSel.svg'), + }; + + // check audio + if (!this.CtrlAudio.checkAudio()) { + Lib.TalkativeLog('-*-disable audio recording'); + this._settings.setOption(Settings.INPUT_AUDIO_SOURCE_SETTING_KEY, 0); + this._settings.setOption( + Settings.ACTIVE_CUSTOM_GSP_SETTING_KEY, + Settings.getGSPstd(false) + ); + } + + // add enter/leave/click event + this.connect('enter_event', () => this.refreshIndicator(true)); + this.connect('leave_event', () => this.refreshIndicator(false)); + this.connect('button_press_event', (actor, event) => + this._onButtonPress(actor, event) + ); + + // prepare setting var + if (this._settings.getOption('i', Settings.TIME_DELAY_SETTING_KEY) > 0) + this.isDelayActive = true; + else + this.isDelayActive = false; + + + // Add the title bar icon and label for time display + this.indicatorBox = new St.BoxLayout(); + this.indicatorIcon = new St.Icon({ + gicon: this._icons.off, + icon_size: 16, + }); + this.timeLabel = new St.Label({ + text: '', + style_class: 'time-label', + y_expand: true, + y_align: Clutter.ActorAlign.CENTER, + }); + + this.indicatorBox.add_child(this.timeLabel); + this.indicatorBox.add_child(this.indicatorIcon); + + // init var + this.recorder = new UtilRecorder.CaptureVideo(); + this.AreaSelected = null; + this.TimeSlider = null; + + this._initMainMenu(); + } + + /** + * @private + */ + _initMainMenu() { + this._addStartStopMenuEntry(); + this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); + this.sub_menu_audio_recording = new PopupMenu.PopupSubMenuMenuItem(_('No audio source'), true); + this.sub_menu_audio_recording.icon.icon_name = 'audio-input-microphone-symbolic'; + this.menu.addMenuItem(this.sub_menu_audio_recording); + this._addAudioRecordingSubMenu(); + + // add sub menu webcam recording + this._addSubMenuWebCam(); + + this._addAreaRecordingSubMenu(); + this._addRecordingDelaySubMenu(); + this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); + this.menu_item_options = new PopupMenu.PopupMenuItem(_('Options')); + this.menu_item_options.actor.insert_child_at_index( + new St.Icon({ + style_class: 'popup-menu-icon', + icon_name: 'preferences-other-symbolic', + }), + 1 + ); + this.menu.addMenuItem(this.menu_item_options); + this.menu_item_options.connect('activate', () => this._openExtensionPreferences()); + } + + /** + * Set a new value for the time label. Integers are + * converted to seconds, minutes, hours. All other + * values are converted to strings. + * + * @param {string|number} newValue new value of the label. if a number, then it's the seconds passed. + * @returns {string} + */ + updateTimeLabel(newValue) { + /** + * @param {number} number a number + */ + function padZeros(number) { + if (number < 10) + number = `0${number}`; + + return number.toString(); + } + + if (typeof newValue === 'number') { + let hours = Math.floor(newValue / 3600); + newValue -= hours * 3600; + + let minutes = Math.floor(newValue / 60); + newValue -= minutes * 60; + + newValue = `${padZeros(hours)}:${padZeros(minutes)}:${padZeros(newValue)}`; + } + + this.timeLabel.set_text(newValue.toString()); + } + + /** + * Left clicking on the icon toggles the recording + * options menu. Any other mouse button will start + * the recording. + * Some submenus are refreshed to account for new + * sources. + * + * @param {Clutter.Actor} actor the actor + * @param {Clutter.Event} event a Clutter.Event + */ + _onButtonPress(actor, event) { + let button = event.get_button(); + + if (button === 1) { + Lib.TalkativeLog('-*-left click indicator'); + + this._setupExtensionMenu(); + } else { + Lib.TalkativeLog('-*-right click indicator'); + + if (this.menu.isOpen) + this.menu.close(); + + this.isShowNotify = this._settings.getOption('b', Settings.SHOW_NOTIFY_ALERT_SETTING_KEY); + this._doRecording(); + } + } + + /** + * Sets up the menu when the user opens it. + */ + _setupExtensionMenu() { + this._addAudioRecordingSubMenu(); + this._addWebcamSubMenu(); + } + + /** + * Sets up all the options for web-cams. Should only run the + * first time the icon is clicked an the CtrlWebcam is still + * null. + */ + _addWebcamSubMenu() { + if (this.CtrlWebcam === null) + this.CtrlWebcam = new UtilWebcam.HelperWebcam(_('Unspecified webcam')); + + // add sub menu webcam recording + this._populateSubMenuWebcam(); + + // start monitoring inputvideo + this.CtrlWebcam.startMonitor(); + } + + /** + * Adds individual webcam items to the webcam menu. + */ + _populateSubMenuWebcam() { + let arrMI = this._createMIWebCam(); + + this.smWebCam.menu.removeAll(); + for (let element in arrMI) + this.smWebCam.menu.addMenuItem(arrMI[element]); + + let i = this._settings.getOption('i', Settings.DEVICE_INDEX_WEBCAM_SETTING_KEY); + Lib.TalkativeLog(`-*-populated submenuwebcam. Settings i=${i}`); + + this.smWebCam.label.text = this.WebCamDevice[i]; + } + + /** + * @private + */ + _addStartStopMenuEntry() { + this.imRecordAction = new PopupMenu.PopupBaseMenuItem(); + this.RecordingLabel = new St.Label({ + text: _('Start recording'), + style_class: 'RecordAction-label', + content_gravity: Clutter.ContentGravity.CENTER, + x_expand: true, + x_align: Clutter.ActorAlign.CENTER, + }); + this.imRecordAction.actor.add_child(this.RecordingLabel); + this.imRecordAction.x_expand = true; + this.imRecordAction.x_fill = true; + this.imRecordAction.x_align = Clutter.ActorAlign.CENTER; + this.imRecordAction.connect('activate', () => { + this.isShowNotify = this._settings.getOption('b', Settings.SHOW_NOTIFY_ALERT_SETTING_KEY); + this._doRecording(); + }); + + this.menu.addMenuItem(this.imRecordAction); + } + + /** + * Refreshes the submenu for audio recording sources. + */ + _addAudioRecordingSubMenu() { + Lib.TalkativeLog('-*-reset the sub menu audio'); + // remove old menu items + this.sub_menu_audio_recording.menu.removeAll(); + + Lib.TalkativeLog('-*-add new items to sub menu audio'); + var arrMI = this._createMIAudioRec(); + for (var ele in arrMI) + this.sub_menu_audio_recording.menu.addMenuItem(arrMI[ele]); + } + + /** + * @private + */ + _addSubMenuWebCam() { + this.smWebCam = new PopupMenu.PopupSubMenuMenuItem('', true); + this.smWebCam.icon.icon_name = 'camera-web-symbolic'; + + this.menu.addMenuItem(this.smWebCam); + } + + /** + * @private + */ + _addAreaRecordingSubMenu() { + this.sub_menu_area_recording = new PopupMenu.PopupSubMenuMenuItem('', true); + this.sub_menu_area_recording.icon.icon_name = 'view-fullscreen-symbolic'; + + var arrMI = this._createMIAreaRec(); + for (var ele in arrMI) + this.sub_menu_area_recording.menu.addMenuItem(arrMI[ele]); + + this.sub_menu_area_recording.label.text = this.AreaType[this._settings.getOption('i', Settings.AREA_SCREEN_SETTING_KEY)]; + this.menu.addMenuItem(this.sub_menu_area_recording); + } + + /** + * @private + */ + _addRecordingDelaySubMenu() { + this.smDelayRec = new PopupMenu.PopupSubMenuMenuItem('', true); + this.smDelayRec.icon.icon_name = 'alarm-symbolic'; + + var arrMI = this._createMIInfoDelayRec(); + for (var ele in arrMI) + this.smDelayRec.menu.addMenuItem(arrMI[ele]); + + var secDelay = this._settings.getOption('i', Settings.TIME_DELAY_SETTING_KEY); + if (secDelay > 0) { + this.smDelayRec.label.text = + secDelay + _(' sec. delay before recording'); + } else { + this.smDelayRec.label.text = _('Start recording immediately'); + } + + this.menu.addMenuItem(this.smDelayRec); + } + + /** + * @returns {Array} + * @private + */ + _createMIAreaRec() { + this.AreaType = [ + _('Record all desktop'), + _('Record a selected monitor'), + _('Record a selected window'), + _('Record a selected area'), + ]; + + this.AreaMenuItem = new Array(this.AreaType.length); + + for (var i = 0; i < this.AreaMenuItem.length; i++) { + this.AreaMenuItem[i] = new PopupMenu.PopupMenuItem( + this.AreaType[i], + { + reactive: true, + activate: true, + hover: true, + can_focus: true, + } + ); + + (function (areaSetting, arr, item, settings) { + this.connectMI = function () { + this.connect('activate', () => { + Lib.TalkativeLog(`-*-set area recording to ${areaSetting} ${arr[areaSetting]}`); + settings.setOption(Settings.AREA_SCREEN_SETTING_KEY, areaSetting); + + item.label.text = arr[areaSetting]; + }); + }; + this.connectMI(); + }.call( + this.AreaMenuItem[i], + i, + this.AreaType, + this.sub_menu_area_recording, + this._settings + )); + } + + return this.AreaMenuItem; + } + + /** + * @returns {Array} + * @private + */ + _createMIWebCam() { + this.WebCamDevice = [_('No WebCam recording')]; + // add menu item webcam device from GST + const devices = this.CtrlWebcam.getDevicesIV(); + this.WebCamDevice.push(...this.CtrlWebcam.getNameDevices()); + Lib.TalkativeLog(`-*-webcam list: ${this.WebCamDevice}`); + this.AreaMenuItem = new Array(this.WebCamDevice.length); + + for (var i = 0; i < this.AreaMenuItem.length; i++) { + let devicePath = ''; + + // i === 0 is "No Webcam selected" + if (i > 0) { + const device = devices[i - 1]; + devicePath = device.get_properties().get_string('device.path'); + Lib.TalkativeLog(`-*-webcam i=${i} devicePath: ${devicePath}`); + } + + Lib.TalkativeLog(`-*-webcam i=${i} menu-item-text: ${this.WebCamDevice[i]}`); + this.AreaMenuItem[i] = new PopupMenu.PopupMenuItem( + this.WebCamDevice[i], + { + reactive: true, + activate: true, + hover: true, + can_focus: true, + } + ); + + (function (index, devPath, arr, item, settings) { + this.connectMI = function () { + this.connect('activate', () => { + Lib.TalkativeLog(`-*-set webcam device to ${index} ${arr[index]} devicePath=${devPath}`); + settings.setOption(Settings.DEVICE_INDEX_WEBCAM_SETTING_KEY, index); + settings.setOption(Settings.DEVICE_WEBCAM_SETTING_KEY, devPath); + item.label.text = arr[index]; + }); + }; + this.connectMI(); + }.call( + this.AreaMenuItem[i], + i, + devicePath, + this.WebCamDevice, + this.smWebCam, + this._settings + )); + } + + return this.AreaMenuItem; + } + + /** + * @returns {Array} + * @private + */ + _createMIAudioRec() { + // add std menu item + this.AudioChoice = [ + { + desc: _('No audio source'), + name: 'N/A', + port: 'N/A', + sortable: true, + resizeable: true, + }, + { + desc: _('Default audio source'), + name: 'N/A', + port: 'N/A', + sortable: true, + resizeable: true, + }, + ]; + // add menu item audio source from PA + var audioList = this.CtrlAudio.getListInputAudio(); + for (var index in audioList) + this.AudioChoice.push(audioList[index]); + + this.AudioMenuItem = new Array(this.AudioChoice.length); + + for (var i = 0; i < this.AudioChoice.length; i++) { + // create label menu + let labelMenu = this.AudioChoice[i].desc; + if (i >= 2) { + labelMenu += + _('\n - Port: ') + + this.AudioChoice[i].port + + _('\n - Name: ') + + this.AudioChoice[i].name; + } + // create submenu + this.AudioMenuItem[i] = new PopupMenu.PopupMenuItem(labelMenu, { + reactive: true, + activate: true, + hover: true, + can_focus: true, + }); + // add icon on submenu + this.AudioMenuItem[i].actor.insert_child_at_index( + new St.Icon({ + style_class: 'popup-menu-icon', + icon_name: 'audio-card-symbolic', + }), + 1 + ); + + // update choice audio from pref + if (i === this._settings.getOption('i', Settings.INPUT_AUDIO_SOURCE_SETTING_KEY)) { + Lib.TalkativeLog(`-*-get audio choice from pref ${i}`); + this.sub_menu_audio_recording.label.text = this.AudioChoice[i].desc; + } + + // add action on menu item + (function (audioIndex, arr, item, settings) { + this.connectMI = function () { + this.connect('activate', () => { + Lib.TalkativeLog(`-*-set audio choice to ${audioIndex}`); + settings.setOption(Settings.INPUT_AUDIO_SOURCE_SETTING_KEY, audioIndex); + item.label.text = arr[audioIndex].desc; + }); + }; + this.connectMI(); + }.call( + this.AudioMenuItem[i], + i, + this.AudioChoice, + this.sub_menu_audio_recording, + this._settings + )); + } + return this.AudioMenuItem; + } + + /** + * @returns {Array} + * @private + */ + _createMIInfoDelayRec() { + this.DelayTimeTitle = new PopupMenu.PopupMenuItem(_('Delay Time'), { + reactive: false, + }); + + this.DelayTimeLabel = new St.Label({ + text: + Math.floor( + this._settings.getOption('i', Settings.TIME_DELAY_SETTING_KEY) + ).toString() + _(' Sec'), + }); + this.DelayTimeTitle.actor.add_child(this.DelayTimeLabel); + // TODO this.DelayTimeTitle.align = St.Align.END; + + this.imSliderDelay = new PopupMenu.PopupBaseMenuItem({ + activate: false, + }); + this.TimeSlider = new Slider.Slider(this._settings.getOption('i', Settings.TIME_DELAY_SETTING_KEY) / 100); + this.TimeSlider.x_expand = true; + this.TimeSlider.y_expand = true; + + this.TimeSlider.connect('notify::value', item => { + this.DelayTimeLabel.set_text( + Math.floor(item.value * 100).toString() + _(' Sec') + ); + }); + + this.TimeSlider.connect('drag-end', () => this._onDelayTimeChanged()); + this.TimeSlider.connect('scroll-event', () => + this._onDelayTimeChanged() + ); + + this.imSliderDelay.actor.add_child(this.TimeSlider); + + return [this.DelayTimeTitle, this.imSliderDelay]; + } + + /** + * @private + */ + _enable() { + // enable key binding + this._enableKeybindings(); + // immediately activate/deactive shortcut on settings change + this._settings._settings.connect( + `changed::${Settings.ACTIVE_SHORTCUT_SETTING_KEY}`, + () => { + if (this._settings.getOption('b', Settings.ACTIVE_SHORTCUT_SETTING_KEY)) { + Lib.TalkativeLog('-^-shortcut changed - enabling'); + this._enableKeybindings(); + } else { + Lib.TalkativeLog('-^-shortcut changed - disabling'); + this._removeKeybindings(); + } + } + ); + + // start monitoring inputvideo + this.CtrlWebcam.startMonitor(); + + // add indicator + this.add_child(this.indicatorBox); + } + + /** + * @private + */ + _disable() { + // remove key binding + this._removeKeybindings(); + // stop monitoring inputvideo + this.CtrlWebcam.stopMonitor(); + // unregister mixer control + this.CtrlAudio.destroy(); + + // remove indicator + this.remove_child(this.indicatorBox); + } + + /** + * @private + */ + _doDelayAction() { + if (this.isDelayActive) { + Lib.TalkativeLog(`-*-delay recording called | delay= ${this.TimeSlider.value}`); + timerD = new Time.TimerDelay( + Math.floor(this.TimeSlider.value * 100), + this._doPreCommand, + this + ); + timerD.begin(); + } else { + Lib.TalkativeLog('-*-instant recording called'); + // start recording + this._doPreCommand(); + } + } + + /** + * @private + */ + _doPreCommand() { + if (this._settings.getOption('b', Settings.ACTIVE_PRE_CMD_SETTING_KEY)) { + Lib.TalkativeLog('-*-execute pre command'); + + const PreCmd = this._settings.getOption('s', Settings.PRE_CMD_SETTING_KEY); + + this.CtrlExe.Execute( + PreCmd, + false, + res => { + Lib.TalkativeLog(`-*-pre command final: ${res}`); + if (res === true) { + Lib.TalkativeLog('-*-pre command OK'); + this.recorder.start(); + } else { + Lib.TalkativeLog('-*-pre command ERROR'); + this.CtrlNotify.createNotify( + _('ERROR PRE COMMAND - See logs for more info'), + this._icons.off + ); + } + }, + line => { + Lib.TalkativeLog(`-*-pre command output: ${line}`); + } + ); + } else { + this.recorder.start(); + } + } + + /** + * @private + */ + _doRecording() { + // start/stop record screen + if (isActive === false) { + Lib.TalkativeLog('-*-start recording'); + + pathFile = ''; + + // get selected area + const optArea = this._settings.getOption('i', Settings.AREA_SCREEN_SETTING_KEY); + if (optArea > 0) { + Lib.TalkativeLog(`-*-type of selection of the area to record: ${optArea}`); + switch (optArea) { + case 3: + new Selection.SelectionArea(); + break; + case 2: + new Selection.SelectionWindow(); + break; + case 1: + new Selection.SelectionDesktop(); + break; + } + } else { + Lib.TalkativeLog('-*-recording full area'); + this._doDelayAction(); + } + } else { + Lib.TalkativeLog('-*-stop recording'); + isActive = false; + + this.recorder.stop(); + + if (timerC !== null) { + // stop counting rec + timerC.halt(); + timerC = null; + } + + // execute post-command + this._doPostCommand(); + } + + this.refreshIndicator(false); + } + + /** + * @private + */ + _doPostCommand() { + if (this._settings.getOption('b', Settings.ACTIVE_POST_CMD_SETTING_KEY)) { + Lib.TalkativeLog('-*-execute post command'); + + // launch cmd after registration + const tmpCmd = `/usr/bin/sh -c "${this._settings.getOption('s', Settings.POST_CMD_SETTING_KEY)}"`; + + const mapObj = { + _fpath: pathFile, + _dirpath: pathFile.substr(0, pathFile.lastIndexOf('/')), + _fname: pathFile.substr( + pathFile.lastIndexOf('/') + 1, + pathFile.length + ), + }; + + const Cmd = tmpCmd.replace(/_fpath|_dirpath|_fname/gi, match => { + return mapObj[match]; + }); + + Lib.TalkativeLog(`-*-post command:${Cmd}`); + + // execute post command + this.CtrlExe.Spawn(Cmd); + } + } + + /** + * @param {boolean} result whether the recording was successful + * @param {string} file file path of the recorded file + */ + doRecResult(result, file) { + if (result) { + isActive = true; + + Lib.TalkativeLog('-*-record OK'); + // update indicator + const indicators = this._settings.getOption('i', Settings.STATUS_INDICATORS_SETTING_KEY); + this._replaceStdIndicator(indicators === 1 || indicators === 3); + + if (this.isShowNotify) { + Lib.TalkativeLog('-*-show notify'); + // create counting notify + this.notifyCounting = this.CtrlNotify.createNotify( + _('Start Recording'), + this._icons.on + ); + this.notifyCounting.connect('destroy', () => { + Lib.TalkativeLog('-*-notification destroyed'); + this.notifyCounting = null; + }); + + // start counting rec + timerC = new Time.TimerCounting((secpassed, alertEnd) => { + this._refreshNotify(secpassed, alertEnd); + }, this); + timerC.begin(); + } + + // update path file video + pathFile = file; + Lib.TalkativeLog(`-*-update abs file path -> ${pathFile}`); + } else { + Lib.TalkativeLog('-*-record ERROR'); + + pathFile = ''; + + if (this.isShowNotify) { + Lib.TalkativeLog('-*-show error notify'); + this.CtrlNotify.createNotify( + _('ERROR RECORDER - See logs for more info'), + this._icons.off + ); + } + } + this.refreshIndicator(false); + } + + /** + * @param {number} sec the seconds passed + * @param {boolean} alertEnd whether the timer is ending + */ + _refreshNotify(sec, alertEnd) { + if (this.notifyCounting !== null && this.notifyCounting !== undefined && this.isShowNotify) { + if (alertEnd) { + this.CtrlNotify.updateNotify( + this.notifyCounting, + _(`Finish Recording / Seconds : ${sec}`), + this._icons.off, + true + ); + } else { + this.CtrlNotify.updateNotify( + this.notifyCounting, + _('Recording ... / Seconds passed : ') + sec, + this._icons.on, + false + ); + } + } + } + + /** + * @private + */ + _openExtensionPreferences() { + try { + this._extension.openPreferences(); + } catch (e) { + Lib.TalkativeLog(`Failed to open preferences: ${e}`); + } + } + + /** + * @private + */ + _onDelayTimeChanged() { + const secDelay = Math.floor(this.TimeSlider.value * 100); + this._settings.setOption(Settings.TIME_DELAY_SETTING_KEY, secDelay); + if (secDelay > 0) + this.smDelayRec.label.text = secDelay + _(' sec. delay before recording'); + else + this.smDelayRec.label.text = _('Start recording immediately'); + } + + /** + * @param {boolean} focus selects the correct icon depending on the focus state + */ + refreshIndicator(focus) { + Lib.TalkativeLog(`-*-refresh indicator -A ${isActive} -F ${focus}`); + + const indicators = this._settings.getOption('i', Settings.STATUS_INDICATORS_SETTING_KEY); + + if (isActive === true) { + if (indicators === 0 || indicators === 1) { + if (focus === true) + this.indicatorIcon.set_gicon(this._icons.onSel); + else + this.indicatorIcon.set_gicon(this._icons.on); + } else if (this._settings.getOption('b', Settings.ACTIVE_SHORTCUT_SETTING_KEY)) { + this.indicatorIcon.set_gicon(null); + } else if (focus === true) { + this.indicatorIcon.set_gicon(this._icons.onSel); + } else { + this.indicatorIcon.set_gicon(this._icons.on); + } + + this.RecordingLabel.set_text(_('Stop recording')); + } else { + if (focus === true) + this.indicatorIcon.set_gicon(this._icons.offSel); + else + this.indicatorIcon.set_gicon(this._icons.off); + + this.RecordingLabel.set_text(_('Start recording')); + } + } + + /** + * @param {boolean} OPTtemp whether to replace the standard indicator or use it + * @private + */ + _replaceStdIndicator(OPTtemp) { + if (Main.panel.statusArea === undefined) { + Lib.TalkativeLog('-*-no Main.panel.statusArea found'); + return; + } + + var stdMenu = Main.panel.statusArea.quickSettings; + if (stdMenu === undefined) { + Lib.TalkativeLog('-*-no quickSettings or aggregateMenu in Main.panel.statusArea'); + return; + } + if (stdMenu._remoteAccess === undefined) { + Lib.TalkativeLog('-*-no _remoteAccess indicator applet found'); + return; + } + var indicator = stdMenu._remoteAccess._indicator; + if (indicator === undefined) { + Lib.TalkativeLog('-*-no _indicator or _recordingIndicator found'); + return; + } + + if (OPTtemp) { + Lib.TalkativeLog('-*-replace STD indicator'); + indicator.visible = false; + } else { + Lib.TalkativeLog('-*-use STD indicator'); + indicator.visible = isActive; + } + } + + /** + * @private + */ + _enableKeybindings() { + if (this._settings.getOption('b', Settings.ACTIVE_SHORTCUT_SETTING_KEY)) { + Lib.TalkativeLog('-*-enable keybinding'); + + Main.wm.addKeybinding( + Settings.SHORTCUT_KEY_SETTING_KEY, + this._settings._settings, + Meta.KeyBindingFlags.NONE, + // available modes: https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/src/shell-action-modes.h + Shell.ActionMode.NORMAL | + Shell.ActionMode.OVERVIEW | + Shell.ActionMode.POPUP | + Shell.ActionMode.SYSTEM_MODAL, + () => { + Lib.TalkativeLog('-*-intercept key combination'); + this._doRecording(); + } + ); + keybindingConfigured = true; + } + } + + /** + * @private + */ + _removeKeybindings() { + if (keybindingConfigured) { + Lib.TalkativeLog('-*-remove keybinding'); + Main.wm.removeKeybinding(Settings.SHORTCUT_KEY_SETTING_KEY); + keybindingConfigured = false; + } + } + + getSelectedRect() { + var recX = this._settings.getOption('i', Settings.X_POS_SETTING_KEY); + var recY = this._settings.getOption('i', Settings.Y_POS_SETTING_KEY); + var recW = this._settings.getOption('i', Settings.WIDTH_SETTING_KEY); + var recH = this._settings.getOption('i', Settings.HEIGHT_SETTING_KEY); + return [recX, recY, recW, recH]; + } + + saveSelectedRect(x, y, h, w) { + this._settings.setOption(Settings.X_POS_SETTING_KEY, x); + this._settings.setOption(Settings.Y_POS_SETTING_KEY, y); + this._settings.setOption(Settings.HEIGHT_SETTING_KEY, h); + this._settings.setOption(Settings.WIDTH_SETTING_KEY, w); + } + + getSettings() { + return this._settings; + } + + getAudioSource() { + return this.CtrlAudio.getAudioSource(); + } + + /** + * Destroy indicator + */ + destroy() { + Lib.TalkativeLog('-*-destroy indicator called'); + + if (isActive) + isActive = false; + + if (this._settings) { + this._settings.destroy(); + this._settings = null; + } + + super.destroy(); + } +}); + +export default class EasyScreenCast extends Extension { + /** + * + */ + enable() { + Lib.TalkativeLog('-*-enableExtension called'); + Lib.TalkativeLog(`-*-version: ${this.metadata.version}`); + Lib.TalkativeLog(`-*-install path: ${this.path}`); + Lib.TalkativeLog(`-*-version (package.json): ${Lib.getFullVersion()}`); + + if (Indicator === null || Indicator === undefined) { + Lib.TalkativeLog('-*-create indicator'); + + Indicator = new EasyScreenCastIndicator(this); + Main.panel.addToStatusArea('EasyScreenCast-indicator', Indicator); + } + + Indicator._enable(); + } + + /** + * + */ + disable() { + Lib.TalkativeLog('-*-disableExtension called'); + + if (timerD !== null) { + Lib.TalkativeLog('-*-timerD stopped'); + timerD.stop(); + timerD = null; + } + + // this might happen, if the extension is disabled during recording + if (timerC !== null) { + // stop counting rec + timerC.halt(); + timerC = null; + } + + + if (Indicator !== null) { + Lib.TalkativeLog('-*-indicator call destroy'); + + Indicator._disable(); + Indicator.destroy(); + Indicator = null; + } + } +} + +export {Indicator}; diff --git a/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/images/Icon_Info.png b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/images/Icon_Info.png new file mode 100644 index 0000000000000000000000000000000000000000..7f15ae806e77a6add82d7d8f3428317f16165110 GIT binary patch literal 4260 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 +image/svg+xml diff --git a/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/images/Icon_Quality.svg b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/images/Icon_Quality.svg new file mode 100644 index 0000000..b7e8d3d --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/images/Icon_Quality.svg @@ -0,0 +1,45 @@ + +image/svg+xml diff --git a/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/images/icon_default.svg b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/images/icon_default.svg new file mode 100644 index 0000000..ff59a8c --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/images/icon_default.svg @@ -0,0 +1,99 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/images/icon_defaultSel.svg b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/images/icon_defaultSel.svg new file mode 100644 index 0000000..7a57f9a --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/images/icon_defaultSel.svg @@ -0,0 +1,99 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/images/icon_recording.svg b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/images/icon_recording.svg new file mode 100644 index 0000000..0608982 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/images/icon_recording.svg @@ -0,0 +1,99 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/images/icon_recordingSel.svg b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/images/icon_recordingSel.svg new file mode 100644 index 0000000..453444c --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/images/icon_recordingSel.svg @@ -0,0 +1,99 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/locale/ca/LC_MESSAGES/EasyScreenCast@iacopodeenosee.gmail.com.mo b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/locale/ca/LC_MESSAGES/EasyScreenCast@iacopodeenosee.gmail.com.mo new file mode 100644 index 0000000000000000000000000000000000000000..1e565d3c0a46be900b73fe9d2fd6432a7051500e GIT binary patch literal 8718 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 literal 0 HcmV?d00001 diff --git a/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/locale/es/LC_MESSAGES/EasyScreenCast@iacopodeenosee.gmail.com.mo b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/locale/es/LC_MESSAGES/EasyScreenCast@iacopodeenosee.gmail.com.mo new file mode 100644 index 0000000000000000000000000000000000000000..d40762abb9187decd39891185502cdc8be62a581 GIT binary patch literal 5999 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 WHYh}WNaC}SFU5|;)#`%=)cg-hK#-mQ literal 0 HcmV?d00001 diff --git a/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/locale/it/LC_MESSAGES/EasyScreenCast@iacopodeenosee.gmail.com.mo b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/locale/it/LC_MESSAGES/EasyScreenCast@iacopodeenosee.gmail.com.mo new file mode 100644 index 0000000000000000000000000000000000000000..35411ef119dc0f966b6fffe94acfeeea2a2c1130 GIT binary patch literal 7775 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

1^7j9ZQNf6-a~&Y$SdkB`0L<%;1|F@0e=(x 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 literal 0 HcmV?d00001 diff --git a/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/locale/uk/LC_MESSAGES/EasyScreenCast@iacopodeenosee.gmail.com.mo b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/locale/uk/LC_MESSAGES/EasyScreenCast@iacopodeenosee.gmail.com.mo new file mode 100644 index 0000000000000000000000000000000000000000..21ae02fcc7276108d2eef0a06420d24a61c5b46f GIT binary patch literal 8481 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 literal 0 HcmV?d00001 diff --git a/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/metadata.json b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/metadata.json new file mode 100644 index 0000000..5fb398b --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/metadata.json @@ -0,0 +1,13 @@ +{ + "_generated": "Generated by SweetTooth, do not edit", + "description": "This extension simplifies the use of the video recording function integrated in gnome shell, allows quickly to change the various settings of the desktop recording.\n\nSOURCE CODE -> https://github.com/EasyScreenCast/EasyScreenCast\n\nVIDEO -> https://youtu.be/81E9AruraKU\n\n**NOTICE**\nif an error occurs during the update is recommended to reload GNOME Shell (Alt + F2, 'r') and reload the extension's installation page.", + "gettext-domain": "EasyScreenCast@iacopodeenosee.gmail.com", + "name": "EasyScreenCast", + "settings-schema": "org.gnome.shell.extensions.EasyScreenCast", + "shell-version": [ + "46" + ], + "url": "https://github.com/EasyScreenCast/EasyScreenCast", + "uuid": "EasyScreenCast@iacopodeenosee.gmail.com", + "version": 50 +} \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/prefs.css b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/prefs.css new file mode 100644 index 0000000..4dc0f17 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/prefs.css @@ -0,0 +1,7 @@ +.options-grid { + margin: 18px; +} + +.borderless { + border: none; +} diff --git a/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/prefs.js b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/prefs.js new file mode 100644 index 0000000..e0dd1a2 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/prefs.js @@ -0,0 +1,1184 @@ +/* + Copyright (C) 2013 Borsato Ivano + + The JavaScript code in this page is free software: you can + redistribute it and/or modify it under the terms of the GNU + General Public License (GNU GPL) as published by the Free Software + Foundation, either version 3 of the License, or (at your option) + any later version. The code is distributed WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU GPL for more details. +*/ + +'use strict'; + +import GIRepository from 'gi://GIRepository'; +GIRepository.Repository.prepend_search_path('/usr/lib64/gnome-shell'); +GIRepository.Repository.prepend_library_path('/usr/lib64/gnome-shell'); + +import Adw from 'gi://Adw'; +import GObject from 'gi://GObject'; +import Gio from 'gi://Gio'; +import Gtk from 'gi://Gtk'; +import Gdk from 'gi://Gdk'; +import Pango from 'gi://Pango'; + +import {ExtensionPreferences, gettext as _} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; + +import * as Lib from './convenience.js'; +import * as UtilWebcam from './utilwebcam.js'; +import * as UtilGSP from './utilgsp.js'; +import * as Settings from './settings.js'; +import * as UtilExeCmd from './utilexecmd.js'; + +const EasyScreenCastSettingsWidget = GObject.registerClass({ + GTypeName: 'EasyScreenCast_SettingsWidget', +}, class EasyScreenCastSettingsWidget extends Gtk.Box { + /** + * @param {ExtensionPreferences} prefs the prefs instance + */ + constructor(prefs) { + super(); + + this._prefs = prefs; + this._settings = new Settings.Settings(this._prefs.getSettings()); + Lib.setDebugEnabled(this._settings.getOption('b', Settings.VERBOSE_DEBUG_SETTING_KEY)); + this.CtrlExe = new UtilExeCmd.ExecuteStuff(this); + this.CtrlWebcam = new UtilWebcam.HelperWebcam(_('Unspecified webcam')); + + let cssProvider = new Gtk.CssProvider(); + cssProvider.load_from_path(`${prefs.path}/prefs.css`); + Gtk.StyleContext.add_provider_for_display( + Gdk.Display.get_default(), + cssProvider, + Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); + + // creates the ui builder and add the main resource file + let uiFilePath = `${this._prefs.path}/Options_UI.glade`; + let builder = new Gtk.Builder(); + builder.set_translation_domain(this._prefs.metadata['gettext-domain']); + + if (builder.add_from_file(uiFilePath) === 0) { + Lib.TalkativeLog(`-^-could not load the ui file: ${uiFilePath}`); + let label = new Gtk.Label({ + label: _('Could not load the preferences UI file'), + vexpand: true, + }); + + this.append(label); + } else { + Lib.TalkativeLog(`-^-UI file receive and load: ${uiFilePath}`); + + // gets the interesting builder objects + let refBoxMainContainer = builder.get_object('Main_Container'); + this.append(refBoxMainContainer); + + // setup tab options + this._initTabOptions(this, builder, this._settings._settings); + + // setup tab quality + this._initTabQuality(this, builder, this._settings._settings); + + // setup tab webcam + this._initTabWebcam(this, builder, this._settings._settings); + + // setup tab file + this._initTabFile(this, builder, this._settings._settings); + + // setup tab support + this._initTabSupport(this, builder, this._settings._settings); + + // setup tab info + this._initTabInfo(this, builder); + + // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + + // update GSP area + this._setStateGSP( + !this._settings.getOption('b', Settings.ACTIVE_CUSTOM_GSP_SETTING_KEY) + ); + + // update list view + this._updateRowShortcut( + this._settings.getOption('as', Settings.SHORTCUT_KEY_SETTING_KEY)[0] + ); + + // update webcam widget state + this._updateStateWebcamOptions(); + + // connect keywebcam signal + this._settings._settings.connect( + `changed::${Settings.DEVICE_INDEX_WEBCAM_SETTING_KEY}`, + () => { + Lib.TalkativeLog('-^-webcam device changed'); + + this._updateStateWebcamOptions(); + } + ); + } + } + + /** + * @param {EasyScreenCastSettingsWidget} ctx the prefs/settings widget + * @param {Gtk.Builder} gtkDB the builder that loaded the UI glade file + * @param {Gio.Settings} tmpS the current settings + * @private + */ + _initTabOptions(ctx, gtkDB, tmpS) { + // implements show timer option + let refSwitchShowNotifyAlert = gtkDB.get_object('swt_ShowNotifyAlert'); + tmpS.bind( + Settings.SHOW_NOTIFY_ALERT_SETTING_KEY, + refSwitchShowNotifyAlert, + 'active', + Gio.SettingsBindFlags.DEFAULT + ); + + // implements show area option + let refSwitchShowAreaRec = gtkDB.get_object('swt_ShowAreaRec'); + tmpS.bind( + Settings.SHOW_AREA_REC_SETTING_KEY, + refSwitchShowAreaRec, + 'active', + Gio.SettingsBindFlags.DEFAULT + ); + + // implements show indicator option + let refComboboxIndicatorsRec = gtkDB.get_object('cbt_StatusIndicatorsRec'); + tmpS.bind( + Settings.STATUS_INDICATORS_SETTING_KEY, + refComboboxIndicatorsRec, + 'active', + Gio.SettingsBindFlags.DEFAULT + ); + + // implements draw cursor option + let refSwitchDrawCursorRec = gtkDB.get_object('swt_DrawCursorRec'); + tmpS.bind( + Settings.DRAW_CURSOR_SETTING_KEY, + refSwitchDrawCursorRec, + 'active', + Gio.SettingsBindFlags.DEFAULT + ); + + // implements enable keybinding option + let refSwitchEnableShortcut = gtkDB.get_object('swt_KeyShortcut'); + tmpS.bind( + Settings.ACTIVE_SHORTCUT_SETTING_KEY, + refSwitchEnableShortcut, + 'active', + Gio.SettingsBindFlags.DEFAULT + ); + + // implements selecting alternative key combo + let refTreeviewShortcut = gtkDB.get_object('treeview_KeyShortcut'); + refTreeviewShortcut.set_sensitive(true); + ctx.Ref_liststore_Shortcut = gtkDB.get_object('liststore_KeyShortcut'); + ctx.Iter_ShortcutRow = ctx.Ref_liststore_Shortcut.append(); + + let renderer = new Gtk.CellRendererAccel({ + editable: true, + }); + renderer.connect( + 'accel-edited', + (_0, _1, key, mods, _2) => { + Lib.TalkativeLog(`-^-edited key accel: key=${key} mods=${mods}`); + + let accel = Gtk.accelerator_name(key, mods); + + ctx._updateRowShortcut(accel); + this._settings.setOption(Settings.SHORTCUT_KEY_SETTING_KEY, [accel]); + } + ); + + renderer.connect('accel-cleared', () => { + Lib.TalkativeLog('-^-cleared key accel'); + + ctx._updateRowShortcut(null); + this._settings.setOption(Settings.SHORTCUT_KEY_SETTING_KEY, []); + }); + + let column = new Gtk.TreeViewColumn(); + column.pack_start(renderer, true); + column.add_attribute( + renderer, + 'accel-key', + Settings.SHORTCUT_COLUMN_KEY + ); + column.add_attribute( + renderer, + 'accel-mods', + Settings.SHORTCUT_COLUMN_MODS + ); + + refTreeviewShortcut.append_column(column); + + // implements post execute command + let refSwitchExecutePostCmd = gtkDB.get_object('swt_executepostcmd'); + tmpS.bind( + Settings.ACTIVE_POST_CMD_SETTING_KEY, + refSwitchExecutePostCmd, + 'active', + Gio.SettingsBindFlags.DEFAULT + ); + + let refTexteditPostCmd = gtkDB.get_object('txe_postcmd'); + tmpS.bind( + Settings.POST_CMD_SETTING_KEY, + refTexteditPostCmd, + 'text', + Gio.SettingsBindFlags.DEFAULT + ); + + // implements pre execute command + let refSwitchExecutePreCmd = gtkDB.get_object('swt_executeprecmd'); + tmpS.bind( + Settings.ACTIVE_PRE_CMD_SETTING_KEY, + refSwitchExecutePreCmd, + 'active', + Gio.SettingsBindFlags.DEFAULT + ); + + let refTexteditPreCmd = gtkDB.get_object('txe_precmd'); + tmpS.bind( + Settings.PRE_CMD_SETTING_KEY, + refTexteditPreCmd, + 'text', + Gio.SettingsBindFlags.DEFAULT + ); + } + + /** + * @param {EasyScreenCastSettingsWidget} ctx the prefs/settings widget + * @param {Gtk.Builder} gtkDB the builder that loaded the UI glade file + * @param {Gio.Settings} tmpS the current settings + * @private + */ + _initTabQuality(ctx, gtkDB, tmpS) { + // implements FPS option + let refSpinnerFrameRateRec = gtkDB.get_object('spb_FrameRateRec'); + // Create an adjustment to use for the second spinbutton + let adjustment1 = new Gtk.Adjustment({ + value: 30, + lower: 1, + upper: 666, + step_increment: 1, + page_increment: 10, + }); + refSpinnerFrameRateRec.configure(adjustment1, 10, 0); + tmpS.bind( + Settings.FPS_SETTING_KEY, + refSpinnerFrameRateRec, + 'value', + Gio.SettingsBindFlags.DEFAULT + ); + + // implements command string rec option + let refTexteditPipeline = gtkDB.get_object('txe_CommandStringRec'); + let refBufferPipeline = refTexteditPipeline.get_buffer(); + tmpS.bind( + Settings.PIPELINE_REC_SETTING_KEY, + refBufferPipeline, + 'text', + Gio.SettingsBindFlags.DEFAULT + ); + + // implements label description GSP + let refLabelDescGSP = gtkDB.get_object('lbl_GSP_Description'); + refLabelDescGSP.set_text( + UtilGSP.getDescr( + this._settings.getOption('i', Settings.QUALITY_SETTING_KEY), + this._settings.getOption('i', Settings.FILE_CONTAINER_SETTING_KEY) + ) + ); + // update label description when container selection changed + this._settings._settings.connect(`changed::${Settings.FILE_CONTAINER_SETTING_KEY}`, () => { + Lib.TalkativeLog('-^- new setting for file container, update gps description'); + refLabelDescGSP.set_text( + UtilGSP.getDescr( + this._settings.getOption('i', Settings.QUALITY_SETTING_KEY), + this._settings.getOption('i', Settings.FILE_CONTAINER_SETTING_KEY) + ) + ); + }); + + + // implements quality scale option + let refScaleQuality = gtkDB.get_object('scl_Quality'); + refScaleQuality.set_valign(Gtk.Align.START); + let adjustment2 = new Gtk.Adjustment({ + value: 1, + lower: 0, + upper: 3, + step_increment: 1, + page_increment: 1, + }); + refScaleQuality.set_adjustment(adjustment2); + refScaleQuality.set_digits(1); + let ind = 0; + for (; ind < 4; ind++) + refScaleQuality.add_mark(ind, Gtk.PositionType.BOTTOM, ''); + + + refScaleQuality.set_value( + this._settings.getOption('i', Settings.QUALITY_SETTING_KEY) + ); + + let oldQualityValue = refScaleQuality.get_value(); + refScaleQuality.connect('value-changed', self => { + // not logging by default - it's too much + // Lib.TalkativeLog(`-^-value quality changed : ${self.get_value()}`); + + // round the value + let roundTmp = parseInt(self.get_value().toFixed(0)); + // not logging by default - it's too much + // Lib.TalkativeLog(`-^-value quality fixed : ${roundTmp}`); + + self.set_value(roundTmp); + + // only update labels for real changes + if (oldQualityValue !== roundTmp) { + oldQualityValue = roundTmp; + this._settings.setOption(Settings.QUALITY_SETTING_KEY, roundTmp); + + // update label descr GSP + refLabelDescGSP.set_text( + UtilGSP.getDescr( + roundTmp, + this._settings.getOption('i', Settings.FILE_CONTAINER_SETTING_KEY) + ) + ); + + // update fps + this._settings.setOption( + Settings.FPS_SETTING_KEY, + UtilGSP.getFps( + roundTmp, + this._settings.getOption('i', Settings.FILE_CONTAINER_SETTING_KEY) + ) + ); + } + }); + + // implements image for scale widget + let refImagePerformance = gtkDB.get_object('img_Performance'); + refImagePerformance.set_from_file(Lib.getImagePath(this._prefs.dir, 'Icon_Performance.svg')); + + let refImageQuality = gtkDB.get_object('img_Quality'); + refImageQuality.set_from_file(Lib.getImagePath(this._prefs.dir, 'Icon_Quality.svg')); + + // implements custom GSPipeline option + let refSwitchCustomGSP = gtkDB.get_object('swt_EnableCustomGSP'); + tmpS.bind( + Settings.ACTIVE_CUSTOM_GSP_SETTING_KEY, + refSwitchCustomGSP, + 'active', + Gio.SettingsBindFlags.DEFAULT + ); + refSwitchCustomGSP.connect('state-set', () => { + // update GSP text area + ctx._setStateGSP(this._settings.getOption('b', Settings.ACTIVE_CUSTOM_GSP_SETTING_KEY)); + }); + + ctx.Ref_stack_Quality = gtkDB.get_object('stk_Quality'); + } + + /** + * @param {EasyScreenCastSettingsWidget} ctx the prefs/settings widget + * @param {Gtk.Builder} gtkDB the builder that loaded the UI glade file + * @param {Gio.Settings} tmpS the current settings + * @private + */ + _initTabWebcam(ctx, gtkDB, tmpS) { + // implements webcam quality option: Type: GtkListStore + ctx.Ref_ListStore_QualityWebCam = gtkDB.get_object( + 'liststore_QualityWebCam' + ); + let refTreeViewQualityWebCam = gtkDB.get_object( + 'treeview_QualityWebam' + ); + // create column data + let capsColumn = new Gtk.TreeViewColumn({ + title: _('WebCam Caps'), + }); + let normalColumn = new Gtk.CellRendererText(); + capsColumn.pack_start(normalColumn, true); + capsColumn.add_attribute(normalColumn, 'text', 0); + + // insert caps column into treeview + refTreeViewQualityWebCam.insert_column(capsColumn, 0); + + // setup selection liststore + let capsSelection = refTreeViewQualityWebCam.get_selection(); + + // connect selection signal + capsSelection.connect('changed', self => { + let [isSelected,, iter] = self.get_selected(); + if (isSelected) { + let Caps = ctx.Ref_ListStore_QualityWebCam.get_value(iter, 0); + Lib.TalkativeLog(`-^-treeview row selected : ${Caps}`); + + this._settings.setOption(Settings.QUALITY_WEBCAM_SETTING_KEY, Caps); + + // update label webcam caps + ctx.Ref_Label_WebCamCaps.set_ellipsize(Pango.EllipsizeMode.END); + ctx.Ref_Label_WebCamCaps.set_text(Caps); + } + }); + + // fill combobox with quality option webcam + ctx._updateWebCamCaps(this._settings.getOption('i', Settings.DEVICE_INDEX_WEBCAM_SETTING_KEY)); + + // implements webcam corner position option + let refComboboxCornerWebCam = gtkDB.get_object('cbt_WebCamCorner'); + tmpS.bind( + Settings.CORNER_POSITION_WEBCAM_SETTING_KEY, + refComboboxCornerWebCam, + 'active', + Gio.SettingsBindFlags.DEFAULT + ); + + // implements webcam margin x position option + let refSpinnerMarginXWebCam = gtkDB.get_object('spb_WebCamMarginX'); + let adjustmentMarginX = new Gtk.Adjustment({ + value: 0, + lower: 0, + upper: 10000, + step_increment: 1, + page_increment: 10, + }); + refSpinnerMarginXWebCam.configure(adjustmentMarginX, 10, 0); + tmpS.bind( + Settings.MARGIN_X_WEBCAM_SETTING_KEY, + refSpinnerMarginXWebCam, + 'value', + Gio.SettingsBindFlags.DEFAULT + ); + + // implements webcam margin y position option + let refSpinnerMarginYWebCam = gtkDB.get_object('spb_WebCamMarginY'); + let adjustmentMarginY = new Gtk.Adjustment({ + value: 0, + lower: 0, + upper: 10000, + step_increment: 1, + page_increment: 10, + }); + refSpinnerMarginYWebCam.configure(adjustmentMarginY, 10, 0); + tmpS.bind( + Settings.MARGIN_Y_WEBCAM_SETTING_KEY, + refSpinnerMarginYWebCam, + 'value', + Gio.SettingsBindFlags.DEFAULT + ); + + // implements webcam aplha channel option + let refSpinnerAlphaWebCam = gtkDB.get_object('spb_WebCamAlpha'); + let adjustmentAlpha = new Gtk.Adjustment({ + value: 0.01, + lower: 0.0, + upper: 1.0, + step_increment: 0.05, + page_increment: 0.25, + }); + refSpinnerAlphaWebCam.configure(adjustmentAlpha, 0.25, 2); + tmpS.bind( + Settings.ALPHA_CHANNEL_WEBCAM_SETTING_KEY, + refSpinnerAlphaWebCam, + 'value', + Gio.SettingsBindFlags.DEFAULT + ); + + // implements webcam type unit dimension option + let refComboboxTypeUnitWebCam = gtkDB.get_object('cbt_WebCamUnitMeasure'); + tmpS.bind( + Settings.TYPE_UNIT_WEBCAM_SETTING_KEY, + refComboboxTypeUnitWebCam, + 'active', + Gio.SettingsBindFlags.DEFAULT + ); + + // implements webcam width option + let refSpinnerWidthWebCam = gtkDB.get_object('spb_WebCamWidth'); + let adjustmentWidth = new Gtk.Adjustment({ + value: 20, + lower: 0, + upper: 10000, + step_increment: 1, + page_increment: 10, + }); + refSpinnerWidthWebCam.configure(adjustmentWidth, 10, 0); + tmpS.bind( + Settings.WIDTH_WEBCAM_SETTING_KEY, + refSpinnerWidthWebCam, + 'value', + Gio.SettingsBindFlags.DEFAULT + ); + + // implements webcam heigth option + let refSpinnerHeightWebCam = gtkDB.get_object('spb_WebCamHeight'); + let adjustmentHeight = new Gtk.Adjustment({ + value: 10, + lower: 0, + upper: 10000, + step_increment: 1, + page_increment: 10, + }); + refSpinnerHeightWebCam.configure(adjustmentHeight, 10, 0); + tmpS.bind( + Settings.HEIGHT_WEBCAM_SETTING_KEY, + refSpinnerHeightWebCam, + 'value', + Gio.SettingsBindFlags.DEFAULT + ); + + // implements webcam stack menu chooser + ctx.Ref_StackSwitcher_WebCam = gtkDB.get_object('sts_Webcam'); + // implements webcam stack obj + ctx.Ref_StackObj_WebCam = gtkDB.get_object('stk_Webcam'); + // implements webcam stack menu chooser + ctx.Ref_Label_WebCam = gtkDB.get_object('lbl_Webcam'); + // implements webcam caps stack menu chooser + ctx.Ref_Label_WebCamCaps = gtkDB.get_object('lbl_WebcamCaps'); + } + + /** + * @param {EasyScreenCastSettingsWidget} ctx the prefs/settings widget + * @param {Gtk.Builder} gtkDB the builder that loaded the UI glade file + * @param {Gio.Settings} tmpS the current settings + * @private + */ + _initTabFile(ctx, gtkDB, tmpS) { + // implements file name string rec option + let refTexteditFileName = gtkDB.get_object('txe_FileNameRec'); + tmpS.bind( + Settings.FILE_NAME_SETTING_KEY, + refTexteditFileName, + 'text', + Gio.SettingsBindFlags.DEFAULT + ); + + // implements file container option + let refComboboxContainer = gtkDB.get_object('cbt_FileContainer'); + tmpS.bind( + Settings.FILE_CONTAINER_SETTING_KEY, + refComboboxContainer, + 'active', + Gio.SettingsBindFlags.DEFAULT + ); + + // implements file container resolution + let refStackFileResolution = gtkDB.get_object('stk_FileResolution'); + + // implements file resolution preset spinner + let refComboboxResolution = gtkDB.get_object('cbt_FileResolution'); + tmpS.bind( + Settings.FILE_RESOLUTION_TYPE_SETTING_KEY, + refComboboxResolution, + 'active', + Gio.SettingsBindFlags.DEFAULT + ); + + // intercept combobox res changed and update width/height value + refComboboxResolution.connect('changed', self => { + var activeRes = self.active; + Lib.TalkativeLog(`-^-preset combobox changed: ${activeRes}`); + if (activeRes >= 0 && activeRes < 15) { + var [h, w] = ctx._getResolutionPreset(activeRes); + + // update width/height + this._settings.setOption(Settings.FILE_RESOLUTION_HEIGHT_SETTING_KEY, h); + this._settings.setOption(Settings.FILE_RESOLUTION_WIDTH_SETTING_KEY, w); + Lib.TalkativeLog(`-^-Res changed h: ${h} w: ${w}`); + } + }); + + // load file resolution pref and upadte UI + var tmpRes = this._settings.getOption('i', Settings.FILE_RESOLUTION_TYPE_SETTING_KEY); + if (tmpRes < 0) + refStackFileResolution.set_visible_child_name('native'); + else if (tmpRes === 999) + refStackFileResolution.set_visible_child_name('custom'); + else + refStackFileResolution.set_visible_child_name('preset'); + + + // setup event on stack switcher + refStackFileResolution.connect('notify::visible-child-name', () => { + Lib.TalkativeLog('-^-stack_FR event grab'); + var page = refStackFileResolution.get_visible_child_name(); + Lib.TalkativeLog(`-^-active page -> ${page}`); + + if (page === 'native') { + // set option to -1 + this._settings.setOption(Settings.FILE_RESOLUTION_TYPE_SETTING_KEY, -1); + } else if (page === 'preset') { + // set option to fullHD 16:9 + this._settings.setOption(Settings.FILE_RESOLUTION_TYPE_SETTING_KEY, 8); + } else if (page === 'custom') { + // set option to 99 + this._settings.setOption(Settings.FILE_RESOLUTION_TYPE_SETTING_KEY, 999); + } else { + Lib.TalkativeLog('-^-page error'); + } + }); + + // implements file width option + let refSpinnerWidthRes = gtkDB.get_object('spb_ResWidth'); + let adjustmentResWidth = new Gtk.Adjustment({ + value: 640, + lower: 640, + upper: 3840, + step_increment: 1, + page_increment: 100, + }); + refSpinnerWidthRes.configure(adjustmentResWidth, 10, 0); + tmpS.bind( + Settings.FILE_RESOLUTION_WIDTH_SETTING_KEY, + refSpinnerWidthRes, + 'value', + Gio.SettingsBindFlags.DEFAULT + ); + + // implements file heigth option + let refSpinnerHeightRes = gtkDB.get_object('spb_ResHeight'); + let adjustmentResHeight = new Gtk.Adjustment({ + value: 480, + lower: 480, + upper: 2160, + step_increment: 1, + page_increment: 100, + }); + refSpinnerHeightRes.configure(adjustmentResHeight, 10, 0); + tmpS.bind( + Settings.FILE_RESOLUTION_HEIGHT_SETTING_KEY, + refSpinnerHeightRes, + 'value', + Gio.SettingsBindFlags.DEFAULT + ); + + // implements keep aspect ratio check box + let refCheckboxKeepAspectRatio = gtkDB.get_object('chb_FileResolution_kar'); + tmpS.bind( + Settings.FILE_RESOLUTION_KAR_SETTING_KEY, + refCheckboxKeepAspectRatio, + 'active', + Gio.SettingsBindFlags.DEFAULT + ); + + // implements resolution width scale option + let refScaleWidthRes = gtkDB.get_object('scl_ResWidth'); + refScaleWidthRes.set_valign(Gtk.Align.START); + refScaleWidthRes.set_adjustment(adjustmentResWidth); + refScaleWidthRes.set_digits(0); + refScaleWidthRes.set_value(this._settings.getOption('i', Settings.FILE_RESOLUTION_WIDTH_SETTING_KEY)); + + // implements resolution height scale option + let refScaleHeightRes = gtkDB.get_object('scl_ResHeight'); + refScaleHeightRes.set_valign(Gtk.Align.START); + refScaleHeightRes.set_adjustment(adjustmentResHeight); + refScaleHeightRes.set_digits(0); + refScaleHeightRes.set_value(this._settings.getOption('i', Settings.FILE_RESOLUTION_HEIGHT_SETTING_KEY)); + + // add marks on width/height file resolution + let ind = 0; + for (; ind < 13; ind++) { + var [h, w] = ctx._getResolutionPreset(ind); + refScaleWidthRes.add_mark(w, Gtk.PositionType.BOTTOM, ''); + refScaleHeightRes.add_mark(h, Gtk.PositionType.BOTTOM, ''); + } + + // implements file folder string rec option + let refFilechooserFileFolder = gtkDB.get_object('fcb_FilePathRec'); + // check state initial value + var tmpFolder = this._settings.getOption('s', Settings.FILE_FOLDER_SETTING_KEY); + Lib.TalkativeLog(`-^-folder for screencast: ${tmpFolder}`); + if (tmpFolder === '' || tmpFolder === null || tmpFolder === undefined) { + let result = null; + ctx.CtrlExe.Execute( + 'xdg-user-dir VIDEOS', + true, + (success, out) => { + Lib.TalkativeLog(`-^-CALLBACK sync S: ${success} out: ${out}`); + if (success && out !== '' && out !== undefined) + result = out.replace(/(\n)/g, ''); + }, + null + ); + + if (result !== null) { + Lib.TalkativeLog(`-^-xdg-user video: ${result}`); + tmpFolder = result; + } else { + Lib.TalkativeLog('-^-NOT SET xdg-user video'); + + ctx.CtrlExe.Execute( + '/usr/bin/sh -c "echo $HOME"', + true, + (success, out) => { + Lib.TalkativeLog(`-^-CALLBACK sync S: ${success} out: ${out}`); + if (success && out !== '' && out !== undefined) + tmpFolder = out.replace(/(\n)/g, ''); + }, + null + ); + } + + // connect keywebcam signal + this._settings._settings.connect( + `changed::${Settings.DEVICE_INDEX_WEBCAM_SETTING_KEY}`, + () => { + Lib.TalkativeLog('-^-webcam device changed'); + this._refreshWebcamOptions(); + } + ); + } + + refFilechooserFileFolder.set_label(`Selected: ${tmpFolder}`); + + refFilechooserFileFolder.connect('clicked', () => { + Lib.TalkativeLog('-^- file chooser button clicked...'); + + let dialog = new Gtk.FileChooserNative({ + 'title': 'Select folder', + 'transient-for': refFilechooserFileFolder.get_root(), + 'action': Gtk.FileChooserAction.SELECT_FOLDER, + 'accept-label': 'Ok', + 'cancel-label': 'Cancel', + }); + dialog.connect('response', (self, response) => { + if (response === Gtk.ResponseType.ACCEPT) { + var tmpPathFolder = self.get_file().get_path(); + Lib.TalkativeLog(`-^-file path get from widget : ${tmpPathFolder}`); + this._settings.setOption( + Settings.FILE_FOLDER_SETTING_KEY, + tmpPathFolder + ); + refFilechooserFileFolder.set_label(`Selected: ${tmpPathFolder}`); + } + ctx.fileChooserDialog = null; + }); + dialog.show(); + ctx.fileChooserDialog = dialog; // keep a reference to the dialog alive + }); + } + + /** + * @param {EasyScreenCastSettingsWidget} ctx the prefs/settings widget + * @param {Gtk.Builder} gtkDB the builder that loaded the UI glade file + * @param {Gio.Settings} tmpS the current settings + * @private + */ + _initTabSupport(ctx, gtkDB, tmpS) { + // implements textentry log + let refTextViewEscLog = gtkDB.get_object('txe_ContainerLog'); + let refBufferLog = refTextViewEscLog.get_buffer(); + + // implements verbose debug option + let refSwitchVerboseDebug = gtkDB.get_object('swt_VerboseDebug'); + tmpS.bind( + Settings.VERBOSE_DEBUG_SETTING_KEY, + refSwitchVerboseDebug, + 'active', + Gio.SettingsBindFlags.DEFAULT + ); + this._settings._settings.connect( + `changed::${Settings.VERBOSE_DEBUG_SETTING_KEY}`, + () => { + Lib.setDebugEnabled(this._settings.getOption('b', Settings.VERBOSE_DEBUG_SETTING_KEY)); + } + ); + + refSwitchVerboseDebug.connect('state-set', self => { + // update log display widgets + refTextViewEscLog.sensistive = self.active; + refComboboxLogChooser.sensitive = self.active; + }); + + // implements file resolution preset spinner + let refComboboxLogChooser = gtkDB.get_object('cbt_LogChooser'); + + // intercept combobox res changed and update width/height value + refComboboxLogChooser.connect('changed', self => { + const activeLog = self.active; + Lib.TalkativeLog(`-^-log combobox changed: ${activeLog}`); + switch (activeLog) { + case 0: + // clear buffer + refBufferLog.delete( + refBufferLog.get_start_iter(), + refBufferLog.get_end_iter() + ); + + ctx.CtrlExe.Execute( + 'journalctl --since "15 min ago" --output=cat --no-pager', + false, + success => { + Lib.TalkativeLog(`-^-CALLBACK async S= ${success}`); + }, + line => { + let esc = line.indexOf('[ESC]'); + if ( + line !== '' && + line !== undefined && + esc !== -1 + ) { + line += '\n'; + refBufferLog.insert( + refBufferLog.get_end_iter(), + line, + line.length + ); + } + } + ); + break; + case 1: + // clear buffer + refBufferLog.delete( + refBufferLog.get_start_iter(), + refBufferLog.get_end_iter() + ); + + ctx.CtrlExe.Execute( + 'journalctl --since "15 min ago" --output=cat --no-pager', + false, + success => { + Lib.TalkativeLog(`-^-CALLBACK async S= ${success}`); + if (success) { + if (refBufferLog.get_line_count() > 0) { + let strNOgsp = _( + 'No Gstreamer pipeline found' + ); + refBufferLog.insert( + refBufferLog.get_end_iter(), + strNOgsp, + strNOgsp.length + ); + } + } + }, + line => { + let esc = line.indexOf('-§-final GSP :'); + if ( + line !== '' && + line !== undefined && + esc !== -1 + ) { + line += '\n'; + refBufferLog.insert( + refBufferLog.get_end_iter(), + line, + line.length + ); + } + } + ); + break; + case 2: + // clear buffer + refBufferLog.delete( + refBufferLog.get_start_iter(), + refBufferLog.get_end_iter() + ); + + ctx.CtrlExe.Execute( + 'journalctl /usr/bin/gnome-shell --since "15 min ago" --output=cat --no-pager', + false, + success => { + Lib.TalkativeLog(`-^-CALLBACK async S= ${success}`); + }, + line => { + if (line !== '' && line !== undefined) { + line += '\n'; + refBufferLog.insert( + refBufferLog.get_end_iter(), + line, + line.length + ); + } + } + ); + break; + default: + break; + } + }); + + // update state of get log + refComboboxLogChooser.sensistive = this._settings.getOption('b', Settings.VERBOSE_DEBUG_SETTING_KEY); + + // implements default button action + let refButtonSetDefaultSettings = gtkDB.get_object('btn_DefaultOption'); + refButtonSetDefaultSettings.connect('clicked', () => + ctx._setDefaultsettings() + ); + } + + /** + * @param {EasyScreenCastSettingsWidget} ctx the prefs/settings widget + * @param {Gtk.Builder} gtkDB the builder that loaded the UI glade file + * @private + */ + _initTabInfo(ctx, gtkDB) { + // implements info img extension + let refImageEsc = gtkDB.get_object('img_ESC'); + refImageEsc.set_from_file(Lib.getImagePath(this._prefs.dir, 'Icon_Info.png')); + + // implements info version label + let refLabelVersion = gtkDB.get_object('lbl_Version'); + refLabelVersion.set_markup(`${_('Version: ')}${this._prefs.metadata.version} (${Lib.getFullVersion()})`); + } + + /** + * @param {number} device device index + * @private + */ + _updateWebCamCaps(device) { + Lib.TalkativeLog(`-^-webcam device index: ${device}`); + + if (device > 0) { + this._initializeWebcamHelper(); + var listCaps = this.CtrlWebcam.getListCapsDevice(device - 1); + Lib.TalkativeLog(`-^-webcam caps: ${listCaps.length}`); + if (listCaps !== null && listCaps !== undefined) { + this.Ref_ListStore_QualityWebCam.clear(); + for (var index in listCaps) { + this.Ref_ListStore_QualityWebCam.set( + this.Ref_ListStore_QualityWebCam.append(), + [0], + [listCaps[index]] + ); + } + } else { + Lib.TalkativeLog('-^-NO List Caps Webcam'); + this.Ref_ListStore_QualityWebCam.clear(); + this._settings.setOption(Settings.QUALITY_WEBCAM_SETTING_KEY, ''); + } + } else { + Lib.TalkativeLog('-^-NO Webcam recording'); + this.Ref_ListStore_QualityWebCam.clear(); + this._settings.setOption(Settings.QUALITY_WEBCAM_SETTING_KEY, ''); + } + } + + /** + * Refreshes the webcam settings. + * + * @private + */ + _refreshWebcamOptions() { + Lib.TalkativeLog('-^-refresh webcam options'); + this._initializeWebcamHelper(); + + // fill combobox with quality option webcam + this._updateWebCamCaps(this._settings.getOption('i', Settings.DEVICE_INDEX_WEBCAM_SETTING_KEY)); + + // update webcam widget state + this._updateStateWebcamOptions(); + } + + /** + * Initializes this.CtrlWebcam if it is null. + * + * @private + */ + _initializeWebcamHelper() { + if (this.CtrlWebcam === null) + this.CtrlWebcam = new UtilWebcam.HelperWebcam(_('Unspecified webcam')); + } + + /** + * @param {string} accel accelerator string parsable by Gtk.accelerator_parse, e.g. "<Super>E" + * @private + */ + _updateRowShortcut(accel) { + Lib.TalkativeLog(`-^-update row combo key accel: ${accel}`); + + let [key, mods] = [0, 0]; + + if (accel !== null && accel !== undefined) { + let ok; + [ok, key, mods] = Gtk.accelerator_parse(accel); + + if (ok !== true) { + Lib.TalkativeLog('-^-couldn\'t parse accel'); + key = 0; + mods = 0; + } + } + + Lib.TalkativeLog(`-^-key: ${key} mods: ${mods}`); + this.Ref_liststore_Shortcut.set( + this.Iter_ShortcutRow, + [Settings.SHORTCUT_COLUMN_KEY, Settings.SHORTCUT_COLUMN_MODS], + [key, mods] + ); + } + + /** + * @param {boolean} active custom or not custom GStream pipeline + * @private + */ + _setStateGSP(active) { + // update GSP text area + if (!active) { + Lib.TalkativeLog('-^-custom GSP'); + + this.Ref_stack_Quality.set_visible_child_name('pg_Custom'); + } else { + Lib.TalkativeLog('-^-NOT custom GSP'); + + this.Ref_stack_Quality.set_visible_child_name('pg_Preset'); + + var audio = false; + if (this._settings.getOption('i', Settings.INPUT_AUDIO_SOURCE_SETTING_KEY) > 0) + audio = true; + + this._settings.setOption( + Settings.PIPELINE_REC_SETTING_KEY, + Settings.getGSPstd(audio) + ); + } + } + + /** + * @private + */ + _updateStateWebcamOptions() { + Lib.TalkativeLog('-^-update webcam option widgets'); + + var tmpDev = this._settings.getOption( + 'i', + Settings.DEVICE_INDEX_WEBCAM_SETTING_KEY + ); + this._updateWebCamCaps(tmpDev); + if (tmpDev > 0) { + var arrDev = this.CtrlWebcam.getNameDevices(); + this.Ref_Label_WebCam.set_text(arrDev[tmpDev - 1]); + + // setup label webcam caps + var tmpCaps = this._settings.getOption( + 's', + Settings.QUALITY_WEBCAM_SETTING_KEY + ); + if (tmpCaps === '') { + this.Ref_Label_WebCamCaps.use_markup = true; + this.Ref_Label_WebCamCaps.set_markup( + _( + 'No Caps selected, please select one from the caps list' + ) + ); + } else { + this.Ref_Label_WebCamCaps.set_text(tmpCaps); + } + + // webcam recording show widget + this.Ref_StackSwitcher_WebCam.set_sensitive(true); + this.Ref_StackObj_WebCam.set_sensitive(true); + } else { + this.Ref_Label_WebCam.set_text(_('No webcam device selected')); + // setup label webcam caps + this.Ref_Label_WebCamCaps.set_text(_('-')); + // webcam NOT recording hide widget + this.Ref_StackSwitcher_WebCam.set_sensitive(false); + this.Ref_StackObj_WebCam.set_sensitive(false); + } + } + + /** + * @param {number} index index of the predefined resolutions + * @returns {Array} + * @private + */ + _getResolutionPreset(index) { + var arrRes = [ + [480, 640], + [480, 854], + [600, 800], + [720, 960], + [720, 1280], + [768, 1024], + [768, 1366], + [1024, 1280], + [1080, 1920], + [1200, 1600], + [1440, 2560], + [2048, 2560], + [2160, 3840], + ]; + if (index >= 0 && index < arrRes.length) + return arrRes[index]; + else + return null; + } + + /** + * function to restore default value of the settings + * + * @private + */ + _setDefaultsettings() { + Lib.TalkativeLog('-^-restore default option'); + + this._settings.setOption(Settings.SHOW_NOTIFY_ALERT_SETTING_KEY, true); + this._settings.setOption(Settings.SHOW_AREA_REC_SETTING_KEY, false); + this._settings.setOption(Settings.STATUS_INDICATORS_SETTING_KEY, 1); + this._settings.setOption(Settings.DRAW_CURSOR_SETTING_KEY, true); + this._settings.setOption(Settings.VERBOSE_DEBUG_SETTING_KEY, false); + this._settings.setOption(Settings.ACTIVE_CUSTOM_GSP_SETTING_KEY, false); + + this._settings.setOption(Settings.FPS_SETTING_KEY, 30); + this._settings.setOption(Settings.X_POS_SETTING_KEY, 0); + this._settings.setOption(Settings.Y_POS_SETTING_KEY, 0); + this._settings.setOption(Settings.WIDTH_SETTING_KEY, 600); + this._settings.setOption(Settings.HEIGHT_SETTING_KEY, 400); + + this._settings.setOption(Settings.FILE_NAME_SETTING_KEY, 'Screencast_%d_%t'); + this._settings.setOption(Settings.FILE_FOLDER_SETTING_KEY, ''); + this._settings.setOption(Settings.ACTIVE_POST_CMD_SETTING_KEY, false); + this._settings.setOption(Settings.ACTIVE_PRE_CMD_SETTING_KEY, false); + this._settings.setOption(Settings.POST_CMD_SETTING_KEY, 'xdg-open _fpath &'); + this._settings.setOption(Settings.INPUT_AUDIO_SOURCE_SETTING_KEY, 0); + this._settings.setOption(Settings.DEVICE_INDEX_WEBCAM_SETTING_KEY, 0); + this._settings.setOption(Settings.DEVICE_WEBCAM_SETTING_KEY, ''); + + this._settings.setOption(Settings.TIME_DELAY_SETTING_KEY, 0); + this._settings.setOption(Settings.FILE_CONTAINER_SETTING_KEY, 0); + this._settings.setOption(Settings.FILE_RESOLUTION_TYPE_SETTING_KEY, -1); + this._settings.setOption(Settings.QUALITY_SETTING_KEY, 1); + this._settings.setOption(Settings.QUALITY_WEBCAM_SETTING_KEY, ''); + this._settings.setOption(Settings.WIDTH_WEBCAM_SETTING_KEY, 20); + this._settings.setOption(Settings.HEIGHT_WEBCAM_SETTING_KEY, 10); + this._settings.setOption(Settings.TYPE_UNIT_WEBCAM_SETTING_KEY, 0); + this._settings.setOption(Settings.MARGIN_X_WEBCAM_SETTING_KEY, 0); + this._settings.setOption(Settings.MARGIN_Y_WEBCAM_SETTING_KEY, 0); + this._settings.setOption(Settings.ALPHA_CHANNEL_WEBCAM_SETTING_KEY, 0.75); + this._settings.setOption(Settings.CORNER_POSITION_WEBCAM_SETTING_KEY, 0); + } +}); + + +export default class EasyScreenCastPreferences extends ExtensionPreferences { + /** + * @param {Adw.PreferencesWindow} window preferences window? + * @returns {EasyScreenCastSettingsWidget} + */ + fillPreferencesWindow(window) { + window._settings = this.getSettings(); + + Lib.TalkativeLog('-^-Init pref widget'); + + const page = new Adw.PreferencesPage(); + + const group = new Adw.PreferencesGroup({ + title: _('EasyScreenCast'), + }); + page.add(group); + + const widget = new EasyScreenCastSettingsWidget(this); + group.add(widget); + + window.add(page); + } +} diff --git a/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/schemas/gschemas.compiled b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/schemas/gschemas.compiled new file mode 100644 index 0000000000000000000000000000000000000000..362d39eb573998ac109b0b56e9637cfdc2a4e295 GIT binary patch literal 2580 zcmZ8jU2GIp7`=#r4Ct%rLR@s>y92rSNq*aO8-GeXA@g_cE>Y+7H)>d6b1{x^#G@702+ZN zVDT(0fo=wtWmpa-S^z9ltjKUH_%@&|!|mYJKn_?7tOM@M&<@^^!2*B1<>^Vz&%Lh@ zqap{kfVU#LQ!Jh#Wd4~fRjfiHGS%4w7&|T1|B_X9imUo_%j*n zfX!{AztN{Q`vtECdJ4x*(5E(W26q9k?%Sy7Q}etY0QUe*JH2!CsTaWS1MdV*PxXF4 zpL!wuJ>Ud5wQ%51`qYfuIQTW-mqUMDpikWhe*%0Q2(}*km_D_M1NaP3E*|)TJ~hw% z5_tYXA>RCSWC?w0j?)ZY1Dt*Kxdy)P)OGMJ@Gjsf`~7CNr>4ILTm*Xd9-X33&HYxu z`+=9=IQlDnYR3O9@C0yh)!Fs*skz^i;7QKjC@8F5!>T0hNa~=J#HdnsQK~|*RuwIkA4!~&imUdR z9CDp91`w9cdyz9{yGf*jXr8c!@}UZ4N%<1Lj)wP1-_4bkKZve=te%lk_omIcvQwFB zxM5-^T6*1EbDnfOcJJQQWu9DIj9}^R_JQ2m+(;r53C0S_<)mU3;JC3Gl~{s~gR))F zA=fpOchJq&ro?ik0_&F*=_awX!wAjGUfNFiVG`R;;;F#aK@z!KIe$`lPnMjj9jkI? z)%+Xd6jwvjf;qu{VW4A9Q1J?O5K2EcI2<~0(X5vBocGHeKpn6YK)RWF%{tEe#sXMU zHUO;Is{lT%)i^R!-&yxr!&&d~I*RoGYc}r=-VdzpydUNPYXH`L-UF=ZybDhvCb^x&?AbGP&ASE*OQ9>>vR&|VeX_Cy^D)} zu-zMMM~B+)vtG8nPWt|spv+w}&x`Yp%4jIi()Q#~QlMw@yc8B4+buf2FH3X#nI_`u z_S!Drd7ICP?WsS#U09w~wLCAM=kCp3?7gxo?(a`R8Exx9vRRJKccjTHL?=FII?V@7 zr}?1iocW;Xoclr3DTJ=_Ak(S%7wa!OQ9=3k>;htZ9XoNNnMlfY;vlN^Vz}8a4av;0 p>^3in%2#I3Ff)E-P88sq^L7J2c2HPq!GM3g9%S#Ui6`g8^FK}H2&Di3 literal 0 HcmV?d00001 diff --git a/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/schemas/org.gnome.shell.extensions.easyscreencast.gschema.xml b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/schemas/org.gnome.shell.extensions.easyscreencast.gschema.xml new file mode 100644 index 0000000..51bbf18 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/schemas/org.gnome.shell.extensions.easyscreencast.gschema.xml @@ -0,0 +1,200 @@ + + + + true +

Enable show notify and alert message + Enable show notify and alert message + + + false + Enable show area screencast during recording + Enable show area screencast during recording + + + 0 + select input audio source + select input audio source + + + false + Active custom GStreamer Pipeline + Active custom GStreamer Pipeline + + + 0 + Time in seconds fot delay recording + Time in seconds fot delay recording + + + false + Enable verbose debug + Enable verbose debug + + + 0 + X position of screencasting + X position of screencasting + + + 0 + Y position of screencasting + Y position of screencasting + + + 600 + width of screencasting + width of screencasting + + + 400 + height of screencasting + height of screencasting + + + 1 + active status indicators + active status indicators + + + true + draw the cursor into screencast + draw the cursor into screencast + + + 30 + fps of screencasting + fps of screencasting + + + 'vp9enc min_quantizer=13 max_quantizer=13 cpu-used=5 deadline=1000000 threads=%T ! queue ! webmmux' + gstreamer pipeline of screencasting + gstreamer pipeline of screencasting + + + 0 + select area of screencast + select area of screencast + + + 'Screencast_%d_%t' + file name template of screencast + file name template of screencast + + + '' + file folder of screencast + file folder of screencast + + + false + enable execute pre command + enable execute pre command + + + '' + command to execute + command to execute + + + false + enable execute post command + enable execute post command + + + 'xdg-open _fpath' + command to execute + command to execute + + + + E']]]> + + + + false + Enable keyboard shortcut + Enable keyboard shortcut + + + 0 + file screencast container + file screencast container + + + -1 + file screencast resolution type + file screencast resolution type [native(-1),preset(0-99),custom(99)] + + + true + file screencast resolution Keep Aspect Ratio + file screencast resolution Keep Aspect Ratio (add borders) + + + 0 + file screencast resolution width + file screencast resolution width + + + 0 + file screencast resolution height + file screencast resolution height + + + 1 + store the quality index option + store the quality index option + + + 0 + select webcam device + select webcam device + + + "" + selected webcam device path + selected webcam device path + + + "" + select webcam quality + select webcam quality + + + 20 + width webcam + width webcam + + + 10 + height webcam + height webcam + + + 0 + type of unit of measure webcam + type of unit of measure + + + 0 + margin x from border webcam + margin x webcam + + + 0 + margin y from border webcam + margin y from border webcam + + + 0.75 + + alpha channel webcam + aplha channel webcam + + + 0 + the corner position of webcam + the corner position of webcam + + + diff --git a/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/selection.js b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/selection.js new file mode 100644 index 0000000..0ed9c7a --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/selection.js @@ -0,0 +1,534 @@ +/* +The MIT License (MIT) +Copyright (c) 2013 otto.allmendinger@gmail.com + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +'use strict'; + +import GObject from 'gi://GObject'; +import Meta from 'gi://Meta'; +import Clutter from 'gi://Clutter'; +import St from 'gi://St'; +import * as Main from 'resource:///org/gnome/shell/ui/main.js'; + +import {gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js'; + +import * as Lib from './convenience.js'; +import * as Ext from './extension.js'; +import * as UtilNotify from './utilnotify.js'; +import {DisplayApi} from './display_module.js'; + +/** + * @type {Capture} + */ +const Capture = GObject.registerClass({ + GTypeName: 'EasyScreenCast_Capture', + Signals: { + 'captured-event': { + param_types: [Clutter.Event.$gtype], + }, + 'stop': {}, + }, +}, class Capture extends GObject.Object { + constructor() { + super(); + Lib.TalkativeLog('-£-capture selection init'); + + this._mouseDown = false; + + this.monitor = Main.layoutManager.focusMonitor; + + this._areaSelection = new St.Widget({ + name: 'area-selection', + style_class: 'area-selection', + visible: 'true', + reactive: 'true', + x: -10, + y: -10, + }); + + Main.uiGroup.add_child(this._areaSelection); + + this._areaResolution = new St.Label({ + style_class: 'area-resolution', + text: '', + }); + this._areaResolution.opacity = 255; + this._areaResolution.set_position(0, 0); + + Main.uiGroup.add_child(this._areaResolution); + + this._grab = Main.pushModal(this._areaSelection); + + if (this._grab) { + this._signalCapturedEvent = this._areaSelection.connect( + 'captured-event', + this._onCaptureEvent.bind(this) + ); + + this._setCaptureCursor(); + } else { + Lib.TalkativeLog('-£-Main.pushModal() === false'); + } + } + + /** + * @private + */ + _setDefaultCursor() { + DisplayApi.set_cursor(Meta.Cursor.DEFAULT); + } + + /** + * @private + */ + _setCaptureCursor() { + DisplayApi.set_cursor(Meta.Cursor.CROSSHAIR); + } + + /** + * @param {Clutter.Actor} actor the actor that received the event + * @param {Clutter.Event} event a Clutter.Event + * @private + */ + _onCaptureEvent(actor, event) { + if (event.type() === Clutter.EventType.KEY_PRESS) { + if (event.get_key_symbol() === Clutter.KEY_Escape) + this._stop(); + } + + this.emit('captured-event', event); + } + + /** + * Draws a on-screen rectangle showing the area that will be captured by screen cast. + * + * @param {object} rect rectangle + * @param {number} rect.x left position in pixels + * @param {number} rect.y top position in pixels + * @param {number} rect.w width in pixels + * @param {number} rect.h height in pixels + * @param {boolean} showResolution whether to display the size of the selected area + */ + drawSelection({x, y, w, h}, showResolution) { + this._areaSelection.set_position(x, y); + this._areaSelection.set_size(w, h); + + if (showResolution && w > 100 && h > 50) { + this._areaResolution.set_text(`${w} X ${h}`); + this._areaResolution.set_position( + x + (w / 2 - this._areaResolution.width / 2), + y + (h / 2 - this._areaResolution.height / 2) + ); + } else { + this._areaResolution.set_position(0, 0); + this._areaResolution.set_text(''); + } + } + + /** + * Clear drawing selection + */ + clearSelection() { + this.drawSelection( + { + x: -10, + y: -10, + w: 0, + h: 0, + }, + false + ); + } + + /** + * @private + */ + _stop() { + Lib.TalkativeLog('-£-capture selection stop'); + + this._areaSelection.disconnect(this._signalCapturedEvent); + this._setDefaultCursor(); + Main.uiGroup.remove_child(this._areaSelection); + Main.popModal(this._grab); + Main.uiGroup.remove_child(this._areaResolution); + this._areaSelection.destroy(); + this.emit('stop'); + } + + _saveRect(x, y, h, w) { + Lib.TalkativeLog(`-£-selection x:${x} y:${y} height:${h} width:${w}`); + + Ext.Indicator.saveSelectedRect(x, y, h, w); + Ext.Indicator._doDelayAction(); + } + + toString() { + return this.GTypeName; + } +}); + +var SelectionArea = GObject.registerClass({ + GTypeName: 'EasyScreenCast_SelectionArea', + Signals: { + 'stop': {}, + }, +}, class SelectionArea extends GObject.Object { + constructor() { + super(); + Lib.TalkativeLog('-£-area selection init'); + + this._mouseDown = false; + this._capture = new Capture(); + this._capture.connect('captured-event', this._onEvent.bind(this)); + this._capture.connect('stop', () => { + this._ctrlNotify.resetAlert(); + this.emit('stop'); + }); + + this._ctrlNotify = new UtilNotify.NotifyManager(); + this._ctrlNotify.createAlert( + _('Select an area for recording or press [ESC] to abort') + ); + } + + /** + * @param {Clutter.actor} capture the actor the captured the event + * @param {Clutter.Event} event a Clutter.Event + * @private + */ + _onEvent(capture, event) { + let type = event.type(); + let [x, y] = global.get_pointer(); + + if (type === Clutter.EventType.BUTTON_PRESS) { + [this._startX, this._startY] = [x, y]; + this._mouseDown = true; + } else if (this._mouseDown) { + let rect = _getRectangle(this._startX, this._startY, x, y); + if (type === Clutter.EventType.MOTION) { + this._capture.drawSelection(rect, true); + } else if (type === Clutter.EventType.BUTTON_RELEASE) { + this._capture._stop(); + + Lib.TalkativeLog(`-£-area x: ${rect.x} y: ${rect.y} height: ${rect.h} width: ${rect.w}`); + + this._capture._saveRect(rect.x, rect.y, rect.h, rect.w); + } + } + } + + toString() { + return this.GTypeName; + } +}); + +var SelectionWindow = GObject.registerClass({ + GTypeName: 'EasyScreenCast_SelectionWindow', + Signals: { + 'stop': {}, + }, +}, class SelectionWindow extends GObject.Object { + constructor() { + super(); + Lib.TalkativeLog('-£-window selection init'); + + this._windows = global.get_window_actors(); + this._capture = new Capture(); + this._capture.connect('captured-event', this._onEvent.bind(this)); + this._capture.connect('stop', () => { + this._ctrlNotify.resetAlert(); + this.emit('stop'); + }); + + this._ctrlNotify = new UtilNotify.NotifyManager(); + this._ctrlNotify.createAlert( + _('Select a window for recording or press [ESC] to abort') + ); + } + + /** + * @param {Clutter.Actor} capture the actor the captured the event + * @param {Clutter.Event} event a Clutter.Event + * @private + */ + _onEvent(capture, event) { + let type = event.type(); + let [x, y] = global.get_pointer(); + + this._selectedWindow = _selectWindow(this._windows, x, y); + + if (this._selectedWindow) + this._highlightWindow(this._selectedWindow); + else + this._clearHighlight(); + + + if (type === Clutter.EventType.BUTTON_PRESS) { + if (this._selectedWindow) { + this._capture._stop(); + + var maxHeight = global.screen_height; + var maxWidth = global.screen_width; + Lib.TalkativeLog(`-£-global screen area H: ${maxHeight} W: ${maxWidth}`); + + var [w, h] = this._selectedWindow.get_size(); + var [wx, wy] = this._selectedWindow.get_position(); + + Lib.TalkativeLog(`-£-windows pre wx: ${wx} wy: ${wy} height: ${h} width: ${w}`); + + if (wx < 0) + wx = 0; + if (wy < 0) + wy = 0; + if (wx + w > maxWidth) + w = maxWidth - wx; + if (wy + h > maxHeight) + h = maxHeight - wy; + + Lib.TalkativeLog(`-£-windows post wx: ${wx} wy: ${wy} height: ${h} width: ${w}`); + + this._capture._saveRect(wx, wy, h, w); + } + } + } + + /** + * @param {Clutter.Actor} win the window to highlight + * @private + */ + _highlightWindow(win) { + let rect = _getWindowRectangle(win); + Lib.TalkativeLog(`-£-window highlight on, pos/meas: x:${rect.x} y:${rect.y} w:${rect.w} h:${rect.h}`); + this._capture.drawSelection(rect, false); + } + + /** + * @private + */ + _clearHighlight() { + Lib.TalkativeLog('-£-window highlight off'); + this._capture.clearSelection(); + } + + toString() { + return this.GTypeName; + } +}); + +var SelectionDesktop = GObject.registerClass({ + GTypeName: 'EasyScreenCast_SelectionDesktop', + Signals: { + 'stop': {}, + }, +}, class SelectionDesktop extends GObject.Object { + constructor() { + super(); + Lib.TalkativeLog('-£-desktop selection init'); + const displayCount = DisplayApi.number_displays(); + Lib.TalkativeLog(`-£-Number of monitor ${displayCount}`); + + for (var i = 0; i < displayCount; i++) { + var tmpM = DisplayApi.display_geometry_for_index(i); + Lib.TalkativeLog(`-£-monitor ${i} geometry x=${tmpM.x} y=${tmpM.y} w=${tmpM.width} h=${tmpM.height}`); + } + + this._capture = new Capture(); + this._capture.connect('captured-event', this._onEvent.bind(this)); + this._capture.connect('stop', () => { + this._ctrlNotify.resetAlert(); + this.emit('stop'); + }); + + this._ctrlNotify = new UtilNotify.NotifyManager(); + this._ctrlNotify.createAlert( + _('Select a desktop for recording or press [ESC] to abort') + ); + } + + /** + * @param {Clutter.Actor} capture the actor that captured the event + * @param {Clutter.Event} event a Clutter.Event + * @private + */ + _onEvent(capture, event) { + let type = event.type(); + + if (type === Clutter.EventType.BUTTON_PRESS) { + this._capture._stop(); + + let tmpM = Main.layoutManager.currentMonitor; + + var x = tmpM.x; + var y = tmpM.y; + var height = tmpM.height; + var width = tmpM.width; + Lib.TalkativeLog(`-£-desktop x: ${x} y: ${y} height: ${height} width: ${width}`); + + this._capture._saveRect(x, y, height, width); + } + } + + toString() { + return this.GTypeName; + } +}); + +var AreaRecording = GObject.registerClass({ + GTypeName: 'EasyScreenCast_AreaRecording', +}, class AreaRecording extends GObject.Object { + constructor() { + super(); + Lib.TalkativeLog('-£-area recording init'); + + this._areaRecording = new St.Widget({ + name: 'area-recording', + style_class: 'area-recording', + visible: 'true', + reactive: 'false', + x: -10, + y: -10, + }); + + var [recX, recY, recW, recH] = Ext.Indicator.getSelectedRect(); + var tmpH = Main.layoutManager.currentMonitor.height; + var tmpW = Main.layoutManager.currentMonitor.width; + + Main.uiGroup.add_child(this._areaRecording); + + Main.overview.connect('showing', () => { + Lib.TalkativeLog('-£-overview opening'); + + Main.uiGroup.remove_child(this._areaRecording); + }); + + Main.overview.connect('hidden', () => { + Lib.TalkativeLog('-£-overview closed'); + + Main.uiGroup.add_child(this._areaRecording); + }); + + if (recX + recW <= tmpW - 5 && recY + recH <= tmpH - 5) + this.drawArea(recX - 2, recY - 2, recW + 4, recH + 4); + } + + /** + * @param {number} x left position + * @param {number} y top position + * @param {number} w width + * @param {number} h height + */ + drawArea(x, y, w, h) { + Lib.TalkativeLog('-£-draw area recording'); + + this._visible = true; + this._areaRecording.set_position(x, y); + this._areaRecording.set_size(w, h); + } + + /** + * Clears the drawing area + */ + clearArea() { + Lib.TalkativeLog('-£-hide area recording'); + + this._visible = false; + this.drawArea(-10, -10, 0, 0); + } + + /** + * @returns {boolean} + */ + isVisible() { + return this._visible; + } + + toString() { + return this.GTypeName; + } +}); + +/** + * @param {number} x1 left position + * @param {number} y1 top position + * @param {number} x2 right position + * @param {number} y2 bottom position + * @returns {{x: number, y: number, w: number, h: number}} + */ +function _getRectangle(x1, y1, x2, y2) { + return { + x: Math.min(x1, x2), + y: Math.min(y1, y2), + w: Math.abs(x1 - x2), + h: Math.abs(y1 - y2), + }; +} + +/** + * @param {Clutter.Actor} win a Clutter.Actor + * @returns {{x: number, y: number, w: number, h: number}} + */ +function _getWindowRectangle(win) { + let [tw, th] = win.get_size(); + let [tx, ty] = win.get_position(); + + return { + x: tx, + y: ty, + w: tw, + h: th, + }; +} + +/** + * @param {Array(Clutter.Actor)} windows all windows on the display + * @param {number} x left position + * @param {number} y top position + * @returns {Clutter.Actor} + */ +function _selectWindow(windows, x, y) { + let filtered = windows.filter(win => { + if ( + win !== undefined && + win.visible && + typeof win.get_meta_window === 'function' + ) { + Lib.TalkativeLog(`-£-selectWin x:${x} y:${y}`); + + let [w, h] = win.get_size(); + let [wx, wy] = win.get_position(); + Lib.TalkativeLog(`-£-selectWin w:${w} h:${h} wx:${wx} wy:${wy}`); + + return wx <= x && wy <= y && wx + w >= x && wy + h >= y; + } else { + return false; + } + }); + + filtered.sort((a, b) => { + return ( + a.get_meta_window().get_layer() <= b.get_meta_window().get_layer() + ); + }); + + return filtered[0]; +} + +export {SelectionArea, SelectionWindow, SelectionDesktop, AreaRecording}; diff --git a/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/settings.js b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/settings.js new file mode 100644 index 0000000..290d2f2 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/settings.js @@ -0,0 +1,192 @@ +/* + Copyright (C) 2013 Borsato Ivano + + The JavaScript code in this page is free software: you can + redistribute it and/or modify it under the terms of the GNU + General Public License (GNU GPL) as published by the Free Software + Foundation, either version 3 of the License, or (at your option) + any later version. The code is distributed WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU GPL for more details. +*/ + +'use strict'; + +import GObject from 'gi://GObject'; + +// setting keys +var INPUT_AUDIO_SOURCE_SETTING_KEY = 'input-audio-source'; +var ACTIVE_POST_CMD_SETTING_KEY = 'execute-post-cmd'; +var POST_CMD_SETTING_KEY = 'post-cmd'; +var ACTIVE_PRE_CMD_SETTING_KEY = 'execute-pre-cmd'; +var PRE_CMD_SETTING_KEY = 'pre-cmd'; +var ACTIVE_CUSTOM_GSP_SETTING_KEY = 'active-custom-gsp'; +var ACTIVE_SHORTCUT_SETTING_KEY = 'active-shortcut'; +var SHORTCUT_KEY_SETTING_KEY = 'shortcut-key'; +var TIME_DELAY_SETTING_KEY = 'delay-time'; +var SHOW_NOTIFY_ALERT_SETTING_KEY = 'show-notify-alert'; +var SHOW_AREA_REC_SETTING_KEY = 'show-area-rec'; +var VERBOSE_DEBUG_SETTING_KEY = 'verbose-debug'; +var PIPELINE_REC_SETTING_KEY = 'pipeline'; +var FPS_SETTING_KEY = 'fps'; +var STATUS_INDICATORS_SETTING_KEY = 'status-indicators'; +var X_POS_SETTING_KEY = 'x-pos'; +var Y_POS_SETTING_KEY = 'y-pos'; +var WIDTH_SETTING_KEY = 'width-rec'; +var HEIGHT_SETTING_KEY = 'height-rec'; +var DRAW_CURSOR_SETTING_KEY = 'draw-cursor'; +var AREA_SCREEN_SETTING_KEY = 'area-screen'; +var FILE_NAME_SETTING_KEY = 'file-name'; +var FILE_FOLDER_SETTING_KEY = 'file-folder'; +var FILE_CONTAINER_SETTING_KEY = 'file-container'; +var FILE_RESOLUTION_TYPE_SETTING_KEY = 'file-resolution-type'; +var FILE_RESOLUTION_KAR_SETTING_KEY = 'file-resolution-kar'; +var FILE_RESOLUTION_WIDTH_SETTING_KEY = 'file-resolution-width'; +var FILE_RESOLUTION_HEIGHT_SETTING_KEY = 'file-resolution-height'; +var QUALITY_SETTING_KEY = 'quality-index'; +var DEVICE_INDEX_WEBCAM_SETTING_KEY = 'device-webcam-index'; +var DEVICE_WEBCAM_SETTING_KEY = 'device-webcam'; +var QUALITY_WEBCAM_SETTING_KEY = 'quality-webcam'; +var WIDTH_WEBCAM_SETTING_KEY = 'width-webcam'; +var HEIGHT_WEBCAM_SETTING_KEY = 'height-webcam'; +var TYPE_UNIT_WEBCAM_SETTING_KEY = 'type-unit-webcam'; +var MARGIN_X_WEBCAM_SETTING_KEY = 'margin-x-webcam'; +var MARGIN_Y_WEBCAM_SETTING_KEY = 'margin-y-webcam'; +var ALPHA_CHANNEL_WEBCAM_SETTING_KEY = 'alpha-channel-webcam'; +var CORNER_POSITION_WEBCAM_SETTING_KEY = 'corner-position-webcam'; + +// shortcut tree view columns +var SHORTCUT_COLUMN_KEY = 0; +var SHORTCUT_COLUMN_MODS = 1; + +var Settings = GObject.registerClass(class EasyScreenCastSettings extends GObject.Object { + constructor(settings) { + super(); + this._settings = settings; + } + + /** + * getter option + * + * @param {string} type value type of the option. one of 'b', 'i', 's', 'd', 'as' + * @param {string} key option key + * @returns {string} + */ + getOption(type, key) { + switch (type) { + case 'b': + return this._settings.get_boolean(key); + case 'i': + return this._settings.get_int(key); + case 's': + return this._settings.get_string(key); + case 'd': + return this._settings.get_double(key); + case 'as': + return this._settings.get_strv(key); + } + + return ''; + } + + /** + * setter option + * + * @param {string} key option key + * @param {boolean|number|string|double|object} option option value + * @returns {string} empty string if successful, 'ERROR' otherwise + */ + setOption(key, option) { + switch (typeof option) { + case 'boolean': + this._settings.set_boolean(key, option); + break; + + case 'number': + this._settings.set_int(key, option); + break; + + case 'string': + this._settings.set_string(key, option); + break; + + case 'double': + this._settings.set_double(key, option); + break; + + case 'object': + this._settings.set_strv(key, option); + break; + + default: + return 'ERROR'; + } + return ''; + } + + destroy() { + if (this._settings) + this._settings = null; + } +}); + + +/** + * get a standard gsp pipeline + * + * @param {boolean} audio with or without audio + * @returns {string} + */ +function getGSPstd(audio) { + // TODO update gsp + if (audio) + return 'queue max-size-buffers=0 max-size-time=0 max-size-bytes=0 ! videorate ! vp8enc min_quantizer=0 max_quantizer=5 cpu-used=3 deadline=1000000 threads=%T ! queue max-size-buffers=0 max-size-time=0 max-size-bytes=0 ! mux. pulsesrc ! queue max-size-buffers=0 max-size-time=0 max-size-bytes=0 ! audioconvert ! vorbisenc ! queue max-size-buffers=0 max-size-time=0 max-size-bytes=0 ! mux. webmmux name=mux '; + else + return 'vp9enc min_quantizer=0 max_quantizer=5 cpu-used=3 deadline=1000000 threads=%T ! queue max-size-buffers=0 max-size-time=0 max-size-bytes=0 ! webmmux'; +} + +export { + getGSPstd, + Settings, + INPUT_AUDIO_SOURCE_SETTING_KEY, + ACTIVE_POST_CMD_SETTING_KEY, + POST_CMD_SETTING_KEY, + ACTIVE_PRE_CMD_SETTING_KEY, + PRE_CMD_SETTING_KEY, + ACTIVE_CUSTOM_GSP_SETTING_KEY, + ACTIVE_SHORTCUT_SETTING_KEY, + SHORTCUT_KEY_SETTING_KEY, + TIME_DELAY_SETTING_KEY, + SHOW_NOTIFY_ALERT_SETTING_KEY, + SHOW_AREA_REC_SETTING_KEY, + VERBOSE_DEBUG_SETTING_KEY, + PIPELINE_REC_SETTING_KEY, + FPS_SETTING_KEY, + STATUS_INDICATORS_SETTING_KEY, + X_POS_SETTING_KEY, + Y_POS_SETTING_KEY, + WIDTH_SETTING_KEY, + HEIGHT_SETTING_KEY, + DRAW_CURSOR_SETTING_KEY, + AREA_SCREEN_SETTING_KEY, + FILE_NAME_SETTING_KEY, + FILE_FOLDER_SETTING_KEY, + FILE_CONTAINER_SETTING_KEY, + FILE_RESOLUTION_TYPE_SETTING_KEY, + FILE_RESOLUTION_KAR_SETTING_KEY, + FILE_RESOLUTION_WIDTH_SETTING_KEY, + FILE_RESOLUTION_HEIGHT_SETTING_KEY, + QUALITY_SETTING_KEY, + DEVICE_INDEX_WEBCAM_SETTING_KEY, + DEVICE_WEBCAM_SETTING_KEY, + QUALITY_WEBCAM_SETTING_KEY, + WIDTH_WEBCAM_SETTING_KEY, + HEIGHT_WEBCAM_SETTING_KEY, + TYPE_UNIT_WEBCAM_SETTING_KEY, + MARGIN_X_WEBCAM_SETTING_KEY, + MARGIN_Y_WEBCAM_SETTING_KEY, + ALPHA_CHANNEL_WEBCAM_SETTING_KEY, + CORNER_POSITION_WEBCAM_SETTING_KEY, + SHORTCUT_COLUMN_KEY, + SHORTCUT_COLUMN_MODS +}; diff --git a/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/stylesheet.css b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/stylesheet.css new file mode 100644 index 0000000..2802bd6 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/stylesheet.css @@ -0,0 +1,36 @@ +.RecordAction-label { + font-size: 15px; + font-weight: bold; +} + +.area-selection { + background-color: rgba(255, 0, 0, 0.5); + border: 2px solid rgba(255, 0, 0, 1); +} + +.area-recording { + border-style: dashed; + border: 2px rgba(255, 0, 0, 1); +} + +.alert-msg { + font-size: 40px; + font-weight: bold; + color: #ffffff; + background-color: rgba(10, 10, 10, 0.7); + border-radius: 5px; + padding: .5em; +} + +.area-resolution { + font-size: 20px; + font-weight: bold; + color: #ffffff; + background-color: rgba(0, 0, 0, 0.0); +} + +.time-label { + font-size: 14px; + padding-right: 5px; + color: #ff0000; +} diff --git a/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/timer.js b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/timer.js new file mode 100644 index 0000000..9e35712 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/timer.js @@ -0,0 +1,259 @@ +/* + Copyright (C) 2013 Borsato Ivano + + The JavaScript code in this page is free software: you can + redistribute it and/or modify it under the terms of the GNU + General Public License (GNU GPL) as published by the Free Software + Foundation, either version 3 of the License, or (at your option) + any later version. The code is distributed WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU GPL for more details. +*/ + +'use strict'; + +import GObject from 'gi://GObject'; +import GLib from 'gi://GLib'; +import * as Lib from './convenience.js'; + +/* + DELAY TIMER +*/ +let DelaySec = 0; +let timerDelayId = null; +let CallbackFuncDelay = null; +let ElapsedSec; + +/** + * @type {TimerDelay} + */ +const TimerDelay = GObject.registerClass({ + GTypeName: 'EasyScreenCast_TimerDelay', +}, class TimerDelay extends GObject.Object { + /** + * Create a new timer + * + * @param {number} delay delay in seconds + * @param {Function} callback callback function that is called after delay seconds (without arguments) + * @param {*} scope scope for the callback + */ + constructor(delay, callback, scope) { + super(); + if (isNaN(delay)) { + Lib.TalkativeLog(`-%-delay is NOT a number :${delay}`); + } else { + Lib.TalkativeLog(`-%-init TimerDelay called - sec : ${delay}`); + + DelaySec = delay; + ElapsedSec = 1; + + this.setCallback(callback); + this.Scope = scope; + } + } + + /** + * Set the callback-function + * + * @param {Function} callback callback function that is called after delay seconds (without arguments) + */ + setCallback(callback) { + Lib.TalkativeLog('-%-setcallback TimerDelay called'); + + if ( + callback === undefined || + callback === null || + typeof callback !== 'function' + ) + throw TypeError("'callback' needs to be a function."); + + CallbackFuncDelay = callback; + } + + /** + * Set the delay time + * + * @param {number} delay delay in seconds + */ + setDelay(delay) { + Lib.TalkativeLog(`-%-setdelay TimerDelay called: ${delay}`); + + DelaySec = delay; + } + + /** + * Start or restart a new timer + */ + begin() { + Lib.TalkativeLog('-%-start TimerDelay called'); + this.stop(); + + timerDelayId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 1000, () => + this._callbackInternal() + ); + } + + /** + * Stop the current timer + */ + stop() { + Lib.TalkativeLog('-%-stop TimerDelay called'); + if (timerDelayId !== null) { + if (GLib.source_remove(timerDelayId)) { + timerDelayId = null; + + ElapsedSec = 1; + } + } + } + + /** + * A convenient way to restart the timer. + */ + restart() { + this.stop(); + this.begin(); + } + + /** + * The internal callback-function. + * + * @private + * @returns {boolean} + */ + _callbackInternal() { + Lib.TalkativeLog(`-%-internalFunction TimerDelay called | Sec = ${ElapsedSec} Sec delay = ${DelaySec}`); + if (ElapsedSec >= DelaySec) { + CallbackFuncDelay.apply(this.Scope, []); + ElapsedSec = 1; + return false; + } else { + ElapsedSec++; + return true; + } + } +}); + +/* + COUNTING TIMER +*/ +let timerCountingId = null; +let CallbackFuncCounting = null; +let isRunning = false; +let secpassed = 0; + +/** + * @type {TimerCounting} + */ +var TimerCounting = GObject.registerClass({ + GTypeName: 'EasyScreenCast_TimerCounting', +}, class TimerCounting extends GObject.Object { + /** + * Callback for the counting timer. + * + * @callback TimerCounting~callback + * @param {number} count seconds passed + * @param {boolean} alertEnd whether the timer is ending + */ + + /** + * Create a new timer + * + * @param {TimerCounting~callback} callback callback function that is called every second + * @param {EasyScreenCast_Indicator} scope scope for the callback function. This is also used to updateTimeLabel. + */ + constructor(callback, scope) { + super(); + Lib.TalkativeLog('-%-init TimerCounting called'); + + this.setCallback(callback); + secpassed = 0; + this.Scope = scope; + } + + /** + * Set the callback-function + * + * @param {TimerCounting~callback} callback callback function that is called every second + */ + setCallback(callback) { + Lib.TalkativeLog('-%-setcallback TimerCounting called'); + + if ( + callback === undefined || + callback === null || + typeof callback !== 'function' + ) + throw TypeError("'callback' needs to be a function."); + + CallbackFuncCounting = callback; + } + + /** + * Start or restart a new timer + */ + begin() { + Lib.TalkativeLog('-%-start TimerCounting called'); + + if (isRunning) + this.stop(); + + isRunning = true; + + timerCountingId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 1000, () => + this._callbackInternal() + ); + } + + /** + * Stop the current timer + */ + stop() { + Lib.TalkativeLog('-%-stop TimerCounting called'); + + isRunning = false; + + if (timerCountingId !== null && GLib.source_remove(timerCountingId)) + timerCountingId = null; + } + + /** + * A convenient way to stop timer + */ + halt() { + isRunning = false; + } + + /** + * The internal callback-function. Calls a function that handles + * the desktop notifications and one that sets the time label next + * to the icon. + * + * @private + * @returns {boolean} + */ + _callbackInternal() { + if (isRunning === false) { + Lib.TalkativeLog('-%-finish TimerCounting '); + + CallbackFuncCounting.apply(this.Scope, [secpassed, true]); + secpassed = 0; + + this.stop(); + this.Scope.updateTimeLabel(''); + + return false; + } else { + secpassed++; + + Lib.TalkativeLog(`-%-continued TimerCounting | sec: ${secpassed}`); + + CallbackFuncCounting.apply(this.Scope, [secpassed, false]); + this.Scope.updateTimeLabel(secpassed); + + return true; + } + } +}); + +export {TimerDelay, TimerCounting}; diff --git a/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/utilaudio.js b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/utilaudio.js new file mode 100644 index 0000000..27201fc --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/utilaudio.js @@ -0,0 +1,321 @@ +/* + Copyright (C) 2015 Borsato Ivano + + The JavaScript code in this page is free software: you can + redistribute it and/or modify it under the terms of the GNU + General Public License (GNU GPL) as published by the Free Software + Foundation, either version 3 of the License, or (at your option) + any later version. The code is distributed WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU GPL for more details. +*/ + +'use strict'; + +import GObject from 'gi://GObject'; +import GIRepository from 'gi://GIRepository'; +GIRepository.Repository.prepend_search_path('/usr/lib/gnome-shell'); +GIRepository.Repository.prepend_library_path('/usr/lib/gnome-shell'); +GIRepository.Repository.prepend_search_path('/usr/lib64/gnome-shell'); +GIRepository.Repository.prepend_library_path('/usr/lib64/gnome-shell'); +import Gvc from 'gi://Gvc'; + +import * as Lib from './convenience.js'; +import * as Settings from './settings.js'; +import * as Ext from './extension.js'; + +/** + * @type {MixerAudio} + */ +var MixerAudio = GObject.registerClass({ + GTypeName: 'EasyScreenCast_MixerAudio', +}, class MixerAudio extends GObject.Object { + constructor() { + super(); + Lib.TalkativeLog('-#-mixer constructor'); + + this._mixerControl = this._createMixerControl(); + this._isConnected = true; + this._mixerControl.connect('state-changed', () => + this._onChangeStatePAC() + ); + + // more log for debug + if (Lib.debugEnabled) { + this._mixerControl.connect('stream_added', (control, id) => { + this._onStreamAdd(control, id); + }); + this._mixerControl.connect('stream_removed', (control, id) => { + this._onStreamRemove(control, id); + }); + } + } + + /** + * @returns {Gvc.MixerControl} + * @private + */ + _createMixerControl() { + Lib.TalkativeLog('-#-mixer create'); + + // https://gitlab.gnome.org/GNOME/libgnome-volume-control + var _mixerTmp = new Gvc.MixerControl({ + name: 'ESC Mixer Control', + }); + _mixerTmp.open(); + + return _mixerTmp; + } + + _onChangeStatePAC() { + Lib.TalkativeLog('-#-mixer state changed'); + + switch (this._mixerControl.get_state()) { + case Gvc.MixerControlState.CLOSED: + Lib.TalkativeLog('-#-Mixer close'); + this._isConnected = false; + break; + case Gvc.MixerControlState.CONNECTING: + Lib.TalkativeLog('-#-Mixer connecting'); + this._isConnected = false; + break; + case Gvc.MixerControlState.FAILED: + Lib.TalkativeLog('-#-Mixer failed'); + this._isConnected = false; + break; + case Gvc.MixerControlState.READY: + Lib.TalkativeLog('-#-Mixer ready'); + this._isConnected = true; + + // more log for debug + if (Lib.debugEnabled) + this._getInfoPA(); + + break; + default: + Lib.TalkativeLog('-#-Mixer UNK'); + this._isConnected = false; + break; + } + } + + /** + * Gets a list of input audio sources. + * + * @returns {Array} + */ + getListInputAudio() { + Lib.TalkativeLog('-#-get list input audio'); + + if (this._isConnected) { + var arrayTmp = []; + + var tmpSinks = this._mixerControl.get_sinks(); + Lib.TalkativeLog(`-#-Mixer sink -> ${tmpSinks.length}`); + for (let x in tmpSinks) { + Lib.TalkativeLog(`-#-sink index: ${tmpSinks[x].index}`); + Lib.TalkativeLog(`-#-sink name: ${tmpSinks[x].name}`); + Lib.TalkativeLog( + `-#-sink description: ${tmpSinks[x].description}` + ); + Lib.TalkativeLog(`-#-sink port: ${tmpSinks[x].port}`); + + arrayTmp.push({ + desc: tmpSinks[x].description, + name: tmpSinks[x].name, + port: tmpSinks[x].port, + sortable: true, + resizeable: true, + }); + } + + var tmpSources = this._mixerControl.get_sources(); + Lib.TalkativeLog(`-#-Mixer sources -> ${tmpSources.length}`); + for (let x in tmpSources) { + Lib.TalkativeLog(`-#-source index: ${tmpSources[x].index}`); + Lib.TalkativeLog(`-#-source name: ${tmpSources[x].name}`); + Lib.TalkativeLog( + `-#-source description: ${tmpSources[x].description}` + ); + Lib.TalkativeLog(`-#-source port: ${tmpSources[x].port}`); + + arrayTmp.push({ + desc: tmpSources[x].description, + name: tmpSources[x].name, + port: tmpSources[x].port, + sortable: true, + resizeable: true, + }); + } + + Lib.TalkativeLog(`-#-MIXER SOURCE TOT -> ${arrayTmp.length}`); + + return arrayTmp; + } else { + Lib.TalkativeLog('-#-Error lib pulse NOT present or NOT respond'); + } + + return []; + } + + /** + * @returns {string} + */ + getAudioSource() { + Lib.TalkativeLog('-#-get source audio choosen'); + + var arrtmp = this.getListInputAudio(); + var index = Ext.Indicator.getSettings().getOption('i', Settings.INPUT_AUDIO_SOURCE_SETTING_KEY) - 2; + + if (index >= 0 && index < arrtmp.length) { + return arrtmp[index].name; + } else { + Lib.TalkativeLog('-#-ERROR, audio source missing'); + Ext.Indicator.getSettings().setOption(Settings.INPUT_AUDIO_SOURCE_SETTING_KEY, 0); + + return ''; + } + } + + /** + * @param {Gvc.MixerControl} control the mixer control to which the stream was added + * @param {number} id the stream id + * @private + */ + _onStreamAdd(control, id) { + Lib.TalkativeLog(`-#-mixer stream add - ID: ${id}`); + var streamTmp = control.lookup_stream_id(id); + + if ( + streamTmp.name === 'GNOME Shell' && + streamTmp.description === 'Record Stream' + ) { + Lib.TalkativeLog('-#-stream gnome recorder captured'); + + Lib.TalkativeLog(`-#-stream index: ${streamTmp.index}`); + Lib.TalkativeLog(`-#-stream card index: ${streamTmp.card_index}`); + Lib.TalkativeLog(`-#-application_ID: ${streamTmp.application_id}`); + Lib.TalkativeLog(`-#-stream name: ${streamTmp.name}`); + Lib.TalkativeLog(`-#-stream icon: ${streamTmp.icon_name}`); + Lib.TalkativeLog(`-#-stream description: ${streamTmp.description}`); + Lib.TalkativeLog(`-#-stream port: ${streamTmp.port}`); + } + } + + /** + * @param {Gvc.MixerControl} control the mixer control from where the stream was removed + * @param {number} id stream id + * @private + */ + _onStreamRemove(control, id) { + Lib.TalkativeLog(`-#-mixer stream remove - ID: ${id}`); + // note: the stream has been already removed, so + // control.lookup_stream_id(id) won't return anything + } + + /** + * @private + */ + _getInfoPA() { + var tmp = this._mixerControl.get_cards(); + Lib.TalkativeLog(`#-# mixer cards -> ${tmp.length}`); + for (let x in tmp) { + Lib.TalkativeLog(`-#-card index: ${tmp[x].index}`); + Lib.TalkativeLog(`-#-card name: ${tmp[x].name}`); + Lib.TalkativeLog(`-#-card icon: ${tmp[x].icon_name}`); + Lib.TalkativeLog(`-#-card profile: ${tmp[x].profile}`); + Lib.TalkativeLog(`-#-card human profile: ${tmp[x].human_profile}`); + } + + tmp = this._mixerControl.get_sources(); + Lib.TalkativeLog(`#-# mixer sources -> ${tmp.length}`); + for (let x in tmp) { + Lib.TalkativeLog(`-#-source index: ${tmp[x].index}`); + Lib.TalkativeLog(`-#-application_ID: ${tmp[x].application_id}`); + Lib.TalkativeLog(`-#-source name: ${tmp[x].name}`); + Lib.TalkativeLog(`-#-source icon: ${tmp[x].icon_name}`); + Lib.TalkativeLog(`-#-source description: ${tmp[x].description}`); + Lib.TalkativeLog(`-#-source port: ${tmp[x].port}`); + } + + tmp = this._mixerControl.get_source_outputs(); + Lib.TalkativeLog(`#-# mixer source output -> ${tmp.length}`); + for (let x in tmp) { + Lib.TalkativeLog(`-#-sourceouput index: ${tmp[x].index}`); + Lib.TalkativeLog(`-#-application_ID: ${tmp[x].application_id}`); + Lib.TalkativeLog(`-#-sourceouput name: ${tmp[x].name}`); + Lib.TalkativeLog(`-#-sourceoutput icon: ${tmp[x].icon_name}`); + Lib.TalkativeLog( + `-#-sourceoutput description: ${tmp[x].description}` + ); + Lib.TalkativeLog(`-#-sourceoutput port: ${tmp[x].port}`); + } + + tmp = this._mixerControl.get_sinks(); + Lib.TalkativeLog(`#-# mixer sink -> ${tmp.length}`); + for (let x in tmp) { + Lib.TalkativeLog(`-#-sink index: ${tmp[x].index}`); + Lib.TalkativeLog(`-#-application_ID: ${tmp[x].application_id}`); + Lib.TalkativeLog(`-#-sink name: ${tmp[x].name}`); + Lib.TalkativeLog(`-#-sink icon: ${tmp[x].icon_name}`); + Lib.TalkativeLog(`-#-sink description: ${tmp[x].description}`); + Lib.TalkativeLog(`-#-sink port: ${tmp[x].port}`); + } + + tmp = this._mixerControl.get_sink_inputs(); + Lib.TalkativeLog(`#-# mixer sink input -> ${tmp.length}`); + for (let x in tmp) { + Lib.TalkativeLog(`-#-sink input index: ${tmp[x].index}`); + Lib.TalkativeLog(`-#-application_ID: ${tmp[x].application_id}`); + Lib.TalkativeLog(`-#-sink input name: ${tmp[x].name}`); + Lib.TalkativeLog(`-#-sink input icon: ${tmp[x].icon_name}`); + Lib.TalkativeLog( + `-#-sink input description: ${tmp[x].description}` + ); + Lib.TalkativeLog(`-#-sink input port: ${tmp[x].port}`); + } + + tmp = this._mixerControl.get_streams(); + Lib.TalkativeLog(`#-# mixer stream -> ${tmp.length}`); + for (let x in tmp) { + Lib.TalkativeLog(`-#-STREAM index: ${tmp[x].index}`); + Lib.TalkativeLog(`-#-application_ID: ${tmp[x].application_id}`); + Lib.TalkativeLog(`-#-stream name: ${tmp[x].name}`); + Lib.TalkativeLog(`-#-stream icon: ${tmp[x].icon_name}`); + Lib.TalkativeLog(`-#-stream description: ${tmp[x].description}`); + + var tmp1 = tmp[x].get_ports(); + for (let y in tmp1) { + Lib.TalkativeLog(`-##-stream port number: ${y}`); + Lib.TalkativeLog(`-##-stream port name: ${tmp1[y].port}`); + Lib.TalkativeLog( + `-##-stream port human name: ${tmp1[y].human_port}` + ); + Lib.TalkativeLog( + `-##-stream port priority: ${tmp1[y].priority}` + ); + } + } + } + + /** + * @returns {boolean} + */ + checkAudio() { + Lib.TalkativeLog(`-#-check GVC lib presence: ${this._isConnected}`); + + return this._isConnected; + } + + /** + * Destroy mixer control + */ + destroy() { + if (this._mixerControl) { + this._mixerControl.close(); + this._mixerControl = null; + } + } +}); + +export {MixerAudio}; diff --git a/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/utilexecmd.js b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/utilexecmd.js new file mode 100644 index 0000000..2ee88c6 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/utilexecmd.js @@ -0,0 +1,266 @@ +/* + Copyright (C) 2017 Borsato Ivano + + The JavaScript code in this page is free software: you can + redistribute it and/or modify it under the terms of the GNU + General Public License (GNU GPL) as published by the Free Software + Foundation, either version 3 of the License, or (at your option) + any later version. The code is distributed WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU GPL for more details. +*/ + +'use strict'; + +import GObject from 'gi://GObject'; +import GLib from 'gi://GLib'; +import Gio from 'gi://Gio'; +import * as Lib from './convenience.js'; + +/** + * @type {ExecuteStuff} + */ +var ExecuteStuff = GObject.registerClass({ + GTypeName: 'EasyScreenCast_ExecuteStuff', +}, class ExecuteStuff extends GObject.Object { + /** + * @param {EasyScreenCastSettingsWidget|EasyScreenCastIndicator} scope the scope for executing callback methods + * @private + */ + constructor(scope) { + super(); + Lib.TalkativeLog(`-¶-init scope:${scope}`); + + this.Scope = scope; + this.Callback = null; + } + + /** + * @param {string} cmd the command to be executed + * @returns {*[]} + * @private + */ + _parseCmd(cmd) { + let successP, argv; + + try { + [successP, argv] = GLib.shell_parse_argv(cmd); + } catch (err) { + Lib.TalkativeLog('-¶-ERROR PARSE'); + successP = false; + } + if (successP) { + Lib.TalkativeLog(`-¶-parse: ${successP} argv: ${argv}`); + return [successP, argv]; + } else { + return [successP, null]; + } + } + + /** + * Result callback. + * + * @callback ExecuteStuff~resultCallback + * @param {boolean} result whether the executed command exited successfully or not + * @param {string} stdout (optional) output of the result, if it was executed synchronously + */ + + /** + * Line output callback for asynchronous commands. + * + * @callback ExecuteStuff~lineCallback + * @param {string} line a single line of output + */ + + /** + * @param {string} cmd the command to be executed + * @param {boolean} sync execute synchronously (wait for return) or fork a process + * @param {ExecuteStuff~resultCallback} resCb callback after the command is finished + * @param {ExecuteStuff~lineCallback} lineCb callback for stdout when command is executed asynchronosly + * @class + */ + Execute(cmd, sync, resCb, lineCb) { + Lib.TalkativeLog(`-¶-execute: ${cmd}`); + + this.CommandString = cmd; + if ( + resCb === undefined && + resCb === null && + typeof resCb !== 'function' + ) { + Lib.TalkativeLog('-¶-resCallback NEED to be a function'); + + this.Callback = null; + } else { + this.Callback = resCb; + } + + if (sync === true) { + Lib.TalkativeLog('-¶-sync execute (wait for return)'); + this._syncCmd(this.CommandString); + } else { + Lib.TalkativeLog('-¶-async execute (fork process)'); + if ( + lineCb === undefined && + lineCb === null && + typeof lineCb !== 'function' + ) { + Lib.TalkativeLog('-¶-lineCallback NEED to be a function'); + + this.lineCallback = null; + } else { + this.lineCallback = lineCb; + } + this._asyncCmd(this.CommandString); + } + } + + /** + * @param {string} cmd the command to be executed + * @returns {*} + * @class + */ + Spawn(cmd) { + let [successP, argv] = this._parseCmd(cmd); + if (successP) { + let successS, pid; + try { + [successS, pid] = GLib.spawn_async( + null, + argv, + null, + GLib.SpawnFlags.SEARCH_PATH | + GLib.SpawnFlags.DO_NOT_REAP_CHILD, + null + ); + } catch (err) { + Lib.TalkativeLog( + `-¶-ERROR SPAWN err:${err.message.toString()}` + ); + successS = false; + } + + if (successS) { + Lib.TalkativeLog(`-¶-spawn: ${successS} pid: ${pid}`); + return true; + } else { + Lib.TalkativeLog('-¶-spawn ERROR'); + return null; + } + } + return null; + } + + /** + * @param {string} cmd the command to be executed + * @private + */ + _syncCmd(cmd) { + let [successP, argv] = this._parseCmd(cmd); + let decoder = new TextDecoder(); + if (successP) { + Lib.TalkativeLog(`-¶-argv: ${argv}`); + let successS, stdOut, stdErr, exit; + try { + [successS, stdOut, stdErr, exit] = GLib.spawn_sync( + null, + argv, + null, + GLib.SpawnFlags.SEARCH_PATH, + () => {} + ); + } catch (err) { + Lib.TalkativeLog('-¶-ERROR SPAWN'); + successS = false; + } + if (successS) { + Lib.TalkativeLog(`-¶-argv: ${argv}`); + Lib.TalkativeLog(`-¶-stdOut: ${decoder.decode(stdOut)}`); + Lib.TalkativeLog(`-¶-stdErr: ${decoder.decode(stdErr)}`); + Lib.TalkativeLog(`-¶-exit: ${exit}`); + + Lib.TalkativeLog('-¶-exe RC'); + if (this.Callback !== null) { + this.Callback.apply(this.Scope, [ + true, + decoder.decode(stdOut), + ]); + } + } else { + Lib.TalkativeLog(`-¶-ERROR exe WC - exit status: ${exit}`); + if (this.Callback !== null) + this.Callback.apply(this.Scope, [false]); + } + } + } + + /** + * @param {string} cmd the command to be executed + * @private + */ + _asyncCmd(cmd) { + let [successP, argv] = this._parseCmd(cmd); + let decoder = new TextDecoder(); + if (successP) { + Lib.TalkativeLog(`-¶-argv: ${argv}`); + let successS, pid, stdIn, stdOut, stdErr; + + try { + [ + successS, + pid, + stdIn, + stdOut, + stdErr, + ] = GLib.spawn_async_with_pipes( + null, // working directory + argv, // argv + null, // envp + GLib.SpawnFlags.SEARCH_PATH, // flags + () => {} // child_setup + ); + } catch (err) { + Lib.TalkativeLog('-¶-ERROR SPAWN'); + successS = false; + } + if (successS) { + Lib.TalkativeLog(`-¶-argv: ${argv}`); + Lib.TalkativeLog(`-¶-pid: ${pid}`); + Lib.TalkativeLog(`-¶-stdIn: ${stdIn}`); + Lib.TalkativeLog(`-¶-stdOut: ${stdOut}`); + Lib.TalkativeLog(`-¶-stdErr: ${stdErr}`); + + let outReader = new Gio.DataInputStream({ + base_stream: new Gio.UnixInputStream({ + fd: stdOut, + }), + }); + let inWriter = new Gio.DataOutputStream({ + base_stream: new Gio.UnixOutputStream({ + fd: stdIn, + }), + }); + inWriter.close(null); + + let [out] = outReader.read_line(null); + while (out !== null) { + if (this.lineCallback !== null) + this.lineCallback.apply(this.Scope, [decoder.decode(out)]); + + [out] = outReader.read_line(null); + } + + if (this.Callback !== null) { + Lib.TalkativeLog('-¶-exe RC'); + this.Callback.apply(this.Scope, [true]); + } + } else { + Lib.TalkativeLog('-¶-ERROR exe WC'); + if (this.Callback !== null) + this.Callback.apply(this.Scope, [false]); + } + } + } +}); + +export {ExecuteStuff}; diff --git a/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/utilgsp.js b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/utilgsp.js new file mode 100644 index 0000000..f9f45a3 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/utilgsp.js @@ -0,0 +1,737 @@ +/* + Copyright (C) 2016 Borsato Ivano + + The JavaScript code in this page is free software: you can + redistribute it and/or modify it under the terms of the GNU + General Public License (GNU GPL) as published by the Free Software + Foundation, either version 3 of the License, or (at your option) + any later version. The code is distributed WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU GPL for more details. +*/ + +'use strict'; + +import * as Lib from './convenience.js'; +import * as Settings from './settings.js'; + +// CONST GSP - base +const SCREEN = + '_SCREENCAST_RES_ _ENCODER_VIDEO_ ! queue max-size-buffers=0 max-size-time=0 max-size-bytes=0 ! _CONTAINER_'; + +// CONST GSP - base plus sound +const SCREEN_SOUND = + 'queue max-size-buffers=0 max-size-time=0 max-size-bytes=0 ! _SCREENCAST_RES_ _ENCODER_VIDEO_ ! queue max-size-buffers=0 max-size-time=0 max-size-bytes=0 ! mux. pulsesrc ! audioconvert ! _ENCODER_AUDIO_ ! queue max-size-buffers=0 max-size-time=0 max-size-bytes=0 ! mux. _CONTAINER_ name=mux '; + +// CONST GSP - base plus webcam +const SCREEN_WEBCAM = + 'queue max-size-buffers=0 max-size-time=0 max-size-bytes=0 ! videomixer name=mix _WEBCAM_OPT_ ! videoconvert ! _SCREENCAST_RES_ _ENCODER_VIDEO_ ! mux. v4l2src _WEBCAM_DEV_ ! _WEBCAM_CAP_ ! videoscale ! video/x-raw, width=_WEBCAM_W_, height=_WEBCAM_H_, add-borders=false ! queue max-size-buffers=0 max-size-time=0 max-size-bytes=0 ! mix. _CONTAINER_ name=mux'; + +// CONST GSP - base plus sound and webcam stream +const SCREEN_WEBCAM_SOUND = + 'queue max-size-buffers=0 max-size-time=0 max-size-bytes=0 ! videomixer name=mix _WEBCAM_OPT_ ! videoconvert ! _SCREENCAST_RES_ _ENCODER_VIDEO_ ! mux. v4l2src _WEBCAM_DEV_ ! _WEBCAM_CAP_ ! videoscale ! video/x-raw, width=_WEBCAM_W_, height=_WEBCAM_H_, add-borders=false ! queue max-size-buffers=0 max-size-time=0 max-size-bytes=0 ! mix. pulsesrc ! audioconvert ! _ENCODER_AUDIO_ ! queue max-size-buffers=0 max-size-time=0 max-size-bytes=0 ! mux. _CONTAINER_ name=mux'; + +// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + +// CONST CONTAINER - WebM +const webmVP8 = { + fileExt: '.webm', + nameGSP: 'webmmux', + quality: [ + { + // quality level 0 + fps: 15, + vq: + 'vp8enc min_quantizer=13 max_quantizer=20 cpu-used=5 deadline=1000000 sharpness=2 target-bitrate=10000 threads=%T', + aq: 'vorbisenc', + descr: + 'FPS: 15 \nVideo -> VP8 Encoder:\n-min_quantizer=13\n-max_quantizer=20\n-cpu-used=5\n-deadline=1000000\n-sharpness=2\n-target-bitrate=10000\nAudio -> Vorbis Encoder', + }, + { + // quality level 1 + fps: 30, + vq: + 'vp8enc min_quantizer=4 max_quantizer=13 cpu-used=2 deadline=500000 sharpness=0 target-bitrate=15000 threads=%T', + aq: 'vorbisenc', + descr: + 'FPS: 30 \nVideo -> VP8 Encoder:\n-min_quantizer=4\n-max_quantizer=13\n-cpu-used=2\n-deadline=500000\n-sharpness=0\n-target-bitrate=15000\nAudio -> Vorbis Encoder', + }, + { + // quality level 2 + fps: 30, + vq: + 'vp8enc min_quantizer=0 max_quantizer=7 cpu-used=1 deadline=500000 sharpness=0 target-bitrate=25000 threads=%T', + aq: 'vorbisenc', + descr: + 'FPS: 30 \nVideo -> VP8 Encoder:\n-min_quantizer=0\n-max_quantizer=7\n-cpu-used=1\n-deadline=500000\n-sharpness=0\n-target-bitrate=25000\nAudio -> Vorbis Encoder', + }, + { + // quality level 3 + fps: 60, + vq: + 'vp8enc min_quantizer=0 max_quantizer=0 cpu-used=0 deadline=100000 sharpness=0 target-bitrate=40000 threads=%T', + aq: 'vorbisenc', + descr: + 'FPS: 60 \nVideo -> VP8 Encoder:\n-min_quantizer=0\n-max_quantizer=0\n-cpu-used=0\n-deadline=100000\n-sharpness=0\n-target-bitrate=40000\nAudio -> Vorbis Encoder', + }, + ], +}; + +const webmVP9 = { + fileExt: '.webm', + nameGSP: 'webmmux', + quality: [ + { + // quality level 0 + fps: 15, + vq: + 'vp9enc min_quantizer=13 max_quantizer=20 cpu-used=5 deadline=1000000 sharpness=2 target-bitrate=10000 threads=%T', + aq: 'vorbisenc', + descr: + 'FPS: 15 \nVideo -> VP9 Encoder:\n-min_quantizer=13\n-max_quantizer=20\n-cpu-used=5\n-deadline=1000000\n-sharpness=2\n-target-bitrate=10000\nAudio -> Vorbis Encoder', + }, + { + // quality level 1 + fps: 30, + vq: + 'vp9enc min_quantizer=4 max_quantizer=13 cpu-used=2 deadline=500000 sharpness=0 target-bitrate=15000 threads=%T', + aq: 'vorbisenc', + descr: + 'FPS: 30 \nVideo -> VP9 Encoder:\n-min_quantizer=4\n-max_quantizer=13\n-cpu-used=2\n-deadline=500000\n-sharpness=0\n-target-bitrate=15000\nAudio -> Vorbis Encoder', + }, + { + // quality level 2 + fps: 30, + vq: + 'vp9enc min_quantizer=0 max_quantizer=7 cpu-used=1 deadline=500000 sharpness=0 target-bitrate=25000 threads=%T', + aq: 'vorbisenc', + descr: + 'FPS: 30 \nVideo -> VP9 Encoder:\n-min_quantizer=0\n-max_quantizer=7\n-cpu-used=1\n-deadline=500000\n-sharpness=0\n-target-bitrate=25000\nAudio -> Vorbis Encoder', + }, + { + // quality level 3 + fps: 60, + vq: + 'vp9enc min_quantizer=0 max_quantizer=0 cpu-used=0 deadline=100000 sharpness=0 target-bitrate=40000 threads=%T', + aq: 'vorbisenc', + descr: + 'FPS: 60 \nVideo -> VP9 Encoder:\n-min_quantizer=0\n-max_quantizer=0\n-cpu-used=0\n-deadline=100000\n-sharpness=0\n-target-bitrate=40000\nAudio -> Vorbis Encoder', + }, + ], +}; + +// CONST CONTAINER - Mp4 +const mp4 = { + fileExt: '.mp4', + nameGSP: 'mp4mux', + quality: [ + { + // quality level 0 + fps: 15, + vq: + 'x264enc psy-tune="none" speed-preset="superfast" subme=1 qp-min=28 qp-max=40 threads=%T', + aq: 'lamemp3enc', + descr: + 'FPS: 15 \nVideo -> x264enc Encoder:\n-psy-tune="none"\n-speed-preset="superfast"\n-subme=1\n-qp-min=28\n-qp-max=40\nAudio -> Mp3 Encoder', + }, + { + // quality level 1 + fps: 30, + vq: + 'x264enc psy-tune="animation" speed-preset="fast" subme=5 qp-min=18 qp-max=28 threads=%T', + aq: 'lamemp3enc', + descr: + 'FPS: 30 \nVideo -> x264enc Encoder:\n-psy-tune="animation"\n-speed-preset="fast"\n-subme=5\n-qp-min=18\n-qp-max=28\nAudio -> Mp3 Encoder', + }, + { + // quality level 2 + fps: 30, + vq: + 'x264enc psy-tune="animation" speed-preset="medium" subme=8 qp-min=10 qp-max=18 threads=%T', + aq: 'lamemp3enc', + descr: + 'FPS: 30 \nVideo -> x264enc Encoder:\n-psy-tune="animation"\n-speed-preset="medium"\n-subme=8\n-qp-min=10\n-qp-max=18\nAudio -> Mp3 Encoder', + }, + { + // quality level 3 + fps: 60, + vq: + 'x264enc psy-tune="film" speed-preset="slower" subme=10 qp-min=0 qp-max=10 threads=%T', + aq: 'lamemp3enc', + descr: + 'FPS: 60 \nVideo -> x264enc Encoder:\n-psy-tune="film"\n-speed-preset="slower"\n-subme=10\n-qp-min=0\n-qp-max=10\nAudio -> Mp3 Encoder', + }, + ], +}; + +const mp4Aac = { + fileExt: '.mp4', + nameGSP: 'mp4mux', + quality: [ + { + // quality level 0 + fps: 15, + vq: + 'x264enc psy-tune="none" speed-preset="superfast" subme=1 qp-min=28 qp-max=40 threads=%T', + aq: 'avenc_aac', + descr: + 'FPS: 15 \nVideo -> x264enc Encoder:\n-psy-tune="none"\n-speed-preset="superfast"\n-subme=1\n-qp-min=28\n-qp-max=40\nAudio -> AAC Encoder', + }, + { + // quality level 1 + fps: 30, + vq: + 'x264enc psy-tune="animation" speed-preset="fast" subme=5 qp-min=18 qp-max=28 threads=%T', + aq: 'avenc_aac', + descr: + 'FPS: 30 \nVideo -> x264enc Encoder:\n-psy-tune="animation"\n-speed-preset="fast"\n-subme=5\n-qp-min=18\n-qp-max=28\nAudio -> AAC Encoder', + }, + { + // quality level 2 + fps: 30, + vq: + 'x264enc psy-tune="animation" speed-preset="medium" subme=8 qp-min=10 qp-max=18 threads=%T', + aq: 'avenc_aac', + descr: + 'FPS: 30 \nVideo -> x264enc Encoder:\n-psy-tune="animation"\n-speed-preset="medium"\n-subme=8\n-qp-min=10\n-qp-max=18\nAudio -> AAC Encoder', + }, + { + // quality level 3 + fps: 60, + vq: + 'x264enc psy-tune="film" speed-preset="slower" subme=10 qp-min=0 qp-max=10 threads=%T', + aq: 'avenc_aac', + descr: + 'FPS: 60 \nVideo -> x264enc Encoder:\n-psy-tune="film"\n-speed-preset="slower"\n-subme=10\n-qp-min=0\n-qp-max=10\nAudio -> AAC Encoder', + }, + ], +}; + +// CONST CONTAINER - Mkv +const mkv = { + fileExt: '.mkv', + nameGSP: 'matroskamux', + quality: [ + { + // quality level 0 + fps: 15, + vq: + 'x264enc psy-tune="none" speed-preset="superfast" subme=1 qp-min=28 qp-max=40 threads=%T', + aq: 'flacenc', + descr: + 'FPS: 15 \nVideo -> x264enc Encoder:\n-psy-tune="none"\n-speed-preset="superfast"\n-subme=1\n-qp-min=28\n-qp-max=40\nAudio -> Flac Encoder', + }, + { + // quality level 1 + fps: 30, + vq: + 'x264enc psy-tune="animation" speed-preset="fast" subme=5 qp-min=18 qp-max=28 threads=%T', + aq: 'flacenc', + descr: + 'FPS: 30 \nVideo -> x264enc Encoder:\n-psy-tune="animation"\n-speed-preset="fast"\n-subme=5\n-qp-min=18\n-qp-max=28\nAudio -> Flac Encoder', + }, + { + // quality level 2 + fps: 30, + vq: + 'x264enc psy-tune="animation" speed-preset="medium" subme=8 qp-min=10 qp-max=18 threads=%T', + aq: 'flacenc', + descr: + 'FPS: 30 \nVideo -> x264enc Encoder:\n-psy-tune="animation"\n-speed-preset="medium"\n-subme=8\n-qp-min=10\n-qp-max=18\nAudio -> Flac Encoder', + }, + { + // quality level 3 + fps: 60, + vq: + 'x264enc psy-tune="film" speed-preset="slower" subme=10 qp-min=0 qp-max=10 threads=%T', + aq: 'flacenc', + descr: + 'FPS: 60 \nVideo -> x264enc Encoder:\n-psy-tune="film"\n-speed-preset="slower"\n-subme=10\n-qp-min=0\n-qp-max=10\nAudio -> Flac Encoder', + }, + ], +}; + +// CONST CONTAINER - Ogg +const ogg = { + fileExt: '.ogg', + nameGSP: 'oggmux', + quality: [ + { + // quality level 0 + fps: 15, + vq: + 'theoraenc speed-level=3 vp3-compatible=true quality=10 bitrate=10000', + aq: 'opusenc', + descr: + 'FPS: 15 \nVideo -> Theora Encoder:\n-speed-level=3\n-vp3-compatible=true\n-quality=10\n-bitrate=10000\nAudio -> Opus Encoder', + }, + { + // quality level 1 + fps: 30, + vq: + 'theoraenc speed-level=1 vp3-compatible=false quality=30 bitrate=25000', + aq: 'opusenc', + descr: + 'FPS: 30 \nVideo -> Theora Encoder:\n-speed-level=1\n-vp3-compatible=false\n-quality=30\n-bitrate=25000\nAudio -> Opus Encoder', + }, + { + // quality level 2 + fps: 30, + vq: + 'theoraenc speed-level=0 vp3-compatible=false quality=50 bitrate=50000', + aq: 'opusenc', + descr: + 'FPS: 30 \nVideo -> Theora Encoder:\n-speed-level=0\n-vp3-compatible=false\n-quality=50\n-bitrate=50000\nAudio -> Opus Encoder', + }, + { + // quality level 3 + fps: 60, + vq: + 'theoraenc speed-level=0 vp3-compatible=false quality=60 bitrate=100000', + aq: 'opusenc', + descr: + 'FPS: 60 \nVideo -> Theora Encoder\n-speed-level=0\n-vp3-compatible=false\n-quality=60\n-bitrate=100000\nAudio -> Opus Encoder', + }, + ], +}; + +// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + +// CONST RESOLUTION +const RESOLUTION = [ + // NATIVE SCREENCAST RESOLUTION + '', + // PRESET/CUSTOM SCREENCAST RESOLUTION + 'videoscale ! video/x-raw, width=_RES_WIDTH_, height=_RES_HEIGHT_, add-borders=_RES_KAR_ ! ', +]; + +// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + +// VAR ARRAY CONTAINER +// see cbt_FileContainer in *.glade files for the combo box +const CONTAINER = [webmVP8, webmVP9, mp4, mkv, ogg, mp4Aac]; + +// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + +/** + * Compose GSP + * + * @param {EasyScreenCastSettings} settings the extension's settings + * @param {MixerAudio} mixer the mixer + * + * @returns {string} + */ +function composeGSP(settings, mixer) { + Lib.TalkativeLog('-§-COMPOSE GSP'); + + let tmpGSP = ''; + + // retrieve options + let deviceWebcam = settings.getOption('s', Settings.DEVICE_WEBCAM_SETTING_KEY); + let deviceAudio = settings.getOption('i', Settings.INPUT_AUDIO_SOURCE_SETTING_KEY); + let qualityGSP = settings.getOption('i', Settings.QUALITY_SETTING_KEY); + let qualityWebcam = settings.getOption('s', Settings.QUALITY_WEBCAM_SETTING_KEY); + let resolutionType = settings.getOption('i', Settings.FILE_RESOLUTION_TYPE_SETTING_KEY); + let resolutionKAR = settings.getOption('b', Settings.FILE_RESOLUTION_KAR_SETTING_KEY); + let resolutionHeight = settings.getOption('i', Settings.FILE_RESOLUTION_HEIGHT_SETTING_KEY); + let resolutionWidth = settings.getOption('i', Settings.FILE_RESOLUTION_WIDTH_SETTING_KEY); + let container = settings.getOption('i', Settings.FILE_CONTAINER_SETTING_KEY); + + Lib.TalkativeLog( + `-§-get option||devW: ${deviceWebcam}||devA: ${deviceAudio}||Qgsp: ${qualityGSP}||Qwc: ${qualityWebcam}||Res: ${resolutionType}||Cont: ${container}` + ); + + if (deviceWebcam !== '') { + switch (deviceAudio) { + case 0: + Lib.TalkativeLog('-§- SCREEN-WEBCAM'); + + tmpGSP = SCREEN_WEBCAM; + + // replace WEBCAM_DEVICE/WEBCAM_CAPS + tmpGSP = _replaceWebcam( + tmpGSP, + deviceWebcam, + qualityWebcam, + settings + ); + + break; + case 1: + Lib.TalkativeLog('-§-SCREEN-WEBCAM-AUDIO(d)'); + + tmpGSP = SCREEN_WEBCAM_SOUND; + + // replace WEBCAM_DEVICE/WEBCAM_CAPS/ENCODER-AUDIO + tmpGSP = _replaceAudio( + _replaceWebcam(tmpGSP, deviceWebcam, qualityWebcam, settings), + true, + container, + qualityGSP, + mixer + ); + + break; + default: + Lib.TalkativeLog('-§-SCREEN-WEBCAM-AUDIO'); + + tmpGSP = SCREEN_WEBCAM_SOUND; + + // replace WEBCAM_DEVICE/WEBCAM_CAPS/ENCODER-AUDIO/AUDIO_DEVICE + tmpGSP = _replaceAudio( + _replaceWebcam(tmpGSP, deviceWebcam, qualityWebcam, settings), + false, + container, + qualityGSP, + mixer + ); + } + } else { + switch (deviceAudio) { + case 0: + Lib.TalkativeLog('-§-SCREEN'); + + tmpGSP = SCREEN; + + break; + case 1: + Lib.TalkativeLog('-§-SCREEN-AUDIO(d)'); + + tmpGSP = SCREEN_SOUND; + + // replace ENCODER-AUDIO + tmpGSP = _replaceAudio( + tmpGSP, + true, + container, + qualityGSP, + mixer + ); + + break; + default: + Lib.TalkativeLog('-§-SCREEN-AUDIO'); + + tmpGSP = SCREEN_SOUND; + + // replace ENCODER-AUDIO/AUDIO_DEVICE + tmpGSP = _replaceAudio( + tmpGSP, + false, + container, + qualityGSP, + mixer + ); + } + } + + // compose resolution string + var resolution = _composeResolution( + resolutionType, + resolutionHeight, + resolutionWidth, + resolutionKAR + ); + + // replace RESOLUTION/ENCODER-VIDEO/CONTAINER + var mapObj = { + _SCREENCAST_RES_: resolution, + _ENCODER_VIDEO_: CONTAINER[container].quality[qualityGSP].vq, + _CONTAINER_: CONTAINER[container].nameGSP, + }; + + tmpGSP = tmpGSP.replace( + /_SCREENCAST_RES_|_ENCODER_VIDEO_|_CONTAINER_/gi, + match => { + return mapObj[match]; + } + ); + + Lib.TalkativeLog(`-§-final GSP :${tmpGSP}`); + + return tmpGSP; +} + +/** + * replace audio + * + * @param {string} gspRA input pipeline to be modified + * @param {boolean} defaultAudio whether to use the default audio device + * @param {int} ConTMP selected output container. Used to determine correct audio encoder + * @param {int} QGSPtmp quality setting + * @param {MixerAudio} mixer audio mixer + * @returns {string} pipeline with audio + */ +function _replaceAudio(gspRA, defaultAudio, ConTMP, QGSPtmp, mixer) { + Lib.TalkativeLog(`-§-replace audio default->${defaultAudio}`); + // replace device/encoder + var aq = CONTAINER[ConTMP].quality[QGSPtmp].aq; + Lib.TalkativeLog(`-§-pipeline pre-audio:${gspRA} aq:${aq}`); + var audioPipeline; + + if (defaultAudio) { + Lib.TalkativeLog('-§-default audio source'); + audioPipeline = gspRA.replace(/_ENCODER_AUDIO_/gi, aq); + } else { + var audiosource = mixer.getAudioSource(); + if (audiosource === undefined) { + Lib.TalkativeLog('-§-failure combination of array audio sources'); + audioPipeline = gspRA.replace(/_ENCODER_AUDIO_/gi, aq); + } else { + Lib.TalkativeLog('-§-correct audio source assignment'); + if (audiosource.indexOf('output') !== -1) + audiosource += '.monitor'; + + var reDev = `pulsesrc device="${audiosource}"`; + + var mapObj = { + pulsesrc: reDev, + _ENCODER_AUDIO_: aq, + }; + + audioPipeline = gspRA.replace( + /pulsesrc|_ENCODER_AUDIO_/gi, + match => { + return mapObj[match]; + } + ); + } + } + + Lib.TalkativeLog(`-§-pipeline post-audio:${audioPipeline}`); + + return audioPipeline; +} + +/** + * replace webcam + * + * @param {string} gspRW input pipeline to be modified + * @param {string} device webcam device file (e.g. /dev/video0) + * @param {string} caps quality options + * @param {EasyScreenCastSettings} settings the extension's settings + * @returns {string} pipeline with webcam settings + */ +function _replaceWebcam(gspRW, device, caps, settings) { + Lib.TalkativeLog(`-§-replace webcam -> ${device} caps: ${caps}`); + + // replace device/caps + var reDev = `device=${device}`; + var reWCopt = _composeWebCamOption(settings); + var [reWCwidth, reWCheight] = _getWebCamDimension(settings); + + Lib.TalkativeLog(`-§-pipeline pre-webcam:${gspRW}`); + + var mapObj = { + _WEBCAM_DEV_: reDev, + _WEBCAM_CAP_: caps, + _WEBCAM_OPT_: reWCopt, + _WEBCAM_W_: reWCwidth, + _WEBCAM_H_: reWCheight, + }; + + var webcamPipeline = gspRW.replace( + /_WEBCAM_DEV_|_WEBCAM_CAP_|_WEBCAM_OPT_|_WEBCAM_W_|_WEBCAM_H_/gi, + match => { + return mapObj[match]; + } + ); + + Lib.TalkativeLog(`-§-pipeline post-webcam:${webcamPipeline}`); + + return webcamPipeline; +} + +/** + * replace resolution + * + * @param {int} tmpRes resolution type: native/custom + * @param {int} h custom height + * @param {int} w custom width + * @param {boolean} kar whether to keep aspect ratio + * @returns {string} pipeline part for scaling resolution + */ +function _composeResolution(tmpRes, h, w, kar) { + Lib.TalkativeLog(`-§-resolution option: ${tmpRes}`); + var strRes = RESOLUTION[0]; + var mapObj = {}; + + switch (tmpRes) { + case -1: + break; + case 999: + mapObj = { + _RES_KAR_: kar ? 'true' : 'false', + _RES_HEIGHT_: h, + _RES_WIDTH_: w, + }; + + strRes = RESOLUTION[1].replace( + /_RES_KAR_|_RES_HEIGHT_|_RES_WIDTH_/gi, + match => { + return mapObj[match]; + } + ); + break; + default: + mapObj = { + _RES_KAR_: 'true', + _RES_HEIGHT_: h, + _RES_WIDTH_: w, + }; + + strRes = RESOLUTION[1].replace( + /_RES_KAR_|_RES_WIDTH_|_RES_HEIGHT_/gi, + match => { + return mapObj[match]; + } + ); + } + + Lib.TalkativeLog(`-§-compose resolution: ${strRes}`); + return strRes; +} + +/** + * compose option webcam position + * + * @param {EasyScreenCastSettings} settings the extension's settings + * + * @returns {string} + */ +function _composeWebCamOption(settings) { + Lib.TalkativeLog('-§-compose webcam option'); + + // retrieve option webcam + var webcamAlpha = settings.getOption('d', Settings.ALPHA_CHANNEL_WEBCAM_SETTING_KEY); + var webcamMarginX = settings.getOption('i', Settings.MARGIN_X_WEBCAM_SETTING_KEY); + var webcamMarginY = settings.getOption('i', Settings.MARGIN_Y_WEBCAM_SETTING_KEY); + var webcamCornerPosition = settings.getOption('i', Settings.CORNER_POSITION_WEBCAM_SETTING_KEY); + var [webcamWidth, webcamHeight, screenWidth, screenHeight] = _getWebCamDimension(settings); + + var posX = 0; + var posY = 0; + + Lib.TalkativeLog( + `-§-alpha=${webcamAlpha} |marX=${webcamMarginX} |marY=${webcamMarginY} |corner=${webcamCornerPosition}` + ); + + // corner top-left + posX = webcamMarginX; + posY = webcamMarginY; + + switch (webcamCornerPosition) { + case 0: + // corner bottom-right + posX = Math.floor(screenWidth - (webcamWidth + webcamMarginX)); + posY = Math.floor(screenHeight - (webcamHeight + webcamMarginY)); + break; + case 1: + // corner bottom-left + posX = webcamMarginX; + posY = Math.floor(screenHeight - (webcamHeight + webcamMarginY)); + break; + case 2: + // corner top-right + posX = Math.floor(screenWidth - (webcamWidth + webcamMarginX)); + posY = webcamMarginY; + break; + default: + } + + // check valid position + if ((posX < 0 || posX > screenWidth) && (posY < 0 || posY > screenHeight)) { + Lib.TalkativeLog('-§-NOT valid position'); + posX = 0; + posY = 0; + } + + var tmpWCopt = + `sink_0::alpha=1 sink_1::alpha=${ + webcamAlpha + } sink_1::xpos=${ + posX + } sink_1::ypos=${ + posY + } `; + + Lib.TalkativeLog(`-§-posX=${posX} |posY=${posY}`); + Lib.TalkativeLog(`-§-webcam option=${tmpWCopt}`); + + return tmpWCopt; +} + +/** + * retrieve dimension webcam + * + * @param {EasyScreenCastSettings} settings the extension's settings + * + * @returns {*[]} array with webcam width,height,screen-width,screen-height + */ +function _getWebCamDimension(settings) { + Lib.TalkativeLog('-§-get webcam dimension'); + + var webcamWidth = settings.getOption('i', Settings.WIDTH_WEBCAM_SETTING_KEY); + var webcamHeight = settings.getOption('i', Settings.HEIGHT_WEBCAM_SETTING_KEY); + var webcamUnit = settings.getOption('i', Settings.TYPE_UNIT_WEBCAM_SETTING_KEY); + var screenWidth = settings.getOption('i', Settings.WIDTH_SETTING_KEY); + var screenHeight = settings.getOption('i', Settings.HEIGHT_SETTING_KEY); + + if (settings.getOption('i', Settings.AREA_SCREEN_SETTING_KEY) === 0) { + screenWidth = global.screen_width; + screenHeight = global.screen_height; + } + + Lib.TalkativeLog( + `-§-WC w=${webcamWidth} WC h=${webcamHeight} WCtype=${webcamUnit} screen W=${screenWidth} screen H=${screenHeight}` + ); + + if (webcamUnit === 0) { + webcamWidth = Math.floor((screenWidth * webcamWidth) / 100); + webcamHeight = Math.floor((screenHeight * webcamHeight) / 100); + } + + Lib.TalkativeLog(`-§-after percentage WCw=${webcamWidth} WCh=${webcamHeight}`); + + return [webcamWidth, webcamHeight, screenWidth, screenHeight]; +} + +/** + * get description + * + * @param {int} quality selected quality + * @param {int} container selected container format + * @returns {string} + */ +function getDescr(quality, container) { + Lib.TalkativeLog(`-§-get description Q-> ${quality} C-> ${container}`); + + return CONTAINER[container].quality[quality].descr; +} + +/** + * get fps + * + * @param {int} quality selected quality + * @param {int} container selected container format + * @returns {number} + */ +function getFps(quality, container) { + Lib.TalkativeLog(`-§-get fps Q-> ${quality} C-> ${container}`); + + return CONTAINER[container].quality[quality].fps; +} + +/** + * get file extension + * + * @param {int} container selected container format + * @returns {string} + */ +function getFileExtension(container) { + Lib.TalkativeLog(`-§-get file extension C-> ${container}`); + + return CONTAINER[container].fileExt; +} + +export {composeGSP, getDescr, getFps, getFileExtension}; diff --git a/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/utilnotify.js b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/utilnotify.js new file mode 100644 index 0000000..1bdb476 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/utilnotify.js @@ -0,0 +1,147 @@ +/* + Copyright (C) 2016 Borsato Ivano + + The JavaScript code in this page is free software: you can + redistribute it and/or modify it under the terms of the GNU + General Public License (GNU GPL) as published by the Free Software + Foundation, either version 3 of the License, or (at your option) + any later version. The code is distributed WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU GPL for more details. +*/ + +'use strict'; + +import GObject from 'gi://GObject'; +import * as Main from 'resource:///org/gnome/shell/ui/main.js'; +// https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/messageTray.js +import * as MessageTray from 'resource:///org/gnome/shell/ui/messageTray.js'; +import St from 'gi://St'; + +import * as Lib from './convenience.js'; +import * as Settings from './settings.js'; +import * as Ext from './extension.js'; + +import {gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js'; + +/** + * @type {NotifyManager} + */ +var NotifyManager = GObject.registerClass({ + GTypeName: 'EasyScreenCast_NotifyManager', +}, class NotifyManager extends GObject.Object { + /** + * Create a notify manager + */ + constructor() { + super(); + Lib.TalkativeLog('-°-init notify manager'); + this._alertWidget = null; + } + + /** + * create notify + * + * @param {string} msg the title + * @param {Gio.FileIcon} icon the icon + * @param {boolean} sound whether to play a sound + * @returns {MessageTray.Notification} + */ + createNotify(msg, icon, sound) { + Lib.TalkativeLog(`-°-create notify :${msg}`); + var source = new MessageTray.Source({ + title: _('EasyScreenCast'), + }); + var notify = new MessageTray.Notification({ + source, + title: msg, + body: null, + gicon: icon, + isTransient: false, + resident: true, + }); + + Main.messageTray.add(source); + source.addNotification(notify); + + if (sound) + notify.playSound(); + + return notify; + } + + /** + * update notify + * + * @param {MessageTray.Notification} notify the already existing notification to update + * @param {string} msg the title + * @param {Gio.FileIcon} icon the icon + * @param {boolean} sound whether to play a sound + */ + updateNotify(notify, msg, icon, sound) { + Lib.TalkativeLog('-°-update notify'); + + notify.set({ + title: msg, + body: null, + gicon: icon, + }); + + if (sound) + notify.playSound(); + } + + /** + * create alert + * + * @param {string} msg the message + */ + createAlert(msg) { + Lib.TalkativeLog(`-°-show alert tweener : ${msg}`); + if (Ext.Indicator.getSettings().getOption('b', Settings.SHOW_NOTIFY_ALERT_SETTING_KEY)) { + var monitor = Main.layoutManager.focusMonitor; + + this.resetAlert(); + this._alertWidget = new St.Label({ + style_class: 'alert-msg', + opacity: 255, + text: msg, + }); + Main.uiGroup.add_child(this._alertWidget); + + this._alertWidget.set_position( + Math.floor(monitor.width / 2 - this._alertWidget.width / 2), + Math.floor(monitor.height / 2 - this._alertWidget.height / 2) + ); + + Lib.TalkativeLog(`-°-show alert tweener : opacity=${this._alertWidget.opacity}`); + + // see org/gnome/shell/ui/environment.js#_easeActor + // TODO: for some reason, no transition is created, so the onComplete + // callback is called _immediately_ + /* + import Clutter from 'gi://Clutter'; + this._alertWidget.ease({ + opacity: 0, + duration: 400, + mode: Clutter.AnimationMode.EASE_OUT_QUAD, + onComplete: () => { + Lib.TalkativeLog(`-°-show alert tweener completed: opacity=${this._alertWidget.opacity}`); + Main.uiGroup.remove_child(this._alertWidget); + this._alertWidget = null; + }, + }); + */ + } + } + + resetAlert() { + if (this._alertWidget !== null) { + this._alertWidget.hide(); + Main.uiGroup.remove_child(this._alertWidget); + this._alertWidget = null; + } + } +}); + +export {NotifyManager}; diff --git a/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/utilrecorder.js b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/utilrecorder.js new file mode 100644 index 0000000..1b0a434 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/utilrecorder.js @@ -0,0 +1,216 @@ +/* + Copyright (C) 2013 Borsato Ivano + + The JavaScript code in this page is free software: you can + redistribute it and/or modify it under the terms of the GNU + General Public License (GNU GPL) as published by the Free Software + Foundation, either version 3 of the License, or (at your option) + any later version. The code is distributed WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU GPL for more details. +*/ + +'use strict'; + +import GObject from 'gi://GObject'; +import Gio from 'gi://Gio'; +import GLib from 'gi://GLib'; +import {loadInterfaceXML} from 'resource:///org/gnome/shell/misc/dbusUtils.js'; +const ScreencastIface = loadInterfaceXML('org.gnome.Shell.Screencast'); + +import * as Lib from './convenience.js'; +import * as Settings from './settings.js'; +import * as Selection from './selection.js'; +import * as UtilGSP from './utilgsp.js'; +import * as Ext from './extension.js'; + +/** + * @type {CaptureVideo} + */ +var CaptureVideo = GObject.registerClass({ + GTypeName: 'EasyScreenCast_CaptureVideo', +}, class CaptureVideo extends GObject.Object { + /** + * Create a video recorder + */ + constructor() { + super(); + Lib.TalkativeLog('-&-init recorder'); + + this.AreaSelected = null; + + // connect to d-bus service + const ScreenCastProxy = Gio.DBusProxy.makeProxyWrapper(ScreencastIface); + this._screenCastService = new ScreenCastProxy( + Gio.DBus.session, + 'org.gnome.Shell.Screencast', + '/org/gnome/Shell/Screencast', + (proxy, error) => { + if (error) + Lib.TalkativeLog(`-&-ERROR(d-bus proxy connected) - ${error.message}`); + else + Lib.TalkativeLog('-&-d-bus proxy connected'); + } + ); + } + + /** + * start recording + */ + start() { + Lib.TalkativeLog('-&-start video recording'); + this.recordingActive = false; + + let fileExt = UtilGSP.getFileExtension( + Ext.Indicator.getSettings().getOption('i', Settings.FILE_CONTAINER_SETTING_KEY) + ); + // prepare variable for screencast + let fileRec = Ext.Indicator.getSettings().getOption('s', Settings.FILE_NAME_SETTING_KEY); + + let folderRec = ''; + if (Ext.Indicator.getSettings().getOption('s', Settings.FILE_FOLDER_SETTING_KEY) !== '') + folderRec = Ext.Indicator.getSettings().getOption('s', Settings.FILE_FOLDER_SETTING_KEY); + + let pipelineRec = ''; + + if (Ext.Indicator.getSettings().getOption('b', Settings.ACTIVE_CUSTOM_GSP_SETTING_KEY)) { + pipelineRec = Ext.Indicator.getSettings().getOption( + 's', + Settings.PIPELINE_REC_SETTING_KEY + ); + } else { + // compose GSP + pipelineRec = UtilGSP.composeGSP(Ext.Indicator.getSettings(), Ext.Indicator.CtrlAudio); + } + + Lib.TalkativeLog(`-&-file template : ${fileRec}`); + fileRec = this._generateFileName(fileRec); + Lib.TalkativeLog(`-&-file final : ${fileRec}`); + const completeFileRecPath = folderRec !== '' + ? `${folderRec}/${fileRec}` + : fileRec; + Lib.TalkativeLog(`-&-file rec path complete : ${completeFileRecPath}${fileExt}`); + + // prefix with a videoconvert element + // see DEFAULT_PIPELINE in https://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/dbusServices/screencast/screencastService.js#L26 + // this videoconvert element was added always previously (< Gnome 40) and needs to be added now explicitly + // https://gitlab.gnome.org/GNOME/gnome-shell/-/commit/51bf7ec17617a9ed056dd563afdb98e17da07373 + pipelineRec = `videoconvert chroma-mode=GST_VIDEO_CHROMA_MODE_NONE dither=GST_VIDEO_DITHER_NONE matrix-mode=GST_VIDEO_MATRIX_MODE_OUTPUT_ONLY n-threads=%T ! queue ! ${pipelineRec}`; + Lib.TalkativeLog(`-&-pipeline : pipeline: ${pipelineRec}`); + + var optionsRec = { + 'draw-cursor': new GLib.Variant( + 'b', + Ext.Indicator.getSettings().getOption('b', Settings.DRAW_CURSOR_SETTING_KEY) + ), + framerate: new GLib.Variant( + 'i', + Ext.Indicator.getSettings().getOption('i', Settings.FPS_SETTING_KEY) + ), + pipeline: new GLib.Variant('s', pipelineRec), + }; + + if (Ext.Indicator.getSettings().getOption('i', Settings.AREA_SCREEN_SETTING_KEY) === 0) { + this._screenCastService.ScreencastRemote( + completeFileRecPath, + optionsRec, + (result, error) => { + if (error) { + Lib.TalkativeLog(`-&-ERROR(screencast execute) - ${error.message}`); + + this.stop(); + Ext.Indicator.doRecResult(false); + } else { + Lib.TalkativeLog(`-&-screencast execute - ${result[0]} - ${result[1]}`); + + let resultingFilePath = result[1]; + if (resultingFilePath.endsWith('.undefined')) { + resultingFilePath = resultingFilePath.substring(0, resultingFilePath.length - '.undefined'.length); + resultingFilePath = `${resultingFilePath}${fileExt}`; + } + this._originalFilePath = result[1]; + this._filePathWithExtension = resultingFilePath; + + Ext.Indicator.doRecResult(result[0], resultingFilePath); + } + } + ); + } else { + this._screenCastService.ScreencastAreaRemote( + Ext.Indicator.getSettings().getOption('i', Settings.X_POS_SETTING_KEY), + Ext.Indicator.getSettings().getOption('i', Settings.Y_POS_SETTING_KEY), + Ext.Indicator.getSettings().getOption('i', Settings.WIDTH_SETTING_KEY), + Ext.Indicator.getSettings().getOption('i', Settings.HEIGHT_SETTING_KEY), + completeFileRecPath, + optionsRec, + (result, error) => { + if (error) { + Lib.TalkativeLog(`-&-ERROR(screencast execute) - ${error.message}`); + + this.stop(); + Ext.Indicator.doRecResult(false); + } else { + Lib.TalkativeLog(`-&-screencast execute - ${result[0]} - ${result[1]}`); + + // draw area recording + if (Ext.Indicator.getSettings().getOption('b', Settings.SHOW_AREA_REC_SETTING_KEY)) + this.AreaSelected = new Selection.AreaRecording(); + + let resultingFilePath = result[1]; + if (resultingFilePath.endsWith('.undefined')) { + resultingFilePath = resultingFilePath.substring(0, resultingFilePath.length - '.undefined'.length); + resultingFilePath = `${resultingFilePath}${fileExt}`; + } + this._originalFilePath = result[1]; + this._filePathWithExtension = resultingFilePath; + + Ext.Indicator.doRecResult(result[0], resultingFilePath); + } + } + ); + } + } + + /** + * Stop recording + * + * @returns {boolean} + */ + stop() { + Lib.TalkativeLog('-&-stop video recording'); + + this._screenCastService.StopScreencastRemote((result, error) => { + if (error) { + Lib.TalkativeLog(`-&-ERROR(screencast stop) - ${error.message}`); + return false; + } else { + Lib.TalkativeLog(`-&-screencast stop - ${result[0]}`); + + + // rename the file... + Lib.TalkativeLog(`-&-screencast: rename ${this._originalFilePath} to ${this._filePathWithExtension}`); + const sourceFile = Gio.File.new_for_path(this._originalFilePath); + const destFile = Gio.File.new_for_path(this._filePathWithExtension); + sourceFile.move(destFile, 0, null, null); + } + + // clear area recording + if (this.AreaSelected !== null && this.AreaSelected.isVisible()) + this.AreaSelected.clearArea(); + + return true; + }); + } + + // without file extension + _generateFileName(template) { + template = template.replaceAll('%d', '%0x').replaceAll('%t', '%0X'); + const datetime = GLib.DateTime.new_now_local(); + let result = datetime.format(template); + result = result.replaceAll(' ', '_'); // remove white space + result = result.replaceAll('/', '_'); // remove path separators + return result; + } +}); + +export {CaptureVideo}; diff --git a/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/utilwebcam.js b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/utilwebcam.js new file mode 100644 index 0000000..d1ab076 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/EasyScreenCast@iacopodeenosee.gmail.com/utilwebcam.js @@ -0,0 +1,315 @@ +/* + Copyright (C) 2015 Borsato Ivano + + The JavaScript code in this page is free software: you can + redistribute it and/or modify it under the terms of the GNU + General Public License (GNU GPL) as published by the Free Software + Foundation, either version 3 of the License, or (at your option) + any later version. The code is distributed WITHOUT ANY WARRANTY; + without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. See the GNU GPL for more details. +*/ + +'use strict'; + +import GObject from 'gi://GObject'; +import GLib from 'gi://GLib'; +import Gst from 'gi://Gst?version=1.0'; +import * as Lib from './convenience.js'; + +var HelperWebcam = GObject.registerClass({ + GTypeName: 'EasyScreenCast_HelperWebcam', +}, class HelperWebcam extends GObject.Object { + /** + * Create a device monitor inputvideo + * + * @param {string} unspecifiedWebcamText localized text for "Unspecified Webcam" + */ + constructor(unspecifiedWebcamText) { + super(); + this._unspecified_webcam_text = unspecifiedWebcamText; + Lib.TalkativeLog('-@-init webcam'); + + Gst.init(null); + + // get gstreamer lib version + var [M, m, micro, nano] = Gst.version(); + Lib.TalkativeLog( + `-@-gstreamer version: ${M}.${m}.${micro}.${nano}` + ); + if (M === 1 && m >= 8) { + // gstreamer version equal or higher 1.8 + this.deviceMonitor = new Gst.DeviceMonitor({ + show_all: true, + }); + } else { + // gstreamer version lower 1.8 + this.deviceMonitor = new Gst.DeviceMonitor(); + } + + // get gstreamer plugin avaiable + let registry = new Gst.Registry(); + let listPI = registry.get_plugin_list(); + Lib.TalkativeLog(`-@-plugin list: ${listPI.length}`); + for (var ind in listPI) { + Lib.TalkativeLog( + `-@-plugin name: ${ + listPI[ind].get_name() + } Pfilename: ${ + listPI[ind].get_filename() + } Pdesc: ${ + listPI[ind].get_description() + } Pversion: ${ + listPI[ind].get_version() + } Pload: ${ + listPI[ind].is_loaded()}` + ); + } + + // create device monitor + if (this.deviceMonitor !== null && this.deviceMonitor !== undefined) { + Lib.TalkativeLog('-@-device monitor created'); + this.dmBus = this.deviceMonitor.get_bus(); + if (this.dmBus !== null && this.dmBus !== undefined) { + Lib.TalkativeLog('-@-dbus created'); + this.dmBus.add_watch(GLib.PRIORITY_DEFAULT, this._getMsg.bind(this)); + let caps = Gst.Caps.new_empty_simple('video/x-raw'); + this.deviceMonitor.add_filter('Video/Source', caps); + this.startMonitor(); + // update device and caps + this.refreshAllInputVideo(); + } else { + Lib.TalkativeLog('-@-ERROR dbus creation'); + } + } else { + Lib.TalkativeLog('-@-ERROR device monitor creation'); + } + } + + /** + * Callback for the DeviceMonitor watcher + * + * @param {Gst.Bus} bus the DeviceMonitor Bus of gstreamer + * @param {Gst.Message} message the message + * @returns {boolean} + */ + _getMsg(bus, message) { + Lib.TalkativeLog('-@-event getmsg'); + switch (message.type) { + case Gst.MessageType.DEVICE_ADDED: + Lib.TalkativeLog('Device added'); + + // update device and caps + this.refreshAllInputVideo(); + break; + case Gst.MessageType.DEVICE_REMOVED: + Lib.TalkativeLog('Device removed'); + + // update device and caps + this.refreshAllInputVideo(); + break; + default: + Lib.TalkativeLog('Device UNK'); + break; + } + + return GLib.SOURCE_CONTINUE; + } + + /** + * refresh all devices info + */ + refreshAllInputVideo() { + Lib.TalkativeLog('-@-refresh all video input'); + + this._listDevices = this.getDevicesIV(); + // compose devices array + this._listCaps = []; + for (var index in this._listDevices) { + this._listCaps[index] = this.getCapsForIV(this._listDevices[index].caps); + + Lib.TalkativeLog(`-@-webcam /dev/video${index} name: ${this._listDevices[index].display_name}`); + Lib.TalkativeLog(`-@-caps available: ${this._listCaps[index].length}`); + Lib.TalkativeLog(`-@-ListCaps[${index}]: ${this._listCaps[index]}`); + } + } + + /** + * get caps from device. + * A single capability might look like: video/x-raw, format=(string)YUY2, width=(int)640, height=(int)480, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction)30/1 + * This encodes a single capability (fixed), but there might also be capabilities which represent options, e.g. + * video/x-raw, format=(string)YUY2, width=(int)640, height=(int)480, pixel-aspect-ratio=(fraction)1/1, framerate=(fraction) { 30/1, 25/1, 20/1 }. + *
+ * The code here will take always the first option and unroll the options for framerate. + * + * @param {Gst.Caps} tmpCaps capabilities of a device + * @returns {string[]} + */ + getCapsForIV(tmpCaps) { + Lib.TalkativeLog('-@-get all caps from a input video'); + Lib.TalkativeLog(`-@-caps available before filtering for video/x-raw: ${tmpCaps.get_size()}`); + + let cleanCaps = []; + for (let i = 0; i < tmpCaps.get_size(); i++) { + let capsStructure = tmpCaps.get_structure(i); + + // only consider "video/x-raw" + if (capsStructure.get_name() === 'video/x-raw') { + Lib.TalkativeLog(`-@-cap : ${i} : original : ${capsStructure.to_string()}`); + + let tmpStr = 'video/x-raw'; + let result, number, fraction; + result = capsStructure.get_string('format'); + if (result !== null) + tmpStr += `, format=(string)${result}`; + [result, number] = capsStructure.get_int('width'); + if (result === true) + tmpStr += `, width=(int)${number}`; + [result, number] = capsStructure.get_int('height'); + if (result === true) + tmpStr += `, height=(int)${number}`; + [result, number, fraction] = capsStructure.get_fraction('pixel-aspect-ratio'); + if (result === true) + tmpStr += `, pixel-aspect-ratio=(fraction)${number}/${fraction}`; + + + if (capsStructure.has_field('framerate')) { + [result, number, fraction] = capsStructure.get_fraction('framerate'); + if (result === true) { + // a single framerate + this._addAndLogCapability(cleanCaps, i, `${tmpStr}, framerate=(fraction)${number}/${fraction}`); + } else { + // multiple framerates + + // unfortunately GstValueList is not supported in this gjs-binding + // "Error: Don't know how to convert GType GstValueList to JavaScript object" + // -> capsStructure.get_value('framerate') <- won't work + // -> capsStructure.get_list('framerate') <- only returns the numerator of the fraction + // + // therefore manually parsing the framerate values from the string representation + let framerates = capsStructure.to_string(); + framerates = framerates.substring(framerates.indexOf('framerate=(fraction){') + 21); + framerates = framerates.substring(0, framerates.indexOf('}')); + framerates.split(',').forEach(element => { + let [numerator, denominator] = element.split('/', 2); + this._addAndLogCapability(cleanCaps, i, `${tmpStr}, framerate=(fraction)${numerator.trim()}/${denominator.trim()}`); + }); + } + } else { + // no framerate at all + this._addAndLogCapability(cleanCaps, i, tmpStr); + } + } else { + Lib.TalkativeLog(`-@-cap : ${i} : skipped : ${capsStructure.to_string()}`); + } + } + return cleanCaps; + } + + /** + * Adds the capability str to the array caps, if it is not already there. Avoids duplicates. + * + * @param {Array} caps the list of capabilities + * @param {int} originalIndex index of the original capabilities list from the device + * @param {string} str the capability string to add + */ + _addAndLogCapability(caps, originalIndex, str) { + if (caps.indexOf(str) === -1) { + caps.push(str); + Lib.TalkativeLog(`-@-cap : ${originalIndex} : added cap : ${str}`); + } else { + Lib.TalkativeLog(`-@-cap : ${originalIndex} : ignore duplicated cap : ${str}`); + } + } + + /** + * get devices IV + * + * @returns {Gst.Device[]} + */ + getDevicesIV() { + Lib.TalkativeLog('-@-get devices'); + + var list = this.deviceMonitor.get_devices(); + Lib.TalkativeLog(`-@-devices number: ${list.length}`); + + // Note: + // Although the computer may have just one webcam connected to + // it, more than one GstDevice may be listed and all pointing to + // the same video device (for example /dev/video0. Each + // GstDevice is supposed to be used with a specific source, for + // example, a pipewiresrc or a v4l2src. For now, we are only + // using v4l2src. + // See also: Gst.DeviceMonitor.get_providers: pipewiredeviceprovider,decklinkdeviceprovider,v4l2deviceprovider + // + // So, here we filter the devices, that have a device.path property, which + // means, these are only v4l2 devices + var filtered = list.filter(device => device.get_properties().get_string('device.path') !== null); + Lib.TalkativeLog(`-@-devices number after filtering for v4l2: ${filtered.length}`); + + return filtered; + } + + /** + * get array name devices IV + * + * @returns {Array} + */ + getNameDevices() { + Lib.TalkativeLog('-@-get name devices'); + let tmpArray = []; + + for (var index in this._listDevices) { + var wcName = this._unspecified_webcam_text; + + if (this._listDevices[index].display_name !== '') + wcName = this._listDevices[index].display_name; + + tmpArray.push(wcName); + } + + Lib.TalkativeLog(`-@-list devices name: ${tmpArray}`); + return tmpArray; + } + + /** + * get array caps + * + * @param {int} index device + * @returns {string[]} + */ + getListCapsDevice(index) { + const tmpArray = this._listCaps[index]; + Lib.TalkativeLog(`-@-list caps of device: ${tmpArray}`); + return tmpArray; + } + + /** + * start listening + */ + startMonitor() { + Lib.TalkativeLog('-@-start video devicemonitor'); + this.deviceMonitor.start(); + } + + /** + * Stop listening + */ + stopMonitor() { + Lib.TalkativeLog('-@-stop video devicemonitor'); + this.disconnectSourceBus(); + this.deviceMonitor.stop(); + } + + /** + * disconect bus + */ + disconnectSourceBus() { + if (this.dmBusId) { + this.dmBus.disconnect(this.dmBusId); + this.dmBusId = 0; + } + } +}); + +export {HelperWebcam}; diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/extension.js b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/extension.js index ee5d735..d7f0daf 100644 --- a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/extension.js +++ b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/extension.js @@ -40,15 +40,23 @@ var VitalsMenuButton = GObject.registerClass({ 'icon-rx': 'network-download-symbolic.svg', 'icon-tx': 'network-upload-symbolic.svg' }, 'storage' : { 'icon': 'storage-symbolic.svg' }, - 'battery' : { 'icon': 'battery-symbolic.svg' } + 'battery' : { 'icon': 'battery-symbolic.svg' }, + 'gpu' : { 'icon': 'gpu-symbolic.svg' } } + // list with the prefixes for the according themes, the index of each + // item must match the index on the combo box + this._sensorsIconPathPrefix = ['/icons/original/', '/icons/gnome/']; + this._warnings = []; this._sensorMenuItems = {}; this._hotLabels = {}; this._hotIcons = {}; this._groups = {}; this._widths = {}; + this._numGpus = 1; + this._newGpuDetected = false; + this._newGpuDetectedCount = 0; this._last_query = new Date().getTime(); this._sensors = new Sensors.Sensors(this._settings, this._sensorIcons); @@ -64,15 +72,16 @@ var VitalsMenuButton = GObject.registerClass({ }); this._drawMenu(); - this.add_actor(this._menuLayout); + this.add_child(this._menuLayout); this._settingChangedSignals = []; this._refreshTimeoutId = null; this._addSettingChangedSignal('update-time', this._updateTimeChanged.bind(this)); this._addSettingChangedSignal('position-in-panel', this._positionInPanelChanged.bind(this)); this._addSettingChangedSignal('menu-centered', this._positionInPanelChanged.bind(this)); + this._addSettingChangedSignal('icon-style', this._iconStyleChanged.bind(this)); - let settings = [ 'use-higher-precision', 'alphabetize', 'hide-zeros', 'fixed-widths', 'hide-icons', 'unit', 'memory-measurement', 'include-public-ip', 'network-speed-format', 'storage-measurement', 'include-static-info' ]; + let settings = [ 'use-higher-precision', 'alphabetize', 'hide-zeros', 'fixed-widths', 'hide-icons', 'unit', 'memory-measurement', 'include-public-ip', 'network-speed-format', 'storage-measurement', 'include-static-info', 'include-static-gpu-info' ]; for (let setting of Object.values(settings)) this._addSettingChangedSignal(setting, this._redrawMenu.bind(this)); @@ -95,21 +104,14 @@ var VitalsMenuButton = GObject.registerClass({ // groups associated sensors under accordion menu if (sensor in this._groups) continue; - this._groups[sensor] = new PopupMenu.PopupSubMenuMenuItem(_(this._ucFirst(sensor)), true); - this._groups[sensor].icon.gicon = Gio.icon_new_for_string(this._extensionObject.path + '/icons/' + this._sensorIcons[sensor]['icon']); + //handle gpus separately. + if (sensor === 'gpu') continue; - // hide menu items that user has requested to not include - if (!this._settings.get_boolean('show-' + sensor)) - this._groups[sensor].actor.hide(); - - if (!this._groups[sensor].status) { - this._groups[sensor].status = this._defaultLabel(); - this._groups[sensor].actor.insert_child_at_index(this._groups[sensor].status, 4); - this._groups[sensor].status.text = _('No Data'); - } - - this.menu.addMenuItem(this._groups[sensor]); + this._initializeMenuGroup(sensor, sensor); } + + for (let i = 1; i <= this._numGpus; i++) + this._initializeMenuGroup('gpu#' + i, 'gpu', (this._numGpus > 1 ? ' ' + i : '')); // add separator this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); @@ -135,7 +137,7 @@ var VitalsMenuButton = GObject.registerClass({ refreshButton.connect('clicked', (self) => { // force refresh by clearing history this._sensors.resetHistory(); - this._values.resetHistory(); + this._values.resetHistory(this._numGpus); // make sure timer fires at next full interval this._updateTimeChanged(); @@ -143,7 +145,7 @@ var VitalsMenuButton = GObject.registerClass({ // refresh sensors now this._querySensors(); }); - customButtonBox.add_actor(refreshButton); + customButtonBox.add_child(refreshButton); // custom round monitor button let monitorButton = this._createRoundButton('org.gnome.SystemMonitor-symbolic', _('System Monitor')); @@ -151,7 +153,7 @@ var VitalsMenuButton = GObject.registerClass({ this.menu._getTopMenu().close(); Util.spawn(this._settings.get_string('monitor-cmd').split(" ")); }); - customButtonBox.add_actor(monitorButton); + customButtonBox.add_child(monitorButton); // custom round preferences button let prefsButton = this._createRoundButton('preferences-system-symbolic', _('Preferences')); @@ -159,10 +161,10 @@ var VitalsMenuButton = GObject.registerClass({ this.menu._getTopMenu().close(); this._extensionObject.openPreferences(); }); - customButtonBox.add_actor(prefsButton); + customButtonBox.add_child(prefsButton); // now add the buttons to the top bar - item.actor.add_actor(customButtonBox); + item.actor.add_child(customButtonBox); // add buttons this.menu.addMenuItem(item); @@ -179,6 +181,24 @@ var VitalsMenuButton = GObject.registerClass({ }); } + _initializeMenuGroup(groupName, optionName, menuSuffix = '', position = -1) { + this._groups[groupName] = new PopupMenu.PopupSubMenuMenuItem(_(this._ucFirst(groupName) + menuSuffix), true); + this._groups[groupName].icon.gicon = Gio.icon_new_for_string(this._sensorIconPath(groupName)); + + // hide menu items that user has requested to not include + if (!this._settings.get_boolean('show-' + optionName)) + this._groups[groupName].actor.hide(); + + if (!this._groups[groupName].status) { + this._groups[groupName].status = this._defaultLabel(); + this._groups[groupName].actor.insert_child_at_index(this._groups[groupName].status, 4); + this._groups[groupName].status.text = _('No Data'); + } + + if(position == -1) this.menu.addMenuItem(this._groups[groupName]); + else this.menu.addMenuItem(this._groups[groupName], position); + } + _createRoundButton(iconName) { let button = new St.Button({ style_class: 'message-list-clear-button button vitals-button-action' @@ -239,7 +259,7 @@ var VitalsMenuButton = GObject.registerClass({ _createHotItem(key, value) { let icon = this._defaultIcon(key); this._hotIcons[key] = icon; - this._menuLayout.add_actor(icon) + this._menuLayout.add_child(icon) // don't add a label when no sensors are in the panel if (key == '_default_icon_') return; @@ -248,7 +268,7 @@ var VitalsMenuButton = GObject.registerClass({ style_class: 'vitals-panel-label', text: (value)?value:'\u2026', // ... y_expand: true, - y_align: Clutter.ActorAlign.START + y_align: Clutter.ActorAlign.CENTER }); // attempt to prevent ellipsizes @@ -258,7 +278,7 @@ var VitalsMenuButton = GObject.registerClass({ this._hotLabels[key] = label; // prevent "called on the widget" "which is not in the stage" errors by adding before width below - this._menuLayout.add_actor(label); + this._menuLayout.add_child(label); // support for fixed widths #55, save label (text) width this._widths[key] = label.width; @@ -266,11 +286,17 @@ var VitalsMenuButton = GObject.registerClass({ _showHideSensorsChanged(self, sensor) { this._sensors.resetHistory(); - this._groups[sensor.substr(5)].visible = this._settings.get_boolean(sensor); + + const sensorName = sensor.substr(5); + if(sensorName === 'gpu') { + for(let i = 1; i <= this._numGpus; i++) + this._groups[sensorName + '#' + i].visible = this._settings.get_boolean(sensor); + } else + this._groups[sensorName].visible = this._settings.get_boolean(sensor); } _positionInPanelChanged() { - this.container.get_parent().remove_actor(this.container); + this.container.get_parent().remove_child(this.container); let position = this._positionInPanel(); // allows easily addressable boxes @@ -284,6 +310,27 @@ var VitalsMenuButton = GObject.registerClass({ boxes[position[0]].insert_child_at_index(this.container, position[1]); } + _redrawDetailsMenuIcons() { + // updates the icons on the 'details' menu, the one + // you have to click to appear + this._sensors.resetHistory(); + for (const sensor in this._sensorIcons) { + if (sensor == "gpu") continue; + this._groups[sensor].icon.gicon = Gio.icon_new_for_string(this._sensorIconPath(sensor)); + } + + // gpu's are indexed differently, handle them here + const gpuKeys = Object.keys(this._groups).filter(key => key.startsWith("gpu#")); + gpuKeys.forEach((gpuKey) => { + this._groups[gpuKey].icon.gicon = Gio.icon_new_for_string(this._sensorIconPath("gpu")); + }); + } + + _iconStyleChanged() { + this._redrawDetailsMenuIcons(); + this._redrawMenu(); + } + _removeHotLabel(key) { if (key in this._hotLabels) { let label = this._hotLabels[key]; @@ -322,7 +369,7 @@ var VitalsMenuButton = GObject.registerClass({ this._drawMenu(); this._sensors.resetHistory(); - this._values.resetHistory(); + this._values.resetHistory(this._numGpus); this._querySensors(); } @@ -370,7 +417,8 @@ var VitalsMenuButton = GObject.registerClass({ } } } - + if(key === "_gpu#1_domain_number_") + console.error('UPDATING: ', key); // have we added this sensor before? let item = this._sensorMenuItems[key]; if (item) { @@ -394,7 +442,7 @@ var VitalsMenuButton = GObject.registerClass({ let split = sensor.type.split('-'); let type = split[0]; let icon = (split.length == 2)?'icon-' + split[1]:'icon'; - let gicon = Gio.icon_new_for_string(this._extensionObject.path + '/icons/' + this._sensorIcons[type][icon]); + let gicon = Gio.icon_new_for_string(this._sensorIconPath(type, icon)); let item = new MenuItem.MenuItem(gicon, key, sensor.label, sensor.value, this._hotLabels[key]); item.connect('toggle', (self) => { @@ -460,17 +508,28 @@ var VitalsMenuButton = GObject.registerClass({ }); // second condition prevents crash due to issue #225, which started when _max_ was moved to the end - if (type == 'default' || !(type in this._sensorIcons)) { - icon.gicon = Gio.icon_new_for_string(this._extensionObject.path + '/icons/' + this._sensorIcons['system']['icon']); + // don't use the default system icon if the type is a gpu; use the universal gpu icon instead + if (type == 'default' || (!(type in this._sensorIcons) && !type.startsWith('gpu'))) { + icon.gicon = Gio.icon_new_for_string(this._sensorIconPath('system')); } else if (!this._settings.get_boolean('hide-icons')) { // support for hide icons #80 let iconObj = (split.length == 2)?'icon-' + split[1]:'icon'; - icon.gicon = Gio.icon_new_for_string(this._extensionObject.path + '/icons/' + this._sensorIcons[type][iconObj]); + icon.gicon = Gio.icon_new_for_string(this._sensorIconPath(type, iconObj)); } return icon; } + _sensorIconPath(sensor, icon = 'icon') { + // If the sensor is a numbered gpu, use the gpu icon. Otherwise use whatever icon associated with the sensor name. + let sensorKey = sensor; + if(sensor.startsWith('gpu')) sensorKey = 'gpu'; + + const iconPathPrefixIndex = this._settings.get_int('icon-style'); + return this._extensionObject.path + this._sensorsIconPathPrefix[iconPathPrefixIndex] + this._sensorIcons[sensorKey][icon]; + } + _ucFirst(string) { + if(string.startsWith('gpu')) return 'Graphics'; return string.charAt(0).toUpperCase() + string.slice(1); } @@ -524,7 +583,8 @@ var VitalsMenuButton = GObject.registerClass({ this._last_query = now; this._sensors.query((label, value, type, format) => { - let key = '_' + type.replace('-group', '') + '_' + label.replace(' ', '_').toLowerCase() + '_'; + const typeKey = type.replace('-group', ''); + let key = '_' + typeKey + '_' + label.replace(' ', '_').toLowerCase() + '_'; // if a sensor is disabled, gray it out if (key in this._sensorMenuItems) { @@ -534,11 +594,39 @@ var VitalsMenuButton = GObject.registerClass({ if (value == 'disabled') return; } + // add/initialize any gpu groups that we haven't added yet + if(typeKey.startsWith('gpu') && typeKey !== 'gpu#1') { + const split = typeKey.split('#'); + if(split.length == 2 && this._numGpus < parseInt(split[1])) { + // occasionally two lines from nvidia-smi will be read at once + // so we only actually update the number of gpus if we have recieved multiple lines at least 3 times in a row + // i.e. we make sure that mutiple queries have detected a new gpu back-to-back + if(this._newGpuDetectedCount < 2) { + this._newGpuDetected = true; + return; + } + + this._numGpus = parseInt(split[1]); + this._newGpuDetectedCount = 0; + this._newGpuDetected = false; + // change label for gpu 1 from "Graphics" to "Graphics 1" since we have multiple gpus now + this._groups['gpu#1'].label.text = this._ucFirst('gpu#1') + ' 1'; + for(let i = 2; i <= this._numGpus; i++) + if(!('gpu#' + i in this._groups)) + this._initializeMenuGroup('gpu#' + i, 'gpu', ' ' + i, Object.keys(this._groups).length); + } + } + let items = this._values.returnIfDifferent(dwell, label, value, type, format, key); for (let item of Object.values(items)) this._updateDisplay(_(item[0]), item[1], item[2], item[3]); }, dwell); + //if a new gpu has been detected during the last query, then increment the amount of times we've detected a new gpu + if(this._newGpuDetected) this._newGpuDetectedCount++; + else this._newGpuDetectedCount = 0; + this._newGpuDetected = false; + if (this._warnings.length > 0) { this._notify('Vitals', this._warnings.join("\n"), 'folder-symbolic'); this._warnings = []; @@ -555,6 +643,7 @@ var VitalsMenuButton = GObject.registerClass({ destroy() { this._destroyTimer(); + this._sensors.destroy(); for (let signal of Object.values(this._settingChangedSignals)) this._settings.disconnect(signal); diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/helpers/subprocess.js b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/helpers/subprocess.js new file mode 100644 index 0000000..df0bf49 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/helpers/subprocess.js @@ -0,0 +1,54 @@ +import GLib from 'gi://GLib'; +import Gio from 'gi://Gio'; + +// convert Uint8Array into a literal string +function convertUint8ArrayToString(contents) { + const decoder = new TextDecoder('utf-8'); + return decoder.decode(contents).trim(); +} + +export function SubProcess(command) { + this.sub_process = Gio.Subprocess.new(command, Gio.SubprocessFlags.STDOUT_PIPE); + this.stdout = this.sub_process.get_stdout_pipe(); +} + +SubProcess.prototype.read = function(delimiter = '') { + return new Promise((resolve, reject) => { + this.stdout.read_bytes_async(512, GLib.PRIORITY_LOW, null, function(stdout, res) { + try { + let read_bytes = stdout.read_bytes_finish(res).get_data(); + + // convert contents to string + let read_str = convertUint8ArrayToString(read_bytes); + + // split read_str by delimiter if passed in + if (delimiter) { + if (read_str == '') + read_str = []; // EOF, ''.split(delimiter) would return [''] + else + read_str = read_str.split(delimiter); + } + + // return results + resolve(read_str); + } catch (e) { + if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.PENDING)) { + // previous read attempt is still waiting for something from stdout + // ignore second attempt, return empty data (like EOF) + if (delimiter) resolve([]); + else resolve(''); + } else { + reject(e.message); + } + } + }); + }); +}; + +SubProcess.prototype.terminate = function() { + const SIGINT = 2; + this.sub_process.send_signal(SIGINT); + this.sub_process = null; + this.stdout.close_async(GLib.PRIORITY_LOW, null, null); + this.stdout = null; +}; diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/battery-symbolic.svg b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/battery-symbolic.svg similarity index 100% rename from gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/battery-symbolic.svg rename to gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/battery-symbolic.svg diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/cpu-symbolic.svg b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/cpu-symbolic.svg new file mode 100644 index 0000000..86ca8bf --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/cpu-symbolic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/fan-symbolic.svg b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/fan-symbolic.svg new file mode 100644 index 0000000..ea2b44f --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/fan-symbolic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/gpu-symbolic.svg b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/gpu-symbolic.svg new file mode 100644 index 0000000..d5cf157 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/gpu-symbolic.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/memory-symbolic.svg b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/memory-symbolic.svg new file mode 100644 index 0000000..1946901 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/memory-symbolic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/network-download-symbolic.svg b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/network-download-symbolic.svg new file mode 100644 index 0000000..4fc170b --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/network-download-symbolic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/network-symbolic.svg b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/network-symbolic.svg new file mode 100644 index 0000000..2ff9778 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/network-symbolic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/network-upload-symbolic.svg b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/network-upload-symbolic.svg new file mode 100644 index 0000000..0d67f65 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/network-upload-symbolic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/storage-symbolic.svg b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/storage-symbolic.svg new file mode 100644 index 0000000..30d9007 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/storage-symbolic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/system-symbolic.svg b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/system-symbolic.svg new file mode 100644 index 0000000..bfbf1bd --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/system-symbolic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/temperature-symbolic.svg b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/temperature-symbolic.svg new file mode 100644 index 0000000..e00a2eb --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/temperature-symbolic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/voltage-symbolic.svg b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/voltage-symbolic.svg new file mode 100644 index 0000000..1aa2210 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/gnome/voltage-symbolic.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/original/battery-symbolic.svg b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/original/battery-symbolic.svg new file mode 100644 index 0000000..70df9ee --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/original/battery-symbolic.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/cpu-symbolic.svg b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/original/cpu-symbolic.svg similarity index 100% rename from gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/cpu-symbolic.svg rename to gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/original/cpu-symbolic.svg diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/fan-symbolic.svg b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/original/fan-symbolic.svg similarity index 100% rename from gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/fan-symbolic.svg rename to gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/original/fan-symbolic.svg diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/original/gpu-symbolic.svg b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/original/gpu-symbolic.svg new file mode 100644 index 0000000..d5cf157 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/original/gpu-symbolic.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/memory-symbolic.svg b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/original/memory-symbolic.svg similarity index 100% rename from gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/memory-symbolic.svg rename to gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/original/memory-symbolic.svg diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/network-download-symbolic.svg b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/original/network-download-symbolic.svg similarity index 100% rename from gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/network-download-symbolic.svg rename to gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/original/network-download-symbolic.svg diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/network-symbolic.svg b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/original/network-symbolic.svg similarity index 100% rename from gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/network-symbolic.svg rename to gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/original/network-symbolic.svg diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/network-upload-symbolic.svg b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/original/network-upload-symbolic.svg similarity index 100% rename from gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/network-upload-symbolic.svg rename to gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/original/network-upload-symbolic.svg diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/storage-symbolic.svg b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/original/storage-symbolic.svg similarity index 100% rename from gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/storage-symbolic.svg rename to gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/original/storage-symbolic.svg diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/system-symbolic.svg b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/original/system-symbolic.svg similarity index 100% rename from gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/system-symbolic.svg rename to gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/original/system-symbolic.svg diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/temperature-symbolic.svg b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/original/temperature-symbolic.svg similarity index 100% rename from gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/temperature-symbolic.svg rename to gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/original/temperature-symbolic.svg diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/voltage-symbolic.svg b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/original/voltage-symbolic.svg similarity index 100% rename from gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/voltage-symbolic.svg rename to gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/icons/original/voltage-symbolic.svg diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/be/LC_MESSAGES/vitals.mo b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/locale/be/LC_MESSAGES/vitals.mo new file mode 100644 index 0000000000000000000000000000000000000000..1001254fce3690135947c7e07cf0fb24cdd829ca GIT binary patch literal 10985 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 rzM^z_lh0?~tl5JVR0%6I9xGk`E_wH`Fz1?GX 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 MF&CMJWOsZ23&)1B%m4rY delta 3202 zcmZvedu&ui6o;o!Eh3b*K!KLhTORF}7Nk&6rTcI|c-_aPR=CDsRM z;)5HAppl>^L<2;qi3-F&C`O`2jS@u#B*YMi2E-6ZNE-cqyHn*4Pxg1enYnY%oOABX zZMUrcwJLEgCw+&(Hlx8PJ>8gn@Q(~G*w&uL+zq!`?tuKvUM_dQ{qQb$81{w7Z2wy* z7eB)R@B+lOxdnT`zah^jOb@)vQKn@-SVBJ!`d~HG1I_SG7=v>Br0uss1^y!J1NXr~ z_z}#5Kf-+Y7c798y^I+H%i##tH*08ULL1ZrdtfO%lAK`7Z%~eV_BMu}$>YM1@xktJ zJXC-ap(;@g&%pUm0heZ`G9LqVe>_wIRj`Eh%`6)IVHjq?=inf?6PCdbpdvm4Rl?px zqsrt!Ej$Uz;S9_9kYvqLr~uZ%9M}l?nN3`B;fpY#iF;|_+Z=%W%rP$6@GILt2X+4n z)I099T!XA_I^hbKNxgNy0kRED9BQ35C_mev{Jfm7H+Dcdcmry| z{ZJ)63H88Ps0S{Q1jP9J>Ljb;gB6qJYjEafst;; zykIBXVn@nBIy*%r&VtHd5R`*L$j_8=(Sp;UDmD-5IIe^WJP!5zCYY>%<+chxP~VfW zPcJaO6-cLCDs>;I z%H?v={7R_6rob||+Hxz@{0}XULd`#3K>d~BmkcQ43s4TOLIsjZM-TRe3LpAf(C1u>yZ6natc!qltV342^DD-)Fzz` zH7^cT`d6Sz`8JfpgHVAVhpO!7mR~~o`35SG(=ZJt(7z^!W6*teM3qsNvPnn_&q6`; zD3U#al;Jv5gJe2p3St3@BN#K%3RQ&F0+Jo=bZK8fM2-i7p#% z8yhT@W&^pt5yF7G#lNIZZ~bn`KS)*94|yMGy&;Y={+_g z*$G)4VmA{)$#78Vtvr zSlDR^hXS#1#8d}jQBxgm47UU}s1c6FOm%C_jhdP|f0OGi?&I$rj=0W<^`@rPA9SN$ zudL#X>bh9WjkJ1~vl8ulvjg3{*8Vx(p8kHXM{c!Oms{+8n>)IDLtV)84cOj(d_cD} z@0me|yt#Qr-rl^3SCAj7XbSk7oKU>QjRgF4L8m_DFcn_3DI5>3cODPK>Vna(NWE?O zlQZnJ_7nN_Y27PESG1QDY)_l$Zz9x~vnd{NI^L{zBOB?)LyiCCw%~trGqv7~!ZL4O z;b8C8!tBf%o908U&B1uoOLK~Qq|ywy-c6^i{YcUNZuuQM8yehDEJ*aOGiR~m20~GP zQ!wCm?D2LN*Li6rOT6_ZMcaM8jQJhM8Yq(YmT#!{yzia%@ug0hH>vC^Z*ch#Z)^F} z-hffhmAOG2g`DZl&2juB(};$HL1%d?_l{#W9XC|v?H;wTKoiZ9=?hHF;$^0GgR3|q LrnWU2b6dPj7@FV>b8=)nqYmEN_~f^8krmV!tN*p`8AKu>#5+ataA)N@X; zP|3xSWn!}za)SwDQPC*Q$X;x+W$6B@8viia+;lGrEY>B9iP=*3#}XFeKHuBZ0ojxL zJ)h_0JkRrce!t&y?mwH~YfD`zT7242j-eH3@nU1n!_U9MgYs0KF}K2#5l=&Y<{Xb4 z_!?XSUx&r;&8Yo5s3ksvrEnIqw7Cj%;g^v4DU-|US|~r_ZLpelIjn*0P!kTpTVM#a z@MP3J0cH5pa2Y%gE8(wTIs6l>fM39sF#oH@)Wdaf4f~t@RP@3Ls0q)(T6i(@f-!%C zS~zd1G5kz954ubZTm+k-3~Yw-L_53$yPyoN&7VJcJ=Ay;)B)~?)$DJ!Q7M5QEP&sE z%i%NdZuoO3i!VXBa4FWvGeuAvw?ZwrC1Mxku%-{nfPPp6hao?6l*jGxX_(TB=cur@ zxd8c@H+dAo_oDU{sPTV5#rRs(Ux>BZcs0BY)J!d+^-$v~ZpfUa0pE zLd_qB@^CWhPfbJv$KjLN#(Xz=VF?+c1&X0uTnTl88mI+hPzG**dT$5R27BQucmT@q zV^H(I4dsz3sC9lc&y;zd$~rn;h7Ir!P$$SCkXo<+YQxf~T?uu+*Fr706|RAMpamzP zz6U>sRq)qvBfJdnge4?|-fw}Gy8r!DYUwx*tKq9qq4+%{(aon3{{>~xBJQS6lm}&4 zF}y2_utn{yd_;7@olu_Xi`xBA1`NT~a0-^{{$HS?FVovF20w+Ju!uy^M*E4BHsZ@rG5rP9`)@#fPu_yciH{&Z^EnS4EEo5XHfA|Y$%X5vXhJK*OXeY{iEh+C z8MRMA#q>oegI|G~{|=NVK7=yxa@76|HqoAgq?M^=l5RsQB+6#{%IN<0)1ir@P#a7@ zx&9cG#ovQE;jnylp1w zAiU-os9g9NR1E(DHSw=dF8e!_p;w_!a0{8Z3$BFnL?Yr7Q1hpt=AVL^cLwS|<0UAM z{3Jz1N%0$~>of~B@!wD}z6P~GuEp027C?pQL8y=oKzV8c%2Q84y?+MEBj=zteiiD( zzl0ip3zDlMasG>%l1fQQgg zbU*4vl$2@bxdk0l^MX6Dqh-5bd$U`c3BZXjx8Wa~T zLf=H+lK+R$1E>YvSo80nQ?nEKlfMQ6QJd9L!BV9G+jDr@6k~;@If%Zh5o8Z^c z5|mQX#nCs=LfK1YW7JU6=n6fKMo@q()Q0%G$P{I=N-bK8?oxyD2-=sa&EKx5n)!S; z(aA8J5%Aa0l0j7(ckht)Ce`%W^<)Vu8oH!+?_e~@dJ4SNZ9EHLe!7lfw$ zNazHn!yX)QrZ+8Fon2`AR+lprnyplN+~JXMdjG8(vsVq+Vd(frOt+VGL(jLOwl(6| zqv6Q()Y8paxpv$Nz0e*_znkA&>Ldft59qLh5$|!!Od-#8}5{?~=`%XfpM`KJ4N7CDuHCH%^F~_$<#!cV#x;2hb)5n+fWK}QNnQ#&w z=8pN^pc7z;38HO+BSGjS((e~kRORj7RoCMjb_3T-)@{L-7HfU|`o_A3`nvjitor(v z`g_v_g{A9yyrexE_pA;aW?T39^UXoEHnY5)bO-I&_>li-Y`{Jga{4myohaW` z)td>h6IiwtIE2e`v~k=EtfWW0T*dmG@<(>}M#1jHTX9b0C+wq6(pGpq(~VOy=djqw zzGoCV04H!G@Sc&=6wf*#S jD;lyU((kWW)wpnK(q(2^$Bz;QQ+;!@L4m8pvCV%0MAQlI delta 2643 zcmYk-e@xVM9LMp`DW-q|BH#}czWEEW?mR(6z>)(EK}j@4G$K#!8!pYguO_jBLx=hyr5 z`5uFz-)fSV^D~||lpVx$qI0w{PvMKV@j>}?oH5yW0kiO19D_rci9h2c{N1Z(@a0(Q zIXD@MFaraqc9otrSY}MpEaPGxH?|{vm_w+skD@vn@aiW}6Fh~vIEbZq38&#rEXK*q zat2mn5ZB@yd=z#61nT*Zu$=MD74LyemZ^>x-~?QTYGq&>>vLj#neGEs+W(1vQT z0X6eZtiT>r1`d0kL}l(QDkC3ba+EP&p)#_LylcUosB!Hi7wT{qYCs3o@BnJS=dc7{ zz;p_czRWpP2VdZw_#H09(R88-RH53}qxx_1>T6JMO*<-M$=zJc;o@<$@D0>!Hi)zE z8dl>3j`D0=fqH%?s-r^~#M4-YKcOa=Su}hIr+LmtO{f;<`-}-86HA(2He4%7pjQ5{ zSAPOE;6c0{-$MS(*L>*xzK#LRoWi7V2`aUZpbqDgsQ%tYW#j|TLDX~Kr)B?#xM0%e z8fxaZP_I=UFRM~C3w6H&HG!3=J>TMeANT49P+N2iHNlrr?cYOf!60fv-+1*QtYUm~ zl?%4dl<>2p(^`RK$JC=5Z1n6#4G=>Put}f})nlH|pawdEn!o^RrSIbc`~>IW4J=2C zlb%%STewieHq^>Ha1HK4t>CQZXQ<~dqMpBkn&2;}U&udE3%P;Xx@-;-$HxRw?N*?+ zVil@=`*ij{#6=fhD76EqRKJ5-;peC=xs05d^gT#7maB<5gtD-n(5iG+MwYo$HWE6d zO9-7AWucD9)$hOF;}yhaLMK`)(5iWDO(mhCRdx_9L@S}m-cM+o9w4+z6^l@+?;&al z6|H<^sivY=wq9Rq|GSAYRlK6qDNQxRy@bw$_HhTXj_4%xo1mZCk!9P63P&paPo@et zc;D;w)46CM<`Z`j$*p{Z2^G#ox~$?;@BV+~J}%aJ6`hYw#4@igwiE4MUFU$^N*Dbg z=~e6^^u{z2O@vKwL{x0kGkjsT;8KFOFa28&>C>)*xKb6$B0}dOqzYyEFy=vAOtcZr z#NC7mt!uOz`{Qvtns5iQ!kIBAVH)-(Y{v~{&rH>2-}0qeCsd6}oy@KFx!3a+yR{Qr z+_Mv_Q@QzVzT&ocY^U9w@HhAP+wHg$iA8Iz_DCY!>san9lM0&`*7$?f{$QmQtf{Ty zx-uBdS{-&0{`K*2)aeZ;V)0t5A>JR2S)pj6KWaPH((v#_pr^ODetTay(i`ZG^|@mU z-mL2IH`!4;KHRD)@qZUqWuUSm5X|cEx5ez9NW$L`cI=13i5<08AmFA7%H6iYLU(52 z9~tp(E9}lL>M9EL_p#z|+)CI{=lrX&;WejTEBevr{!@~jWA)gUy(h9Ya{f4X-Djul zNfl2$Hp=I?XNvu){OS9A?n^To-7zJb+*2j1QZq^meWgA2ZrkdMMI)?=o@0*XM55t{ TW9=p*5yx$|7W%r~eOAf8;HxYA diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/menuItem.js b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/menuItem.js index 47a60fb..cf112ab 100644 --- a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/menuItem.js +++ b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/menuItem.js @@ -21,18 +21,18 @@ export const MenuItem = GObject.registerClass({ this._gIcon = icon; // add icon - this.add(new St.Icon({ style_class: 'popup-menu-icon', gicon : this._gIcon })); + this.add_child(new St.Icon({ style_class: 'popup-menu-icon', gicon : this._gIcon })); // add label this._labelActor = new St.Label({ text: label }); - this.add(this._labelActor); + this.add_child(this._labelActor); // add value this._valueLabel = new St.Label({ text: value }); this._valueLabel.set_x_align(Clutter.ActorAlign.END); this._valueLabel.set_x_expand(true); this._valueLabel.set_y_expand(true); - this.add(this._valueLabel); + this.add_child(this._valueLabel); this.actor._delegate = this; } diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/metadata.json b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/metadata.json index 400c547..4c78f3a 100644 --- a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/metadata.json +++ b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/metadata.json @@ -1,13 +1,17 @@ { "_generated": "Generated by SweetTooth, do not edit", "description": "A glimpse into your computer's temperature, voltage, fan speed, memory usage, processor load, system resources, network speed and storage stats. This is a one stop shop to monitor all of your vital sensors. Uses asynchronous polling to provide a smooth user experience. Feature requests or bugs? Please use GitHub.", + "donations": { + "paypal": "corecoding" + }, "gettext-domain": "vitals", "name": "Vitals", "settings-schema": "org.gnome.shell.extensions.vitals", "shell-version": [ - "45" + "45", + "46" ], "url": "https://github.com/corecoding/Vitals", "uuid": "Vitals@CoreCoding.com", - "version": 63 + "version": 66 } \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/prefs.js b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/prefs.js index 8cace02..07916bd 100644 --- a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/prefs.js +++ b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/prefs.js @@ -48,7 +48,8 @@ const Settings = new GObject.Class({ 'show-network', 'show-storage', 'use-higher-precision', 'alphabetize', 'hide-zeros', 'include-public-ip', 'show-battery', 'fixed-widths', 'hide-icons', - 'menu-centered', 'include-static-info' ]; + 'menu-centered', 'include-static-info', + 'show-gpu', 'include-static-gpu-info' ]; for (let key in sensors) { let sensor = sensors[key]; @@ -61,7 +62,7 @@ const Settings = new GObject.Class({ } // process individual drop down sensor preferences - sensors = [ 'position-in-panel', 'unit', 'network-speed-format', 'memory-measurement', 'storage-measurement', 'battery-slot' ]; + sensors = [ 'position-in-panel', 'unit', 'network-speed-format', 'memory-measurement', 'storage-measurement', 'battery-slot', 'icon-style' ]; for (let key in sensors) { let sensor = sensors[key]; @@ -90,7 +91,7 @@ const Settings = new GObject.Class({ } // makes individual sensor preference boxes appear - sensors = [ 'temperature', 'network', 'storage', 'memory', 'battery', 'system', 'processor' ]; + sensors = [ 'temperature', 'network', 'storage', 'memory', 'battery', 'system', 'processor', 'gpu' ]; for (let key in sensors) { let sensor = sensors[key]; diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/prefs.ui b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/prefs.ui index 76d1473..ab07185 100644 --- a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/prefs.ui +++ b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/prefs.ui @@ -45,6 +45,7 @@ end + 5
@@ -146,6 +147,7 @@ 0 start 5 + 5 Seconds between updates
@@ -170,6 +172,7 @@ 100 0 + 0 0 @@ -181,6 +184,7 @@ 0 start 5 + 5 Position in panel @@ -217,12 +221,14 @@ 0 start 5 + 5 Use higher precision end + 5
@@ -244,12 +250,14 @@ 0 start 5 + 5 Alphabetize sensors
end + 5
@@ -271,12 +279,14 @@ 0 start 5 + 5 Hide zero values
end + 5
@@ -298,12 +308,14 @@ 0 start 5 + 5 Use fixed widths
end + 5 @@ -325,12 +337,14 @@ 0 start 5 + 5 Hide icons in top bar end + 5 @@ -352,49 +366,55 @@ 0 start 5 + 5 Menu always centered end + 5 + + + + + + + + + 100 + 0 + 0 + + + 0 + 6 + 6 + + + 1 + 0 + start + 5 + 5 + Icon style + + + + + 0 + 5 + 0 + + Original + GNOME + - - - - - - - - - - 0 - start - baseline - About - - - - - - - - 0 - - - 0 - start - baseline - 5 - Feature requests or bugs? Please visit <a href="https://github.com/corecoding/Vitals/issues">GitHub</a>. No warranty, expressed or implied. <a href="https://corecoding.com/donate.php">Donate</a> if you found this useful. - 1 - 1 - 0 @@ -427,423 +447,494 @@ 0 - - - 0 - - - 100 - 0 - - + + + 0 + + + 100 + 0 + + + 0 + center + 6 + 6 + + + 1 0 - center - 6 - 6 - - - 1 - 0 - start - 5 - Monitor temperature - - - - - 0 - 6 - - - 1 - center - center - - - 0 - emblem-system-symbolic - - - - - - - - end - center - - - - + start + 5 + 5 + Monitor temperature - - - - - - 100 - 0 - + + 0 - center - 6 - 6 + 6 - - 1 - 0 - start - 5 - Monitor voltage + + 1 + center + center + + + 0 + emblem-system-symbolic + + + - + end + center + 5 - + - - - - 100 - 0 - - - 0 - center - 6 - 6 - - - 1 - 0 - start - 5 - Monitor fan - - - - - end - - - - - - - - - 100 - 0 - - - 0 - center - 6 - 6 - - - 1 - 0 - start - 5 - Monitor memory - - - - - 0 - 6 - - - 1 - center - center - - - 0 - emblem-system-symbolic - - - - - - - - end - center - - - - - - - - - - - 100 - 0 - - - 0 - center - 6 - 6 - - - 1 - 0 - start - 5 - Monitor processor - - - - - 0 - 6 - - - 1 - center - center - - - 0 - emblem-system-symbolic - - - - - - - - end - center - - - - - - - - - - - 100 - 0 - - - 0 - center - 6 - 6 - - - 1 - 0 - start - 5 - Monitor system - - - - - 0 - 6 - - - 1 - center - center - - - 0 - emblem-system-symbolic - - - - - - - - end - center - - - - - - - - - - - 100 - 0 - - - 0 - center - 6 - 6 - - - 1 - 0 - start - 5 - Monitor network - - - - - 0 - 6 - - - 1 - center - center - - - 0 - emblem-system-symbolic - - - - - - - - end - center - - - - - - - - - - - 100 - 0 - - - 0 - center - 6 - 6 - - - 1 - 0 - start - 5 - Monitor storage - - - - - 0 - 6 - - - 1 - center - center - - - 0 - emblem-system-symbolic - - - - - - - - end - center - - - - - - - - - - - 100 - 0 - - - 0 - center - 6 - 6 - - - 1 - 0 - start - 5 - Monitor battery - - - - - 0 - 6 - - - 1 - center - center - - - 0 - emblem-system-symbolic - - - - - - - - end - center - - - - - - - - + + + + + 100 + 0 + + + 0 + center + 6 + 6 + + + 1 + 0 + start + 5 + 5 + Monitor voltage + + + + + end + 5 + + + + + + + + + 100 + 0 + + + 0 + center + 6 + 6 + + + 1 + 0 + start + 5 + 5 + Monitor fan + + + + + end + 5 + + + + + + + + + 100 + 0 + + + 0 + center + 6 + 6 + + + 1 + 0 + start + 5 + 5 + Monitor memory + + + + + 0 + 6 + + + 1 + center + center + + + 0 + emblem-system-symbolic + + + + + + + + end + center + 5 + + + + + + + + + + + 100 + 0 + + + 0 + center + 6 + 6 + + + 1 + 0 + start + 5 + 5 + Monitor processor + + + + + 0 + 6 + + + 1 + center + center + + + 0 + emblem-system-symbolic + + + + + + + + end + center + 5 + + + + + + + + + + + 100 + 0 + + + 0 + center + 6 + 6 + + + 1 + 0 + start + 5 + 5 + Monitor system + + + + + 0 + 6 + + + 1 + center + center + + + 0 + emblem-system-symbolic + + + + + + + + end + center + 5 + + + + + + + + + + + 100 + 0 + + + 0 + center + 6 + 6 + + + 1 + 0 + start + 5 + 5 + Monitor network + + + + + 0 + 6 + + + 1 + center + center + + + 0 + emblem-system-symbolic + + + + + + + + end + center + 5 + + + + + + + + + + + 100 + 0 + + + 0 + center + 6 + 6 + + + 1 + 0 + start + 5 + 5 + Monitor storage + + + + + 0 + 6 + + + 1 + center + center + + + 0 + emblem-system-symbolic + + + + + + + + end + center + 5 + + + + + + + + + + + 100 + 0 + + + 0 + center + 6 + 6 + + + 1 + 0 + start + 5 + 5 + Monitor battery + + + + + 0 + 6 + + + 1 + center + center + + + 0 + emblem-system-symbolic + + + + + + + + end + center + 5 + + + + + + + + + + + 100 + 0 + + + 0 + center + 6 + 6 + + + 1 + 0 + start + 5 + 5 + Monitor gpu (beta; NVIDIA only) + + + + + 0 + 6 + + + 1 + center + center + + + 0 + emblem-system-symbolic + + + + + + + + end + center + 5 + + + + + + + + + @@ -854,6 +945,44 @@ + + + start + 0 + 12 + 9 + 12 + About + + + + + + + + 0 + 6 + 6 + + + 0 + start + baseline + 5 + 5 + 5 + 5 + Feature requests or bugs? Please visit <a href="https://github.com/corecoding/Vitals/issues">GitHub</a>. No warranty, expressed or implied. <a href="https://corecoding.com/donate.php">Donate</a> if you found this useful. + 1 + 1 + 0 + + + + + + + 1 @@ -1197,6 +1326,57 @@ end + 5 + + + + + + + + + + + + + 0 + 12 + 12 + 6 + 6 + vertical + + + 0 + + + 0 + none + + + 100 + 1 + 0 + + + 0 + 6 + 6 + 6 + 6 + 12 + + + 1 + 0 + start + Include static GPU info + + + + + end + 5 diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/schemas/gschemas.compiled b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/schemas/gschemas.compiled index 7f4d0c0245fb00f704dd9dffffc261d44f72d7a1..936fdb3a506ffb8d2405e995628fbde747e729c0 100644 GIT binary patch literal 1972 zcmZWqUuYaf93C~bHEEh_`p>A<7EvzB+z~1|PRe;k)nKZ)azIzu)Zq z?zxxzEc6pA%IkjcbfK$vm)>3A8?_(D$$WNHoD%22eSJdgI3UCwTq`?ai08#B_;WyK z?OHq0v8tIsMNv(4tV&F%6H}WFtsfZ<7ovK^kr14l>k;<=m|Aek9{Qn)ff9q@J-}XI zAFv-dSmF?vd5n~J0Q}%K9EK(yF7e&@HwKu4%SX(L3Kky+j$U~B$$K$|x&r?c_yypn zM6J-L-VZ+jr$B40(WOs40RK(!Md0el(mDFneef@V7l6t9+8llA-SC&eE5K$=pX$(ti5XtbYf59$0-V_=`UEA@~d6 zMc|M5W3CR=gYZ|uUjVNi-xvltJq&*hH`jp=ZvQexpL!4cAHY8Y-!CoFa+>jQvA==* z!iO$jYWfv?v!x%5&!Y5MrNw_r> z1ojB_6rTSIa38>P&pyH)z@D)SV2@xAVm$0E>>)gU>_x*s5Vn*Io9JJ-aToG+K^m*G zGD!F?PUp|~N$)<;RvNTFof$7yvCg_)Zt#vLJkvF(qZetv<&DKKyj~Hrju-nK&l5vO zj)|&oiq(qO%XJu!G`1TRwPbzEXk@H>gN=z*+1i;KpT`=7)|qU^Ejq$&wJf5Lk<_;D Zqul5J`KW^Pu%7$q=2fN{9PZ1p{{VT+hkyV8 literal 1780 zcmZ8hPiP%Q9G+@pYtxuCtu<8xDWbfm?0XHB*djtff*w2sG@@RXdGAfKqq{rn&TR4$ ztMpKzik`d_G{l<)seevN1<57YV-8ZhiFheOQw62uRKIU#pJ`qA_`dh;yqVwpX7+pG zRat78J5fIq;Mam~+*5mdz}H&8&5-%-xOh>V1%Gp|5JL|NaU0K#`(TKd#Gl~50aGrv z7ITxSmQ7Tewp8D#+-j5C){=HIwHz))V=}PdTEt#p2-sI+KlpxN7#OKB3MR&C90HHu zfy2-b0o=;~$Dkhu9swQ&wqJhi75rd~{r)E7Dz#jvR zeepJZ>izI9g4clGb9I?M^%3~rgExqG-y7z6P!GYs3f=~;U-|Acj;H4QZ1NEBZ1;%< zedia{@dM<+3fWdvD=6(8{?{S}Qu1{a%Jk%UN0iFVWUSHetb=Lj~@C#-~JsSjZM8SpId)$_O8^r?9+bKrU4)`veHrB8hrege*bk)6>deQNsWz!!ko>ZfJ; z)V_Z38t{?%;0^lJoc|K|GVspK&T0D8?DGbA6X;EMR_If6{1*5Z;MZ#Q2l~{k|2p^v zU=y<(b)<8uT)}HRjZQN$F0%N%OljjxWu{z-D=QaOEMmK2oyy|W$X-01!H9F^mQDFq zRQBUc_TyNLPMs7DX`6oPFkXl~oVUvLf5G6F(#_1kGiB7xdVY2PjYr{MQT-A%*=DFC z%9ONKsWMeZ3^PPDbXcq|g_d8>SFj-S!S6w-wos}UEtoQs|F5T2NS9!I8-dgI#k76k zw08ri9RjC~=7lYyel&-x*6S9=YKLr!bRHElS82#1)>&B>;!4D8SEzxromi`M^6A9_A-A4_5}?Bkxey6LXW9$b4i@BHnx^9t79dDzd2w zZRRrG-;U>DLBHcxr`~AwaNMuJjy{h~^b>2-YjId5R-9=XyOz2BJ*&UbS yuKTcLQdghMZok4sx@+E|>ZF{v7~IpMC!LC%&J_E>bMqChs?rP^%5&j6JpTd@+h;TY diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/schemas/org.gnome.shell.extensions.vitals.gschema.xml b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/schemas/org.gnome.shell.extensions.vitals.gschema.xml index 71e4935..7a0decd 100644 --- a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/schemas/org.gnome.shell.extensions.vitals.gschema.xml +++ b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/schemas/org.gnome.shell.extensions.vitals.gschema.xml @@ -136,5 +136,20 @@ Include processor static information Display processor static information that doesn't change + + false + Monitor GPU + Display GPU information (requires the nvidia-smi tool) + + + false + Include GPU static information + Display GPU static information that doesn't change + + + 0 + Icon styles + Set the style for the displayed sensor icons ('original', 'updated') + diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/sensors.js b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/sensors.js index 39d175a..2ba8c2e 100644 --- a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/sensors.js +++ b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/sensors.js @@ -25,6 +25,7 @@ */ import GObject from 'gi://GObject'; +import * as SubProcessModule from './helpers/subprocess.js'; import * as FileModule from './helpers/file.js'; import { gettext as _ } from 'resource:///org/gnome/shell/extensions/extension.js'; import NM from 'gi://NM'; @@ -48,6 +49,15 @@ export const Sensors = GObject.registerClass({ this._last_processor = { 'core': {}, 'speed': [] }; + this._settingChangedSignals = []; + this._addSettingChangedSignal('show-gpu', this._reconfigureNvidiaSmiProcess.bind(this)); + this._addSettingChangedSignal('update-time', this._reconfigureNvidiaSmiProcess.bind(this)); + //this._addSettingChangedSignal('include-static-gpu-info', this._reconfigureNvidiaSmiProcess.bind(this)); + + this._nvidia_smi_process = null; + this._nvidia_labels = []; + this._bad_split_count = 0; + if (hasGTop) { this.storage = new GTop.glibtop_fsusage(); this._storageDevice = ''; @@ -58,6 +68,10 @@ export const Sensors = GObject.registerClass({ } } + _addSettingChangedSignal(key, callback) { + this._settingChangedSignals.push(this._settings.connect('changed::' + key, callback)); + } + _refreshIPAddress(callback) { // check IP address new FileModule.File('https://corecoding.com/vitals.php').read().then(contents => { @@ -473,6 +487,166 @@ export const Sensors = GObject.registerClass({ }).catch(err => { }); } + _queryGpu(callback) { + if (!this._nvidia_smi_process) { + this._disableGpuLabels(callback); + return; + } + + this._nvidia_smi_process.read('\n').then(lines => { + /// for debugging multi-gpu on systems with only one gpu + /// duplicates the first gpu's data 3 times, for 4 total gpus + ///if(lines.length == 0) return; + ///for(let _gpuNum = 1; _gpuNum <= 3; _gpuNum++) + /// lines.push(lines[0]); + + for (let i = 0; i < lines.length; i++) { + this._parseNvidiaSmiLine(callback, lines[i], i + 1, lines.length > 1); + } + + + // if we've already updated the static info during the last parse, then stop doing so. + // this is so the _parseNvidiaSmiLine function won't return static info anymore + // and the nvidia-smi commmand won't be queried for static info either + if(!this._nvidia_static_returned) { + this._nvidia_static_returned = true; + //reconfigure the process to stop querying static info + this._reconfigureNvidiaSmiProcess(); + } + }).catch(err => { + this._disableGpuLabels(callback); + this._terminateNvidiaSmiProcess(); + }); + } + + _parseNvidiaSmiLine(callback, csv, gpuNum, multiGpu) { + const expectedSplitLength = 19; + let csv_split = csv.split(','); + + // occasionally the nvidia-smi command can get cut off before it can be fully read, thus the parse function only gets part of a line + // hence we count the number of bad splits and only terminate the process after a few bad splits in a row + // this prevents anomalous readings from terminating the process + if (csv_split.length < expectedSplitLength) { + this._bad_split_count++; + //if we've had 2 bad splits/reads in a row, try to restart the process + if (this._bad_split_count == 2) this._reconfigureNvidiaSmiProcess(); + //if we still get a bad read after that, then it's not an anomaly; terminate the process + else if (this._bad_split_count >= 3) this._terminateNvidiaSmiProcess(); + return; + } + this._bad_split_count = 0; + + let [ + label, + fan_speed_pct, + temp_gpu, temp_mem, + mem_total, mem_used, mem_reserved, mem_free, + util_gpu, util_mem, util_encoder, util_decoder, + clock_gpu, clock_mem, clock_encode_decode, + power, power_avg, + link_gen_current, link_width_current + ] = csv_split; + + const staticNames = [ + 'temp_limit', 'power_limit', + 'link_gen_max', 'link_width_max', + 'addressing_mode', + 'driver_version', 'vbios', 'serial', + 'domain_num', 'bus_num', 'device_num', 'device_id', 'sub_device_id' + ]; + let staticInfo = {}; + + // if we have queried static info this time around, populate our static info object + if(csv_split.length == (expectedSplitLength + staticNames.length)){ + for(let i = 0; i < staticNames.length; i++) { + //set the static info to a default (0) if it's undefined + const value = csv_split[expectedSplitLength + i]; + staticInfo[staticNames[i]] = (typeof value !== "undefined") ? value : 0; + } + } + + + const typeName = 'gpu#' + gpuNum; + const globalLabel = 'GPU' + (multiGpu ? ' ' + gpuNum : ''); + + const memTempValid = !isNaN(parseInt(temp_mem)); + + + this._returnGpuValue(callback, 'Graphics', parseInt(util_gpu) * 0.01, typeName + '-group', 'percent'); + + this._returnGpuValue(callback, 'Name', label, typeName, ''); + + this._returnGpuValue(callback, globalLabel, parseInt(fan_speed_pct) * 0.01, 'fan', 'percent'); + this._returnGpuValue(callback, 'Fan', parseInt(fan_speed_pct) * 0.01, typeName, 'percent'); + + this._returnGpuValue(callback, globalLabel, parseInt(temp_gpu) * 1000, 'temperature', 'temp'); + this._returnGpuValue(callback, 'Temperature', parseInt(temp_gpu) * 1000, typeName, 'temp'); + this._returnGpuValue(callback, 'Memory Temperature', parseInt(temp_mem) * 1000, typeName, 'temp', memTempValid); + this._returnStaticGpuValue(callback, 'Temperature Limit', parseInt(staticInfo['temp_limit']) * 1000, typeName, 'temp'); + + this._returnGpuValue(callback, 'Memory Usage', parseInt(mem_used) / parseInt(mem_total), typeName, 'percent'); + this._returnGpuValue(callback, 'Memory Total', parseInt(mem_total) * 1000, typeName, 'memory'); + this._returnGpuValue(callback, 'Memory Used', parseInt(mem_used) * 1000, typeName, 'memory'); + this._returnGpuValue(callback, 'Memory Reserved', parseInt(mem_reserved) * 1000, typeName, 'memory'); + this._returnGpuValue(callback, 'Memory Free', parseInt(mem_free) * 1000, typeName, 'memory'); + + this._returnGpuValue(callback, 'Memory Utilization', parseInt(util_mem) * 0.01, typeName, 'percent'); + this._returnGpuValue(callback, 'Utilization', parseInt(util_gpu) * 0.01, typeName, 'percent'); + this._returnGpuValue(callback, 'Encoder Utilization', parseInt(util_encoder) * 0.01, typeName, 'percent'); + this._returnGpuValue(callback, 'Decoder Utilization', parseInt(util_decoder) * 0.01, typeName, 'percent'); + + this._returnGpuValue(callback, 'Frequency', parseInt(clock_gpu) * 1000 * 1000, typeName, 'hertz'); + this._returnGpuValue(callback, 'Memory Frequency', parseInt(clock_mem) * 1000 * 1000, typeName, 'hertz'); + this._returnGpuValue(callback, 'Encoder/Decoder Frequency', parseInt(clock_encode_decode) * 1000 * 1000, typeName, 'hertz'); + + //this._returnGpuValue(callback, 'Encoder Sessions', parseInt(encoder_sessions), typeName, 'string'); + + this._returnGpuValue(callback, 'Power', power, typeName, 'watt-gpu'); + this._returnGpuValue(callback, 'Average Power', power_avg, typeName, 'watt-gpu'); + this._returnStaticGpuValue(callback, 'Power Limit', parseInt(staticInfo['power_limit']), typeName, 'watt-gpu'); + + this._returnGpuValue(callback, 'Link Speed', link_gen_current + 'x' + link_width_current, typeName, 'pcie'); + this._returnStaticGpuValue(callback, 'Maximum Link Speed', staticInfo['link_gen_max'] + 'x' + staticInfo['link_width_max'], typeName, 'pcie'); + + this._returnStaticGpuValue(callback, 'Addressing Mode', staticInfo['addressing_mode'], typeName, 'string'); + + this._returnStaticGpuValue(callback, 'Driver Version', staticInfo['driver_version'], typeName, 'string'); + this._returnStaticGpuValue(callback, 'vBIOS Version', staticInfo['vbios'], typeName, 'string'); + this._returnStaticGpuValue(callback, 'Serial Number', staticInfo['serial'], typeName, 'string'); + + this._returnStaticGpuValue(callback, 'Domain Number', staticInfo['domain_num'], typeName, 'string'); + this._returnStaticGpuValue(callback, 'Bus Number', staticInfo['bus_num'], typeName, 'string'); + this._returnStaticGpuValue(callback, 'Device Number', staticInfo['device_num'], typeName, 'string'); + this._returnStaticGpuValue(callback, 'Device ID', staticInfo['device_id'], typeName, 'string'); + this._returnStaticGpuValue(callback, 'Sub Device ID', staticInfo['sub_device_id'], typeName, 'string'); + } + + _disableGpuLabels(callback) { + for (let labelObj of this._nvidia_labels) + this._returnValue(callback, labelObj.label, 'disabled', labelObj.type, labelObj.format); + } + + _returnStaticGpuValue(callback, label, value, type, format) { + //if we've already tried to return existing static info before or if the option isn't enabled, then do nothing. + if (this._nvidia_static_returned || !this._settings.get_boolean('include-static-gpu-info')) + return; + + //we don't need to disable static info labels, so just use ordinary returnValue function + this._returnValue(callback, label, value, type, format); + } + + _returnGpuValue(callback, label, value, type, format, display = true) { + if(!display) return; + + if(value === 'N/A' || value === '[N/A]' || isNaN(value)) return; + + let nvidiaLabel = {'label': label, 'type': type, 'format': format}; + if (!this._nvidia_labels.includes(nvidiaLabel)) + this._nvidia_labels.push(nvidiaLabel); + + this._returnValue(callback, label, value, type, format); + } + _returnValue(callback, label, value, type, format) { // don't return if value is not a number - will revisit later //if (isNaN(value)) return; @@ -564,6 +738,74 @@ export const Sensors = GObject.registerClass({ this._returnValue(callback, 'Kernel', kernelArray[2], 'system', 'string'); }).catch(err => { }); } + + // Launch nvidia-smi subprocess if nvidia querying is enabled + this._reconfigureNvidiaSmiProcess(); + } + + // The nvidia-smi subprocess will keep running and print new sensor data to stdout every + // `update_time` seconds. _queryNvidiaSmi() will be called at roughly the same interval and + // read from the subprocess's stdout to get new sensor data. + + // Regarding "keeping main process & sub process in sync", there are two possible scenarios: + // - For some reason, nvidia-smi prints at a somewhat higher frequency than we call + // _queryNvidiaSmi() to read data. This is okay, eventually one call to _queryNvidiaSmi() + // will read two sensor data updates in a single call. + // - For some reason, _queryNvidiaSmi() is called at a somewhat higher frequency than + // nvidia-smi prints data. This is the more likely scenario with user actions triggering + // additional reads. This eventually triggers an "IO PENDING" error while attempting to + // read, because the previous async read is still waiting. To solve this, the subprocess + // module simply ignores PENDING errors. After ignoring the error, the earlier read will + // eventually return and sensor data will be updated, so this scenario is handled correctly. + + // Generally speaking, the call to _queryNvidiaSmi() and nvidia-smi's printing to stdout do + // not happen at the same time. So the async call in _queryNvidiaSmi() will usually have to + // wait up to `update_time` seconds before getting any results and reporting them through the + // callback. + _reconfigureNvidiaSmiProcess() { + if (this._settings.get_boolean('show-gpu')) { + this._terminateNvidiaSmiProcess(); + + try { + let update_time = this._settings.get_int('update-time'); + let query_interval = Math.max(update_time, 1); + let command = [ + 'nvidia-smi', + '--query-gpu=name,' + + 'fan.speed,' + + 'temperature.gpu,temperature.memory,' + + 'memory.total,memory.used,memory.reserved,memory.free,' + + 'utilization.gpu,utilization.memory,utilization.encoder,utilization.decoder,' + + 'clocks.gr,clocks.mem,clocks.video,' + + 'power.draw.instant,power.draw.average,' + + 'pcie.link.gen.gpucurrent,pcie.link.width.current,' + + (!this._nvidia_static_returned && this._settings.get_boolean('include-static-gpu-info') ? + 'temperature.gpu.tlimit,' + + 'power.limit,' + + 'pcie.link.gen.max,pcie.link.width.max,' + + 'addressing_mode,'+ + 'driver_version,vbios_version,serial,' + + 'pci.domain,pci.bus,pci.device,pci.device_id,pci.sub_device_id,' + : ''), + '--format=csv,noheader,nounits', + '-l', query_interval.toString() + ]; + + this._nvidia_smi_process = new SubProcessModule.SubProcess(command); + } catch(e) { + // proprietary nvidia driver not installed + this._terminateNvidiaSmiProcess(); + } + } else { + this._terminateNvidiaSmiProcess(); + } + } + + _terminateNvidiaSmiProcess() { + if (this._nvidia_smi_process) { + this._nvidia_smi_process.terminate(); + this._nvidia_smi_process = null; + } } _processTempVoltFan(callback, sensor_types, name, path, file) { @@ -664,8 +906,18 @@ export const Sensors = GObject.registerClass({ resetHistory() { this._next_public_ip_check = 0; this._hardware_detected = false; + this._nvidia_static_returned = false; this._processor_uses_cpu_info = true; this._battery_time_left_history = []; this._battery_charge_status = ''; + this._nvidia_labels = []; + this._bad_split_count = 0; + } + + destroy() { + this._terminateNvidiaSmiProcess(); + + for (let signal of Object.values(this._settingChangedSignals)) + this._settings.disconnect(signal); } }); diff --git a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/values.js b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/values.js index 77c47f1..a7cabb0 100644 --- a/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/values.js +++ b/gnome/.local/share/gnome-shell/extensions/Vitals@CoreCoding.com/values.js @@ -190,6 +190,10 @@ export const Values = GObject.registerClass({ value = value / 1000000; ending = 'W'; break; + case 'watt-gpu': + format = (use_higher_precision)?'%.2f %s':'%.1f %s'; + ending = 'W'; + break; case 'watt-hour': format = (use_higher_precision)?'%.2f %s':'%.1f %s'; value = value / 1000000; @@ -198,6 +202,11 @@ export const Values = GObject.registerClass({ case 'load': format = (use_higher_precision)?'%.2f %s':'%.1f %s'; break; + case 'pcie': + let split = value.split('x'); + value = 'PCIe ' + parseInt(split[0]) + (split.length > 1 ? ' x' + parseInt(split[1]) : ''); + format = '%s'; + break; default: format = '%s'; break; @@ -324,14 +333,22 @@ export const Values = GObject.registerClass({ return output; } - resetHistory() { + resetHistory(numGpus) { // don't call this._history = {}, as we want to keep network-rx and network-tx // otherwise network history statistics will start over for (let sensor in this._sensorIcons) { + //each gpu has it's own sensor name and thus must be handled separately + if(sensor === 'gpu') continue; + this._history[sensor] = {}; this._history[sensor + '-group'] = {}; //this._history2[sensor] = {}; //this._history2[sensor + '-group'] = {}; } + + for(let i = 1; i <= numGpus; i++){ + this._history['gpu#' + i] = {}; + this._history['gpu#' + i + '-group'] = {}; + } } }); diff --git a/gnome/.local/share/gnome-shell/extensions/auto-activities@CleoMenezesJr.github.io/metadata.json b/gnome/.local/share/gnome-shell/extensions/auto-activities@CleoMenezesJr.github.io/metadata.json index c57a2f7..230b379 100644 --- a/gnome/.local/share/gnome-shell/extensions/auto-activities@CleoMenezesJr.github.io/metadata.json +++ b/gnome/.local/share/gnome-shell/extensions/auto-activities@CleoMenezesJr.github.io/metadata.json @@ -11,9 +11,11 @@ "original-author": "mi-jan-sena@proton.me", "settings-schema": "org.gnome.shell.extensions.auto-activities", "shell-version": [ - "45" + "45", + "46" ], "url": "https://github.com/CleoMenezesJr/auto-activities", "uuid": "auto-activities@CleoMenezesJr.github.io", - "version": 12 + "version": 13, + "version-name": "46.1" } \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/block-caribou-36@lxylxy123456.ercli.dev/extension.js b/gnome/.local/share/gnome-shell/extensions/block-caribou-36@lxylxy123456.ercli.dev/extension.js deleted file mode 100644 index fb9e0f9..0000000 --- a/gnome/.local/share/gnome-shell/extensions/block-caribou-36@lxylxy123456.ercli.dev/extension.js +++ /dev/null @@ -1,28 +0,0 @@ -import * as KeyboardUI from 'resource:///org/gnome/shell/ui/keyboard.js'; - -function _modifiedLastDeviceIsTouchscreen() { - return false; -} - -export default class BlockCaribou { - constructor() { - this._originalLastDeviceIsTouchscreen = null; - } - - enable() { - this._originalLastDeviceIsTouchscreen = KeyboardUI.KeyboardManager.prototype._lastDeviceIsTouchscreen; - KeyboardUI.KeyboardManager.prototype._lastDeviceIsTouchscreen = _modifiedLastDeviceIsTouchscreen; - } - - /* - * In the lock screen, the on-screen keyboard (Caribou) also pops up by - * default. So this extension requires the "unlock-dialog" session mode to - * block Caribou in lock screen. - */ - disable() { - if (this._originalLastDeviceIsTouchscreen !== null) { - KeyboardUI.KeyboardManager.prototype._lastDeviceIsTouchscreen = this._originalLastDeviceIsTouchscreen; - this._originalLastDeviceIsTouchscreen = null; - } - } -} diff --git a/gnome/.local/share/gnome-shell/extensions/block-caribou-36@lxylxy123456.ercli.dev/metadata.json b/gnome/.local/share/gnome-shell/extensions/block-caribou-36@lxylxy123456.ercli.dev/metadata.json deleted file mode 100644 index 730bd6a..0000000 --- a/gnome/.local/share/gnome-shell/extensions/block-caribou-36@lxylxy123456.ercli.dev/metadata.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "_generated": "Generated by SweetTooth, do not edit", - "description": "Blocks caribou (the on screen keyboard) from popping up when you use a touchscreen. Even if it's disabled in the accessibility services menu. Continuation of keringar's work. Tested on GNOME Shell version 3.36 - 45 on Fedora 32 - 39. For a higher version see https://github.com/lxylxy123456/cariboublocker#installing-on-high-gnome-shell-version .", - "name": "Block Caribou 36", - "session-modes": [ - "unlock-dialog", - "user" - ], - "shell-version": [ - "45" - ], - "url": "https://github.com/lxylxy123456/cariboublocker", - "uuid": "block-caribou-36@lxylxy123456.ercli.dev", - "version": 10 -} \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/appfolders.js b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/appfolders.js index cabce01..d16f32b 100644 --- a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/appfolders.js +++ b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/appfolders.js @@ -37,11 +37,11 @@ let _zoomAndFadeIn = function () { let blur_effect = this.get_effect("appfolder-blur"); - blur_effect.sigma = 0; + blur_effect.radius = 0; blur_effect.brightness = 1.0; Tweener.addTween(blur_effect, { - sigma: sigma, + radius: sigma * 2, brightness: brightness, time: FOLDER_DIALOG_ANIMATION_TIME / 1000, transition: 'easeOutQuad' @@ -85,7 +85,7 @@ let _zoomAndFadeOut = function () { let blur_effect = this.get_effect("appfolder-blur"); Tweener.addTween(blur_effect, { - sigma: 0, + radius: 0, brightness: 1.0, time: FOLDER_DIALOG_ANIMATION_TIME / 1000, transition: 'easeInQuad' @@ -165,7 +165,7 @@ export const AppFoldersBlur = class AppFoldersBlur { let blur_effect = new Shell.BlurEffect({ name: "appfolder-blur", - sigma: sigma, + radius: sigma * 2, brightness: brightness, mode: Shell.BlurMode.BACKGROUND }); diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/applications.js b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/applications.js index 8334473..1a454ca 100644 --- a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/applications.js +++ b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/applications.js @@ -1,18 +1,20 @@ import Shell from 'gi://Shell'; import Clutter from 'gi://Clutter'; import Meta from 'gi://Meta'; +import Gio from 'gi://Gio'; import * as Main from 'resource:///org/gnome/shell/ui/main.js'; import { PaintSignals } from '../effects/paint_signals.js'; import { ApplicationsService } from '../dbus/services.js'; - export const ApplicationsBlur = class ApplicationsBlur { constructor(connections, settings, _) { this.connections = connections; this.settings = settings; this.paint_signals = new PaintSignals(connections); + this.mutter_gsettings = new Gio.Settings({ schema: 'org.gnome.mutter' }); + // stores every blurred window this.window_map = new Map(); // stores every blur actor @@ -67,14 +69,11 @@ export const ApplicationsBlur = class ApplicationsBlur { this.connections.connect( Main.overview, 'hidden', _ => { - let active_workspace = - global.workspace_manager.get_active_workspace(); - this.window_map.forEach((meta_window, _pid) => { let window_actor = meta_window.get_compositor_private(); if ( - meta_window.get_workspace() !== active_workspace + !meta_window.get_workspace().active ) window_actor.hide(); }); @@ -325,7 +324,7 @@ export const ApplicationsBlur = class ApplicationsBlur { /// Add the blur effect to the window. create_blur_effect(pid, window_actor, meta_window, brightness, sigma) { let blur_effect = new Shell.BlurEffect({ - sigma: sigma, + radius: sigma * 2, brightness: brightness, mode: Shell.BlurMode.BACKGROUND }); @@ -420,13 +419,15 @@ export const ApplicationsBlur = class ApplicationsBlur { } /// Compute the size and position for a blur actor. - /// On wayland, it seems like we need to divide by the scale to get the - /// correct result. + /// If `scale-monitor-framebuffer` experimental feature if on, we don't need to manage scaling. + /// Else, on wayland, we need to divide by the scale to get the correct result. compute_allocation(meta_window) { + const scale_monitor_framebuffer = this.mutter_gsettings.get_strv('experimental-features') + .includes('scale-monitor-framebuffer'); const is_wayland = Meta.is_wayland_compositor(); const monitor_index = meta_window.get_monitor(); // check if the window is using wayland, or xwayland/xorg for rendering - const scale = is_wayland && meta_window.get_client_type() == 0 + const scale = !scale_monitor_framebuffer && is_wayland && meta_window.get_client_type() == 0 ? Main.layoutManager.monitors[monitor_index].geometry_scale : 1; @@ -464,7 +465,7 @@ export const ApplicationsBlur = class ApplicationsBlur { /// Updates the blur effect by overwriting its sigma and brightness values. update_blur_effect(blur_actor, brightness, sigma) { let effect = blur_actor.get_effect('blur-effect'); - effect.sigma = sigma; + effect.radius = sigma * 2; effect.brightness = brightness; } @@ -500,6 +501,7 @@ export const ApplicationsBlur = class ApplicationsBlur { this._log("removing blur from applications..."); this.service?.unexport(); + delete this.mutter_gsettings; this.blur_actor_map.forEach(((_blur_actor, pid) => { this.remove_blur(pid); @@ -545,4 +547,4 @@ export const ApplicationsBlur = class ApplicationsBlur { if (this.settings.DEBUG) console.log(`[Blur my Shell > applications] ${str}`); } -}; \ No newline at end of file +}; diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/dash_to_dock.js b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/dash_to_dock.js index 3c56588..7d84c23 100644 --- a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/dash_to_dock.js +++ b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/dash_to_dock.js @@ -1,9 +1,12 @@ import St from 'gi://St'; import Shell from 'gi://Shell'; +import Meta from 'gi://Meta'; +import Mtk from 'gi://Mtk'; import * as Main from 'resource:///org/gnome/shell/ui/main.js'; const Signals = imports.signals; import { PaintSignals } from '../effects/paint_signals.js'; +import { BlurEffect } from '../effects/blur_effect.js'; const DASH_STYLES = [ "transparent-dash", @@ -12,72 +15,191 @@ const DASH_STYLES = [ ]; +// An helper function to find the monitor in which an actor is situated, +/// there might be a pre-existing function in GLib already +function find_monitor_for(actor) { + let extents = actor.get_transformed_extents(); + let rect = new Mtk.Rectangle({ + x: extents.get_x(), + y: extents.get_y(), + width: extents.get_width(), + height: extents.get_height(), + }); + + let index = global.display.get_monitor_index_for_rect(rect); + + return Main.layoutManager.monitors[index]; +} + + /// This type of object is created for every dash found, and talks to the main /// DashBlur thanks to signals. /// /// This allows to dynamically track the created dashes for each screen. class DashInfos { - constructor(dash_blur, dash, background_parent, effect, settings) { + constructor(dash_blur, dash, dash_container, dash_background, background, background_parent, effect) { // the parent DashBlur object, to communicate this.dash_blur = dash_blur; + this.dash_container = dash_container; // the blurred dash this.dash = dash; + this.dash_background = dash_background; this.background_parent = background_parent; + this.background = background; this.effect = effect; - this.settings = settings; + this.settings = dash_blur.settings; this.old_style = this.dash._background.style; dash_blur.connections.connect(dash_blur, 'remove-dashes', () => { this._log("removing blur from dash"); this.dash.get_parent().remove_child(this.background_parent); - this.dash._background.style = this.old_style; - - DASH_STYLES.forEach( - style => this.dash.remove_style_class_name(style) - ); + this.remove_style(); }); dash_blur.connections.connect(dash_blur, 'update-sigma', () => { - this.effect.sigma = this.dash_blur.sigma; + if (this.dash_blur.is_static) { + this.dash_blur.update_size(); + } + this.effect.radius = 2 * this.dash_blur.sigma * this.effect.scale; }); dash_blur.connections.connect(dash_blur, 'update-brightness', () => { this.effect.brightness = this.dash_blur.brightness; }); - dash_blur.connections.connect(dash_blur, 'override-background', () => { - this.dash._background.style = null; + dash_blur.connections.connect(dash_blur, 'update-corner-radius', () => { + if (this.dash_blur.is_static) { + let monitor = find_monitor_for(this.dash); + let corner_radius = this.dash_blur.corner_radius * monitor.geometry_scale; + this.effect.corner_radius = Math.min( + corner_radius, this.effect.width / 2, this.effect.height / 2 + ); + } + }); - DASH_STYLES.forEach( - style => this.dash.remove_style_class_name(style) - ); + dash_blur.connections.connect(dash_blur, 'override-background', () => { + this.remove_style(); this.dash.set_style_class_name( DASH_STYLES[this.settings.dash_to_dock.STYLE_DASH_TO_DOCK] ); }); - dash_blur.connections.connect(dash_blur, 'reset-background', () => { - this.dash._background.style = this.old_style; - - DASH_STYLES.forEach( - style => this.dash.remove_style_class_name(style) - ); - }); + dash_blur.connections.connect(dash_blur, 'reset-background', () => this.remove_style()); dash_blur.connections.connect(dash_blur, 'show', () => { - this.effect.sigma = this.dash_blur.sigma; + if (this.dash_blur.is_static) + this.background_parent.show(); + else + this.effect.radius = this.dash_blur.sigma * 2 * this.effect.scale; }); dash_blur.connections.connect(dash_blur, 'hide', () => { - this.effect.sigma = 0; + if (this.dash_blur.is_static) + this.background_parent.hide(); + else + this.effect.radius = 0; }); + + dash_blur.connections.connect(dash_blur, 'update-wallpaper', () => { + if (this.dash_blur.is_static) { + let bg = Main.layoutManager._backgroundGroup.get_child_at_index( + Main.layoutManager.monitors.length + - find_monitor_for(this.dash).index - 1 + ); + if (bg && bg.get_content()) { + this.background.content.set({ + background: bg.get_content().background + }); + this._log('wallpaper updated'); + } else { + this._warn("could not get background for dash-to-dock"); + } + } + }); + + dash_blur.connections.connect(dash_blur, 'update-size', () => { + if (this.dash_blur.is_static) { + let [x, y] = this.get_dash_position(this.dash_container, this.dash_background); + + this.background.x = -x; + this.background.y = -y; + + this.effect.width = this.dash_background.width; + this.effect.height = this.dash_background.height; + + this.dash_blur.set_corner_radius(this.dash_blur.corner_radius); + + if (dash_container.get_style_class_name().includes("top")) { + this.background.set_clip(x, y + this.dash.y + this.dash_background.y, this.dash_background.width, this.dash_background.height); + } else if (dash_container.get_style_class_name().includes("bottom")) { + this.background.set_clip(x, y + this.dash.y + this.dash_background.y, this.dash_background.width, this.dash_background.height); + } else if (dash_container.get_style_class_name().includes("left")) { + this.background.set_clip(x + this.dash.x + this.dash_background.x, y + this.dash.y + this.dash_background.y, this.dash_background.width, this.dash_background.height); + } else if (dash_container.get_style_class_name().includes("right")) { + this.background.set_clip(x + this.dash.x + this.dash_background.x, y + this.dash.y + this.dash_background.y, this.dash_background.width, this.dash_background.height); + } + } else { + this.background.width = this.dash_background.width; + this.background.height = this.dash_background.height; + + this.background.x = this.dash_background.x; + this.background.y = this.dash_background.y + this.dash.y; + } + }); + + dash_blur.connections.connect(dash_blur, 'change-blur-type', () => { + this.background_parent.remove_child(this.background); + if (this.effect.chained_effect) + this.effect.get_actor()?.remove_effect(this.effect.chained_effect); + this.effect.get_actor()?.remove_effect(this.effect); + + let [background, effect] = this.dash_blur.add_blur(this.dash, this.dash_background, this.dash_container); + this.background = background; + this.effect = effect; + this.background_parent.add_child(this.background); + }); + } + + remove_style() { + this.dash._background.style = this.old_style; + + DASH_STYLES.forEach( + style => this.dash.remove_style_class_name(style) + ); + } + + get_dash_position(dash_container, dash_background) { + var x, y; + + let monitor = find_monitor_for(dash_container); + let dash_box = dash_container._slider.get_child(); + + if (dash_container.get_style_class_name().includes("top")) { + x = (monitor.width - dash_background.width) / 2; + y = dash_box.y; + } else if (dash_container.get_style_class_name().includes("bottom")) { + x = (monitor.width - dash_background.width) / 2; + y = monitor.height - dash_container.height; + } else if (dash_container.get_style_class_name().includes("left")) { + x = dash_box.x; + y = dash_container.y + (dash_container.height - dash_background.height) / 2 - dash_background.y; + } else if (dash_container.get_style_class_name().includes("right")) { + x = monitor.width - dash_container.width; + y = dash_container.y + (dash_container.height - dash_background.height) / 2 - dash_background.y; + } + + return [x, y]; } _log(str) { if (this.settings.DEBUG) console.log(`[Blur my Shell > dash] ${str}`); } + + _warn(str) { + console.warn(`[Blur my Shell > dash] ${str}`); + } } export const DashBlur = class DashBlur { @@ -92,11 +214,13 @@ export const DashBlur = class DashBlur { this.brightness = this.settings.dash_to_dock.CUSTOMIZE ? this.settings.dash_to_dock.BRIGHTNESS : this.settings.BRIGHTNESS; + this.corner_radius = this.settings.dash_to_dock.CORNER_RADIUS; + this.is_static = this.settings.dash_to_dock.STATIC_BLUR; this.enabled = false; } enable() { - this.connections.connect(Main.uiGroup, 'actor-added', (_, actor) => { + this.connections.connect(Main.uiGroup, 'child-added', (_, actor) => { if ( (actor.get_name() === "dashtodockContainer") && (actor.constructor.name === 'DashToDock') @@ -107,6 +231,9 @@ export const DashBlur = class DashBlur { this.blur_existing_dashes(); this.connect_to_overview(); + this.update_wallpaper(); + this.update_size(); + this.enabled = true; } @@ -143,13 +270,6 @@ export const DashBlur = class DashBlur { // Blurs the dash and returns a `DashInfos` containing its information blur_dash_from(dash, dash_container) { - // the effect to be applied - let effect = new Shell.BlurEffect({ - brightness: this.brightness, - sigma: this.sigma, - mode: Shell.BlurMode.BACKGROUND - }); - // dash background parent, not visible let background_parent = new St.Widget({ name: 'dash-blurred-background-parent', @@ -158,92 +278,50 @@ export const DashBlur = class DashBlur { height: 0 }); - // dash background widget - let background = new St.Widget({ - name: 'dash-blurred-background', - style_class: 'dash-blurred-background', - x: 0, - y: dash_container._slider.y, - width: dash.width, - height: dash.height, + // finally blur the dash + let dash_background = dash.get_children().find(child => { + return child.get_style_class_name() === 'dash-background'; }); + let [background, effect] = this.add_blur(dash, dash_background, dash_container); + + this.update_wallpaper(); + this.update_size(); + // updates size and position on change - this.connections.connect(dash_container._slider, 'notify::y', _ => { - background.y = dash_container._slider.y; - }); this.connections.connect(dash, 'notify::width', _ => { - background.width = dash.width; + this.update_size(); }); this.connections.connect(dash, 'notify::height', _ => { - background.height = dash.height; + this.update_size(); + }); + this.connections.connect(dash_container, 'notify::width', _ => { + this.update_size(); + }); + this.connections.connect(dash_container, 'notify::height', _ => { + this.update_size(); + }); + this.connections.connect(dash_container, 'notify::y', _ => { + this.update_wallpaper(); + this.update_size(); + }); + this.connections.connect(dash_container, 'notify::x', _ => { + this.update_wallpaper(); + this.update_size(); }); - // add the widget to the dash - background.add_effect(effect); background_parent.add_child(background); dash.get_parent().insert_child_at_index(background_parent, 0); - // HACK - // - //`Shell.BlurEffect` does not repaint when shadows are under it. [1] - // - // This does not entirely fix this bug (shadows caused by windows - // still cause artifacts), but it prevents the shadows of the panel - // buttons to cause artifacts on the panel itself - // - // [1]: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2857 - - if (this.settings.HACKS_LEVEL === 1) { - this._log("dash hack level 1"); - this.paint_signals.disconnect_all(); - - let rp = () => { - effect.queue_repaint(); - }; - - dash._box.get_children().forEach((icon) => { - try { - let zone = icon.get_child_at_index(0); - - this.connections.connect(zone, [ - 'enter-event', 'leave-event', 'button-press-event' - ], rp); - } catch (e) { - this._warn(`${e}, continuing`); - } - }); - - this.connections.connect(dash._box, 'actor-added', (_, actor) => { - try { - let zone = actor.get_child_at_index(0); - - this.connections.connect(zone, [ - 'enter-event', 'leave-event', 'button-press-event' - ], rp); - } catch (e) { - this._warn(`${e}, continuing`); - } - }); - - let show_apps = dash._showAppsIcon; - - this.connections.connect(show_apps, [ - 'enter-event', 'leave-event', 'button-press-event' - ], rp); - - this.connections.connect(dash, 'leave-event', rp); - } else if (this.settings.HACKS_LEVEL === 2) { - this._log("dash hack level 2"); - - this.paint_signals.connect(background, effect); - } else { - this.paint_signals.disconnect_all(); - } - // create infos let infos = new DashInfos( - this, dash, background_parent, effect, this.settings + this, + dash, + dash_container, + dash_background, + background, + background_parent, + effect ); // update the background @@ -253,6 +331,128 @@ export const DashBlur = class DashBlur { return infos; } + add_blur(dash, dash_background, dash_container) { + let monitor = find_monitor_for(dash); + + // dash background widget + let background = this.is_static + ? new Meta.BackgroundActor({ + meta_display: global.display, + monitor: monitor.index, + }) + : new St.Widget({ + name: 'dash-blurred-background', + style_class: 'dash-blurred-background', + x: dash_background.x, + y: dash_background.y + dash.y, + width: dash_background.width, + height: dash_background.height, + }); + + // the effect to be applied + let effect; + if (this.is_static) { + let corner_radius = this.corner_radius * monitor.geometry_scale; + corner_radius = Math.min(corner_radius, dash_background.width / 2, dash_background.height / 2); + + effect = new BlurEffect({ + radius: 2 * this.sigma * monitor.geometry_scale, + brightness: this.brightness, + width: dash_background.width, + height: dash_background.height, + corner_radius: corner_radius + }); + + // connect to every background change (even without changing image) + // FIXME this signal is fired very often, so we should find another one + // fired only when necessary (but that still catches all cases) + this.connections.connect( + Main.layoutManager._backgroundGroup, + 'notify', + _ => this.update_wallpaper() + ); + } else { + effect = new Shell.BlurEffect({ + brightness: this.brightness, + radius: this.sigma * 2 * monitor.geometry_scale, + mode: Shell.BlurMode.BACKGROUND + }); + + // HACK + // + //`Shell.BlurEffect` does not repaint when shadows are under it. [1] + // + // This does not entirely fix this bug (shadows caused by windows + // still cause artifacts), but it prevents the shadows of the panel + // buttons to cause artifacts on the panel itself + // + // [1]: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/2857 + + if (this.settings.HACKS_LEVEL === 1) { + this._log("dash hack level 1"); + this.paint_signals.disconnect_all(); + + let rp = () => { + effect.queue_repaint(); + }; + + dash._box.get_children().forEach((icon) => { + try { + let zone = icon.get_child_at_index(0); + + this.connections.connect(zone, [ + 'enter-event', 'leave-event', 'button-press-event' + ], rp); + } catch (e) { + this._warn(`${e}, continuing`); + } + }); + + this.connections.connect(dash._box, 'actor-added', (_, actor) => { + try { + let zone = actor.get_child_at_index(0); + + this.connections.connect(zone, [ + 'enter-event', 'leave-event', 'button-press-event' + ], rp); + } catch (e) { + this._warn(`${e}, continuing`); + } + }); + + let show_apps = dash._showAppsIcon; + + this.connections.connect(show_apps, [ + 'enter-event', 'leave-event', 'button-press-event' + ], rp); + + this.connections.connect(dash, 'leave-event', rp); + } else if (this.settings.HACKS_LEVEL === 2) { + this._log("dash hack level 2"); + + this.paint_signals.connect(background, effect); + } else { + this.paint_signals.disconnect_all(); + } + } + + // store the scale in the effect in order to retrieve it in set_sigma + effect.scale = monitor.geometry_scale; + + background.add_effect(effect); + + return [background, effect]; + } + + change_blur_type() { + this.is_static = this.settings.dash_to_dock.STATIC_BLUR; + this.emit('change-blur-type', true); + + this.update_wallpaper(); + this.update_background(); + this.update_size(); + } + /// Connect when overview if opened/closed to hide/show the blur accordingly connect_to_overview() { this.connections.disconnect_all_for(Main.overview); @@ -276,6 +476,15 @@ export const DashBlur = class DashBlur { this.emit('reset-background', true); } + update_wallpaper() { + if (this.is_static) + this.emit('update-wallpaper', true); + } + + update_size() { + this.emit('update-size', true); + } + set_sigma(sigma) { this.sigma = sigma; this.emit('update-sigma', true); @@ -286,6 +495,11 @@ export const DashBlur = class DashBlur { this.emit('update-brightness', true); } + set_corner_radius(radius) { + this.corner_radius = radius; + this.emit('update-corner-radius', true); + } + // not implemented for dynamic blur set_color(c) { } set_noise_amount(n) { } diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/lockscreen.js b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/lockscreen.js index bd10908..00895ea 100644 --- a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/lockscreen.js +++ b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/lockscreen.js @@ -21,6 +21,7 @@ export const LockscreenBlur = class LockscreenBlur { this.connections = connections; this.settings = settings; this.effects_manager = effects_manager; + this.enabled = false; } enable() { @@ -43,6 +44,8 @@ export const LockscreenBlur = class LockscreenBlur { : this.settings.NOISE_LIGHTNESS; this.update_lockscreen(); + + this.enabled = true; } update_lockscreen() { @@ -64,7 +67,7 @@ export const LockscreenBlur = class LockscreenBlur { let blur_effect = new Shell.BlurEffect({ name: 'blur', - sigma: sigma, + radius: sigma * 2, brightness: brightness }); @@ -118,7 +121,7 @@ export const LockscreenBlur = class LockscreenBlur { if (blur_effect) { blur_effect.set({ brightness: brightness, - sigma: sigma * blur_effect.scale, + radius: sigma * 2 * blur_effect.scale, }); } } @@ -158,6 +161,8 @@ export const LockscreenBlur = class LockscreenBlur { original_updateBackgroundEffects; this.connections.disconnect_all(); + + this.enabled = false; } _log(str) { diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/overview.js b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/overview.js index 3e04ac4..d612370 100644 --- a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/overview.js +++ b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/overview.js @@ -160,6 +160,7 @@ export const OverviewBlur = class OverviewBlur { create_background_actor(monitor, is_transition) { let bg_actor = new Meta.BackgroundActor({ + name: "blur-my-shell_background_actor", meta_display: global.display, monitor: monitor.index }); @@ -184,10 +185,9 @@ export const OverviewBlur = class OverviewBlur { brightness: this.settings.overview.CUSTOMIZE ? this.settings.overview.BRIGHTNESS : this.settings.BRIGHTNESS, - sigma: this.settings.overview.CUSTOMIZE + radius: (this.settings.overview.CUSTOMIZE ? this.settings.overview.SIGMA - : this.settings.SIGMA - * monitor.geometry_scale, + : this.settings.SIGMA) * 2 * monitor.geometry_scale, mode: Shell.BlurMode.ACTOR }); @@ -235,7 +235,7 @@ export const OverviewBlur = class OverviewBlur { set_sigma(s) { this.effects.forEach(effect => { - effect.blur_effect.sigma = s * effect.blur_effect.scale; + effect.blur_effect.radius = s * 2 * effect.blur_effect.scale; }); } @@ -264,13 +264,15 @@ export const OverviewBlur = class OverviewBlur { } remove_background_actors() { - Main.layoutManager.overviewGroup.get_children().forEach(actor => { - if (actor.constructor.name === 'Meta_BackgroundActor') { - actor.get_effects().forEach(effect => { + Main.layoutManager.overviewGroup.get_children().forEach(child => { + if (child instanceof Meta.BackgroundActor + && child.get_name() == "blur-my-shell_background_actor" + ) { + child.get_effects().forEach(effect => { this.effects_manager.remove(effect); }); - Main.layoutManager.overviewGroup.remove_child(actor); - actor.destroy(); + Main.layoutManager.overviewGroup.remove_child(child); + child.destroy(); } }); this.effects = []; diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/panel.js b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/panel.js index a904f92..d1d3edb 100644 --- a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/panel.js +++ b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/panel.js @@ -53,6 +53,9 @@ export const PanelBlur = class PanelBlur { // the blur when a window is near a panel this.connect_to_windows_and_overview(); + // update the classname if the panel to have or have not light text + this.update_light_text_classname(); + // connect to every background change (even without changing image) // FIXME this signal is fired very often, so we should find another one // fired only when necessary (but that still catches all cases) @@ -167,10 +170,9 @@ export const PanelBlur = class PanelBlur { brightness: this.settings.panel.CUSTOMIZE ? this.settings.panel.BRIGHTNESS : this.settings.BRIGHTNESS, - sigma: this.settings.panel.CUSTOMIZE + radius: (this.settings.panel.CUSTOMIZE ? this.settings.panel.SIGMA - : this.settings.SIGMA - * monitor.geometry_scale, + : this.settings.SIGMA) * 2 * monitor.geometry_scale, mode: this.settings.panel.STATIC_BLUR ? Shell.BlurMode.ACTOR : Shell.BlurMode.BACKGROUND @@ -317,7 +319,7 @@ export const PanelBlur = class PanelBlur { Main.layoutManager.monitors.length - this.find_monitor_for(actors.widgets.panel).index - 1 ); - if (bg) + if (bg && bg.get_content()) actors.widgets.background.content.set({ background: bg.get_content().background }); @@ -408,6 +410,9 @@ export const PanelBlur = class PanelBlur { this.connections.connect( appDisplay, 'hide', this.show.bind(this) ); + this.connections.connect( + Main.overview, 'hidden', this.show.bind(this) + ); } } @@ -436,10 +441,10 @@ export const PanelBlur = class PanelBlur { } // manage windows at their creation/removal - this.connections.connect(global.window_group, 'actor-added', + this.connections.connect(global.window_group, 'child-added', this.on_window_actor_added.bind(this) ); - this.connections.connect(global.window_group, 'actor-removed', + this.connections.connect(global.window_group, 'child-removed', this.on_window_actor_removed.bind(this) ); @@ -487,6 +492,14 @@ export const PanelBlur = class PanelBlur { this.window_signal_ids = new Map(); } + /// Update the css classname of the panel for light theme + update_light_text_classname(disable = false) { + if (this.settings.panel.FORCE_LIGHT_TEXT && !disable) + Main.panel.add_style_class_name("panel-light-text"); + else + Main.panel.remove_style_class_name("panel-light-text"); + } + /// Callback when a new window is added on_window_actor_added(container, meta_window_actor) { this.window_signal_ids.set(meta_window_actor, [ @@ -532,6 +545,7 @@ export const PanelBlur = class PanelBlur { && meta_window.get_window_type() !== Meta.WindowType.DESKTOP // exclude Desktop Icons NG && meta_window.get_gtk_application_id() !== "com.rastersoft.ding" + && meta_window.get_gtk_application_id() !== "com.desktop.ding" ); // check if at least one window is near enough to each panel and act @@ -590,7 +604,7 @@ export const PanelBlur = class PanelBlur { /// enabling/disabling other effects. invalidate_blur(actors) { if (this.settings.panel.STATIC_BLUR && actors.widgets.background) - actors.widgets.background.get_content().invalidate(); + actors.widgets.background.get_content()?.invalidate(); } invalidate_all_blur() { @@ -599,7 +613,7 @@ export const PanelBlur = class PanelBlur { set_sigma(s) { this.actors_list.forEach(actors => { - actors.effects.blur.sigma = s * actors.effects.blur.scale; + actors.effects.blur.radius = s * 2 * actors.effects.blur.scale; this.invalidate_blur(actors); }); } @@ -662,6 +676,8 @@ export const PanelBlur = class PanelBlur { this.disconnect_from_windows_and_overview(); + this.update_light_text_classname(true); + this.actors_list.forEach(actors => { this.set_should_override_panel(actors, false); this.effects_manager.remove(actors.effects.noise); diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/screenshot.js b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/screenshot.js index 34bb3c4..8241f0c 100644 --- a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/screenshot.js +++ b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/screenshot.js @@ -82,10 +82,9 @@ export const ScreenshotBlur = class ScreenshotBlur { brightness: this.settings.screenshot.CUSTOMIZE ? this.settings.screenshot.BRIGHTNESS : this.settings.BRIGHTNESS, - sigma: this.settings.screenshot.CUSTOMIZE + radius: (this.settings.screenshot.CUSTOMIZE ? this.settings.screenshot.SIGMA - : this.settings.SIGMA - * monitor.geometry_scale, + : this.settings.SIGMA) * 2 * monitor.geometry_scale, mode: Shell.BlurMode.ACTOR }); @@ -117,7 +116,7 @@ export const ScreenshotBlur = class ScreenshotBlur { set_sigma(s) { this.effects.forEach(effect => { - effect.blur_effect.sigma = s * effect.blur_effect; + effect.blur_effect.radius = s * 2 * effect.blur_effect; }); } @@ -150,6 +149,7 @@ export const ScreenshotBlur = class ScreenshotBlur { if (actor._blur_actor) { actor.remove_child(actor._blur_actor); actor._blur_actor.destroy(); + delete actor._blur_actor; } }); this.effects = []; diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/window_list.js b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/window_list.js index 6a60564..2ba50b4 100644 --- a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/window_list.js +++ b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/components/window_list.js @@ -24,7 +24,7 @@ export const WindowListBlur = class WindowListBlur { // if is window-list this.connections.connect( Main.layoutManager.uiGroup, - 'actor-added', + 'child-added', (_, child) => this.try_blur(child) ); @@ -46,9 +46,9 @@ export const WindowListBlur = class WindowListBlur { let blur_effect = new Shell.BlurEffect({ name: 'window-list-blur', - sigma: this.settings.window_list.CUSTOMIZE - ? this.settings.window_list.SIGMA - : this.settings.SIGMA, + radius: (this.settings.window_list.CUSTOMIZE + ? this.settings.window_list.SIGMA + : this.settings.SIGMA) * 2, brightness: this.settings.window_list.CUSTOMIZE ? this.settings.window_list.BRIGHTNESS : this.settings.BRIGHTNESS, @@ -65,7 +65,7 @@ export const WindowListBlur = class WindowListBlur { this.connections.connect( child._windowList, - 'actor-added', + 'child-added', (_, window) => this.blur_window_button(window) ); @@ -117,7 +117,7 @@ export const WindowListBlur = class WindowListBlur { set_sigma(s) { this.effects.forEach(effect => { - effect.blur_effect.sigma = s; + effect.blur_effect.radius = s * 2; }); } diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/conveniences/keys.js b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/conveniences/keys.js index 5a87ba4..71a357c 100644 --- a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/conveniences/keys.js +++ b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/conveniences/keys.js @@ -49,6 +49,7 @@ export const Keys = [ { type: Type.D, name: "noise-lightness" }, { type: Type.B, name: "static-blur" }, { type: Type.B, name: "unblur-in-overview" }, + { type: Type.B, name: "force-light-text" }, { type: Type.B, name: "override-background" }, { type: Type.I, name: "style-panel" }, { type: Type.B, name: "override-background-dynamically" }, @@ -67,6 +68,7 @@ export const Keys = [ { type: Type.B, name: "unblur-in-overview" }, { type: Type.B, name: "override-background" }, { type: Type.I, name: "style-dash-to-dock" }, + { type: Type.I, name: "corner-radius" }, ] }, { diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/dbus/services.js b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/dbus/services.js index 9b566c2..4b1f4f0 100644 --- a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/dbus/services.js +++ b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/dbus/services.js @@ -65,6 +65,9 @@ export const ApplicationsService = class ApplicationsService { if (type_str.includes('MetaSurfaceActor')) actor = target.get_parent(); + if (!actor.toString().includes('WindowActor')) + actor = actor.get_parent(); + if (!actor.toString().includes('WindowActor')) return send_picked_signal('window-not-found'); diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/blur_effect.glsl b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/blur_effect.glsl new file mode 100644 index 0000000..37059ae --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/blur_effect.glsl @@ -0,0 +1,114 @@ +uniform sampler2D tex; +uniform float sigma; +uniform int dir; +uniform float brightness; +uniform float corner_radius; +uniform float width; +uniform float height; + +float circleBounds(vec2 p, vec2 center, float clip_radius) { + vec2 delta = p - center; + float dist_squared = dot(delta, delta); + + float outer_radius = clip_radius + 0.5; + if (dist_squared >= (outer_radius * outer_radius)) + return 0.0; + + float inner_radius = clip_radius - 0.5; + if (dist_squared <= (inner_radius * inner_radius)) + return 1.0; + + return outer_radius - sqrt(dist_squared); +} + +vec4 shapeCorner(vec4 pixel, vec2 p, vec2 center, float clip_radius) { + float alpha = circleBounds(p, center, clip_radius); + return vec4(pixel.rgb * alpha, min(alpha, pixel.a)); +} + +vec4 getTexture(vec2 uv) { + if (uv.x < 2. / width) + uv.x = 2. / width; + + if (uv.y < 2. / height) + uv.y = 2. / height; + + if (uv.x > 1. - 3. / width) + uv.x = 1. - 3. / width; + + if (uv.y > 1. - 3. / height) + uv.y = 1. - 3. / height; + + return texture2D(tex, uv); +} + +void main(void) { + vec2 uv = cogl_tex_coord_in[0].xy; + + vec2 pos = uv * vec2(width, height); + + vec2 direction = vec2(dir, (1.0 - dir)); + + float pixel_step; + if (dir == 0) + pixel_step = 1.0 / height; + else + pixel_step = 1.0 / width; + + vec3 gauss_coefficient; + gauss_coefficient.x = 1.0 / (sqrt(2.0 * 3.14159265) * sigma); + gauss_coefficient.y = exp(-0.5 / (sigma * sigma)); + gauss_coefficient.z = gauss_coefficient.y * gauss_coefficient.y; + + float gauss_coefficient_total = gauss_coefficient.x; + + vec4 ret = getTexture(uv) * gauss_coefficient.x; + gauss_coefficient.xy *= gauss_coefficient.yz; + + int n_steps = int(ceil(1.5 * sigma)) * 2; + + for (int i = 1; i <= n_steps; i += 2) { + float coefficient_subtotal = gauss_coefficient.x; + gauss_coefficient.xy *= gauss_coefficient.yz; + coefficient_subtotal += gauss_coefficient.x; + + float gauss_ratio = gauss_coefficient.x / coefficient_subtotal; + + float foffset = float(i) + gauss_ratio; + vec2 offset = direction * foffset * pixel_step; + + ret += getTexture(uv + offset) * coefficient_subtotal; + ret += getTexture(uv - offset) * coefficient_subtotal; + + gauss_coefficient_total += 2.0 * coefficient_subtotal; + gauss_coefficient.xy *= gauss_coefficient.yz; + } + vec4 outColor = ret / gauss_coefficient_total; + + // apply brightness and rounding on the second pass (dir==0 comes last) + if (dir == 0) { + // left side + if (pos.x < corner_radius) { + // top left corner + if (pos.y < corner_radius) { + outColor = shapeCorner(outColor, pos, vec2(corner_radius + 2., corner_radius + 2.), corner_radius); + // bottom left corner + } else if (pos.y > height - corner_radius) { + outColor = shapeCorner(outColor, pos, vec2(corner_radius + 2., height - corner_radius - 1.), corner_radius); + } + // right side + } else if (pos.x > width - corner_radius) { + // top right corner + if (pos.y < corner_radius) { + outColor = shapeCorner(outColor, pos, vec2(width - corner_radius - 1., corner_radius + 2.), corner_radius); + // bottom right corner + } else if (pos.y > height - corner_radius) { + outColor = shapeCorner(outColor, pos, vec2(width - corner_radius - 1., height - corner_radius - 1.), corner_radius); + } + } + + outColor.rgb *= brightness; + } + + cogl_color_out = outColor; +} \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/blur_effect.js b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/blur_effect.js new file mode 100644 index 0000000..71d28d0 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/effects/blur_effect.js @@ -0,0 +1,236 @@ +import GLib from 'gi://GLib'; +import GObject from 'gi://GObject'; +import Clutter from 'gi://Clutter'; +import Shell from 'gi://Shell'; + +const SHADER_PATH = GLib.filename_from_uri(GLib.uri_resolve_relative(import.meta.url, 'blur_effect.glsl', GLib.UriFlags.NONE))[0]; + + +const get_shader_source = _ => { + try { + return Shell.get_file_contents_utf8_sync(SHADER_PATH); + } catch (e) { + console.warn(`[Blur my Shell] error loading shader from ${SHADER_PATH}: ${e}`); + return null; + } +}; + +export const BlurEffect = new GObject.registerClass({ + GTypeName: "BlurEffect", + Properties: { + 'radius': GObject.ParamSpec.double( + `radius`, + `Radius`, + `Blur radius`, + GObject.ParamFlags.READWRITE, + 0.0, 2000.0, + 200.0, + ), + 'brightness': GObject.ParamSpec.double( + `brightness`, + `Brightness`, + `Blur brightness`, + GObject.ParamFlags.READWRITE, + 0.0, 1.0, + 0.6, + ), + 'width': GObject.ParamSpec.double( + `width`, + `Width`, + `Width`, + GObject.ParamFlags.READWRITE, + 0.0, Number.MAX_SAFE_INTEGER, + 0.0, + ), + 'height': GObject.ParamSpec.double( + `height`, + `Height`, + `Height`, + GObject.ParamFlags.READWRITE, + 0.0, Number.MAX_SAFE_INTEGER, + 0.0, + ), + 'corner_radius': GObject.ParamSpec.double( + `corner_radius`, + `Corner Radius`, + `Corner Radius`, + GObject.ParamFlags.READWRITE, + 0, Number.MAX_SAFE_INTEGER, + 0, + ), + 'direction': GObject.ParamSpec.int( + `direction`, + `Direction`, + `Direction`, + GObject.ParamFlags.READWRITE, + 0, 1, + 0, + ), + 'chained_effect': GObject.ParamSpec.object( + `chained_effect`, + `Chained Effect`, + `Chained Effect`, + GObject.ParamFlags.READABLE, + GObject.Object, + ), + } +}, class BlurEffect extends Clutter.ShaderEffect { + constructor(params, settings) { + super(params); + + this._sigma = null; + this._brightness = null; + this._width = null; + this._height = null; + this._corner_radius = null; + + this._static = true; + this._settings = settings; + + this._direction = 0; + + this._chained_effect = null; + + if (params.sigma) + this.sigma = params.sigma; + if (params.brightness) + this.brightness = params.brightness; + if (params.width) + this.width = params.width; + if (params.height) + this.height = params.height; + if (params.corner_radius) + this.corner_radius = params.corner_radius; + if (params.direction) + this.direction = params.direction; + + // set shader source + this._source = get_shader_source(); + if (this._source) + this.set_shader_source(this._source); + } + + get radius() { + return this._radius; + } + + set radius(value) { + if (this._radius !== value) { + this._radius = value; + + // like Clutter, we use the assumption radius = 2*sigma + this.set_uniform_value('sigma', parseFloat(this._radius / 2 - 1e-6)); + + if (this._chained_effect) { + this._chained_effect.radius = value; + } + } + } + + get brightness() { + return this._brightness; + } + + set brightness(value) { + if (this._brightness !== value) { + this._brightness = value; + + this.set_uniform_value('brightness', parseFloat(this._brightness - 1e-6)); + + if (this._chained_effect) { + this._chained_effect.brightness = value; + } + } + } + + get width() { + return this._width; + } + + set width(value) { + if (this._width !== value) { + this._width = value; + + this.set_uniform_value('width', parseFloat(this._width + 3.0 - 1e-6)); + + if (this._chained_effect) { + this._chained_effect.width = value; + } + } + } + + get height() { + return this._height; + } + + set height(value) { + if (this._height !== value) { + this._height = value; + + this.set_uniform_value('height', parseFloat(this._height + 3.0 - 1e-6)); + + if (this._chained_effect) { + this._chained_effect.height = value; + } + } + } + + get corner_radius() { + return this._corner_radius; + } + + set corner_radius(value) { + if (this._corner_radius !== value) { + this._corner_radius = value; + + this.set_uniform_value('corner_radius', parseFloat(this._corner_radius - 1e-6)); + + if (this._chained_effect) { + this._chained_effect.corner_radius = value; + } + } + } + + get direction() { + return this._direction; + } + + set direction(value) { + if (this._direction !== value) { + this._direction = value; + } + } + + get chained_effect() { + return this._chained_effect; + } + + vfunc_set_actor(actor) { + super.vfunc_set_actor(actor); + + if (this._direction == 0) { + this._chained_effect = new BlurEffect({ + radius: this.radius, + brightness: this.brightness, + width: this.width, + height: this.height, + corner_radius: this.corner_radius, + direction: 1 + }); + if (actor !== null) + actor.add_effect(this._chained_effect); + } + } + + vfunc_paint_target(paint_node = null, paint_context = null) { + this.set_uniform_value("tex", 0); + this.set_uniform_value("dir", this._direction); + + if (paint_node && paint_context) + super.vfunc_paint_target(paint_node, paint_context); + else if (paint_node) + super.vfunc_paint_target(paint_node); + else + super.vfunc_paint_target(); + } +}); \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/extension.js b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/extension.js index 5aa7b9f..cd65616 100644 --- a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/extension.js +++ b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/extension.js @@ -28,7 +28,7 @@ const INDEPENDENT_COMPONENTS = [ /// The main extension class, created when the GNOME Shell is loaded. export default class BlurMyShell extends Extension { - /// Enables the extension + /// Enables the extension. enable() { // add the extension to global to make it accessible to other extensions // create it first as it is very useful when debugging crashes @@ -69,12 +69,30 @@ export default class BlurMyShell extends Extension { this._applications_blur = new ApplicationsBlur(...init()); this._screenshot_blur = new ScreenshotBlur(...init()); - // maybe disable clipped redraw - this._update_clipped_redraws(); - // connect each component to preferences change this._connect_to_settings(); + // enable the lockscreen blur, only one important in both `user` session and `unlock-dialog` + if (this._settings.lockscreen.BLUR && !this._lockscreen_blur.enabled) + this._lockscreen_blur.enable(); + + // ensure we take the correct action for the current session mode + this._user_session_mode_enabled = false; + this._on_session_mode_changed(Main.sessionMode); + + // watch for changes to the session mode + this._connection.connect(Main.sessionMode, 'updated', + _ => this._on_session_mode_changed(Main.sessionMode) + ); + } + + /// Enables the components related to the user session (everything except lockscreen blur). + _enable_user_session() { + this._log("changing mode to user session..."); + + // maybe disable clipped redraw + this._update_clipped_redraws(); + // enable every component // if the shell is still starting up, wait for it to be entirely loaded; // this should prevent bugs like #136 and #137 @@ -112,30 +130,44 @@ export default class BlurMyShell extends Extension { this._log("Could not enable panel blur directly"); this._log(e); } + + // tells the extension we have enabled the user session components, so that we do not + // disable them later if they were not even enabled to begin with + this._user_session_mode_enabled = true; } - /// Disables the extension + /// Disables the extension. + /// + /// This extension needs to use the 'unlock-dialog' session mode in order to change the blur on + /// the lockscreen. We have kind of two states of enablement for this extension: + /// - the 'enabled' state, which means that we have created the necessary components (which only + /// are js objects) and enabled the lockscreen blur (which means swapping two functions from + /// the `UnlockDialog` constructor with our ones; + /// - the 'user session enabled` mode, which means that we are in the 'enabled' mode AND we are + /// in the user mode, and so we enable all the other components that we created before. + /// We switch from one state to the other thanks to `this._on_session_mode_changed`, and we + /// track wether or not we are in the user mode with `this._user_session_mode_enabled` (because + /// `this._on_session_mode_changed` might be called multiple times while in the user session + /// mode, typically when going back from simple lockscreen and not sleep mode). disable() { this._log("disabling extension..."); - // disable every component - this._panel_blur.disable(); - this._dash_to_dock_blur.disable(); - this._overview_blur.disable(); + // disable every component from user session mode + if (this._user_session_mode_enabled) + this._disable_user_session(); + + // disable lockscreen blur too this._lockscreen_blur.disable(); - this._appfolder_blur.disable(); - this._window_list_blur.disable(); - this._applications_blur.disable(); - this._screenshot_blur.disable(); // untrack them this._panel_blur = null; this._dash_to_dock_blur = null; this._overview_blur = null; - this._lockscreen_blur = null; this._appfolder_blur = null; + this._lockscreen_blur = null; this._window_list_blur = null; this._applications_blur = null; + this._screenshot_blur = null; // make sure no settings change can re-enable them this._settings.disconnect_all_settings(); @@ -157,16 +189,52 @@ export default class BlurMyShell extends Extension { this._settings = null; } - /// Restart the extension. + /// Disables the components related to the user session (everything except lockscreen blur). + _disable_user_session() { + this._log("disabling user session mode..."); + + // disable every component except lockscreen blur + this._panel_blur.disable(); + this._dash_to_dock_blur.disable(); + this._overview_blur.disable(); + this._appfolder_blur.disable(); + this._window_list_blur.disable(); + this._applications_blur.disable(); + this._screenshot_blur.disable(); + + // remove the clipped redraws flag + this._reenable_clipped_redraws(); + + // tells the extension we have disabled the user session components, so that we do not + // disable them later again if they were already disabled + this._user_session_mode_enabled = false; + } + + /// Restarts the components related to the user session. _restart() { this._log("restarting..."); - this.disable(); - this.enable(); + this._disable_user_session(); + this._enable_user_session(); this._log("restarted."); } + /// Changes the extension to operate either on 'user' mode or 'unlock-dialog' mode, switching + /// from one to the other means enabling/disabling every component except lockscreen blur. + _on_session_mode_changed(session) { + if (session.currentMode === 'user' || session.parentMode === 'user') { + if (!this._user_session_mode_enabled) + // we need to activate everything + this._enable_user_session(); + } + else if (session.currentMode === 'unlock-dialog') { + if (this._user_session_mode_enabled) + // we need to disable the components related to the user session mode + this._disable_user_session(); + } + } + /// Add or remove the clutter debug flag to disable clipped redraws. /// This will entirely fix the blur effect, but should not be used except if /// the user really needs it, as clipped redraws are a huge performance @@ -192,7 +260,7 @@ export default class BlurMyShell extends Extension { ); } - /// Enables every component needed, should be called when the shell is + /// Enables every component from the user session needed, should be called when the shell is /// entirely loaded as the `enable` methods interact with it. _enable_components() { // enable each component if needed, and if it is not already enabled @@ -206,9 +274,6 @@ export default class BlurMyShell extends Extension { if (this._settings.overview.BLUR && !this._overview_blur.enabled) this._overview_blur.enable(); - if (this._settings.lockscreen.BLUR) - this._lockscreen_blur.enable(); - if (this._settings.appfolder.BLUR) this._appfolder_blur.enable(); @@ -328,6 +393,12 @@ export default class BlurMyShell extends Extension { this._panel_blur.connect_to_windows_and_overview(); }); + // force light text toggled on/off + this._settings.panel.FORCE_LIGHT_TEXT_changed(() => { + if (this._settings.panel.BLUR) + this._panel_blur.update_light_text_classname(); + }); + // panel override background toggled on/off this._settings.panel.OVERRIDE_BACKGROUND_changed(() => { if (this._settings.panel.BLUR) @@ -358,11 +429,16 @@ export default class BlurMyShell extends Extension { } }); - // TODO implement static blur for dash // static blur toggled on/off this._settings.dash_to_dock.STATIC_BLUR_changed(() => { - //if (this._settings.dash_to_dock.BLUR) - // this._dash_to_dock_blur.change_blur_type(); + if (this._settings.dash_to_dock.BLUR) + this._dash_to_dock_blur.change_blur_type(); + }); + + // dash-to-dock corner radius changed + this._settings.dash_to_dock.CORNER_RADIUS_changed(() => { + if (this._settings.dash_to_dock.STATIC_BLUR) + this._dash_to_dock_blur.set_corner_radius(this._settings.dash_to_dock.CORNER_RADIUS); }); // dash-to-dock override background toggled on/off diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/af/LC_MESSAGES/blur-my-shell@aunetx.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/af/LC_MESSAGES/blur-my-shell@aunetx.mo new file mode 100644 index 0000000000000000000000000000000000000000..a190bd4e1bfad65e8a3eef6418f046ec0c023368 GIT binary patch literal 11393 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 literal 0 HcmV?d00001 diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ar/LC_MESSAGES/blur-my-shell.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ar/LC_MESSAGES/blur-my-shell@aunetx.mo similarity index 73% rename from gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ar/LC_MESSAGES/blur-my-shell.mo rename to gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ar/LC_MESSAGES/blur-my-shell@aunetx.mo index 4a999d6a07cd0453691f3d206c6ba8e6423db08e..d44c239dfb548c33007d03c72d6f97e5bcf1c94a 100644 GIT binary patch delta 2469 zcmY+_e@srx>v_&S=Xt*8dA{fJ z-Il)s!E0#)j~k8vF_I{bHfBHWj^%^nbi6U6@eGc@3pfbB!6Lkg^D!^M7#p|YS9k?| z*u}*bevC=@Ee^wnGa3Wgt~7pD&Ygj*ybgihNp2mUPX<&ERBc34h*tt<_ZlB^aGY*A8LRi9#@%{ zp(fabnjnDunHoM0V+&FSCYkJpqYrhRAC>rY)I1AtB9@@$+oknaV;?7U!*L`@a}xd7 zi%R5s)ZX=>uKO1?U^MGli7B`Wn^8sjB~HPcxDGQOq>iu&^?>J4TbJZx{R?RnQz07g zFcxDc&cK_v9LG?yx}g>)U@xjzucGd|j+*#aOdr5%unbe_kIXP8A4`#3Oe>aSC)VMg zK^muM*t~mxV+@s*g?F$JGkN#e4HG~u-Sem=ej8PU7b0H6@$_$_63rareQ)DR`mI=s zmr*M|-trO&PNne^ugy{1#TU(Ey*>K_HQ*hjuub+j@5X7U1Qw$9d?RX)1IS{Tders% zBc8xq`rW9NyNpZlu4m9JdDz>#m(k*j8`zGqncjqlP>FQnLHrEK$&|26XRsbsr0LoG z_}~b94G*Fc&EjSyR){>jS&P)G*@?+|{}0iK=fp{5^~{^7*W+{Ci|M3Yg0EmB-ar-O z`W$cIDr}?Q66wc0;w3&RVh$?7>8LH6i=SY*`pj>Jv#~RE0VQKS(zp@djb_n(WlOB3mMl+dfFU&1GkeH!Zv7SrlK zv>tN_Jw`Oa4~zTDk$@Ws9aMHcJVMm_ewBRH3QFCPI6A-=QsM zvx#R2ipfyXZfVZL{$n`}6+;a17~vxli3J3&j@e9<68*q0Nax5gz}HPw|>jaH+*voZ8fN`2f?tKz;>R$%LPtFg+q zwpG;GH509-20PGHV>MUVb+oJNDy_=8t+jS;LzP`qlikpNXO&%R=Y=YLfv7~kKi5CS z^3Rx+Ul4MJwMIov4wa8+OdRWUJ3Y=v;Wo?Z4!4Cnob%y*&Uq`mhx2EhUgw?g!O*45 zi-UsquDf@QdqW$SbJhQDa1L3V{eaZxesY}r!eNfxA76r=+f>E>qK}EJ@ zMFC@CQZ)pF$R9#5(Zp;74TQw_Xe9hWh>1}Gjm7|C)Tl9_jmGb9W}0}@v!8osXXl=| z_ssO#x(kWq#bD;^MoSPk5ltCpdvH}YAG9IA*>oJnQhXcp@B}WyFK`JK6NGz#Zpfgz11*szrZz!g^WX}3shnb)?g7fU>PpQ z#kc{R@F+IpCDfhH+m&vn)z*iEzEG1Tw6P>J>-m$KD(J8r^3JdC<-NzkkVdyvJlcQC07eLyFUr%)G|#%(I&2x@{V z)CBd&pEdIF3U(mdZx^rxFQLv;wn{u3HBlkX#WK`lwer!CL$ZncK3$TpPpq1a8BFcp0zbOG%!& z2%RA+su_q8yI|-$qLGZ$`c|-z*>&e#qS|}NJJvEX>@UhyRjQEgPap87a?;T$kL9F) p3=Q}KwGCCZ(eh~B!un{sw~AV()0iT diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/az/LC_MESSAGES/blur-my-shell.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/az/LC_MESSAGES/blur-my-shell@aunetx.mo similarity index 100% rename from gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/az/LC_MESSAGES/blur-my-shell.mo rename to gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/az/LC_MESSAGES/blur-my-shell@aunetx.mo diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/be/LC_MESSAGES/blur-my-shell@aunetx.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/be/LC_MESSAGES/blur-my-shell@aunetx.mo new file mode 100644 index 0000000000000000000000000000000000000000..2643e110d602b1b49c73c7a35f0a6c15b850695c GIT binary patch literal 326 zcmYL@&rZWI4917x6mjCrAqQ??{@h9s5``5}X{A$Dkl>cJrVC1wDRI&IAiN&Wf_vFM z=_gC}XZ!m*Ir^Qk4wzHsj5%a3m`Mq9%)?u*lV_)8@ZZ=FgpCQ@%rWjusAajjxjq8+5R))mvAKOM=J^%m! literal 0 HcmV?d00001 diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/bg/LC_MESSAGES/blur-my-shell.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/bg/LC_MESSAGES/blur-my-shell@aunetx.mo similarity index 100% rename from gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/bg/LC_MESSAGES/blur-my-shell.mo rename to gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/bg/LC_MESSAGES/blur-my-shell@aunetx.mo diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ca/LC_MESSAGES/blur-my-shell.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ca/LC_MESSAGES/blur-my-shell.mo deleted file mode 100644 index 2309a34cff58b035efb21cc836cf44c0107a2002..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1402 zcmZWoJ&znk5FN0=)W}KKdT;9e_44U&5{xsjS7Afg z3$QO?ar^@N1NIp9BJANaN%9K(*YGdF{{$cJ{tEvY{O|BTz+QVcN&d$Aw^QAFKc7yL z*Rg&KPw;=jpN0Pi-oc-FE=h1LL3lf`Y~RIk@_e_|{^Qwh48~(mBi%R(mcmqs>sqUl zgR;iwG@L3=`1zo;rjZ1uNn^@*%36hGo(?Tl656XH@qwK9Mh8!|^ZIv_~6@Hme>U~;W8XP_>Pom&vEd97;&uW@ZneVA(!_^%UpDfshv#3 zi76#dX*H6;iQ1o7bO_&w^}m^1j%bnC&c)4@ERx$bm%x$?+oIYz*-2Z&LYc8$#OPq_ z|2A8?WHOO5tP|5zRa0>^XWa-bI-Y1|fmcfvDaeyOXFo@Dc4M4= zU7Utc`=ZyIS|4PbpSaVjJ1o8zX*dG#)T-p(@#6)RobKM(y><+~pKqjBtO;UJ@3ID< zAp4wni$Xd#HnTcHO#}FUZvG((i0; zQ#ai)bZ&?G+v%rS*H0}ocRL#BLf+rX`)M+mNF{2Y#^S|HY{@g!hOeu|LlaRFCD?}~ z2KO8Ed8Y&HL>X`(bRs(@1P5nFm>9GuI?U(k9-70B0982>?P-P9 o3mpGTxK53UIU zfBf;j7;&uW!Ixjt2VCrvmYL{yrgkzBC#H}*rPW9VCwxEkv5fHb=>HqZ#TYFfwli@v zCG%v*FdQY05iV#f6GjBd73&J|%fMFrj0Er6TAW^xpV~QWnD*M-x_w`BJb%J4$cgk- zyr6;`MD1-Qq&dLt1zAV1G_kH?L;;e0BR)@Vzzm2@hAl(wn(U-?W3J5D&f^Qg)<>Id z?qo8NBCHeBRFzY4G-KTe&6i1|%7T0?Wz0vO>^XZ2r?ac$>=SVwIq0|iWYr?`Q_=bY zH%7uidQ)oaLbmHmHO?+JrO$@8PwC!`?550AyqH}^Fn#K6^xn$4-K^K6?q+}E?Kd|t z(rfHPHgs$}Lbk3?A2wPHy?ZNy$F{vtR;+Yh*y=r;Hf6)5WJBSqPnS5bW}KdeQ2TzT zGqpa*IG@WX5|~?8c94r0i0?!W9(sS~tKiPD@jeof?q1#9IgY%WZ={#3K~CW8qDC}9 z4nn8atjre5m7SNc{qgWhwt0Lm28Hs=c1&T%%9MTD9I24*!4K9MDyQ;&GIjguw|iT( zTy7hBb(^|d>1WxpvRhg{U4}&OAeQ_(#0^~!U zgD+4sD@|f2N|FPiyx1|t;&pa}g^6W5Lv^Kls0}+pu*#8W)Fvv#I=@maL$~a`ln5ix z_`LYSYK^0sq1Hkj-lMgTkUMC_1<0fb;@4JwEd_b_vndoFUOTDW>k6XPh=!)nFz8x4 zDcRU<+Hj!QhwFIwbo49nUOr0+6G{;jl*?9;4A7ir426U!FBpl+kf`RvpP0ZG;yz;< z{#K|ir>L;b;rJ2XFydR91mcF0;Z$%kij4xvIP-Fz4%ETnT{J$t47!mvhvrZ=2F(z8 z&{E+cm_YruG=bCji6%ByF~LXL=a5{Bd`IoaG{hS;Q3jbtRvBGn1Ubj;^UL7k`V?8~ i)R@=;&|+A(JX8|g;rH0)Rmvl4O{|yOc;@h4p8OB0={=zU literal 0 HcmV?d00001 diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/cs/LC_MESSAGES/blur-my-shell.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/cs/LC_MESSAGES/blur-my-shell@aunetx.mo similarity index 52% rename from gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/cs/LC_MESSAGES/blur-my-shell.mo rename to gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/cs/LC_MESSAGES/blur-my-shell@aunetx.mo index e2ddfb112e9e274c7afbd9efab6522ee67803818..f16a79263315ea5c6201d489717f25897a8fd0fc 100644 GIT binary patch delta 3132 zcmZA3e~c7o9mnx!y}NSdhaf#TI20a13Y>S#(o)Kg^A7OjxC%XmqF7Lv-JSiBo1NM2 z&Mw?F=4{#qnidjzsSP2~Qj-#tgT$>R#*{yLw{5ijqY1V#G10~}M%!p;j4{Dze1B#a zFnz)^uV;pNetn0ws(Su8OaZ$P3nB@?|F0?osx8V@( z!X0=TU3?ec!A-o>i7j*JgUfI(_Tds7#`(rfm?Vt_JSZW3&6CahQ+O};KWg6BQ4_t7 zaa_V^TF4OY!hN_UX3SYEaDRQCF>ScxvyFueA&<-vRKEgtFuyrYqm>7znm&)8@LzdxZC{1GyTxq+L|EF`+{AZpy7;t2j3Cy1um z#I`ihPW(2Gpa!^rTKQGf1lLd#yovlV?{GPVA7DHBtZpeDL%nwfweS~F^Sq2bco{X{ z?-hSF{=x%w_$RVx^KaaM^N5#1Ho!#-I)FMu7xjJ_HSic_@oC(Te?ukfj>X1o#KZU< zJcEPyG4^AkllW`L0ja99d<(bZEK*bh@5Vj&2)>5raWfudn|tvLs^1@R9j;(jCGjw- z|9;d$j&OO4d0O}Md%W8$`j@_8eihU+t`mc@Bv)E zitwY0+RLFCxYB|M97ppy15FQqY!NATCk#Ae;SL`C0!KMf_9 z)ATV^$0txBeg+AOc^)6cpW{jVsCi#r)A;rL87g@ft!@0Et-*)6-;9dX3Dno{0`ik# zUcxr!H&*W)}1Zu|)>IjPX9=_X4{2!w63U53334R^-uWy{~k5N0W;~e}Q5_R(-lABS!=&NX< zZlbEpZ*cp%i&eKRpC-mm{&)wJD1tbrb7I! zW_u@+_)&g5jEWv#Zd8bR^iQ^K^eg#Q>cn9#ho~HN^aF7K2dTG8j)symNmcf@QdRn> zJEB(OqGMFOi;36&b1}InfJ5S&1BqE z7`G$7H)frxllPpY=h|cWFlWo56XsJk=~YUTPb^+t%Pww>4O{2`roBC0(eYic$5zU2 zrsCOSIoGGH@w0wVaC^%+*YnntZ}rT%1vfsK?OZ;Qa(tU~)i2$c^V18P-IweiE);`O z==h=a0~X|N?OUJhZ@eDn@@4C!!hF>U-E@x~3o5pp3o2e(?`mAuo6KizIiD>!w(58l zo|J7qq`&8N*|ZzFrF>ALyDhpU;!|+^lv|G1vYp3cb2s)T?(f~O#U>J46Sa?*tcp#} z>sl3CH<{>K8hfDjP*Lt5J#V9#lQ;+Gv_#tAXlla zS$jP;65SR{0nv9yLp$ySqwG7U_ow1^FerzWqCb6+u9b0?6%>Nh^i=aWMyD_40>&EW zt@_!h$7G^=+2s80e;oYOO01^1bu#s9`Ouv?6%AWIo7dR&YtvKJ>GMo_YX=&-K#Z#u zJEViN`*m>f$(!A4C%kAWQ77hUEZr?=@zF-7;yS9q`W4UBRII*IWRWF*<{T3=j;yGO zol%`uDsOow3~Z+2kEUFk94m7IzDsDlJBxEdTXnrr4mGzvNOPi`t`4$CTML8wHFdNc a@^~&N)z9b2;p+73qk%sbuifm<#Qp~??ghXA delta 2287 zcmY+^Z%kEn9LMqRjlc3o1ylq?uc!#dg$wc@1T+McjDI2^6e3_!1{+DObe$ZtnPpp& z)9gtt`@3apw|oGO&8=c?^n?ffnPuez9<*9pYt_cm-k)>teb8@w&+B&%=bqp1_x*j( zdFjwk-Olag$O}drBGwVr5oRx9Uo;2W^RZ^@@f4=xn;3^P*oa@^PF%jsY#3W{9EU51NcgoTs85kc%-`fGJppnb?fA zID*yq0oLInYNcCQ-YzUgCG%-qjnCl`d<~ysd|RTU0mex~6+Vl-cnvkvWM;DpGf@*O z;-CTQQNL?LO|%Djl=WjNj^Q}Ii+XNavRMmuBFVCM(9wfFq0@!4s0XZJnVNAnY5*T< zfD+`-syLj(7G(SF2Ta37)P0(*CLWC%C<*g06E)u6kX_2ZelWxZCTWjhA)Z7{ zLf!Z~=3)UQtK#fI-9LyLa16ho=+5H(oVRjO*H3cLN-v@&as}(~E}p>J470Cs#-XFv z?mUMa{1}zeZ&5||Gm=%ihk9TN7nK<=GN$=a8QX&_%1)prejdwl0ePb>o_F{WT!Dj3 zcodaEXJJDywUyrB%z&LE3;1aqdTD$U#;4 zIpmeMOBjXkp+0CI;c1*j4P3u9n8|&p`;K5TV=!7u1hbW{`<=~Urgs2hv61#fs6{hZIB zR`@IK#U&iT21>pe-^VTZC-MogbY>TiK4kG$fgX$@!c7xo#~pV-U5q4HklQqwaMJ?^ zi57zAyTzziR4Z4jCW;9aS0@o}%AA@q)$I0y2fa-@hy)@+pFO2iX$3BJH3jVY|;?=JOYN3yUgC0=Lrn*S(Ca^s2aSU*quT z@c6*-vGGc8*YM$E1ILHGCHek9^}31Jz})7Ms6f-U1y5isFV-{ljn5nSD!<0_AK?Ak AvH$=8 diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/de/LC_MESSAGES/blur-my-shell.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/de/LC_MESSAGES/blur-my-shell@aunetx.mo similarity index 71% rename from gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/de/LC_MESSAGES/blur-my-shell.mo rename to gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/de/LC_MESSAGES/blur-my-shell@aunetx.mo index 2a7d711fda231b07e519c843dc8d2a9f811d4848..7785a819257c886d6baa226cf3fef7f17624221d 100644 GIT binary patch delta 2478 zcmYk-TWnNC9LMpgg>G9eMQ#NuFp7fEZfQ&9QYtMVltQ@|3W$Y6d$zlA_iWkS0)n!N z#sCS#q(P%i2*`sN#YC4F66-CzDEi_Bcz}pC+QvkK_+&IhzrVAsVZwhua}IlE{%7Vt z+i!P%-ZB;LeH_$w9}lQ#E_FlG!l#v;#{8H3kBoXPc)!D|;a(LOB4OUM{z09WFl zxG0BUmKfK`QN|3%K2#zD$UpNhA9`-oXk*4RznMg57&n50R^k0zFF*~@hyh%WY?g%R380UCH+ zW!{3CpcOSi2>EBCe4N1Nkuor&$!;rnF@()z1&lpA{B6q2Or z!AiVEdjVxyU>*+L6 zAsX-mHsR~I5c_d0PN!t`Kn!Q&1yr$KM?Kevn)r8on-Yj%+)jnbgQy95@F9E)N#0yRtxO*(kvpj4`wv#&B+e|kn?~G$ z4%TBYYD@0oR!rwlXHqiWg@?J(XR}MZ`@!r0A=E^NQHh*HCGZBSHr_{_o=d0+KSpiQ zRa8yfK;|+(V-RzBi$<)(s=+SKATTzL%qE;%58b6Ll@i-PTzZo~13dLzS9BYsxZ|X50 zH)1{RK%JHzR56`Ly-_df`78JY_M;Ljox`sxu0V~u4LLZb6?-s==>(mk((Do+K~?*k z=-?kXA2*d{SL7Hj=DH7;;Z!zs1n$NNMzImEVH9n7_PGIHv`^j$S=$57K7y2J*8eEmNz>yU%sx5xQ>jL?g0?fyKkINjvm z&wgkfmk=X~Tte$pO(@N$2sIUh8cCWeVxukw+Zxo`>$NShkWjf(%>FM~D=s4LY1(pr z6A6|1Y=VOGOS}$;+FCl=d~KXIRcA|Ut##)Fm^NY)G1OMl*+~=6e=d z@DIao{|-mJ+sPkSu!<`c*7nSE`7Z`W*l469oU$qRKq~Wh(cVC#b?&)kL-B-7gD>?LJ*p0d6nU3NEId#>+imG76JX=*+ zQ&Cx3K`U%>lBr;G!ts((ClycBXo3w+qRrhGiAG&p+nI=WI59WjMZ8F6%H*P)oa)S+ zDd~aiG%x@-}N%*XH*wB){S`lm(m#eM(A>H!nQj}yCIvqceyupFdAtK s+lXh^#AACRo|B5iJsXRpY`Yu#|6#IsxRJ08{=03~pyiqG%F;Ri0R!qVuK)l5 delta 2236 zcmYk-eN0t#9LMqR9SB?m1SAj%x)owb7cS58q@X-&paCLD(#1=r8Pw$tXE|>Sbv>+q zqFT$^vSrJyhqb%ddKl|rgKGZKm>YjMaXri}x7PA6TW$6JoFiMm@jb8KIi7QV-}C!@ zf7iBjBmH-#B(7v%{3DfJ~NMz^GpI37tWlN4+4M&s4@mr~&+_ z0jiNdYvAw__9Dw~S1}i_qwZ6-N<0BIPzK(Q`Ka-_Z#$^@*8?Fgkfa^Oay*Gjk1B{G59t|u^nuOYeGB0hxIuo>&wyIP88a37w18QmdP_;0GyxT_6kJH$NALCB^ z3;VH&uj9j__A;GOE?h(vTgts=cVQMrunK4O@2D?tDrC8^14H;O>I=P_+(ffbHB*A@ zM5{w3-ih(pi>!wAjK{aQGkXJ7e~`|8IyLw?4&tBKfL(0b9e4)U;&<4E zm+=@Du)w~f?mujb?+}gKHj#V2NQ|a#?CZKp~u;$x~R3$&1xEawdu)Sb^qkhwPs%PHw?xY~Bp(V}a?b`si4n&TFNO1B`f zmso9WbPf=zq*S7w2oY&SJF%UpBZ{1K>GTi}5~`3S02g;GlDbGMSxDTJP=PY=qb!dn;)sF;<@bcw+3goQS8P z(jTbx2daJLRrOW1B>`IU?%-s^-yaT+PaX?KCc^c;?r-P9Gk2ZG6Nr7VG3t%A6jpj;EB-0Ze@G_R-2eap diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/el/LC_MESSAGES/blur-my-shell.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/el/LC_MESSAGES/blur-my-shell@aunetx.mo similarity index 100% rename from gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/el/LC_MESSAGES/blur-my-shell.mo rename to gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/el/LC_MESSAGES/blur-my-shell@aunetx.mo diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/es/LC_MESSAGES/blur-my-shell.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/es/LC_MESSAGES/blur-my-shell@aunetx.mo similarity index 53% rename from gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/es/LC_MESSAGES/blur-my-shell.mo rename to gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/es/LC_MESSAGES/blur-my-shell@aunetx.mo index cf6538f64b939a4b702c9ccd19f8ea4e8763b69a..c9ea2a6b33dec656ec3de76536bb9bb080e7c1a3 100644 GIT binary patch delta 3190 zcmZwIe~cVu9mnx!?Om_!QK;>;M~iR|tp!T&w$~rramUfStEKJPmXrR_Vku>IcW!rd zcIG-Wd+n8&1qtdOmRL*E5R{}60%(gNOC&LB(DMh07^_D8gQTK~2pSV&{1sH<`!ln> zHpVA?=Jm{Wo*(mkzt7wo2Y+3tUtHXB+E6^|2dJev#^{H0bGfL@H|7S&;R>|40Pn!< zxD7|~F?8_)zJ`4~)QNN2>4VqdRXBv#;uv0IOx+Y{EaHa<>1!To-k-pmxPPj7{{z%S zzrs9T%V=82cHD-0a3E*Q6IkW`7YmJP#nG#?g=|NDGKW$9s@TE&<`|6@emK$ei}-%- z&!7f)9^3HixCCFu>+#1pjBn!*uHkh?Z~|F_c^0?eOQ_BK2QJ0;Z~{Ac>qX3O9;7ja zpGQqJhuQDIc07pNQ7e8LJMabMpPAvJiGGRd_dC>r|A@?C-oZXJi`iZ1M~(Yc9LG1Y z&Tg7MUP}XQ!H?lMYJg`^D}Na^!FNy-{1EwPUgL5C-@thou)5`V6!qLm)WXl8=J^VC z;|r+yUf2Gs@fJU*!{3lan}6YYT*!WD%Z9mVLHkiLbWzX8sDY=kjE~}8{4*+9N0%A1 z3Gc&u@g#1=KjCKV?PUM;#v!SySpEn{u#FVez&mgk?!#~3S-c$&@S3~vB&y$Ua1C}b ztCDyO)qgK)A&0q~COMDeE!;2SsNIAEbsBoJ2k;X(iCWO>IE@?0v_If^ycJJ#78S!+ zP&@Z;T#fU)vfNmQI!#+q3)qi5VjNtH58-uq4u`P*DvgaaT5T5V0X)S02!5IsKZQQ` zH?GXK{4rz`%;QMnoAaoNzSaEwRaDOW7L_w^p?2V%=6(CBtltu3VRf^ThPG}L@4`>w z2)>9r@h_-1-Tc8UhC5NQe+IRXuc5O0`$*VLKilyf?nW)(?|2yB!y|Y<`>q_ifJ=4$ zFVf&7n7^VXYP&hh<_>J-{(59=vkHfC2Zs1LR1W+T6}oK%Ry*<{Dv4jgBK{mTejjhC z@y2i-j$;e+n*%ho@q)3z2!GG3e6ZQ9Ie^kDVjBS38>bRJXffm+<Zj+px#9trtYL_%T)%c+Gdq~)YWP0 z@?}A@$tIbPHrrcJ$vT&MH&uzJSgR0~^iQ_h`bsJ%>i2O`OvsJ&le-_cQZJPXjYZS~ zwV&ETRnf;|G;L*<4}+3eMImyi_fuP`DhjiT@`AK7AE$EQ^!}I2LYn#*DXAu?Iwl9G zq(^#`mZSdks@zV!m#RFuhpLi(xUyz??P|99s;6H;-QG#vM7^4tSGJ7NP-)kt@u_)_ zw6$B`D_0VmxW|&lyVtzbvUE>a3rcRu7Q-lTBO5s-uNF7XcRZOJ&f0b&jBHYIZKNl? zplscV3AdQ!?Rel%TW8Age5c^M_NbRsY@9fWSF{Dc7M*%{+3H4lSxaurI#*0PJKm%d zxPG^-#qLDSw?`{(KwIONgRtuM#1+@~Z;mhZthiM-f2!PhL%rw(w&1E?DVy_u7q(!i zuz9RH8Agc{BsK_HkUKcEuCO_KJgIoGb&82MlR z)v;5KU*nh9dI|k~e}yf%i5q!gM0Y#sM(j`335srlVRW~p2aXY_3f3Nja$|p&eapo_l`TZ7F@Z2 zY*xl=hH~bcJZ6hECn$xMZLBqWrORe3(^YHMDd7N?9t3wMIv%J4pq+$k}%(RwEJN0zt^n)E&u=k delta 2368 zcmYk+e@xVM9LMqZ1^0TDz{k5JU`4iFSX5=6uj6%5cw)DG?dncU%>La^4AG`Cu< z9JV$6qui?5A6f0ne@a)QvYP$l+FDBH+M*w>-0Bb7T0fqz`?2*I?|Xc{U%vPG@&3HO z_jS*${o$M0$uAnsOB51yNoG%D_gp?`Po$bH!zXbGzJlraK5oZPaSP5*GxK2^Ud4-; zhZ8*P#IraLKfuNKIW8~@+xK)bx$!&l9ZR}9cAbGGTrZ1XZ$nMA7v1<0@)f&+&3Fwr zI?VE!Wr*wc46`}-5o#eGUmt3#w@P$Py?*N6fDDqSdB}u z1?%xJ*5Mo2fHSC_u3~$QScOXFC@#Xsu@6t<2=m)tbTmPbG;G3g+>aMgE6rv#Ik*(H zuyuTBf+p1W_MjHpg$!kfa03P~h_9o@&CfP##ZDwy_8NvY&^vVY;bqhSxolG_E_R=?i<&Ti?^1Nn;A*bxxmkh(s0}=igZMJ;!}J2PG3>z~aXL)r zUOFH1?&*x~pi)#yg{{OIWRrFf^_GNC3wR3kTE2j#_!csh-9Q!NELLI_59ufe@Bjwz z1PlHWk8mAsbH-A83E6~AAq8yHsEKZ)?$4qI$}Ec2L>{s!TOPlzMSZUk8Qb=tGB=Fd z@C-KKEo{M}d!ic++YlX{)i~;mzd}uT9fSA>p2xo8*u)D~P~lwX;ZYn#)yU7taoa3X z$Cg3*lu0M5NL{G$Hz1E#9oFmp_s|J&;~eVjvp7JV*&)=9zCab{H`t4}Q4_STiVfI< znqUBv@hEB`BX|;@MJ;e41>(XYoP({H!~E7sN2wmfjX0uz;M;LOiU0pPDl;><75_!D zX8FQrzhS0#-|w7v0;8})3&TqCBLw-6zRb&UGm&UJ>7)`mG#w~EHqk=Zg2jY~ z*h3`RHah!>bRvVOCA@^Hw3(>yYhsY($h`R{=nyBd|R->4#DcXzu zrt0U4bF&6w9nnFk%_Sa)_RJoROZ`M!IiKA`A#pIe1v-ty3gZ7wRiny#DDrpeL`vjT z=7r=)=b|%?NL603WAfF-OCrbfn;qdwS9!IoywX`wQM-O!X*n%@rzdpG)e-dgLq|Nv z0>N76)MTjF6LdEFg8r#KW=8e*ANTb8Tpd2oP_46l*yBGO8kj67_{~usNiTG#MRu>8o)c*) R{mBuTaCJK(|CDt({sY+r`wRd8 diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/fr/LC_MESSAGES/blur-my-shell.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/fr/LC_MESSAGES/blur-my-shell@aunetx.mo similarity index 54% rename from gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/fr/LC_MESSAGES/blur-my-shell.mo rename to gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/fr/LC_MESSAGES/blur-my-shell@aunetx.mo index 6dcf7e46acde23004320278482776bac78132093..0b253694253c2b24dc724791a2aa83441b4b90e8 100644 GIT binary patch delta 3186 zcmZYAd2AF_9Ki9nQfL7y_hC_Zf>(7&)9})EZK#5D9_!Cz4#TD$);*!TJoU9crEs#Jm6WB z$X`Vn;B}M%-bVh^L3X?F3#>zz=+4B=DA(;q349OAI8R|SzJxN~XOe&E9OZ=Ea104r z{fTq1o_tBlI@n1-Yf;wFpj;oIJa`M{aR;u!A5e<5bD~mnaXns-yYUMA4i{qUB=Rpa z_9#_Z%Xe@Q)>5MK;AOZHuf|vKNxTHFW16dQH_Cm7u?eR!suXcI%Kd9l0@=XsAjNqr z&f>U>S8X~5Wjah&J%lzsj~j3T6}Al{Jc7UDY&^uf*ovo5OHz0lN--`+Vpj!}4Bd$m zz`aN^)T1afez|)56JE}7d8kgRv>WAyowynw#_dG>9d6{fM7UA|AD|5QDN^|AHJpU9tV0TwC>{xV7tKZ#O|KcdFr&HN^jT|h@> z+JQ2ICAb;aU=|OcJh-(*DJH3w;zsoFDtsT8@zCU4|yx0@{YS#|H>!R{O^pQSC^kuBrB=9(Y0GLX#yJ zOOqOqja7>OWlLYal9$uU>)G8vqn6@N?pnNpc6=+)8BOb>&7;-OWNW8&#=T@G>n}AT z+jN>mlh;n_O1Ak4@$yoCY8{O?QRaVgleNBx)=QIDs*ZLYje3a-hp%k>@qzd=d_7W| zaS_V78)=KAQ{ARjmG^yWwJ)#mT-q75v{XxX^#`d?Rk@>XTkS~g*!e=JLvu@5`D4`n znhC4D$jzFp&Un6SeC=CVI|?cy%+nJg;QA#%b13U~-Y8Hy4acU!I?L zy`pIe3dV67gX4D=Owpw8&rh0K&RDMQGjd-x8S}q^jcD&%*j+4nerUO&c0B?z3)*M* zEle&C3wEHbOlbF8p~*JuEncL9f)_bixmKP_ynS|F2X?+_>3++JI1^|)zmW zH#*~3wqJQ|#_VAYtF0}b%R{x(X!*WJj&(L-J#4q~b<=^=O8?~VlKD_)|9f3p_cWS- zAMBvyxwb6Erl`^CHyIf)=g0(QT{cCP7iQg_DxVsIE_so!xr60!jTNyVq0OP=`N1Y8 z?lcmdoU+La=flF_bH!@>aanZr^sZW>*T`z6)!OQXk!!SFwDLygb!q^nS(nNt3iaUL z&}R|j>jwuYqa@h>&CmpKDuT4EYEQhDJh{5K=E$A>cp-Gg@^!{Imd*|igo6XJ-p0460f&hG Lz3OMT?8F<` z=$Pfx%agSCWtyeobyOmA$e;blhkkb(SJJ=zNhOsFnOVLO%%+`(dO$gbuo_oj0~X>g z+=iprj2~kQE}%xbmf>y3I@Dy2V-CKEkKr45oc`@D6?JfoX=uXd@gQD8Wf~!yl~{;M ztdDV+`NNEjs_#sGQ)!KiGmVl=W}m|-{o8j`G#X;ZbQvj58i_#=wOIQ7A3-965cu0#Z-bB^GZ{o(1VT;dUKJN z_s^pXwOLh~i8`X5=p~Xx?++Dn_cor_;6qEZg;+|Y=(VS*+dzbgWa$ekB<{VC_9nkT z%@oJi?k8eI1HozX&b`+45V7e@c4$RnBeh|I^)WV=Hy1h!$+DYD2BAf3Beab*&#eTz z-5w@-h-B%Ya*$X|WD=VREo>IiNo*q;2{x`u!dpZwkY3J@5WM!hx6LBtpNm&?SXHzm z+P#|pPGx3{b@h%!E$$D#)0TfAs2>PqV|hiJV33FshrJbT?Hi4Qve0gv;|q5uE@ diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/he/LC_MESSAGES/blur-my-shell.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/he/LC_MESSAGES/blur-my-shell@aunetx.mo similarity index 100% rename from gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/he/LC_MESSAGES/blur-my-shell.mo rename to gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/he/LC_MESSAGES/blur-my-shell@aunetx.mo diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/hi/LC_MESSAGES/blur-my-shell@aunetx.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/hi/LC_MESSAGES/blur-my-shell@aunetx.mo new file mode 100644 index 0000000000000000000000000000000000000000..91c892e7e1567898f56e141bbe73f746dd04490e GIT binary patch literal 19509 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 Q^*wK#219R!;eqIX0i^iLga7~l literal 0 HcmV?d00001 diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/hu/LC_MESSAGES/blur-my-shell.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/hu/LC_MESSAGES/blur-my-shell@aunetx.mo similarity index 53% rename from gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/hu/LC_MESSAGES/blur-my-shell.mo rename to gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/hu/LC_MESSAGES/blur-my-shell@aunetx.mo index 594115a5c02c9301bad37e75742f68c291cf1c8a..b1831e1e4ec873cf8c77695b6a1c08a75ee12f9d 100644 GIT binary patch delta 2847 zcmajgTWl0n9LMoPZ$P0?5h!x&6c7-~a+AA4xwVu_0mUN9#cerzf!STMGhLu+)@VWm zLjpl!2x{7pV5;&$D>3q-*^prLK_7&82?R_aC`jU~ihh5y+khs9lm6#(W_IRW|1-U~ z<@WaMl_4d^4JAU1Ce{`ka}ZxC<3Q=?XUtga#F6+pmgA4ufH!a{hWZ<0aSwitm#_*? zakGQxaUlMLBk&duHYRI|1{hPxg(1i@W_;m%8cyVVapByeI?7-OKSkOwH?ban#|3=| zdP#8ZRTxu>*H8nwiTs(rIq12HLBK^?WBo_ifN;6q5;<_ONk4ou@^RJ*H(Fd006Sys(lqN0Yb<7T{zYM_DXYUG5Q3Icc>Sr0&ViT&rm$m+?yvYSUa2y$=If*mz z3~C@(QG0h6b>Cm828&tGC=SMFaW5)KzrrW+25!Mo!^tCTLrt&;wRHolSpPaIYsnBb zco^5>37n5Na2-~YvU(taPv99;vR+0#cMa9?9sHOi?8h?bzE8OLI9^2-)s&7R&u|1j zgY{V|`>342Z*U0jU=99^Q?Qgw)68e!L|lwoVvD4O$)W~ur11N@xRCQ4>b1Rx%{Yb= zO~6O3cn>yV_6sV97;$Aa`@w~iPJW527zL|r#-O%f7OJCVNSme!l@l)N?eS4F+mGtt z1JnR}a6Dc>P2d);#L98O3S><)6}={1$QxvCqs2c^9fo;Y4>9TT{Yb!Yp{d1P12x2UB31vR02Sf&;S(YmsC7&16B7B!$c)YiO#_4p_5z~z(j z13iU$?kvXeJd#&t!sPsb7NI88fMwW>`h6RAppOGJqhVwUbu$i2aSiImji?4XZ0%=35*pT^rb0H;jPKR0(e>(3y}QZDqt zzJ!V%*4}A5ULaIT2v#^K`rP&wy;hdkKrr55hE1p>RZ+)Ujk!cK(OZ-QK}IpD;GGZ7 zIVedqOJ#8}p|?OElm5guLS=Iv!??{XVq@W4tRZ-tO(WqD^9f!uLp}%FrWId61V#Jb zTeS2o1lt&VG^%k4(OcG0(LO3iw9I^)g5^|h@KTsoLLZghqAk+4Xp1U{MMQ)cL^Kd} zL{=Y*iG<2}LZ4B6V3Z(A!Wl#np+r&{nI}ltm4*5y)IPJl!N2I)_#B~9Myw8M`G01r zYRgsl#D{{91|K`~lCDse6BB~k{lhA%VPZ@7oPMW^YEtQVG@cB*&Yp16y3XFXA9GfO zy_n;toDI6v{ayKoMg3DrKOOdbyR-Y%iud|tS0=+PuJs&0W}OzdEuD@hqfROkoIkY1 zS|=WHJnPz4+H>N`;3>P$w@ELaN>1{e)E=LT7c%v!bgOmTcr@laK6m6VcusfC;CSCg zC;Y%qP9&8M8Vcr7>$G_`(#CvZHc4H>izZVEJI#w(*QJj_qcNMXq3#32uaqua+V0r2 z-D&-JVJ)niNO`$VFHA@OS`r2y&7JYRTvs&Lm0^imN3Sd{Uz1;>c0bj9x_VU+YZSFR zb6xI!+a7nq|JQh~(|=g=wN6Y!Xt{7SL$8TkS8~78Vso9Y%c;f}ZwV*4;$&c#b#v$3 zj1AS8HM-Mlw`p#(zVBq>Zmu($@*J-{cP?Y2-FIrX_21h3pR07{wI^vk?5o#cIb*h6 kgW!6~t9@`G@3-max)R|BpWU5GhmLKWJiL3y)OeqN03aN(oB#j- delta 2167 zcmYk-e@Inl9LMqRyU%vShhb(jDA7G^-mB{6hVK~$g%h5oGa|X?|D7v-1D60dA`qc zjxV{kx9+PoDeuf?RDGp!@CMKEP!hJXe z%eXlU*Wp-<;8Z+}g-WYEH^;pAsGnV*hk9#?P zLND=HH_jVCJ@RL*942802Job7)a*2s54g~aYIp?`@G4Hk>zILeumWFU7z4$+sP@IF51+IyUa z@%*U!GEoDcgX*Xd^DvC+a97MW)cu`E-}XHgVb4U?Un9BA1+r?xu^XSG9{3t};0Uh6 z7Sf|l*pDCMJ#4@v^85)lqh@#>wN(FLC6=an&pUu2&X3}1{5_5Q>&6te>O8DPZNhfc z0KP?acmjWBlU+jHw~;i=!9z$=tPk_CAM5Zbwqq%chtR=n{BFA0eC$I__)e6{hg2RT zZ7j$;$TC_MY5+y3-^)?2;db1Jov497LZv#L9a@XIc#MIz;Q`KlnO^D-BFVB&RK`!E zHg)tzDq8yi)N3(_n#o<%gMC@vfKqU_vF4}&EyHTujhgWJ_{}qFH6SXM^k!RUM)BxV0QXkIo zz7JRNOU~b;2G+#7sofsj$^Nql750M-qel7$b)$x>j>e;YPs4MVkIKv-&c(kl9s{}F zeaWcy*{A^(qSkspYWE*TE%8a5O8<6|N)=wmV)XM=-4H^JbOkCCb+{e(;8q+$ZKeWt z4Vlq}NVExtcN-9cG7uMq|EXU<}UPg|f8gwIVtrvZ` zfzXTs1TTg=%Sv2DaEn{ka#Z#bh)hELsVFl%E9$<-eon^fDn%nz(JudjSVOEPRDy&y zTN5#hC?gUH6;{Fhhot%z9Vp5Y+rgc+&PNOLv#*Fot$z*`&3YT5Le|`UupSEtZ8~Kq zj^J%`zg%F2I#9xdvZbPZ5OQnYlBufKPDM+rqVI`5W^6M{rhi*TloBkzWfAV?LzS7t zB4UM3Vnw^1&xQM6u^LwrT7MONLpBk$gx;DG;v-_TY^L)0=m}OY{@=;MSY5B5HlRw9 zhr82N)kkAFkxDcW6-2(%o7m@fc8|H}cc!KE_?)~6tqIPvDUafve>1A$oZ9Rfzf+vk Ll;ph3@9_Nx!rjEa diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/id/LC_MESSAGES/blur-my-shell@aunetx.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/id/LC_MESSAGES/blur-my-shell@aunetx.mo new file mode 100644 index 0000000000000000000000000000000000000000..2f8f20ff29535364ae5d1fdde658894b94620f5f GIT binary patch literal 11597 zcmb7~TZ|;vS;xy+J9fr47vtP;Vk!>AHlFUi*zsk3$?ojz&3n!6tT)Di)8h6Kegk-`HCNLJv1$TEaWq)5ndBuI#mOeDwy;_~~S zbE>*}b{0D=*ZjL`>zwnQ@B4q3^R@r!mTP}6;*)T_k87|iiuB-5-p(I=-VsH&1J{5* z560jM_%L`BJOUmBKLc9uRq&hO{k-&UaMz8D0dE6u0v`e210Dx|8tj2T0~R1dqu&bm z&wwA|{`2Af8=%(t2e1pihsh+zQSb` zuYywLkHL3>{{wD8T?&P>+E9jhrt`cr@*72JOjQ4-T-C@_g-)d)O*i@lKVMO>wE!R1-}Anz3&A4KB)Kq14QKLzrelV z%_vLy`Urm{&jnESv!LEDLCre{hv096=fQsi#nXfDilY0#kAqKw&w}gV55dR4J&;rT z%|Y4mufPM~^^jBZ9s^H;8=&5Q0eldA4Lk+Dm(6P25WE|F5fp#_2GscPfRf{1z|X_W zw{f$F`xkEW__rX`iFV<1lIs@mEO-%2!9N236nrOSLnYBGAVZ?>fztQ?hUYinoU+IJ z1MUT--@_oPh|Ym`fg@0Qd=`}4FM#{N?}C#1)?Z)@csuw2@(#dX;r?^6*Y}S>UXA`6 zl-%$8fak?Mpyaz3lwFR2@~6|F?0G&sx1e}51~EZYf-(3z;3MFd!4HGq5BIm<;m1D( zp62-k6d(T#L^aXNU>|%9)H>@QjH2HMp8&P~zk>(B{{%0A5B#Fn%NIcD>m^Y7csby= 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 literal 0 HcmV?d00001 diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/it/LC_MESSAGES/blur-my-shell.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/it/LC_MESSAGES/blur-my-shell@aunetx.mo similarity index 53% rename from gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/it/LC_MESSAGES/blur-my-shell.mo rename to gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/it/LC_MESSAGES/blur-my-shell@aunetx.mo index 58a2339614f9fcc75b5c4e2ef4eb9d5ee27a8cdb..f1eb271637bcdc8c19eb971f0bebb6f7cfa806a9 100644 GIT binary patch delta 3139 zcmZA2eT)?K9mnzC%HaVAf_OZL1%7~t)MMcU4}~jthbM3?3Y-<}L8Y_1v%8bd&MY&t z2b^s-Nc4|d+8{p0hotroVpFy08ch2~n}+z1RBe+!{9{uZ(zI3Erin2cnl^oZX7LPpE=Ku2KpW9xr?X?zmJSz{)K&L=Cix78P)F(a1Z_ko9w3P zV_E8GJ08G2s1DAeX8tN_fS;iTcpdpOZ}D>q|AaFzV0PEyQPh2>Q4@axHO}+cgD;`R zdsq9f#^1Q02R=e3ZT^kDIEVexmJRTu3EhLrp^LgdMs<7~EBGMZjsHLu>(D}DHsK-s z3ZBMc`~bJ%hDGeZRvc2Q%H6BHIXuE0(D%64dNSi^<;a2Gy=ci^v3 zxms|2HqaO+Hs)EpA61ms-oWOBr1s zppB^F8pci>#Vc_PnTv67J3fdtd=ph{eK%5I_$^dFe??vh^9dGlHie;y)lvODgfs9I zPG@}cI1OG!^9(+NFQZmY zIA4wWlowGcd;pv3@L3wl&5uyUcn%|c6TgmId$J-si~4}Ph7RVas8KAUiuN3)E6!)d zRmVZDzldG+YWfdnC;ueC>LHZhk zDG_8YJ@ifS2upMlI<#|lrmgHpsl7(|{~Do+A0WO&xP*=^#No8X2M8(XPaU(`XKa?) z-)^fwc@fe=y9<@x6@(75lm3^jwhH%lqN&O~NKiBBCs%nKCMJ(6jd?_Y*i3W~I{FEv zZu0md4OO|0m4rjwN2soJ+?J8n3uR@-2;M-g|MH<6ZzT2*WkOYdFQJ?l3BI!F*ACK; zmc9q7lYP3t@l|3_jrOs;Egzb+@^z{=L0{0Th`g$0goX}PsA+w3#>vhu>wA@IViWgR z(z-PFm5v3YVIwHHC0h)mz>RF=l)OgVda?WI+(6d0!(A)a^;=6LWTUuL} z49=YE`D}cggtl1qoG5H1tKOTwY}Bb#ypT>=trJv2KeSF1g-IBcoFr@=T6;0KZ^S1t z>1~W>{WZ!!LO&(%^1U@TNW#1w_TqXNcm<^T;kY<)d*LTTwXzQU@te$^?wQ4sbrdObpSY=&(IO^Zaw@&no<^Bhf%kWVE delta 2259 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 AXaE2J literal 0 HcmV?d00001 diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/nl/LC_MESSAGES/blur-my-shell.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/nl/LC_MESSAGES/blur-my-shell@aunetx.mo similarity index 52% rename from gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/nl/LC_MESSAGES/blur-my-shell.mo rename to gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/nl/LC_MESSAGES/blur-my-shell@aunetx.mo index d100839edd977be11fd67f54cf7c362ca768c694..e0be4d03e32e5ab2099e762168975e44981378a7 100644 GIT binary patch delta 3181 zcmZA2e~c969mnzKV@%CtXw2nCh`ei#rq>gAE!Qum*Jn`!{T@59 zjovhoKHQ0exUtEY?_r7ScV`bZ<>9;PvdPoV~y z#^|@&J{>%-%@GoT2=0CU&XA>`lY%4#S(7mV}I@I$Ks^cSAz+*Us7g3wFcabqS;eH&( z<9G-D4Yy#|V&bnASJ4`W0|}0IO@Igcs(v>RBhsZ z)cZrIi5%eP6*lKXcmvm#qjoLss?pGjBOJtIxCj4$qqv5h_C7v`EXstOMdn~0M{U{@ zsQa%XK{G!?wvl-U71;~OV$DBL1Gg+sPQ!Yf{X5;{v9Z2xZJ*Yhspe7ihB5)X$x=B=oP9Q<6nIF?==f+u7?mj`y zZ09OE!{<;dxrh(oXQ<7%@2g422l1O+Ka7gRr}#8py*k;HFXCRVPoh%&DJnI4iGQ2U z|9%=;Nfot{W2oKy9h{CYAki}~<7RvdkD^(VO#CrC$mLH^{mi>ANx@3ggf}23%^XKf z{0FF%zlJT0Z{DOqD9l-W6wjkVx0O4GLK+QGkczfR(cxM!5Mr4e~tTbkey@kb=-mHu!@Vwn>OuJxE{~r z9XPLpeS!C(COCl#`7f}D=kR0P*h&0%(XcnNVX%a^;~!BoUe=YoIGFk%5*%{~*_(|s z%t0~Js2WH`5xTtWFV>wDw+kVR;Z(R z6;&liCGw4;jpkD=RXJDDr+0UwmHaG)`O5!6s=~UJ`ZcPfs%)YjXta`(usUr|F*9ut z4DMTr=g-9YU+=)9-T4E27aL! z+t?kB>z~az)4Xu7QZ46P&SooN*@ZUra(*?cpIY#I)7GSI^OexXMQ1}j>6Z)EF4`#eVn1s$K{cFwbkXX1VNr8azx6H~_ELYNUfBihwi>y7 zHL&AFSEjB03*}15bwouM1Z$$HH;b<1IwuQ@m({Xf*=C&H%Ozv}|HNkYWVZB|Mk`_L zm1A43Fd?_8=f=#I6{+JiLT)RC|soJPmsRlVctA3ep#xK~&FO)nx<^@&m zMAnaaKM0oCoQqxPS3+L5qb?*qC9j-yQD?od_;Azgn>xBSbgb{P>u%lDwXXj6w#`jV zH`muL`Ji>-Ez6Wq&Y)EHb{D>F(>(PMxDu{iXFm-NWgi=;&%D%-w21G{%5N$WIy$q=#C zY#LjF3AvgbbK#ih6<&oD$|JB_L1D>%MnepWXZW_rG)|!( z?EBpNBCO?pN&3DG)lo0j<2dpcyNT_13mZLV z74-5v_uWNi^YAOwKyD&G`=HgU3`)L?H?-Y;3&(m5nsUpoI;J%$7o8i8a1#r zT-3o<)c)a(N3ok?psiumbO)-qUC`@LW_!CAb=^QT=tK?bG_}4?{d)koGJ-gd?bdTt#-r zZlK zs2BghIt-DrO3oPS{R5~DhjD_WJB1H&ALd~#4x%O$$1XgBJMkAhg3-lhxABTYg+bcu zoITpGaa1x+qMlD7leB3h9qbNj31^W>*uSWb%gIQ_YOS~%`>_o_MQz1w`hE^$40sD? z`V`Nd^Gn^OT^Vp2tVb<<8SmAO7|0; zk88QDMYhxWQ3HAzHN#QV|4!pcoWMa0)w!SIF>K@hGjxto`IE{TJiLmdg6D7@-a!q> zPljoUcj6B0$LH`eZoyKPO#|A4dT%W4IMTOWL=WZ>nWE%o=bh9!)x#WuiKdFaR+*xi z9UwXh`b(V>9Z}6(rHP0T8gLJhDcU*}`nK(Q(pjx;1n@)kN;yL|-9Ya~-@_w_l-lpR#Ogf>m!l^i^Pfiy#rQ=gXIT0eV2&J@&&YFrg zN}I3JP3UX|i55c1p+l>p)O|EnBN5V)C#e$Vs!XdQo=i=FN-MF9_6Z|e22)*F>4~!(w(f|Me diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/nn/LC_MESSAGES/blur-my-shell.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/nn/LC_MESSAGES/blur-my-shell@aunetx.mo similarity index 100% rename from gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/nn/LC_MESSAGES/blur-my-shell.mo rename to gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/nn/LC_MESSAGES/blur-my-shell@aunetx.mo diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/pl/LC_MESSAGES/blur-my-shell.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/pl/LC_MESSAGES/blur-my-shell@aunetx.mo similarity index 70% rename from gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/pl/LC_MESSAGES/blur-my-shell.mo rename to gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/pl/LC_MESSAGES/blur-my-shell@aunetx.mo index 2fc21509f41066f83bdae64fdb6e7241b4ec110b..2f3fe0618f477de0b8f79e3d6ab5fcf57ca48ce5 100644 GIT binary patch delta 2457 zcmYk-TWnNC9LMolDeck%_TuAbprYT#NT` zS%6@a1oxQ{#tg-qsEG_Bf93%fJvU;cG29ltn%FI%>jiA$^;pxEN1k8n2`J-7toi!9$oQYvvjib@U6i;T=>5>v&zw zybU$LZqxvs$e)RGIfDJjHZUWZ-9)TFeXb5Q@g=BnR%10bqsDth`B&vl8uY+%WRm6- z*5LqZB0r7*FC-yoH-^DqB_$Byctkpf>Au)N?mc1OJIP*n~mSpiKNqBTeQ$Dih-?joFCP zun7}+DrqVo<0YKK8PqWxf*HC~Dw~s8jPT zF2Zq~W%aiKm6?1CmEFwvL)1h@SYC?zk?fg6$o@0$qTX}>*&gO1YHwUYot~?x34D+G z+&$Dl|KU^&PBUf!&cdCz3)k!XU!bCt1bAJgXcNY;9objr3)Fzu@I}1s--l-y^A7iW zP@D5Ew&Oq8i(8-cCjKR|isn01KYySy_yB`C|K(44Z#)4l{xJnLp$0sGZ=*Kjj4JQk zwxT+?gxZu>{Pr7u`>L5XmOywgg+P%edyf2Jt*uj0f zfBz{y$NgWZj@Qif*0Kkcf%j3VAHWS*%xw4J7F>=J%m!n)-XE=6{V1jxn+f~(3;wWCdl}1f6d5-cgxdUweuGf&ma4|xFR2R+r5kO zwvy1ah7f$QxZfPZ@C8Dp&BM*@eCk{Ld$Ezw+BFdtv6SE>xo3AY?k1KIj}$FA--(2_ zv+|;xP9++Mhh-C$ATgA9me3Y1Ba}~exSQXt_^_;{vWqAsv?j}mPJ$mL_jkGx>xn9N zx>U6A+Xx+6Ew*+>?XkNhm91;2sk9JU)*50Jv4ChLREh~LwTh0j3cJHCIxH-x`#rYT zZQ-};SR^=h*m~|F#P-5#!8c0EtavQiP)3Ar^~i_BS|}6 zZDlidXEtv2b=gVkv1HVWCQ}JJl=YDq_unRvuWrR%NqqV8OmV_Pd?scbyg<2dQY-gL@IC2JCP!J60*2rMk@ zos)j%1QKrrVQo3g1j`4Q}mro9t-HYs`96ja6H{>6ddI5hrO|(T<#zy?iOx k7va%vJLCAhWSm^wx_l~~>PYp)GCdLRWoinO=Qaoa2N$g*5C8xG delta 2242 zcmYk-eN0t#9LMqR9RwE=5ikh}y+xuZ7w#1mftx(UgNliSJSk~6ki@53mn$u6T^Mdz zEtjLRC%4+Nty&N6rvK#JY%6M`)##7@VCdoxH(kxvUpfEj{W<5d^&8*w`kmuBzu)hC z&-ZuzZO^UV__f^Bw~RJOJV1m}%wEC%G!C>euh|M5$L07TX5zQlia%fjF3vDJfV*%S zFJV4TaI+8J$3=J<@5i4o+bnMLbe3@8ALJQJxz|0EdQ>1tlD5jUWc`5fMdFX0friKEPKcj;(?C~2t06Sx;Ip;ns9YL;RV zYGLa+Xo4oxa~-IK_8~*re%yo+jN&J#aSL+I+OZ2smYv7A2D(6}2d|(8SjKB=#U-c- z{HO^wB7auP;dN|BKEKUj0p38}r`2lVX{d>Eundb(^KDPsqx|cEK`yXJJA^@e5w(yn zk*{M{Q1?xv2AsjC@fvnw3wc#>zK0v|BKF}e+=5NZ+!vfceX?1s$HIK_uL1k1kj;1y zAH$DOH{Qllte|97oPDVK2T&76aF(Kb6_tS@F4DCzR0iI~HvAa3;olg=nnHF0ei5gm zZFh*nL-;akqR&u8_6;f%Gs)}os1*K*n(z*;!8~r(#39r!>B5b87B$|_sEquM`&e+0 zJ*|br-&pCUHpS;wX9j9Ju0*|Q04WO#p=zQXwOhJT3)qXg?>K6rab!q)4J+|;R54%2 ztyue@n~{@9hT`@soniiA7O5X=CJmaf51+y#cm{t#6=S&AtQUvz8T<~l;L3;Hecpt6 zz8{sj2&zcqs2VzjK0J+W+W%kCIm?B+sN$Pku3tb6conHL zo5EC_Lw%xo9LL+J1w6Z&g2NN2=ibIV=C=>%D1~36w#jAG1UHl3!F0|u*0>qU!3xe- zA#1cQ)Pygf20n!pxShr^Jdf>IQtB4%C~o5X48{lP{FuDpU(4?|=Yyz$FQUHTENUBO zujB2p2nX;WHsUlggk`gOEu9q2*5#6nZX_~JXAs?N*TD&x|5x9Q~@Xj3r(-9 zkG7TY5mf|R$Jwhn_yn<;_+Qf}brbv~Dlf{V_QV!qq3xjKCG^1_CHSFnil70Di7?SY zEVO1i+DFQ(zC{h8Z^wT&&VPS(SWT2T%cZlEc%0BC)jm>1R7~c03%i==sdW-PgrBG< z))Tu4wKQUz(=*$XbZycA_7nW{*uLbo#>sJSUPdct`-$GfIqyVzBDmymdg5k&%+pZm z4+i{!YG1IbCQ!L9K+D__9*OyPN5jWPj)Y^8XpOHs@_g*Tz+qo#)a}&Aj>p2sBC&A! dK;&rRTtS`36HLr4AMqvzig$Svi^^I({{dN&+NA&h diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/pt/LC_MESSAGES/blur-my-shell.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/pt/LC_MESSAGES/blur-my-shell@aunetx.mo similarity index 52% rename from gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/pt/LC_MESSAGES/blur-my-shell.mo rename to gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/pt/LC_MESSAGES/blur-my-shell@aunetx.mo index fb807053f467c5def38fd4841a791cff9421cdd3..1387462e5a5209c31dfc757875aa41bc407589b4 100644 GIT binary patch delta 2853 zcmajgTWl0n9LMpqgeQg%}J728a(xqJ|eR`u)u=1fDqQe?DiXGw1R@ z=d?epduL9F2eAP-AkYWUw*Acu<3UVv1yo3ySwHs-s?v;Aco1<`OQ) zzpyz(&`S^Zezh^Bcn&p?OURG;kBh#m9%9T0`ZuGg4CFz5(HVFb_f4n<+OZs0;c#4! z<8d1<#JxBlzr|K8V_KSN8!pB*sARs5Bk>T%@Hh^me>0Zp_hJ~;(GhIH4{;-2LXCI{ zqZ)yor~!6yQAb(Sce_yoehF#Yyo_`3FsAVos@)YeOa}WfN7l?qDr)FFuE#5=2HKde zM!p`^!DdtkG33W2x$MX1k!@gxFuE}~3iVziYT!+%eimaGJ5l{Tqx`F~hX?xLATmhv zCN|+4j`Z1I20elov2Ov9nQjwxBEkO&Y?QKjEC5S6{JBkJ<7ug_!F{<<{x|l zOUD|s8n@)Ayh!B}`~{migZf}NJ4`c}iONtMbv(038|DDgmpO*Y&^O5bGbd3UUqCHI z4QF>LhOr5EpqBJ~T#LDnscdJ&W%R04?zE&8&mxmIzoR<1hMMW%y2A5OsD`GaPR|_F zfLc)RtwHUXEvSLSQ3KnJ3-BZ4)a1;cRN8njZDL^tK58v@qZ&Smn(=9j;#FjSnvIi; z*@r3Ap16kkE_5$P6W5|L@)fdO%#WxgxKMn46)SZ9OYbW*Fa(w25!j54n8t0m3eVtr zj7%;pNgt}=SMVu(4><^?VoIUCai~2q5z8=)%IHjd4Oe0n{hRYt_|{xOy;ysHVTR*T z$EN{jV@vV*4%Cvofa>5?RKtg`6F)_^lPP7V>NM41Db7S?t{Jn~fw@Pid`(4bH}ZkP zCW)XLieU$yz|B}P&6s8AU>hFAD!hVv?>at&?cu^MKY;DrUq*gRQ+;7cqDB3B^3U>{ z-8=|kIiaF-a&&{=>A0v2BuG$D*f=+fX5}8$p_8CB)=?ZpJV~f%AE-@(yy6YVlHtH!M+WaLz&e6 z3X0bMMroq5m0&dtdoB1oun=z){UNF#w3bT=t@&VLF~R0HU4)kNMp;f}6H!T26D>rH z(5cY!wGz2`T(tRAw99pbbY7!GEzv-f5IQ<4I*Kanv0yK#zJ_?5h!Bg2nZ#N`MH_lW zP%Hd1QtrrXK z@7QA4CSulilWrI7*+eS%%6&THru>ALn&Mk;dxnZ1G0VMlmur)W?s&##c%$&ZxB0rE ziSl;q-0~|M^U^^>!92n?>$|Zm^NG7D>Ka~m%Ik6K{kWS<(nqn;xZC4K@_n_tLd}gc z>Sr|C##!?k=1yy%RCX}o`ZZ}MqT6elzBT+ZMcyw8)e0F43 zebnvEcaCWtFm0*p$Gja`*LvhNp~T+IN|)DjTY~fZ#$7L|EaumVdilNyzlCy(GKpS? zucJ2_ir%@UWSFc5c?gnA3Te)!93`~>X#WY;E9%%nqWh0{L3;a-I;4$fo=v*Ft`f{6 zoA0UHQ?ZiPvOTx_mbs)gsKS)Ow*T`?B556u1k;Mgn>`LAw#n=+OV76?Jd*!=>ZZ{D DwX~ab delta 2251 zcmYk-TTEP46vpv2Kq=6cwopnzg{cKBGEjzchuZ0dqAk56g+al|q&Dcl5C*V`%Eb18 zm{yE2HYg!ArV=k{eVF*rs)-NQ_@J>S+NhB}R1;#18e3l^lKB7584`E8=C{vq&ffd1 zz4r7{@7G=NTRCa387)NIOO&LVokd?dAGF2{vm$K5LhQyYjA1)Y;4b_ePhv)<*_Swk z`PjnEUObMgaTGV<3%J%SZg0?8#~1G*&)7%F>+4Bxq9$0tDlA{+E}$FtaUI4c56|Nu z*S|2!3Ou&PT|hVT&xZNffD@R8uR6xfrs=Hbi&@lzAK*&-5OeVpybr&@o%koV;Gi=n#3UffVWZie|(R-@Sji_S|8`k z>DU$V!9CW3Iv!o9%tVnoGTq16Hidif9c;kgQCnC_g+7Wt9A=?sP?@{S+2urAFSE0D z>qm|IO!7KDNk;=*L>-Gc)B@f|r+84caRar0?@<}JgGza^*F6n=*v|C~YQaCFw(JgS z+)Cc@B;2Z?cI-9h6||s zvbo@ZSRU$BY{fdefOTYMegoz{}W&i`a%eRCqgHM7_WQ#vi8hH=Q8vc+l(-oJJqsM(yR=3fCfJ zm#h*!sDjf%(+FiqM>s%eay_qhl;E^EHAKlc#S6|aCBw&^bDY8#T9KNHO0A2~QPLjj ztg59Gdh^E!w%_@+%Rn`f=DeNykL!b`w`cpE|0i_4+*rRoK?Jq`Y`=9AAwrF0IF;Xt z+X(GhKaoms+MHi5uxfqKT8SM_&)u%ZWM5mOreaf5EvV_3tKcac%hLYuA({!c)4YUI zzTArF)DYU1<)$rAo$MmCultDxLQO|h)vh{FQR_r(Cze|;ode4k*jE3)i>hQl4|U|! zGF^-savHxYrkYVf_7FRX%EWBOTuS1pRhLo{1=%y6gm2yO%EYhvidTeqYe@ANKCsy#N3J diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/pt_BR/LC_MESSAGES/blur-my-shell.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/pt_BR/LC_MESSAGES/blur-my-shell@aunetx.mo similarity index 53% rename from gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/pt_BR/LC_MESSAGES/blur-my-shell.mo rename to gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/pt_BR/LC_MESSAGES/blur-my-shell@aunetx.mo index ff2e1e186fe8850bd5979fa6f440bc96f70cff6c..a68cb99b634d27040e78b3862558c7368c414837 100644 GIT binary patch delta 3190 zcmZA1ZH!b`9mnxAWr2kS!2-J!3LFvqiJBVSv>HpIjnqb)SYwQ_qR1OHYGVBUW`>7) zvS&W$oIUqE{_j0`@QYskw>Niu$&h^Vt>nTqW7P1i8T=^CGG;ksa0yzRjazUShj0+T zfDV6w7jPq;dT?47&)`y=g9Er2M{u4ob(5nopN1HD)|_b9PvLFUzt*n5hMMSCn8n46 zriBdS5RT!!8DqYT73#m7Ys_>U{6K3V!$^}kjC!tu3z^>>rO-jcskYDH2dO`Y8sHl^ z6TgiM@H{TVH*g!ihXZ&A+u4pqWDVwJ+<~v44)dS52>**kT*$8HGrxI)!Z<#SnrIrc zZ^15n6o*kOehC-iIpohw@uP{}LOu6;)Pnzv%wewJMl?5by08f~?l*B1|A=)?(`;m0 z8fXVTf}^MbUPi6_JZgehQ4_q5{Fw{Cx)!<7CeILcN(?u=TP&!h->j2YQA@L z{wn;520ie1WYOk7xDMxXUOKXE{AfXYQFrK2{S(x{$FPJ?;U4@eDp&`*jaiR}@Bp61 zop=eiVt)_kuN_B(s_yb9xE*H_q8j*q+>H<8cX1Lwg8SL#$MH1kxp(mnT*0gg;t|yI zdr%8G%+HSq&f|DH^#NYBmFVge6#bt^hcDoMRD?YN2k;;G7Oubxyo>kXUr-ZR8ufav zMNPB|S)(bU{$Fp`Poj?g>&RNoo2cNdU!tHR%G%al=kXKNAH$Fp{{R)OYkCPxdoH6*chBP%-ld)LV54wV*4gezVxNVrdc5ziyUMxRZuWs5{A_j(8G>@i)jD zW_mwt%!9ZNHSp(9JAMlDcm|0>)3M5!ui|1q>N0M`f3@5DIYw>ZKAeSPsH-}JJ1|9U zMve|6Y-SL?k!fghv(HZqr4*57(?1hun$$Yza0Vzc?Ib~KHw zlTe!1;@a;JB`yAba(BD+Ce#Vtt?$3?N~`De4Oe(A>0}o!U*k~_)!$%I4m9oJjJhp?IS zjW|Fi=9(WYHGY!3U4?d9(Y6Pdx62W|s~8QaQD$JDN8B zJ@1u{MPpGdEVzQrM{($48+!%6mNd>T{7Pn9t89x=Y}2x{v3mMp$+}|E<wbnGx&VFzvPRs$S@VwYHYHVlA*o$}Xg= z@k?P;aeYbI1;Og%>XT(xaoLGd&+>ZS3vJHnxk78s|6kbbf!x-SN;Qg8FHCJ1u^_j3 z;I7=(R`;~*C)UfS{0H_B|YXVG?+0 z6mPb@Ltf60?4GP0bII|?Bl|#{?X?3*Hf~lQi?=hiA2bGTS(?dgXdGN}v2!lBz^z3# zA9!)pSiSPh^jpU~1}Q{|VU*GMkz`s$T5bhQQj+fR&!RPLfzSf z&}3NJ@=-i9!un=Y6ckS&9S8qQ_*tD*@5D{(_-6$d5x?L~eM8c_;I7T<_;;G5j jRIT-~Y@*2a=A$sxx@OmsVH9+0<2Q zR7>-ZTGr+tS$4~p zp6CosWW>K>lpbO}Q59!)47+AqW80K3HJ+P_v=v|wV@kdLq4%fSdZga=`hQo zmwxVBW|>XLFHi%yg#6i$T=d-^m_`5g50!Wx%$glF1Jk+BMm11?30R1kSb_Pt5g){T zScPY?8gHOxx|HeFVi{^N58@nr8u#GKc!2)xE){hUU>VlnA>4)+P$SJ?G+CIB8dwPz zbx?=;t{FAZ4x}mDiL20$0elD5Zcc_-6Sg9YWp86h4V|abj-#js<}yuY{c^;dP?YAE=2XCO>(`YsD8K{oZaV6%X`r8n*UF)w8dU(Jf?Qtx|Cs6}AhwP4x zqTaiVYH%F);smx}J?pCEJcVWWA$H(zxDM;)MkhFo+On%yjd|IuzZ&c!Lp<1vkK&uC z7jIz!7Lu|`&JNW3yHOqb@q3c)I4@Yrsf8(7HmHVjt z$=NH#G%`ya)S-^uCgfZ5BYoKM*#F;(-M@!g+OJVta2u6$seG)J*o@lB=dc-HzySvQ z6DkQqO-_y+l?%vZ?PJu^kD~^19o6tnR6~jPM^8yAYCu`2_gtu4sYJbBgUfLnuEV3~ z!7*&WN#vk}to{MB$9T|+I)-OZGd_#E@gknaWvr`mU<{k^TkOTWMbUvDLDIoaqjKpy z(t&-6O44!E_g7Irbk}g5&i^EpK_0AK9Nqg5u$6oL`e-HEPz~?FEl_tBD!~jsB;^R z-G7cccK2{Swvd5T?Ih~GG1S1vkv{AiIxvBlDx6Fs1wxT?s)z9e3lJ%5VhYVfd7wR4 zCrUaUQ4&2;G*Hc^oQP~&<<%8qJrQw8F?DnhVAGXNl(ZOX)|{bS_6_Qa?o`arb;7~L_(YP5Rpx!5H$qZ zZC*l$cB*Ktw-L#Neil~~J%rY}p3pB=C7~>%gd*o^Gc~1SH!+teB&HEcVHIVB3dv%1 zky>~_EJ}o$5mSFEGk`H?paYpNpAE82VGkN-hp7B zchDbL?X33&2D}43erKb9zc1*lDlYbTR#lc16|dOe=MDA`1uH5ls)vHUK+rwl5BT=? zJ>lNFZ?Jc$JDi)B=SV4X7rT0V2a>I|f5fpgGu%A?qr~un#V4nSzgvFM5x%*y+%c^+ OIC9AC4DTr{aQp{~Z}$WM diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ro/LC_MESSAGES/blur-my-shell@aunetx.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ro/LC_MESSAGES/blur-my-shell@aunetx.mo new file mode 100644 index 0000000000000000000000000000000000000000..7b7e190a5fb2c27ed2f472ce2453990925cd3566 GIT binary patch literal 1762 zcmZuxO>Z1U5N#kpGQa_Z5JCt_7KB(Zv$IYjtn~+3n*=P`iDeeTwRfg=xAAQEsJq9G zO(Y^24jecj4xEAyJ|J=9fDnp&;(+)Kyq+;@6Q!lr>yPTHSJnOc&*x5k zDbSule;NIA^k>okMh`80M2J^_ZQx75bzlVC1Tt_7_zUn4;M2fw9u?w6;19rH_bc#m z;P1dEf%lK*e*uHPe}KQ??3u@ecq8ne65=)BX&ibU7y~~8E&+c8-U9}|pFSbP3&7jJ z5ce)H`2QAo2KYS?rs5~ytH66egsE*X6sOSKBzw9%3w*s;_ZlY|TBWnUG_?~rn?Vh1jhDB$2nFe}SKWzs97T|&K) za(uItTes#D z&V0O*#~-nEVBe`d$K##YjkqW-$x5@o5p8g3tdG~+Q04JbHFR;$bSPTC7H{yD3J2qN zrRNUKq%#-d^n5&%QhT)3mTtcliE)-E6C-%iqK*@Sw5@=l4IJm2uGvXDy8;ku=D>=!=lU5RIp?Lum}zWB1v zOs@2>L$iJ5qjm6*MSKNM)^$ji_0%n#pQC2DpcfX}^bV!ep>r6gbn_+#ueZ~b7O{Hv zEH#sP6n1(VmTg$h%tar^%}c6_dA%tCT}&>5y#6{ZuJ*cc%427njztiMOcr2iU%2zgo!E8Iu`!Ho&CL_@)Pl8E%1XoN+H#Rx*3Bd z7zbfvm7C~bnaLo!dLiYAbbal%(L8u z^QkKmg$Odow}r*2x(rkQ2|Qjrq3@}aiVmMq;3}3v?Ya~0bfo6hYOJ)`RUx)mu8L5o bBSnXmM$;=tdd7+*d>omtib{pTH9zvdA6!qwBcUm*pHoMz*3ot-0-KN}kkA?X@keRcPsPF%-B#w?|(K>$`k4NG7v?1Y

#oHn<3O!Fft$RS0E13n|E6bn#nJC! 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 delta 2247 zcmYk-eN0t#9LMqR9eBB5m^=g_V%IFh%hN?69wdPRL?i?i0io!^MId?Du4E5uUK#$Q zu7{1@m=6YGikB(sw^=;c5=?laqfbGQ!AVH$plJMn95!ZoR8qu7Pl z@Dk?YJU{m1J9r;{h7aO5c)wZHexb9L3wMxvENQiSo{oi_Z-}3_pawdCWq1a;#g?%Z zSFqM&md7YlobO9FTZLbsCbEqD+0Ptw-=CPx`1UuQWG-Qf8TEi1UQ;tJ zL=8}i8lVdKv+W#S#XZRK+fSH>w@|;+Y&CH&YM=}(!2;BH?QwgRf87w~0+Y1oumWE} zP2>WyI(8ZLyKATiuHYEnz8e@+qebGDOnX~KkD}*r~zm2JVkd3%Q>&)VgSQPGVFEKMBYbD^dEc)yYtOr zcr{ALPbbRW(~aj)Z+sQ`vmZDpGk4?HeN>)On}aICjU0-w0hz0fV?7>6?Uv6`zyBBa zV;XyTj0q3n2*2^q^S zVj+Hu9r#z=rj6_z&R;_&7Paeil$zgA1Jpk3rnV9FQ5wJ#cm*{;%O>{$ojA?;BI*rO zA8}Kjje3D1R3@uY&uu}~PzUDWUaZpopQLk=3-4hamORQ^;~45eS5O0dhuS{Z?Z7H*L#6Z>D)pyOOK}#d zANvTq@GDf2iz`UsTY!pYF4lz6!*s^!Xq$YGdoe5ER{tSX zF)g7c^eaA&xAAE#Ep~U!X)NXZOZ4F#)P(OL$ueJwnFmvdL{sgs;+@X+(8Xke7jl}u zR*9wzj1Wpa&vX8HXp5@I)HFfud1bC=;ifk?x|?32DLkIteYNYJHf{%9k%>`0{(2>8WYg zsV=m1jl@<$-v~7?vCHY19gNGWJ1xj@kXTPV<6Pk%-NKwND|IJlLquQftZzOgRRCqn_4ab!kO~KUh^)wXHZvOX~<7nJwKP2~8iF49(6&>iiwgPlx>Nqmk+1(a4y; vJ{*~u2oF!p&Q44>j!lIoCd)=E+e diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ta/LC_MESSAGES/blur-my-shell.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ta/LC_MESSAGES/blur-my-shell@aunetx.mo similarity index 57% rename from gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ta/LC_MESSAGES/blur-my-shell.mo rename to gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/ta/LC_MESSAGES/blur-my-shell@aunetx.mo index 6854bc43596c18cb4e47011398042712d740d16f..f524fad4b139f17937ef96fd7a19842133e7e5b6 100644 GIT binary patch delta 2897 zcmY+_32anF7{Kwbbh%of2c?Bl;FY6XZ7D}V&bFMkP(kFdfRv?uyDctTXtynRWK&c` zp=f+!xC8|>LS#!>L5u-ZJTQ2~n2IrkY=9Vy8o@vUnxOyhy%liMdB2&r^X8uECp%;I zz8Mp|nC#jngeqbNaapX$X58I@2jOfdk-qpPrsGwN!`RLuv#=W$;UY9~JAQ?CFb&U9 z*ucx!1zqtXJuwLrM1nGmL?SOHAm7OBXnrAPk@rON&8Q9S!CZ`>b|isXXJR^zj}dX> zYVy0finPbh-JFgjAg^RF>Ua5=Li)?!C&#O@fxK4@V9w&Enb zj)j=Zuymv~I2E5loy^nN13yO(Ucf}!muU>Y0T-Y)bPgxt_qY@j=#BRHaZJGm)DCXu zp$)x``rRSa4j)D8mJ>J@&tfh9gIaHGvdCNvVUSsrJ0!HCIEJ?v(@-m@LG5`EwSkSO z4QxgJ&Qbp)CYA9b5P4qM6I|8y;zEm;4#$A+BsEZ3=YIHEW_y-#wmC!mHF2Zk7KLqTE2vZ z_$_M1iEPz5n1K&qHJ0K&)biJGDCRM2-MmXszpF&;z#2TtrreC{$xrF+Y|ax{NIomb znfsW87k|K^?5rJppl7acJCU9JMCOtGAXB6QJC zglA9(lFpCk(Tlq=STM*rj~7sXxQVA?MZV6W5FObv%$fQd!xXTmoPZ^$<)6dJcmSD^pj;wxoEOV-otfx9g5HvEL)w%bc_KgKXQ&mt z%f?uS=kPiX8Rd*Hoz@!Z@LJT4{KB;Sjkht6_c!yM3odJ%(}8I?T+e?K36@6=BL_jg zKwZn9un@1{Q5?huc#?{K#O>r4FsxzZe@ES{JtsL!P=c4puR@ASDZ^#CWg}+dKGb$T z#mTfU=Sh4>MLniCBmAzw*`?P|N0MLY+;}rkXCQ!=(ZV6vSi~KIZy>8BS8y&SOyzRI za%3_ki9&@~g!6F&2DK+`ByMk!x=eAJ~+eqaPmx%7s;>2+jtAZ_~$Hk$q+d_Md$M^21MedZuH%;j8vm z1&n~XE)f1J;XPN6`8D4R?dP+UH*BGmXaTK$TG!a0jX@jFrCnTB|8_P}rO5iYYeS_ceRB zzBO*Y>B~0i>r79*&uFYN{iL;iufJxsnNwF~`h0`y{`<1ZTy5rty=m)Wx{k@o8=aFk z-WWM%Lf**mZ#_$5I_Bq8nhkMcwPt2mPxS2?_M{(6%XuXd3P(bxjY#N)Na#qUWm6>7 z!jt^ANN8`QrCFb$Q~EY^$Z8poYDI>*;&#|SP$F!7G$Pl!k(V4^IBH#d+~!EA)&8k9 z{LSPmv4fA@S4YUM<{&kPA}t#tp`%VS8)?=m@0}fPE86Nx+!<+Ux?2Znt7v$d_5Q4G z@mkFOvN_jEDoM5c#mQq2*iG@|6FPa2tX=!ve(Mi3_PjHi({^VzSxw`6g*`KGwi|GW zpY${B3MIEi2i4L<`RKe@Wz#dPd4qbTL_){xLR8nB9i4qEv#59ay$Pfv_r_1d){3ki eR!ebml72&#G{^7SU8{9kfz>x}U^rNOCiY)b8Wx`b delta 2305 zcmZA3e@v8h9Ki9=<(jT+9Y+61 zHrFnjVa=%JYBd%-liEsF_QO@wACBq|&89j3sA+^dvs4^ha4xcRVG`$F)CTe~76a(Ua?HTZ zSd9;31-^|TyoNf{Jf>HRt56s70DACg?8O&xKmE&XD%!z5mSG(}i92u-b)+svlZ+Xt z11sjB9n_nw%rJ3QuDP{(@ClpJGjL2zARYU4xzM&MUdtkMCm$bJIvb?8WbK1&`Rv-2V?| z#!wIQY;ENaA7s-gE?6SMNBTK*;Zf8X-M}o&St_y&>riL72ix#0HlZ&^z5-G1JqfzlB%O#k0gM@+Y#bQdnVaStDvkdr?;)jG7x~P$%|i6^V#P zQCD&X3+Z33QprSjwaCv{j4LoD#6Dv+vO6+_%{YeRcnA5&do?2W;!V^6)Yn=$(~jK? z;0T`K`VAUmk>y=RF^m^6{1=tJ^}GzQyMg`1*bUaXY!rEk^HZoZt=uH?9d=+k4F?*n zfi!JqS-E}(*)=)TWWAy%@IlTmBe$FH5-^L0;}YF}&0;MMBG0T@Z>wn4oY5{$bmqFR zsf0eF8H5&A*L*_Qb~91+nigGREh`De^`j=I=y2IthIYdkB7i%wI&(NXTLHR}|zPLi5B&JVc}rVNHk_B9YLt*uqRe z^201G9NP&VVF?k%#C?Po{hc5k%(6XdK~&9!P9mM?ie9V5Wzjn5Sgn5~cH;fU=W#=^ zMn~e9!^rTA*diyrSw@=IVKeroK5lcC_=DyCqLS>QvbCkf#&ut#EjH-y*}XqrB8j=_ zk%L)Iqc82WH{uC+A{T>h<3!1Df^Ezo7{~FqFks`hF<`(1Im#FUqi(`LE;8=O9VQpY{cJmHOHaGmwSyt1iiwF5 z#5hSXh(r`oR6?y1B_W!u7zlzUN>HL`)EHt&)ISWy81VZ$Ed<~2^z)vxbKcAIzV8Xw z*InI|yi%OE*HD7QP-1;oV|L*y-T9%M$v5V1Jd34x6?D*Ew9)IbVpbsm=D zWS=oMM!4SJ$Cz$d&^J4fLgbbig?g_V2hhKnK_!nHt8%Wzeq3)tHSierz^&LHlQ;}J zum)2&4gbU$=x17*X*15k9jIh}f&=k0Y{Kubi2luNrr(AuQ5~JbsrVJH!$L-*5r=UA zwxI^Niyw7#0QKHc)PUbd+BP5IL_C8ryoqWzR&2~NJcdcKXl_tZLp_<^8XSabpcyst zB&vgFP#rvv{4+1{vm4(+wuPC<=!Reo>bW}9z&D}#*@6|=hU)Ki&00`m%mggMI;_Jvn8xY&cM18|j3=>G zwU&Eu27ZBRxQMN~7>DA67{VoZ2=)9QI2tRNwl?ot)O(Gn0kq&@HsvnV`&D-_c-(@T z_`W2S1}cYfB^Gc7wI?>>CA@<7;t6(~AHPL)kk6SMjsuXk%>-2DmZDO=IrsN4DwDgA zIhj+q6fdGqO|pzuyv>ChxzUEtG2)B3gX_)rWKYNU$QaE}sF~i#-Op!q8bBY^DH?^^ z3l+%NO*L{bOf72QHjcswj?rBAQdz-`Pq7AzM;NmZYf&jWfI2QmQ4RMi^IkNi80UH} zvVYAozOYDJ{a@Rj#DgB#Ysl1Fnb`nS4>_@U|-bKyi z0;-{}QA_n3R^nf%ftQm<4WJqea29fK%wn8_Hj)(cCXz&R4)y%+m{bSBLMzgIB6+31v=&F?yYfKJ$)ZUhamDAE(VLT9(b( zs+YMHTK{^YCov)S2c=GBIKdKo$4=>1(fZCM^p)E{sMKZgz8}io1G#IVENbbrUvwNF zCT=? z#8g7XBGwRn`EP^wRnj?C(O%F-EGPIx-!6lxX$Lpv?o7r2Q9~3F3kj74g!W5y`icCf zd-Ss0P#_q$;?A~s`k%rN@&?v6C!&o`qt(zHi#jnYW;ccst?Bm$?Dy4V>sC{9%!&sc zE2bwy(SYSNH8~A&zqKstwp(_a9dhk@*Ri&S;z6r5ZpT9nR=t~ubv#uvG94(%^DVIK zJG#ByUW*-d+zKnv>NF)>YirPnQdj$dXmi9F*BW$OcU0@GH-k>Z@uvfWw)y%@7*{!d zT-9W&vT{mgRmZi#Wd-eaIMEuk>+92{LyCO9>h##sJq5)xJC9^iVJqUqqaka1bIi5V zACI`)t*kE5W^)nGq})g*b^4$c?mTh&pkuY$u}sS9JYu(GQt1~*|KeMgdop4(XD1vF zWgp2t;kW8+H=0RpZ?Lno4qNpJ*XB;xRktBh5>B|@9TF6BL$QuX`S6a8vDX93HFYc0 zc_b9I?CdCGPBiSQgYAqV`(DNWGNDJ?8#Ae>*LvKE*sWaLemIkgg~=duU~ZWd561lI JXDgz<{{VE0j5q)Q delta 2288 zcmZA3Z%kEn9LMqRjf)r1Yk(mC1jz_e{wpL`NDzSv6BJY=NI=jMK^i$)542UATRTNd(sHv{MLn=Nb4}W4bFIzVdSY9f>;1Xs-Y5OW_r8ATa?bgE&+qsB z9r(TPZjUpc>OWz$Az}ql7iac5_AcUsb~M2(4`0P>d>4~&1|P$3a1$;~G~0*Ua1N(2 z11C8-AK%6$_yuO-w|KvqV+(YW`QmTn8jD-(9S5{mW?-5pG0eEWxvpD%(-JyS7-;|$adR$~CmaT%`1T-<{7 zcmV7018l(Cs3$Gr@fxuTHJLA9I=+JY@hzNSeEXM<1{h}=YVjrP!D&>csbrIexv0d} z@}U8mP}gloCEAVL%KGpT9K&%ukGgMGs#!bkL?+A5p`#mpOs5Mkqi(RA$5h6Jr~yh* z15_hFR?Ekm*p4i}-NG!qjXF=+D)B|Afl{ypb5Y~9M(xu4>w+P^AW0j>N<4x})({k?tCs9lG3pQX*2J^2Q_EI4=_$+S4 z_fRMPg{!fgl2vhbqs|{h4LFA9DY_}F;kc47OK}+Wq^EEY&*2VC%u&gk?ZF#3@6cIA zXPUiNhBr|IBv4^1F%31fRj3(iLrrae^!Eo*Gxi3Ot6jo2ypGxx1?*j&e-QWJ1Wu9g zbv(kc)1U8E{VgOHTR=VOJ=Cs9c)&{_h&nDpt$7KOt5qWfZyl(_2e1f7aSfip?f4aH zMpJp(R_s7#$g#6@v>iS~-8khz@4{?6%yBb*gcngYu)o0UDICFLIE#^@ddS;eT}U0< zC@Qg|sA4`I^&~Pmb`~487&CO99)A%Q{lkK&K&6or`jqx~x>5Okz=xB{@U#!a5 zq?4%KF@=5jGqzw2C9m@wT#PO*!7q_9Yz}=GAYx53$ZR-~eX1}01Tz(BwNZuEa*)uQ zi@YL#Jhr0NP_2&8p06f$60xTDhZ;HBmPpV0(9AqaD8V?bzot~#Clax?E7~bTZLe*y zUtlYto$@%5Ppl`{O_6P^E&4Q}>HUAxjP?_(hEZyf?Y&X!A8Sw2Ng%X_n+fe_P3I;; z>pVbcE5%wf9j$8;5hOMcLxgHa%TiB-h(bcGjp!g$1A7Txg65R-aUY=yRa51vQG<~p zQ@@kwB3MRiAl4E)2sPEk6Oo>`E!EYUtErfK3B4y&S89y}J2uvotM`wD3Tn6eb;4x8 z?M}YncXQLv_`>gGtaNiS{62Ri^RO?tuC$`2v@(=mQMI8m6uy&HkTh~&@A$rf;ekWX oyV=>vK3|1foO3+U{h{Dyy!-u{-+bX?MY-V>rFY$z%SL_w0i;~klmGw# diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/uk/LC_MESSAGES/blur-my-shell.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/uk/LC_MESSAGES/blur-my-shell@aunetx.mo similarity index 73% rename from gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/uk/LC_MESSAGES/blur-my-shell.mo rename to gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/uk/LC_MESSAGES/blur-my-shell@aunetx.mo index dfbfc128736df89faa94b1cf3f6d365687988155..7a24fdd6ae3eb3db9c98fb87be2ebf4058ef8edc 100644 GIT binary patch delta 2532 zcmYk-Yiv|S7{>AGg|_rYDbNB{IEc1fx@!xir3Iy2qyhy*3KbD_t-IT%+b!(2fEQd^ z@B%^rD^-F~NP{sk5W*Hy1gi4IsF<8h2#{bT7=`%3fPU1V{+~UIFzI`KGiUeA%$a#- zdw#>|aO9`_)B}d%BOV~?Q;gY(ucdLJ9L_Li93H{3_!Va2Rjk7sI2YYRjq&0JynvUm z5c~MDg=a7uf5g%F8xAujVv@6r$>T;o@{F07XuGhO_T!1R7d6l(bmIWhhq;Lh@lUKy zA{eEOb~wkFA$T1%k(2wun5y}IgY?ad=Oi4 z4(`O+_$}6A8n2}{t;2cPfLhG=aTI=pKJ3Rl#y3U0{w6F%4b+FT@H1SCH&HX5&#Xq` zGSmc{xM-kG)N|da3GYJsHv6y=4`T=~qxxN(&&%MO7-7}SB`WIZXKchU(!k9j36JejJ7?aWg7OzsCx^forg+fIPxZ)C=~bwl2Gn^{=H;Pll+& zJy?$iaVFltr8u6H)dOuf8IPfo^)l+Y>!^W$$G=I!43?pcc50F145TaL!yWiKYT_vo z&fFC$t+<{C7m!)gX!mjEG?7cl%bJPfo%=IUOWcauf;STFgZMD*C_aT(P!pYO8S@;j z#5O#E>TlcxRvRPJsWc^%z4$pdT=b$n`vtWHw@?pEc*L<1b$$c)V+=V(7$B{)a z7mzuaU(v!L#m-6;qgJ#Ly*mF#sf4+aRl+`D1oz`1)BvtY&iSsvPic3dR%i;ZcL&!Y z2gIzM;(Q*!^R!1zb(Z`JY9hB$E0S00tY8i1>HIfPQF3`v9fxr(eu5`3+2x$?DE865 zjq2zfoD1`#O>q zCXe-AfiBdWM39#>A7dVVhb)%4iiNWE?+iq4RJ8L|of^Tku0w~im~b*R$lVA!vCf~-ii#S%hUt97>s-ZcL2 z@*x~ftS5N6`-`@m-$dd?LYbtj(8kUo?v|xglr=+$1%x&-i}~V9 zqyEAzNsB97W##-??&yb;cIOoR|M8$5<(YdQ$F}!es~F|hH|-PlIs23q+iuxkGM52; r)9#P;mRhmB^tCfF76bMisVpc_AJ)Brc`V-RSt|Ffh&!5HS(*GF<&AdE delta 2236 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 literal 0 HcmV?d00001 diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/zh_Hans/LC_MESSAGES/blur-my-shell.mo b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/zh_TW/LC_MESSAGES/blur-my-shell@aunetx.mo similarity index 53% rename from gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/zh_Hans/LC_MESSAGES/blur-my-shell.mo rename to gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/locale/zh_TW/LC_MESSAGES/blur-my-shell@aunetx.mo index 199a39c6398825a9f6a5d011570f7a86d58b8628..4d7557c32854d570fa3f8b14be9fdd4e560b1b78 100644 GIT binary patch delta 4066 zcmZu!X>3#36~40wsn7+OX<=BxD-1~n3ImL$6%W^0H@(!5QxbK8^7q;4{GQ z>~QnOlg@_sfv_n)03s;j3h*c}2HXSu9gre&A4rP#YeJj^eiulN27nuZy})i@3ivUw z8R4LH9Z2#+z*E3Ky793NAKFg#=vzQK!7&Hlak7v z$G8JX3Jbuuf&Ty!cMjvH8R!D80fvF3=Ngbw_FLcqfzxinF7QU208+@#0m-3DKr;C0 z{0D1-8;>76wC~VM+QFBP96GS~z`+9t*1qk!+_|r%!*%iU1y^T##}N%P7tj6Nb*^<^ zORMXXBigIy+b*_VZq=Hx>1PpnOx+wFv$U@8Y0IA4o>b%ymr4oI6l0c+B7}oD6Ou2-*qPnV)JGTCcQT&@hSc zX{XvXS4U^tN3JuSYc=Ojuy01DN0wsdd_ct$a+*T6vt4_w9cNYgg7o{%iJP2u%4;ql{fkTo%X8aIMc5Xlg*WjU zbA#8caj)geuvz`^_H`T0Y*-C1SiNzI>%dK{=J{5{UG z>=Y9zQxW8Vh$Kr(hA+rWVK11G(o=%ZR$|f`8CBklLtdLY99-7Od_4w^8JTR2#dkds z<7&!E1v^0#^yk5$XTg5 z^V%TPSYxZ88765@xf@F?TwTq|%CtEds6U~7`u=4KmR-(FP>N3~W`=HKnLjXtGO;`{ zb-h<^D5h1uh`3gZ-7@Qgd-|Um8jsl$g7?c z%y_AEXl^MFWBP`#KJziVAdF8hz8127z2w=2kM7diMqbuyntLLn#!C;qttmw4 zco(%3JI=@rIsy`H1_Rbevc@~=26vX2Lw0VWed<=li31n_j>~~DIyRRQMaHJI43C-5 z`pT3!yVMXLZnXMuv@K7D0{Y+KUoI+p$K>bKZ&97~rDY}tjJ|HN2%5{_B70ejd$mA~ zo|~;)nyQwQGU`#YH;joQcxO!71p;c<*eG+oW?%uQsTPOj%A(bETLt58<|TJtvcc`9kQOPH{D*<_DmyzMUe@$lhK`Um^V9z>#XD2T?GF zvoeI%l8~Mrvca15KkwST-qd?I8hCGXW1z2l{#7^HhW5s(cYg4?RxPaH3Mb$D(lQjN zZ_T8L%iaOb1yji4I^`-5^>r?s1gpq3R1fG0pPc3rj3W(JSMP_onyl2Q3{K%5G&1>W zrJD;4osg``Tu`Ng)_5263OPI~$MZ~hVFjW_IqN`;=O}_GC}erM&2mV8VfPMqEu;K! z`T~pCl=HTtQZ1rM*7Xnj*;3cZ)zS){Ez}k40Qrl7~=~neBDfp-Su>-zNF0csEHA9^F`xMA0BeD@w3Qd%j*$s`kto7Co?zn z_nVsB_KS&ha{)VV7fu(%9`smx;Nmo9Dr3YdeEs8M#|OVvNdY%KzB3<6+LtFudgu*H zk5nYneoor-b5GzBP!YTx=wZoMtsNbdd1aV;Gp-*ZLDt8ep>|C}093=1jRbHRtAPbv j)Ob{oroO9q!aQ6y5@qK}$m!#{5NdN>7Wh90&Y$=np!1HS delta 4110 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 diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/metadata.json b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/metadata.json index 32ca8d1..497ccca 100644 --- a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/metadata.json +++ b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/metadata.json @@ -5,16 +5,20 @@ "github": "aunetx", "kofi": "aunetx" }, - "gettext-domain": "blur-my-shell", + "gettext-domain": "blur-my-shell@aunetx", "name": "Blur my Shell", "original-authors": [ "me@aunetx.dev" ], + "session-modes": [ + "unlock-dialog", + "user" + ], "settings-schema": "org.gnome.shell.extensions.blur-my-shell", "shell-version": [ - "45" + "46" ], - "url": "https://github.com/aunetx/gnome-shell-extension-blur-my-shell", + "url": "https://github.com/aunetx/blur-my-shell", "uuid": "blur-my-shell@aunetx", - "version": 54 + "version": 59 } \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/dash.js b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/dash.js index ef8d9ed..3a42ff2 100644 --- a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/dash.js +++ b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/dash.js @@ -10,6 +10,8 @@ export const Dash = GObject.registerClass({ InternalChildren: [ 'blur', 'customize', + 'static_blur', + 'corner_radius', 'override_background', 'style_dash_to_dock', 'unblur_in_overview' @@ -24,6 +26,16 @@ export const Dash = GObject.registerClass({ 'blur', this._blur, 'active', Gio.SettingsBindFlags.DEFAULT ); + this.preferences.dash_to_dock.settings.bind( + 'static-blur', + this._static_blur, 'active', + Gio.SettingsBindFlags.DEFAULT + ); + this.preferences.dash_to_dock.settings.bind( + 'corner-radius', + this._corner_radius, 'value', + Gio.SettingsBindFlags.DEFAULT + ); this.preferences.dash_to_dock.settings.bind( 'override-background', this._override_background, 'enable-expansion', diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/panel.js b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/panel.js index 6d9f72b..6243f1f 100644 --- a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/panel.js +++ b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/panel.js @@ -12,6 +12,7 @@ export const Panel = GObject.registerClass({ 'customize', 'static_blur', 'unblur_in_overview', + 'force_light_text', 'override_background', 'style_panel', 'override_background_dynamically', @@ -36,6 +37,10 @@ export const Panel = GObject.registerClass({ 'unblur-in-overview', this._unblur_in_overview, 'active', Gio.SettingsBindFlags.DEFAULT ); + this.preferences.panel.settings.bind( + 'force-light-text', this._force_light_text, 'active', + Gio.SettingsBindFlags.DEFAULT + ); this.preferences.panel.settings.bind( 'override-background', this._override_background, 'enable-expansion', diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/window_row.js b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/window_row.js index c9786c9..fd150e0 100644 --- a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/window_row.js +++ b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/preferences/window_row.js @@ -7,14 +7,14 @@ import Gtk from 'gi://Gtk'; import { pick, on_picking, on_picked } from '../dbus/client.js'; - export const WindowRow = GObject.registerClass({ GTypeName: 'WindowRow', Template: GLib.uri_resolve_relative(import.meta.url, '../ui/window-row.ui', GLib.UriFlags.NONE), InternalChildren: [ 'window_picker', 'window_class', - 'picking_failure_toast' + 'picking_failure_toast', + 'window_not_found_toast' ], }, class WindowRow extends Adw.ExpanderRow { constructor(list, app_page, app_name) { @@ -88,7 +88,7 @@ export const WindowRow = GObject.registerClass({ if (remove_if_failed) this._remove_row(); } - }, 15); + }, 250); on_picking(_ => has_responded = true @@ -98,6 +98,9 @@ export const WindowRow = GObject.registerClass({ if (should_take_answer) { if (wm_class == 'window-not-found') { console.warn("Can't pick window from here"); + this._app_page._preferences_window.add_toast( + this._window_not_found_toast + ); return; } this._window_class.buffer.text = wm_class; diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/schemas/gschemas.compiled b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/schemas/gschemas.compiled index c5aa01a980b3f4ba7164801abb4ec56fc8dce54f..36fefef596a7827343c536a7c6cca7d6cb6b78c3 100644 GIT binary patch literal 8296 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 Dg@E0D literal 8160 zcmds+e{5A}9md}}y1{^f9bnmDGPA|oxZ8GsOWlU63DZttHvS-uKbD=_d+j~p_TFpn zZK3-i{evcr62%F#DvgcPjVLBnF=CucNnkdaBwgZSjWaSu!(XNvrWnlh`Mmdj?+>JS z%3o$Dd3c`tzsS%UnWixe?=#6QGBU>tWYQO=l}ja;&e}{?5Pw1g z#Qjf+kFR%bu<_wz#LwK~+}(=1TXmlsoV(P1X&>>AZ**?6;$z~Yw>g&^=xgoE=K52u zg>)*DX-(}drm}@Fmo2m=GJ^y0{^5A(Kk`8~l~D&87CmC!!8`yBtK%BX1@mCAxzLcg zi9NigyT4FP~aM9Q}61^Ws5a=o6n@O&r~*_=tE+D6HGQg*bY-;^X2; z!NwiUxWlu;_RZT?(H>1dbK(XCPT%q6=ZK@56mJ%96kdDy+ug*`s}ye+-!Du*`MKrH zE1G_~#E%PKf9}u|BCnSyKB6C^!dO223~}@_#Se-P3oqRDDyMmUqvDhLaZK2}Vc$Q9 zqint77?g(sWE-2xtF zZqRu6QE^7VtHjZGH7_0%@Fa0Go*WS$5XeE|X!;))PYUERaWuI+C4OEY*NCHOKO_Dt zx?B^{u%=fy__yht2P z|0l$!gtng?=p&BC({tkA36=wBJa=BaRtpbaq&=GWChP@|vCh{&OB~I8o)w=LUVr+T9}!3MTo=V{now#1 zaWv!BDc&J8HQe(WaWwt(h z@E2Ag2k^dLg(`l;Yr1`h@9MHzza!sI^+erJGAN|u#auk8I$L_M$ox1fT5Wx`@c-}EftrFAeSOl!7E@TPt}IljRQJ+)Cn)Cfi9nMZ`T46S>4t1+ zUc~u!iq5tbmw}0V{qn0wpi`y9jEo~RfuO&L#4N8a*g+^Jz+MP+Y`@(g`ziN7_2_%XruL}Z z`*HCE@$y~?&HWq|e_yb@6578Dh))TLuk8F8{h(<-D`vl)%LlzSvwznAlWz-^L-Hh* z4HDYyXiwxDUvWRgy2U!B*9t#xysK%c_v;ouWqvuBb1k1Pkx|~0-2`=XXM*f*y&=Sc zLd#;xdF4HEp-k8PTTXDD=y_4=VKT#Se@gooWIT7-4y=A(ReW9b!v=0?ckdK{6^z`m~SlXr>Dd}7R<9~ zJUcDEgf8a_nq2u8tQV2ekZ92lvq7e2UwrNBdfm-40bDTpv)8Qyi{C5qZOP}Vcv!H# zBAVPD6CV<6uZSjx$HfzZ?G@4Foo^9 z4`}9LgSbPmy&{^N?-KKE%yJ;Q|7!-2(Z5Q5z3KOft>#7Eiy3bhqlVc*{@7YZ-r8D5 zKHEBG%zUExM#+4-w>j4$F#p8S%zuY?yMVulqw!alc&A|biKd?(@lyi6qdgkmO^S~R z_?I{u|4xg4De!%dIGXQ!XT^UK8otoiL>x{0qS)yhD&N_NquCFw7OxfX9dR_i+a$hI z;Cmf$H1(xJyiFhvh@-jxE^#+nUgi5C8ehYF!;QQqM0me1RdUs9OA1{ndS29e!LJK- zJDu8n&O#}}ld-N|`BR?mtMqZP_CkIgD1CRVd^+>p`1)G+5k%)-;lrkHSM$Nf_6K;E zHHU-sh4qHDoHYmkvKHZId>wh+seMP*lhUspmMfMoT-(04n5X$pk0++Z7X_=mXuP{r z-|p84R(sLpMzeUMV6_)b4#dP;1*^Si`tKBX308a2_IdHw&}EOJ@#qop z3BhVFnjDxB^LK_Cn=Qg;)j_;k`Nc$-VToFezSDoSq1)EzmbK50O3wVn5Xgsx7ykEd0#L@JBQ2bK?PZ3AssTuLF1oJqW z_GiWG^tYyE7asgI?a{pR$HeUd-Y1U6`<>z)0^TQ%#{1o3{&r<4ZuwnT8q{9HmuS(y zjF07@RMaZBG+O%i%^fREkDc?WJjrBvTx00Q`w?k6?vxWzUB&l5~EU_M0qnjtl_&*eVEe;j!9|KEodPh7Q3*VXCr`W^ - + 30 -

Global sigma (gaussian blur radius) to use + Global gaussian sigma to use @@ -56,7 +57,8 @@ - + true @@ -70,7 +72,7 @@ 30 - Sigma (gaussian blur radius) to use for the blur effect + Gaussian sigma to use for the blur effect @@ -100,7 +102,8 @@ - + true @@ -114,7 +117,7 @@ 30 - Sigma (gaussian blur radius) to use for the blur effect + Gaussian sigma to use for the blur effect @@ -144,7 +147,8 @@ - + true @@ -158,7 +162,7 @@ 30 - Sigma (gaussian blur radius) to use for the blur effect + Gaussian sigma to use for the blur effect @@ -190,6 +194,11 @@ true Boolean, whether to disable blur from this component when opening the overview or not + + + false + Boolean, whether or not to force the panel to have light text, useful when using light theme + true @@ -208,7 +217,8 @@ - + false @@ -222,7 +232,7 @@ 30 - Sigma (gaussian blur radius) to use for the blur effect + Gaussian sigma to use for the blur effect @@ -264,13 +274,19 @@ false Boolean, whether to disable blur from this component when opening the overview or not + + + 12 + Radius for the corner rounding effect + - + - true + false Boolean, whether to blur activate the blur for this component or not @@ -281,7 +297,7 @@ 30 - Sigma (gaussian blur radius) to use for the blur effect + Gaussian sigma to use for the blur effect @@ -325,13 +341,14 @@ - ["Plank"] + ["Plank","com.desktop.ding", "Conky"] List of applications not to blur - + true @@ -345,7 +362,7 @@ 30 - Sigma (gaussian blur radius) to use for the blur effect + Gaussian sigma to use for the blur effect @@ -370,7 +387,8 @@ - + true @@ -384,7 +402,7 @@ 30 - Sigma (gaussian blur radius) to use for the blur effect + Gaussian sigma to use for the blur effect @@ -409,7 +427,8 @@ - + true @@ -423,7 +442,7 @@ 30 - Sigma (gaussian blur radius) to use for the blur effect + Gaussian sigma to use for the blur effect @@ -448,7 +467,8 @@ - + false @@ -457,7 +477,8 @@ - + true diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/stylesheet.css b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/stylesheet.css index 91cfb1f..7cfc773 100644 --- a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/stylesheet.css +++ b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/stylesheet.css @@ -68,7 +68,7 @@ } -/*** DASH ***/ +/*** DASH-TO-DOCK ***/ /* * `.transparent-dash` @@ -107,7 +107,6 @@ */ .overview-components-transparent .workspace-thumbnail { - background-color: rgba(0, 0, 0, 0); border: 1px solid rgba(100, 100, 100, 0.35); } @@ -122,53 +121,88 @@ color: rgba(255, 255, 255, 0.65); } -.overview-components-transparent .search-section-content { - border: none; - box-shadow: none; -} - -.overview-components-transparent .search-section-content, -.overview-components-transparent .app-folder .overview-icon { - background-color: rgba(0, 0, 0, 0); -} - +.overview-components-transparent .overview-tile, +.overview-components-transparent .overview-icon, +.overview-components-transparent .list-search-result, +.overview-components-transparent .search-provider-icon, /* prevents the extension from interfering with Just Perfection */ -.overview-components-transparent.just-perfection .search-section-content { +.overview-components-transparent.just-perfection .search-section-content, +/* remove the rectangular background from the dash */ +.overview-components-transparent #dash .overview-tile { background-color: transparent; } -.overview-components-transparent .app-folder .overview-icon { - border-color: transparent; -} - -.overview-components-transparent .app-folder:hover .overview-icon, -.overview-components-transparent .app-folder:focus .overview-icon { - background-color: rgba(230, 230, 230, 0.08); -} - -.overview-components-transparent .app-folder:active .overview-icon, -.overview-components-transparent .app-folder:focus:hover .overview-icon, -.overview-components-transparent .app-folder:drop .overview-icon { - background-color: rgba(230, 230, 230, 0.12); -} - -.overview-components-transparent .app-folder:focus:active .overview-icon { - background-color: rgba(230, 230, 230, 0.15); -} - +.overview-components-transparent .workspace-thumbnail, +.overview-components-transparent .search-section-content, +.overview-components-transparent .overview-tile.app-folder, +.overview-components-transparent .page-navigation-arrow, +.overview-components-transparent .app-folder-dialog .icon-button, /* this shouldn't apply to Dash to Dock */ .overview-components-transparent StBoxLayout>StWidget>#dash>.dash-background { background-color: rgba(0, 0, 0, 0); } +.overview-components-transparent .overview-tile:hover, +.overview-components-transparent .overview-tile:focus, +.overview-components-transparent .overview-tile:selected, +.overview-components-transparent .overview-tile:highlighted, +.overview-components-transparent .list-search-result:hover, +.overview-components-transparent .list-search-result:focus, +.overview-components-transparent .list-search-result:selected, +.overview-components-transparent .list-search-result:highlighted, +.overview-components-transparent .search-provider-icon:hover, +.overview-components-transparent .search-provider-icon:focus, +.overview-components-transparent .page-navigation-arrow:hover, +.overview-components-transparent .page-navigation-arrow:focus, +.overview-components-transparent .app-folder-dialog .icon-button:hover, +.overview-components-transparent .app-folder-dialog .icon-button:focus, +.overview-components-transparent #dash .overview-tile:hover .overview-icon, +.overview-components-transparent #dash .overview-tile:focus .overview-icon, +.overview-components-transparent #dash .show-apps:hover .overview-icon, +.overview-components-transparent #dash .show-apps:focus .overview-icon { + background-color: rgba(230, 230, 230, 0.08); +} + +.overview-components-transparent .overview-tile:active, +.overview-components-transparent .overview-tile:focus:hover, +.overview-components-transparent .overview-tile:drop, +.overview-components-transparent .overview-tile:selected:hover, +.overview-components-transparent .overview-tile:highlighted:hover, +.overview-components-transparent .list-search-result:active, +.overview-components-transparent .list-search-result:focus:hover, +.overview-components-transparent .list-search-result:selected:hover, +.overview-components-transparent .list-search-result:highlighted:hover, +.overview-components-transparent .search-provider-icon:active, +.overview-components-transparent .search-provider-icon:focus:hover, +.overview-components-transparent .page-navigation-arrow:active, +.overview-components-transparent .page-navigation-arrow:focus:hover, +.overview-components-transparent .app-folder-dialog .icon-button:active, +.overview-components-transparent .app-folder-dialog .icon-button:focus:hover, +.overview-components-transparent #dash .overview-tile:active .overview-icon, +.overview-components-transparent #dash .overview-tile:focus:hover .overview-icon, +.overview-components-transparent #dash .overview-tile:drop .overview-icon, +.overview-components-transparent #dash .show-apps:checked .overview-icon { + background-color: rgba(230, 230, 230, 0.12); +} + +.overview-components-transparent .overview-tile:focus:active, +.overview-components-transparent .overview-tile:selected:active, +.overview-components-transparent .overview-tile:highlighted:active, +.overview-components-transparent .list-search-result:focus:active, +.overview-components-transparent .list-search-result:selected:active, +.overview-components-transparent .list-search-result:highlighted:active, +.overview-components-transparent .search-provider-icon:focus:active, +.overview-components-transparent .page-navigation-arrow:focus:active, +.overview-components-transparent .app-folder-dialog .icon-button:focus:active, +.overview-components-transparent #dash .show-apps:checked .overview-icon:hover { + background-color: rgba(230, 230, 230, 0.15); +} + + /* * `.overview-components-light` */ -.overview-components-light .workspace-thumbnail { - background-color: rgba(200, 200, 200, 0.2); -} - .overview-components-light .search-entry { color: white; background-color: rgba(200, 200, 200, 0.2); @@ -180,54 +214,88 @@ color: rgba(255, 255, 255, 0.65); } -.overview-components-light .search-section-content { - border: none; - box-shadow: none; -} - -.overview-components-light .search-section-content, -.overview-components-light .app-folder .overview-icon { - background-color: rgba(200, 200, 200, 0.2); -} - +.overview-components-light .overview-tile, +.overview-components-light .overview-icon, +.overview-components-light .list-search-result, +.overview-components-light .search-provider-icon, /* prevents the extension from interfering with Just Perfection */ -.overview-components-light.just-perfection .search-section-content { +.overview-components-light.just-perfection .search-section-content, +/* remove the rectangular background from the dash */ +.overview-components-light #dash .overview-tile { background-color: transparent; } -.overview-components-light .app-folder .overview-icon { - border-color: transparent; -} - -.overview-components-light .app-folder:hover .overview-icon, -.overview-components-light .app-folder:focus .overview-icon { - background-color: rgba(230, 230, 230, 0.2); -} - -.overview-components-light .app-folder:active .overview-icon, -.overview-components-light .app-folder:focus:hover .overview-icon, -.overview-components-light .app-folder:drop .overview-icon { - background-color: rgba(230, 230, 230, 0.25); -} - -.overview-components-light .app-folder:focus:active .overview-icon { - background-color: rgba(230, 230, 230, 0.3); -} - +.overview-components-light .workspace-thumbnail, +.overview-components-light .search-section-content, +.overview-components-light .overview-tile.app-folder, +.overview-components-light .page-navigation-arrow, +.overview-components-light .app-folder-dialog .icon-button, /* this shouldn't apply to Dash to Dock */ .overview-components-light StBoxLayout>StWidget>#dash>.dash-background { background-color: rgba(200, 200, 200, 0.2); } +.overview-components-light .overview-tile:hover, +.overview-components-light .overview-tile:focus, +.overview-components-light .overview-tile:selected, +.overview-components-light .overview-tile:highlighted, +.overview-components-light .list-search-result:hover, +.overview-components-light .list-search-result:focus, +.overview-components-light .list-search-result:selected, +.overview-components-light .list-search-result:highlighted, +.overview-components-light .search-provider-icon:hover, +.overview-components-light .search-provider-icon:focus, +.overview-components-light .page-navigation-arrow:hover, +.overview-components-light .page-navigation-arrow:focus, +.overview-components-light .app-folder-dialog .icon-button:hover, +.overview-components-light .app-folder-dialog .icon-button:focus, +.overview-components-light #dash .overview-tile:hover .overview-icon, +.overview-components-light #dash .overview-tile:focus .overview-icon, +.overview-components-light #dash .show-apps:hover .overview-icon, +.overview-components-light #dash .show-apps:focus .overview-icon { + background-color: rgba(230, 230, 230, 0.2); +} + +.overview-components-light .overview-tile:active, +.overview-components-light .overview-tile:focus:hover, +.overview-components-light .overview-tile:drop, +.overview-components-light .overview-tile:selected:hover, +.overview-components-light .overview-tile:highlighted:hover, +.overview-components-light .list-search-result:active, +.overview-components-light .list-search-result:focus:hover, +.overview-components-light .list-search-result:selected:hover, +.overview-components-light .list-search-result:highlighted:hover, +.overview-components-light .search-provider-icon:active, +.overview-components-light .search-provider-icon:focus:hover, +.overview-components-light .page-navigation-arrow:active, +.overview-components-light .page-navigation-arrow:focus:hover, +.overview-components-light .app-folder-dialog .icon-button:active, +.overview-components-light .app-folder-dialog .icon-button:focus:hover, +.overview-components-light #dash .overview-tile:active .overview-icon, +.overview-components-light #dash .overview-tile:focus:hover .overview-icon, +.overview-components-light #dash .overview-tile:drop .overview-icon, +.overview-components-light #dash .show-apps:checked .overview-icon { + background-color: rgba(230, 230, 230, 0.25); +} + +.overview-components-light .overview-tile:focus:active, +.overview-components-light .overview-tile:selected:active, +.overview-components-light .overview-tile:highlighted:active, +.overview-components-light .list-search-result:focus:active, +.overview-components-light .list-search-result:selected:active, +.overview-components-light .list-search-result:highlighted:active, +.overview-components-light .search-provider-icon:focus:active, +.overview-components-light .page-navigation-arrow:focus:active, +.overview-components-light .app-folder-dialog .icon-button:focus:active, +.overview-components-light #dash .show-apps:checked .overview-icon:hover { + background-color: rgba(230, 230, 230, 0.3); +} + /* * `.overview-components-dark` */ -.overview-components-dark .workspace-thumbnail { - background-color: rgba(100, 100, 100, 0.35); -} - .overview-components-dark .search-entry { color: white; background-color: rgba(100, 100, 100, 0.35); @@ -239,45 +307,83 @@ color: rgba(255, 255, 255, 0.65); } -.overview-components-dark .search-section-content { - border: none; - box-shadow: none; -} - -.overview-components-dark .search-section-content, -.overview-components-dark .app-folder .overview-icon { - background-color: rgba(100, 100, 100, 0.35); -} - +.overview-components-dark .overview-tile, +.overview-components-dark .overview-icon, +.overview-components-dark .list-search-result, +.overview-components-dark .search-provider-icon, /* prevents the extension from interfering with Just Perfection */ -.overview-components-dark.just-perfection .search-section-content { +.overview-components-dark.just-perfection .search-section-content, +/* remove the rectangular background from the dash */ +.overview-components-dark #dash .overview-tile { background-color: transparent; } -.overview-components-dark .app-folder .overview-icon { - border-color: transparent; -} - -.overview-components-dark .app-folder:hover .overview-icon, -.overview-components-dark .app-folder:focus .overview-icon { - background-color: rgba(120, 120, 120, 0.35); -} - -.overview-components-dark .app-folder:active .overview-icon, -.overview-components-dark .app-folder:focus:hover .overview-icon, -.overview-components-dark .app-folder:drop .overview-icon { - background-color: rgba(120, 120, 120, 0.4); -} - -.overview-components-dark .app-folder:focus:active .overview-icon { - background-color: rgba(120, 120, 120, 0.45); -} - +.overview-components-dark .workspace-thumbnail, +.overview-components-dark .search-section-content, +.overview-components-dark .overview-tile.app-folder, +.overview-components-dark .page-navigation-arrow, +.overview-components-dark .app-folder-dialog .icon-button, /* this shouldn't apply to Dash to Dock */ .overview-components-dark StBoxLayout>StWidget>#dash>.dash-background { background-color: rgba(100, 100, 100, 0.35); } +.overview-components-dark .overview-tile:hover, +.overview-components-dark .overview-tile:focus, +.overview-components-dark .overview-tile:selected, +.overview-components-dark .overview-tile:highlighted, +.overview-components-dark .list-search-result:hover, +.overview-components-dark .list-search-result:focus, +.overview-components-dark .list-search-result:selected, +.overview-components-dark .list-search-result:highlighted, +.overview-components-dark .search-provider-icon:hover, +.overview-components-dark .search-provider-icon:focus, +.overview-components-dark .page-navigation-arrow:hover, +.overview-components-dark .page-navigation-arrow:focus, +.overview-components-dark .app-folder-dialog .icon-button:hover, +.overview-components-dark .app-folder-dialog .icon-button:focus, +.overview-components-dark #dash .overview-tile:hover .overview-icon, +.overview-components-dark #dash .overview-tile:focus .overview-icon, +.overview-components-dark #dash .show-apps:hover .overview-icon, +.overview-components-dark #dash .show-apps:focus .overview-icon { + background-color: rgba(120, 120, 120, 0.35); +} + +.overview-components-dark .overview-tile:active, +.overview-components-dark .overview-tile:focus:hover, +.overview-components-dark .overview-tile:drop, +.overview-components-dark .overview-tile:selected:hover, +.overview-components-dark .overview-tile:highlighted:hover, +.overview-components-dark .list-search-result:active, +.overview-components-dark .list-search-result:focus:hover, +.overview-components-dark .list-search-result:selected:hover, +.overview-components-dark .list-search-result:highlighted:hover, +.overview-components-dark .search-provider-icon:active, +.overview-components-dark .search-provider-icon:focus:hover, +.overview-components-dark .page-navigation-arrow:active, +.overview-components-dark .page-navigation-arrow:focus:hover, +.overview-components-dark .app-folder-dialog .icon-button:active, +.overview-components-dark .app-folder-dialog .icon-button:focus:hover, +.overview-components-dark #dash .overview-tile:active .overview-icon, +.overview-components-dark #dash .overview-tile:focus:hover .overview-icon, +.overview-components-dark #dash .overview-tile:drop .overview-icon, +.overview-components-dark #dash .show-apps:checked .overview-icon { + background-color: rgba(120, 120, 120, 0.4); +} + +.overview-components-dark .overview-tile:focus:active, +.overview-components-dark .overview-tile:selected:active, +.overview-components-dark .overview-tile:highlighted:active, +.overview-components-dark .list-search-result:focus:active, +.overview-components-dark .list-search-result:selected:active, +.overview-components-dark .list-search-result:highlighted:active, +.overview-components-dark .search-provider-icon:focus:active, +.overview-components-dark .page-navigation-arrow:focus:active, +.overview-components-dark .app-folder-dialog .icon-button:focus:active, +.overview-components-dark #dash .show-apps:checked .overview-icon:hover { + background-color: rgba(120, 120, 120, 0.45); +} + /*** APPFOLDER DIALOG ***/ @@ -331,4 +437,98 @@ background-color: rgba(100, 100, 100, 0.35); border: 0; box-shadow: none; +} + + +/*** PANEL LIGHT TEXT ***/ + +/* +* `.panel-light-text`, adapted from gnome-shell-light.css +*/ + +#panel.panel-light-text .panel-button, +#panel.panel-light-text .panel-button.clock-display, +#panel.panel-light-text .netSpeedLabel { + color: #f6f5f4; + box-shadow: none; +} + +#panel.panel-light-text .panel-button:active, +#panel.panel-light-text .panel-button:focus, +#panel.panel-light-text .panel-button:checked, +#panel.panel-light-text .panel-button.clock-display:active .clock, +#panel.panel-light-text .panel-button.clock-display:focus .clock, +#panel.panel-light-text .panel-button.clock-display:checked .clock { + box-shadow: inset 0 0 0 100px rgba(246, 245, 244, 0.25); +} + +#panel.panel-light-text .panel-button:active:hover, +#panel.panel-light-text .panel-button:focus:hover, +#panel.panel-light-text .panel-button:checked:hover, +#panel.panel-light-text .panel-button.clock-display:active:hover, +#panel.panel-light-text .panel-button.clock-display:focus:hover, +#panel.panel-light-text .panel-button.clock-display:checked:hover, +#panel.panel-light-text .panel-button.clock-display:active .clock:hover, +#panel.panel-light-text .panel-button.clock-display:focus .clock:hover, +#panel.panel-light-text .panel-button.clock-display:checked .clock:hover { + box-shadow: inset 0 0 0 100px rgba(246, 245, 244, 0.35); +} + +#panel.panel-light-text .panel-button:hover, +#panel.panel-light-text .panel-button.clock-display:hover, +#panel.panel-light-text .panel-button.clock-display:hover .clock { + box-shadow: inset 0 0 0 100px rgba(246, 245, 244, 0.2); +} + +#panel.panel-light-text .panel-button#panelActivities .workspace-dot { + background-color: #f6f5f4; +} + +#panel.panel-light-text .panel-button.clock-display:active, +#panel.panel-light-text .panel-button.clock-display:focus, +#panel.panel-light-text .panel-button.clock-display:checked, +#panel.panel-light-text .panel-button.clock-display:hover { + box-shadow: none !important; +} + +#panel.panel-light-text .panel-button.screen-recording-indicator { + color: #f6f5f4; + box-shadow: inset 0 0 0 100px rgba(192, 28, 40, 0.8); +} + +#panel.panel-light-text .panel-button.screen-recording-indicator:active, +#panel.panel-light-text .panel-button.screen-recording-indicator:focus, +#panel.panel-light-text .panel-button.screen-recording-indicator:checked { + box-shadow: inset 0 0 0 100px #c01c28; +} + +#panel.panel-light-text .panel-button.screen-recording-indicator:active:hover, +#panel.panel-light-text .panel-button.screen-recording-indicator:focus:hover, +#panel.panel-light-text .panel-button.screen-recording-indicator:checked:hover { + box-shadow: inset 0 0 0 100px rgba(192, 28, 40, 0.95); +} + +#panel.panel-light-text .panel-button.screen-recording-indicator:hover { + box-shadow: inset 0 0 0 100px rgba(192, 28, 40, 0.9); +} + +#panel.panel-light-text .panel-button.screen-sharing-indicator { + color: #282828; + box-shadow: inset 0 0 0 100px rgba(255, 120, 0, 0.8); +} + +#panel.panel-light-text .panel-button.screen-sharing-indicator:active, +#panel.panel-light-text .panel-button.screen-sharing-indicator:focus, +#panel.panel-light-text .panel-button.screen-sharing-indicator:checked { + box-shadow: inset 0 0 0 100px #ff7800; +} + +#panel.panel-light-text .panel-button.screen-sharing-indicator:active:hover, +#panel.panel-light-text .panel-button.screen-sharing-indicator:focus:hover, +#panel.panel-light-text .panel-button.screen-sharing-indicator:checked:hover { + box-shadow: inset 0 0 0 100px rgba(255, 120, 0, 0.95); +} + +#panel.panel-light-text .panel-button.screen-sharing-indicator:hover { + box-shadow: inset 0 0 0 100px rgba(255, 120, 0, 0.9); } \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/applications.ui b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/applications.ui index 0b4b83c..54b0a02 100644 --- a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/applications.ui +++ b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/applications.ui @@ -27,7 +27,7 @@ To get the best results possible, make sure to choose the option “No artifact Opacity The opacity of the window on top of the blur effect, a higher value will be more legible. - opacity + opacity_scale diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/dash.ui b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/dash.ui index 5eac21b..1afdbc2 100644 --- a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/dash.ui +++ b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/dash.ui @@ -17,7 +17,47 @@ + + + + + + + Static blur + Uses a static blurred image, can be used with rounding effect. +<b>Important notice:</b> with this activated, you should not use a big sigma value as it will deteriorate performances. + static_blur + + + + center + + + + + + + + Rounded corner radius + The radius for the rounding effect. Only available with static blur. + corner_radius_scale + + + + + + center + true + 200px + true + right + horizontal + 0 + corner_radius + + @@ -70,4 +110,10 @@ Dark + + + 0 + 50 + 1 + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/panel.ui b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/panel.ui index 41d9cd1..f7a40e0 100644 --- a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/panel.ui +++ b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/panel.ui @@ -38,13 +38,13 @@ - Disable in overview - Disables the blur from the panel when entering the overview. - unblur_in_overview + Force light text + Use a light text for the panel, useful when using gnome-shell's light theme. + force_light_text - + center @@ -89,6 +89,21 @@ Recommended unless you want to customize your GNOME theme. + + + + Disable in overview + Disables the blur from the panel when entering the overview. + unblur_in_overview + + + + + center + + + + diff --git a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/window-row.ui b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/window-row.ui index c4d8201..953585f 100644 --- a/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/window-row.ui +++ b/gnome/.local/share/gnome-shell/extensions/blur-my-shell@aunetx/ui/window-row.ui @@ -40,4 +40,8 @@ Could not pick window, make sure that the extension is enabled. + + + Could not pick window from here, does not seem like a valid window. + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/forge@jmmaranan.com/config/windows.json b/gnome/.local/share/gnome-shell/extensions/forge@jmmaranan.com/config/windows.json index 4a5096e..2b9f450 100644 --- a/gnome/.local/share/gnome-shell/extensions/forge@jmmaranan.com/config/windows.json +++ b/gnome/.local/share/gnome-shell/extensions/forge@jmmaranan.com/config/windows.json @@ -16,6 +16,14 @@ { "wmClass": "gnome-terminal-server", "wmTitle": "Preferences – General", "mode": "float" }, { "wmClass": "gnome-terminal-preferences", "mode": "float" }, { "wmClass": "Guake", "mode": "float" }, - { "wmClass": "zoom", "mode": "float" } + { "wmClass": "zoom", "mode": "float" }, + { "wmClass": "firefox", "wmTitle": "About Mozilla Firefox", "mode": "float" }, + { "wmClass": "firefox", "wmTitle": "!Mozilla Firefox", "mode": "float" }, + { "wmClass": "org.mozilla.firefox.desktop", "wmTitle": "About Mozilla Firefox", "mode": "float" }, + { "wmClass": "org.mozilla.firefox.desktop", "wmTitle": "!Mozilla Firefox", "mode": "float" }, + { "wmClass": "thunderbird", "wmTitle": "About Mozilla Thunderbird", "mode": "float" }, + { "wmClass": "thunderbird", "wmTitle": "!Mozilla Thunderbird", "mode": "float" }, + { "wmClass": "org.mozilla.Thunderbird.desktop", "wmTitle": "About Mozilla Thunderbird", "mode": "float" }, + { "wmClass": "org.mozilla.Thunderbird.desktop", "wmTitle": "!Mozilla Thunderbird", "mode": "float" } ] } diff --git a/gnome/.local/share/gnome-shell/extensions/forge@jmmaranan.com/lib/extension/indicator.js b/gnome/.local/share/gnome-shell/extensions/forge@jmmaranan.com/lib/extension/indicator.js index 8132731..309dcf2 100644 --- a/gnome/.local/share/gnome-shell/extensions/forge@jmmaranan.com/lib/extension/indicator.js +++ b/gnome/.local/share/gnome-shell/extensions/forge@jmmaranan.com/lib/extension/indicator.js @@ -81,6 +81,14 @@ export class FeatureMenuToggle extends QuickMenuToggle { )) ); + this.menu.addMenuItem( + (this._focusMovePointer = new SettingsPopupSwitch( + _("Move Pointer with the Focus"), + this.extension, + "move-pointer-focus-enabled" + )) + ); + // Add an entry-point for more settings this.menu.addMenuItem(new PopupSeparatorMenuItem()); const settingsItem = this.menu.addAction(_("Settings"), () => this.extension.openPreferences()); diff --git a/gnome/.local/share/gnome-shell/extensions/forge@jmmaranan.com/lib/extension/tree.js b/gnome/.local/share/gnome-shell/extensions/forge@jmmaranan.com/lib/extension/tree.js index 8035211..ea0d767 100644 --- a/gnome/.local/share/gnome-shell/extensions/forge@jmmaranan.com/lib/extension/tree.js +++ b/gnome/.local/share/gnome-shell/extensions/forge@jmmaranan.com/lib/extension/tree.js @@ -79,6 +79,7 @@ export class Node extends GObject.Object { this.tab = null; this.decoration = null; this.app = null; + this.pointer = null; if (this.isWindow()) { // When destroy() is called on Meta.Window, it might not be @@ -474,9 +475,9 @@ export class Node extends GObject.Object { child: new St.Icon({ icon_name: "window-close-symbolic" }), }); - tabContents.add(iconBin); - tabContents.add(titleButton); - tabContents.add(closeButton); + tabContents.add_child(iconBin); + tabContents.add_child(titleButton); + tabContents.add_child(closeButton); let clickFn = () => { this.parentNode.childNodes.forEach((c) => { @@ -553,6 +554,17 @@ export class Node extends GObject.Object { set tile(value) { this.float = !value; } + + resetLayoutSingleChild() { + let tabbedOrStacked = this.isTabbed() || this.isStacked(); + if (tabbedOrStacked && this.singleOrNoChild()) { + this.layout = LAYOUT_TYPES.HSPLIT; + } + } + + singleOrNoChild() { + return this.childNodes.length <= 1; + } } /** @@ -946,6 +958,7 @@ export class Tree extends Node { } this.resetSiblingPercent(parentNode); this.resetSiblingPercent(parentTarget); + parentNode.resetLayoutSingleChild(); return true; } @@ -953,7 +966,7 @@ export class Tree extends Node { * Give the next sibling/parent/descendant on the tree based * on a given Meta.MotionDirection * - * @param {Tree.Node} node + * @param {Node} node * @param {Meta.MotionDirection} direction * * Credits: borrowed logic from tree.c of i3 @@ -1511,7 +1524,7 @@ export class Tree extends Node { } else { decoration.hide(); } - if (!decoration.contains(child.tab)) decoration.add(child.tab); + if (!decoration.contains(child.tab)) decoration.add_child(child.tab); } child.render(); @@ -1561,7 +1574,23 @@ export class Tree extends Node { } debugTree() { + // this.debugChildNodes(this); + } + + debugChildNodes(node) { this.debugNode(this); + node.childNodes.forEach((child) => { + this.debugChildNodes(child); + }); + } + + debugParentNodes(node) { + if (node) { + if (node.parentNode) { + this.debugParentNodes(node.parentNode); + } + this.debugNode(node); + } } debugNode(node) { @@ -1576,7 +1605,7 @@ export class Tree extends Node { let attributes = ""; - if (node.isWindow()) { + if (node.isWindow && node.isWindow()) { let metaWindow = node.nodeValue; attributes += `class:'${metaWindow.get_wm_class()}',title:'${ metaWindow.title @@ -1590,6 +1619,9 @@ export class Tree extends Node { if (node.rect) { attributes += `,rect:${node.rect.width}x${node.rect.height}+${node.rect.x}+${node.rect.y}`; + const pointerCoord = global.get_pointer(); + const pointerInside = Utils.rectContainsPoint(node.rect, pointerCoord) ? "yes" : "no"; + attributes += `,pointer:${pointerInside}`; } if (level !== 0) Logger.debug(`${spacing}|`); @@ -1598,10 +1630,6 @@ export class Tree extends Node { node.index !== null ? node.index : "-" } @${attributes}` ); - - node.childNodes.forEach((child) => { - this.debugNode(child); - }); } findParent(childNode, parentNodeType) { diff --git a/gnome/.local/share/gnome-shell/extensions/forge@jmmaranan.com/lib/extension/window.js b/gnome/.local/share/gnome-shell/extensions/forge@jmmaranan.com/lib/extension/window.js index 8fc9627..b5d3ceb 100644 --- a/gnome/.local/share/gnome-shell/extensions/forge@jmmaranan.com/lib/extension/window.js +++ b/gnome/.local/share/gnome-shell/extensions/forge@jmmaranan.com/lib/extension/window.js @@ -68,49 +68,46 @@ export class WindowManager extends GObject.Object { !production ? "DEV" : `${PACKAGE_VERSION}-${ext.metadata.version}` }`; this.windowProps = this.ext.configMgr.windowProps; + this.windowProps.overrides = this.windowProps.overrides.filter((override) => !override.wmId); this._kbd = this.ext.keybindings; this._tree = new Tree(this); this.eventQueue = new Queue(); this.theme = this.ext.theme; + this.lastFocusedWindow = null; Logger.info("forge initialized"); } - addFloatOverride(metaWindow, byClass = true) { + addFloatOverride(metaWindow, withWmId) { let overrides = this.windowProps.overrides; - let wmTitle = metaWindow.get_title(); let wmClass = metaWindow.get_wm_class(); + let wmId = metaWindow.get_id(); for (let override in overrides) { - if (!byClass) { - if (override.wmClass === wmClass && override.wmTitle === wmTitle) return; - } else { - if (override.wmClass === wmClass && !override.wmTitle) return; - } + // if the window is already floating + if (override.wmClass === wmClass && override.mode === "float" && !override.wmTitle) return; } overrides.push({ wmClass: wmClass, - wmTitle: !byClass ? wmTitle : undefined, + wmId: withWmId ? wmId : undefined, mode: "float", }); this.windowProps.overrides = overrides; this.ext.configMgr.windowProps = this.windowProps; } - removeFloatOverride(metaWindow, byClass = true) { + removeFloatOverride(metaWindow, withWmId) { let overrides = this.windowProps.overrides; - let wmTitle = metaWindow.get_title(); let wmClass = metaWindow.get_wm_class(); - - if (byClass) { - // remove purely wmClass - by checking also if override title exists - overrides = overrides.filter( - (override) => !(override.wmClass === wmClass) && !override.wmTitle - ); - } else { - overrides = overrides.filter( - (override) => !(override.wmClass === wmClass && override.wmTitle === wmTitle) - ); - } + let wmId = metaWindow.get_id(); + overrides = overrides.filter( + (override) => + !( + override.wmClass === wmClass && + // rules with a Title are written by the user and peristent + !override.wmTitle && + (!withWmId || override.wmId === wmId) + ) + ); this.windowProps.overrides = overrides; this.ext.configMgr.windowProps = this.windowProps; @@ -121,26 +118,18 @@ export class WindowManager extends GObject.Object { if (!nodeWindow || !(action || action.mode)) return; if (nodeWindow.nodeType !== NODE_TYPES.WINDOW) return; - let floatToggle = action.name === "FloatToggle"; - let floatClassToggle = action.name === "FloatClassToggle"; + let withWmId = action.name === "FloatToggle"; let floatingExempt = this.isFloatingExempt(metaWindow); if (floatingExempt) { - if (floatClassToggle) { - this.removeFloatOverride(metaWindow); - } else if (floatToggle) { - this.removeFloatOverride(metaWindow, false); - } - nodeWindow.mode = WINDOW_MODES.TILE; + this.removeFloatOverride(metaWindow, withWmId); if (!this.isActiveWindowWorkspaceTiled(metaWindow)) { nodeWindow.mode = WINDOW_MODES.FLOAT; + } else { + nodeWindow.mode = WINDOW_MODES.TILE; } } else { - if (floatClassToggle) { - this.addFloatOverride(metaWindow); - } else if (floatToggle) { - this.addFloatOverride(metaWindow, false); - } + this.addFloatOverride(metaWindow, withWmId); nodeWindow.mode = WINDOW_MODES.FLOAT; } } @@ -350,6 +339,7 @@ export class WindowManager extends GObject.Object { const focusNodeWindow = this.tree.findNode(this.focusMetaWindow); this.updateStackedFocus(focusNodeWindow); this.updateTabbedFocus(focusNodeWindow); + this.movePointerWith(focusNodeWindow); }, }; this.queueEvent(eventObj); @@ -444,6 +434,7 @@ export class WindowManager extends GObject.Object { let currentLayout; switch (action.name) { + case "FloatNonPersistentToggle": case "FloatToggle": case "FloatClassToggle": this.toggleFloatingMode(action, focusWindow); @@ -499,6 +490,7 @@ export class WindowManager extends GObject.Object { if (prev) prev.parentNode.lastTabFocus = prev.nodeValue; this.renderTree("move-tabbed-queue"); } + this.movePointerWith(focusNodeWindow); } }, }); @@ -523,6 +515,7 @@ export class WindowManager extends GObject.Object { focusNodeWindow.nodeValue.raise(); this.updateTabbedFocus(focusNodeWindow); this.updateStackedFocus(focusNodeWindow); + this.movePointerWith(focusNodeWindow); this.renderTree("swap", true); break; case "Split": @@ -679,6 +672,7 @@ export class WindowManager extends GObject.Object { ); let lastActiveNodeWindow = this.tree.findNode(lastActiveWindow); this.tree.swapPairs(lastActiveNodeWindow, focusNodeWindow); + this.movePointerWith(focusNodeWindow); this.renderTree("swap-last-active"); } break; @@ -914,7 +908,7 @@ export class WindowManager extends GObject.Object { try { nodeWindow.tab.remove_style_class_name("window-tabbed-tab-active"); } catch (e) { - Logger.warn(e); + // Logger.warn(e); } } } @@ -1425,6 +1419,8 @@ export class WindowManager extends GObject.Object { this.updateDecorationLayout(); this.updateStackedFocus(); this.updateTabbedFocus(); + let focusNodeWindow = this.tree.findNode(this.focusMetaWindow); + this.movePointerWith(focusNodeWindow); }, }); let focusNodeWindow = this.tree.findNode(this.focusMetaWindow); @@ -1495,6 +1491,8 @@ export class WindowManager extends GObject.Object { .get_workspace() .activate_with_focus(metaWindow, global.display.get_current_time()); this.moveCenter(metaWindow); + } else { + this.movePointerWith(metaWindow); } } } @@ -1613,9 +1611,10 @@ export class WindowManager extends GObject.Object { let nodeWindow; nodeWindow = this.tree.findNodeByActor(actor); - if (nodeWindow) { + if (nodeWindow?.isWindow()) { this.tree.removeNode(nodeWindow); this.renderTree("window-destroy-quick", true); + this.removeFloatOverride(nodeWindow.nodeValue, true); } // find the next attachNode here @@ -1777,10 +1776,26 @@ export class WindowManager extends GObject.Object { */ movePointerWith(nodeWindow) { if (!nodeWindow || !nodeWindow._data) return; - let rect = nodeWindow._data.get_frame_rect(); - global.get_pointer(); - const seat = Clutter.get_default_backend().get_default_seat(); - seat.warp_pointer(rect.x, rect.y); + if (this.ext.settings.get_boolean("move-pointer-focus-enabled")) { + this.storePointerLastPosition(this.lastFocusedWindow); + if (this.canMovePointerInsideNodeWindow(nodeWindow)) { + this.warpPointerToNodeWindow(nodeWindow); + } + } + this.lastFocusedWindow = nodeWindow; + this.tree.debugParentNodes(nodeWindow); + } + + warpPointerToNodeWindow(nodeWindow) { + const newCoord = this.getPointerPositionInside(nodeWindow); + if (newCoord && newCoord.x && newCoord.y) { + const seat = Clutter.get_default_backend().get_default_seat(); + if (seat) { + const wmTitle = nodeWindow.nodeValue.get_title(); + Logger.debug(`moved pointer to [${wmTitle}] at (${newCoord.x},${newCoord.y})`); + seat.warp_pointer(newCoord.x, newCoord.y); + } + } } getPointer() { @@ -1820,6 +1835,7 @@ export class WindowManager extends GObject.Object { const horizontal = parentNodeTarget.isHSplit() || parentNodeTarget.isTabbed(); const isMonParent = parentNodeTarget.nodeType === NODE_TYPES.MONITOR; const isConParent = parentNodeTarget.nodeType === NODE_TYPES.CON; + const centerLayout = this.ext.settings.get_string("dnd-center-layout").toUpperCase(); const stacked = parentNodeTarget.isStacked(); const tabbed = parentNodeTarget.isTabbed(); const stackedOrTabbed = stacked || tabbed; @@ -1917,28 +1933,35 @@ export class WindowManager extends GObject.Object { const isCenter = Utils.rectContainsPoint(centerRegion, currPointer); if (isCenter) { - if (stackedOrTabbed) { - containerNode = parentNodeTarget; - referenceNode = null; + if (centerLayout == "SWAP") { + referenceNode = nodeWinAtPointer; previewParams = { - className: stacked ? "window-tilepreview-stacked" : "window-tilepreview-tabbed", targetRect: targetRect, }; } else { - if (isMonParent) { - childNode.createCon = true; + if (stackedOrTabbed) { containerNode = parentNodeTarget; - referenceNode = nodeWinAtPointer; + referenceNode = null; previewParams = { + className: stacked ? "window-tilepreview-stacked" : "window-tilepreview-tabbed", targetRect: targetRect, }; } else { - containerNode = parentNodeTarget; - referenceNode = null; - const parentTargetRect = this.tree.processGap(parentNodeTarget); - previewParams = { - targetRect: parentTargetRect, - }; + if (isMonParent) { + childNode.createCon = true; + containerNode = parentNodeTarget; + referenceNode = nodeWinAtPointer; + previewParams = { + targetRect: targetRect, + }; + } else { + containerNode = parentNodeTarget; + referenceNode = null; + const parentTargetRect = this.tree.processGap(parentNodeTarget); + previewParams = { + targetRect: parentTargetRect, + }; + } } } } else if (isLeft) { @@ -2117,7 +2140,6 @@ export class WindowManager extends GObject.Object { } else if (isTop || isBottom) { childNode.layout = LAYOUT_TYPES.VSPLIT; } else if (isCenter) { - const centerLayout = this.ext.settings.get_string("dnd-center-layout").toUpperCase(); childNode.layout = LAYOUT_TYPES[centerLayout]; } } else if (childNode.detachWindow) { @@ -2125,6 +2147,9 @@ export class WindowManager extends GObject.Object { isLeft || isRight ? ORIENTATION_TYPES.HORIZONTAL : ORIENTATION_TYPES.VERTICAL; this.tree.split(childNode, orientation); containerNode.insertBefore(childNode.parentNode, referenceNode); + } else if (isCenter && centerLayout == "SWAP") { + this.tree.swapPairs(referenceNode, focusNodeWindow); + this.renderTree("drag-swap"); } else { // Child Node is a WINDOW containerNode.insertBefore(childNode, referenceNode); @@ -2134,11 +2159,11 @@ export class WindowManager extends GObject.Object { if (!stackedOrTabbed) containerNode.layout = LAYOUT_TYPES.VSPLIT; } else if (isCenter) { if (containerNode.isHSplit() || containerNode.isVSplit()) { - const centerLayout = this.ext.settings.get_string("dnd-center-layout").toUpperCase(); containerNode.layout = LAYOUT_TYPES[centerLayout]; } } } + previousParent.resetLayoutSingleChild(); } else { updatePreview(focusNodeWindow, previewParams); } @@ -2147,6 +2172,70 @@ export class WindowManager extends GObject.Object { } } + canMovePointerInsideNodeWindow(nodeWindow) { + if (nodeWindow && nodeWindow._data) { + const metaWindow = nodeWindow.nodeValue; + const metaRect = metaWindow.get_frame_rect(); + const pointerCoord = global.get_pointer(); + return ( + metaRect && + // xdg-copy creates a 1x1 pixel window to capture mouse events. + metaRect.width > 8 && + metaRect.height > 8 && + !Utils.rectContainsPoint(metaRect, pointerCoord) && + !metaWindow.minimized && + !Main.overview.visible && + !this.pointerIsOverParentDecoration(nodeWindow, pointerCoord) + ); + } + return false; + } + + pointerIsOverParentDecoration(nodeWindow, pointerCoord) { + if (pointerCoord && nodeWindow && nodeWindow.parentNode) { + let node = nodeWindow.parentNode; + if (node.isTabbed() || node.isStacked()) { + return Utils.rectContainsPoint(node.rect, pointerCoord); + } + } + return false; + } + + getPointerPositionInside(nodeWindow) { + if (nodeWindow && nodeWindow._data) { + const metaWindow = nodeWindow.nodeValue; + const metaRect = metaWindow.get_frame_rect(); + // on: last position of cursor inside window + // on: titlebar: near to app toolbars, menubar, tabs, etc... + let [wx, wy] = nodeWindow.pointer + ? [nodeWindow.pointer.x, nodeWindow.pointer.y] + : [metaRect.width / 2, 8]; + let px = wx >= metaRect.width ? metaRect.width - 8 : wx; + let py = wy >= metaRect.height ? metaRect.height - 8 : wy; + return { + x: metaRect.x + px, + y: metaRect.y + py, + }; + } + return null; + } + + storePointerLastPosition(nodeWindow) { + if (nodeWindow && nodeWindow._data) { + const metaWindow = nodeWindow.nodeValue; + const metaRect = metaWindow.get_frame_rect(); + const pointerCoord = global.get_pointer(); + if (Utils.rectContainsPoint(metaRect, pointerCoord)) { + let px = pointerCoord[0] - metaRect.x; + let py = pointerCoord[1] - metaRect.y; + if (px > 0 && py > 0) { + nodeWindow.pointer = { x: px, y: py }; + Logger.debug(`stored pointer for [${metaWindow.get_title()}] at (${px},${py})`); + } + } + } + } + findNodeWindowAtPointer(focusNodeWindow) { let pointerCoord = global.get_pointer(); @@ -2451,37 +2540,34 @@ export class WindowManager extends GObject.Object { knownFloats.filter((kf) => { let matchTitle = false; let matchClass = false; + let matchId = false; if (kf.wmTitle) { if (kf.wmTitle === " ") { matchTitle = kf.wmTitle === windowTitle; } else { let titles = kf.wmTitle.split(","); - matchTitle = titles.filter((t) => { - if (windowTitle) { - if (t.startsWith('!')) { - return !windowTitle.includes(t.slice(1)) - } else { - return windowTitle.includes(t) + matchTitle = + titles.filter((t) => { + if (windowTitle) { + if (t.startsWith("!")) { + return !windowTitle.includes(t.slice(1)); + } else { + return windowTitle.includes(t); + } } - } - return false - }).length > 0; + return false; + }).length > 0; } } if (kf.wmClass) { matchClass = kf.wmClass.includes(metaWindow.get_wm_class()); } - - if (kf.wmClass && kf.wmTitle) { - return matchTitle && matchClass; - } else { - if (kf.wmTitle) { - return matchTitle; - } else { - return matchClass; - } + if (kf.wmId) { + matchId = kf.wmId === metaWindow.get_id(); } + + return (!kf.wmId || matchId) && (!kf.wmTitle || matchTitle) && matchClass; }).length > 0; return floatByType || floatOverride; diff --git a/gnome/.local/share/gnome-shell/extensions/forge@jmmaranan.com/lib/prefs/settings.js b/gnome/.local/share/gnome-shell/extensions/forge@jmmaranan.com/lib/prefs/settings.js index cfc520a..9333fe2 100644 --- a/gnome/.local/share/gnome-shell/extensions/forge@jmmaranan.com/lib/prefs/settings.js +++ b/gnome/.local/share/gnome-shell/extensions/forge@jmmaranan.com/lib/prefs/settings.js @@ -101,6 +101,7 @@ export class SettingsPage extends PreferencesPage { type: "s", bind: "dnd-center-layout", items: [ + { id: "swap", name: _("Swap") }, { id: "tabbed", name: _("Tabbed") }, { id: "stacked", name: _("Stacked") }, ], @@ -129,6 +130,19 @@ export class SettingsPage extends PreferencesPage { ], }); + this.add_group({ + title: _("Behavior"), + children: [ + new SwitchRow({ + title: _("Move Pointer with the Focus"), + subtitle: _("Move the pointer when focusing or swapping via keyboard"), + experimental: true, + settings, + bind: "move-pointer-focus-enabled", + }), + ], + }); + if (!production) { this.add_group({ title: _("Logger"), diff --git a/gnome/.local/share/gnome-shell/extensions/forge@jmmaranan.com/locale/it/LC_MESSAGES/forge.mo b/gnome/.local/share/gnome-shell/extensions/forge@jmmaranan.com/locale/it/LC_MESSAGES/forge.mo index 5532b20e1322570b1359f244937084cad021d642..39f77a4cd20ba7c1a68f9ff37eecc74327660d70 100644 GIT binary patch literal 5667 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 LOn4g2OHa#R-usAh diff --git a/gnome/.local/share/gnome-shell/extensions/forge@jmmaranan.com/locale/pt_BR/LC_MESSAGES/forge.mo b/gnome/.local/share/gnome-shell/extensions/forge@jmmaranan.com/locale/pt_BR/LC_MESSAGES/forge.mo index 071947e0e4dbef702ef0d520e407f33f613438ed..30dce8dbdd40cf70ea0449e9d12a09eb7190aeb8 100644 GIT binary patch literal 4264 zcmaKuON<;x8Gs8C2rPj-2#@eAAdVC8?8C&ySuY!}y}N$kwU?bqqDYWXGhI7Vc28Hk zx_j4aB&1v-A#p(p7sNvW2`dPs1PKBJE{w#13qs-)MQ{TN4jg<%gzvBJnccMmt?B-{ zx~l&AU-j4g<=)%BrMN!F{SodzzeTCD@Ef=B;CktHrQQZ#hVtnZI0avA_XOplRhLi=uERoIy%n0_k>K3BEOQ$8z$PxWQHqfV6}Rm*nMRB5S~ zWuVED)-r?jDVvq7aNg{Q;>$L*C5zjurAFr}D{MKf*MltzyM^cj~VHq+Y!9&P-X z)}6fLbr$J*6B2da_H71yzb|gFTQ*f|e#`20k5E2syK)c>h)dOd60CgOFY=>ttf2{9 zv2F5P-X&IeuU_YZ&#c0+Th4ByT2^94Uvydze#>Fswhxz!-1Mv_)UIa>ad2_j<86&?QPWA3)P^OF^|MfIV%#hBf?E_F7G~U{NM5KGP3=*# zj5UWtn>bV2bZ23vTGZVgoz(fm{IbLx1P%PQZld+Y%JnYm{axgMD|O-m%MrbC4)AtU z?AutSpPblRi&SyL=;g`u7}R!YdY5gY8t#d=CZ#1)#i5h#-CVM&UF9~Y_D)ustEywV zUBuM*Us9Uhy+U}mlhjnw+M9Fxbf~Av7zzH9al`60lbOC9vguSEZ`LMF4;Fgh`h!*~ z`KC9mVXN6#6mNtqsJ<$ksBe&+Egp zhv!A9oxhmW*oADNw@~enC50)k>4i(N9ZvLz z#--CeKU`!^)~|3=t7FZOwZ`pvotMv?+?ZNBySB2c=G^q`loUIB+Uo4&Xd?Szh63cW zp)cBBj1 zP{)U+bUh;hq*VK%_$IbIt)LU5rLY?kYiP28XVWwv5NU(ezA5TGlQ2BzfY6srW>Zs0 zfwx1x*mPhLQ^YcF%3!ueFBUqHiPTGNwFv>AnlMxN6v(=&w7t~mrsUVn!s50}Xv#kEWl2WJ0(D)9<0wpy)u;7Zg^gae zbR!`i0`#brtFDXJs-cNnzc~yXJ~Cc&DAfL{&F7#PMj7g2KDs{oIpq$q9a*(#_FHrr zExzAm5JedOtfp028RDV~{D`kJ4D-2H6nk>~TJ$)RsoQ%7tNNH&q12A9H<8@i&=-fU zbcnx#Y|!@C9D&^pu-AKstEh6~n{&jd3r==4%W|T`!y@3UbxBtje6$*6(CF4aoP<*i z<10-XWCgi4NftRvVoX@-g3SiiP@OSdN)0j5>|p9<H6rVm4_M?Ye%m6%Uv=kt3#w%p}hP z2TeR@>K(-h&QaMHb%K)6o376qbxMpgs<;2M4x<-x(yAEukMj+$Cv4q4&*m}YhRm{zLcFbd(GZs;wSo}FKS1qFTQWqm{QY8u|bkg_##n#j7|5bJULG}H{ zzp3!a5Yqq6^`4A~9#p5PbW%7c{yf)|xXCyP)^5I{_-4ffFZ(nxXq5*?J2!6MFm0ux zG+vi&!^uft3qratPj(YxiHaawU;b$CAHpKHM)}q+F>$?|n53l?m%yL*aV_BR9KC?X GUi}xr9i{I8 delta 1011 zcmXZbJ808U6vy$CnrHKBYifN|O{;xSp`f*!s2L1`v|w8VB^I@bMu@4^M28Lm2fj^N?*Gr_-g8fGo^<{0sI0bm=Zw}* zbP^el*)YyG(b2AMGV|dK^4LwfW}L+c-o`LGOyNV+{7;SVYv|>D9rxf*Ok*b>d(0{} z#h{H3cTf}O={oQchOmY~TtYv-L2bN@Job@pGk(T#{Dn$jgiiCv@d%zlt#cpSaRC$T zZ#4!1KD@w8@4S zQS*veAvv36(2BP(gZGffzBb&zQQm!|9mfgWhgs~yyQulkQ3<_5o%lOy<3A0(T$KI1 zM^FhL4pVK_@)edX<*pUoQ1pX48>_m%u@ml8 K{G>bDlK%(S this.settings.set_int("enable-tap-gesture", num)) @@ -52,7 +53,7 @@ class KeyboardMenuToggle extends QuickSettings.QuickMenuToggle { } _refresh() { - for (var i in this._itemsSection._getMenuItems()){ + for (var i in this._itemsSection._getMenuItems()) { this._itemsSection._getMenuItems()[i].setIcon(this.settings.get_int("enable-tap-gesture") == i ? 'emblem-ok-symbolic' : null) } } @@ -97,7 +98,7 @@ export default class GjsOskExtension extends Extension { this.openInterval = setInterval(() => { this.Keyboard.get_parent().set_child_at_index(this.Keyboard, this.Keyboard.get_parent().get_n_children() - 1); this.Keyboard.set_child_at_index(this.Keyboard.box, this.Keyboard.get_n_children() - 1); - if (!this.Keyboard.openedFromButton && this.lastInputMethod) { + if (!this.Keyboard.openedFromButton && this.lastInputMethod) { if (Main.inputMethod.currentFocus != null && Main.inputMethod.currentFocus.is_focused() && !this.Keyboard.closedFromButton) { this._openKeyboard(); } else if (!this.Keyboard.closedFromButton) { @@ -123,6 +124,10 @@ export default class GjsOskExtension extends Extension { keycodes = JSON.parse(contents)[['qwerty', 'azerty', 'dvorak', "qwertz"][this.settings.get_int("lang")]]; } this.Keyboard = new Keyboard(this.settings); + + this._originalLastDeviceIsTouchscreen = KeyboardUI.KeyboardManager.prototype._lastDeviceIsTouchscreen; + KeyboardUI.KeyboardManager.prototype._lastDeviceIsTouchscreen = () => { return false }; + this._indicator = null; this.openInterval = null; if (this.settings.get_boolean("indicator-enabled")) { @@ -151,9 +156,9 @@ export default class GjsOskExtension extends Extension { this.open_interval(); } this.openFromCommandHandler = this.openBit.connect("changed", () => { - this.openBit.set_boolean("opened", false) - this._toggleKeyboard(); - }) + this.openBit.set_boolean("opened", false) + this._toggleKeyboard(); + }) this.settingsHandler = this.settings.connect("changed", key => { this.Keyboard.openedFromButton = false; let [ok, contents] = GLib.file_get_contents(this.path + '/keycodes.json'); @@ -175,7 +180,7 @@ export default class GjsOskExtension extends Extension { style_class: 'system-status-icon' }); this._indicator.add_child(icon); - + this._indicator.connect("button-press-event", () => this._toggleKeyboard()); this._indicator.connect("touch-event", (_actor, event) => { if (event.type() == 11) this._toggleKeyboard() @@ -222,6 +227,10 @@ export default class GjsOskExtension extends Extension { this.settings = null this.Keyboard = null keycodes = null + if (this._originalLastDeviceIsTouchscreen !== null) { + KeyboardUI.KeyboardManager.prototype._lastDeviceIsTouchscreen = this._originalLastDeviceIsTouchscreen; + this._originalLastDeviceIsTouchscreen = null; + } } } @@ -237,10 +246,11 @@ class Keyboard extends Dialog { } _init(settings) { + this.inputDevice = Clutter.get_default_backend().get_default_seat().create_virtual_device(Clutter.InputDeviceType.KEYBOARD_DEVICE); this.startupInterval = setInterval(() => { this.init = KeyboardManager.getKeyboardManager()._current.id; this.initLay = Object.keys(KeyboardManager.getKeyboardManager()._layoutInfos); - if (this.initLay == undefined || this.init == undefined) { + if (this.initLay == undefined || this.init == undefined || this.inputDevice == undefined) { return; } this.settings = settings; @@ -268,9 +278,8 @@ class Keyboard extends Dialog { this.delta = []; this.checkMonitor(); this._dragging = false; - this.inputDevice = Clutter.get_default_backend().get_default_seat().create_virtual_device(Clutter.InputDeviceType.KEYBOARD_DEVICE); clearInterval(this.startupInterval); - }, 200); + }, 200); } destroy() { @@ -290,7 +299,7 @@ class Keyboard extends Dialog { clearInterval(this.textboxChecker); this.textboxChecker = null; } - if (this.stateTimeout !== null ) { + if (this.stateTimeout !== null) { clearTimeout(this.stateTimeout); this.stateTimeout = null; } @@ -316,7 +325,7 @@ class Keyboard extends Dialog { opacity: 200, duration: 100, mode: Clutter.AnimationMode.EASE_OUT_QUAD, - onComplete: () => {} + onComplete: () => { } }); let device = event.get_device(); let sequence = event.get_event_sequence(); @@ -356,7 +365,7 @@ class Keyboard extends Dialog { opacity: 255, duration: 100, mode: Clutter.AnimationMode.EASE_OUT_QUAD, - onComplete: () => {} + onComplete: () => { } }); this._grabbedSequence = null; this._grabbedDevice = null; @@ -410,17 +419,18 @@ class Keyboard extends Dialog { snapMovement(xPos, yPos) { let monitor = Main.layoutManager.primaryMonitor + let snap_px = this.settings.get_int("snap-spacing-px") if (Math.abs(xPos - ((monitor.width * .5) - ((this.width * .5)))) <= 50) { xPos = ((monitor.width * .5) - ((this.width * .5))); - } else if (Math.abs(xPos - 25) <= 50) { - xPos = 25; - } else if (Math.abs(xPos - (monitor.width - this.width - 25)) <= 50) { - xPos = monitor.width - this.width - 25 + } else if (Math.abs(xPos - snap_px) <= 50) { + xPos = snap_px; + } else if (Math.abs(xPos - (monitor.width - this.width - snap_px)) <= 50) { + xPos = monitor.width - this.width - snap_px } - if (Math.abs(yPos - (monitor.height - this.height - 25)) <= 50) { - yPos = monitor.height - this.height - 25; - } else if (Math.abs(yPos - 25) <= 50) { - yPos = 25; + if (Math.abs(yPos - (monitor.height - this.height - snap_px)) <= 50) { + yPos = monitor.height - this.height - snap_px; + } else if (Math.abs(yPos - snap_px) <= 50) { + yPos = snap_px; } else if (Math.abs(yPos - ((monitor.height * .5) - (this.height * .5))) <= 50) { yPos = (monitor.height * .5) - (this.height * .5); } @@ -442,7 +452,7 @@ class Keyboard extends Dialog { refresh() { let monitor = Main.layoutManager.primaryMonitor; this.box.remove_all_children(); - this.box.set_style_class_name("boxLay") + this.box.set_style_class_name("boxLay") this.widthPercent = (monitor.width > monitor.height) ? this.settings.get_int("landscape-width-percent") / 100 : this.settings.get_int("portrait-width-percent") / 100; this.heightPercent = (monitor.width > monitor.height) ? this.settings.get_int("landscape-height-percent") / 100 : this.settings.get_int("portrait-height-percent") / 100; this.buildUI(); @@ -468,12 +478,12 @@ class Keyboard extends Dialog { this.startupTimeout = setTimeout(() => { this.init = KeyboardManager.getKeyboardManager()._current.id; this.initLay = Object.keys(KeyboardManager.getKeyboardManager()._layoutInfos); - if (this.initLay == undefined || this.init == undefined) { + if (this.initLay == undefined || this.init == undefined) { this.refresh(); return; } this.close(); - }, 200); + }, 200); this.mod = []; this.modBtns = []; this.capsL = false; @@ -495,7 +505,7 @@ class Keyboard extends Dialog { this.startupTimeout = setTimeout(() => { this.init = KeyboardManager.getKeyboardManager()._current.id; this.initLay = Object.keys(KeyboardManager.getKeyboardManager()._layoutInfos); - if (this.initLay == undefined || this.init == undefined) { + if (this.initLay == undefined || this.init == undefined) { this.open(); return; } @@ -522,13 +532,13 @@ class Keyboard extends Dialog { this.state = "opened" }, 500); let monitor = Main.layoutManager.primaryMonitor; - let posX = [25, ((monitor.width * .5) - ((this.width * .5))), monitor.width - this.width - 25][(this.settings.get_int("default-snap") % 3)]; - let posY = [25, ((monitor.height * .5) - ((this.height * .5))), monitor.height - this.height - 25][Math.floor((this.settings.get_int("default-snap") / 3))]; + let posX = [this.settings.get_int("snap-spacing-px"), ((monitor.width * .5) - ((this.width * .5))), monitor.width - this.width - this.settings.get_int("snap-spacing-px")][(this.settings.get_int("default-snap") % 3)]; + let posY = [this.settings.get_int("snap-spacing-px"), ((monitor.height * .5) - ((this.height * .5))), monitor.height - this.height - this.settings.get_int("snap-spacing-px")][Math.floor((this.settings.get_int("default-snap") / 3))]; this.set_translation(posX, posY, 0); } }); this.opened = true; - }, 200); + }, 200); } close() { @@ -537,8 +547,8 @@ class Keyboard extends Dialog { KeyboardManager.getKeyboardManager().apply(this.init); } let monitor = Main.layoutManager.primaryMonitor; - let posX = [25, ((monitor.width * .5) - ((this.width * .5))), monitor.width - this.width - 25][(this.settings.get_int("default-snap") % 3)]; - let posY = [25, ((monitor.height * .5) - ((this.height * .5))), monitor.height - this.height - 25][Math.floor((this.settings.get_int("default-snap") / 3))]; + let posX = [this.settings.get_int("snap-spacing-px"), ((monitor.width * .5) - ((this.width * .5))), monitor.width - this.width - this.settings.get_int("snap-spacing-px")][(this.settings.get_int("default-snap") % 3)]; + let posY = [this.settings.get_int("snap-spacing-px"), ((monitor.height * .5) - ((this.height * .5))), monitor.height - this.height - this.settings.get_int("snap-spacing-px")][Math.floor((this.settings.get_int("default-snap") / 3))]; this.state = "closing" this.box.ease({ opacity: 0, @@ -559,39 +569,64 @@ class Keyboard extends Dialog { }, }); this.openedFromButton = false + this.releaseAllKeys(); } buildUI() { this.keys = []; let monitor = Main.layoutManager.primaryMonitor - var topRowWidth = Math.round(((monitor.width - 90) * this.widthPercent) / 15); - var topRowHeight = Math.round(((monitor.height - 190) * this.heightPercent) / 6); + var topRowWidth = Math.round((monitor.width - 40 - this.settings.get_int("snap-spacing-px") * 2) * this.widthPercent / 15) + var topRowHeight = Math.round((monitor.height - 140 - this.settings.get_int("snap-spacing-px") * 2) * this.heightPercent / 6) let row1 = new St.BoxLayout({ pack_start: true }); for (var num in keycodes.row1) { const i = keycodes.row1[num] + if (i.lowerName == "") { + i.lowerName = i._lowerName; + i.upperName = i._upperName; + } var w = topRowWidth; - row1.add_child(new St.Button({ - label: i.lowerName, + let params = { height: topRowHeight, width: w - })); - var isMod = false; - for (var j of [42, 54, 29, 125, 56, 100, 97, 58]) { - if (i.code == j) { - isMod = true; + } + let styleClass = "" + switch (i.lowerName) { + case "delete": + case "backspace": + case "tab": + case "capslock": + case "shift": + case "enter": + case "ctrl": + case "super": + case "alt": + case "space": + case "left": + case "up": + case "down": + case "right": + styleClass = i.lowerName; + i._lowerName = i.lowerName; + i._upperName = i.upperName; + i.lowerName = ""; + i.upperName = ""; break; - } + default: + params.label = i.lowerName; + break; + } + row1.add_child(new St.Button(params)); + if (styleClass != "") { + row1.get_children()[num].add_style_class_name(styleClass + "_btn"); + } + i.isMod = false + if ([42, 54, 29, 125, 56, 100, 97, 58].some(j => { return i.code == j })) { + i.isMod = true; } row1.get_children()[num].char = i; - if (!isMod) { - row1.get_children()[num].connect("clicked", () => this.decideMod(i)) - } else { - const modButton = row1.get_children()[num]; - row1.get_children()[num].connect("clicked", () => this.decideMod(i, modButton)) - } } this.keys.push.apply(this.keys, row1.get_children()); row1.add_style_class_name("keysHolder"); @@ -600,6 +635,10 @@ class Keyboard extends Dialog { }); for (var num in keycodes.row2) { const i = keycodes.row2[num] + if (i.lowerName == "") { + i.lowerName = i._lowerName; + i.upperName = i._upperName; + } var w; if (num == 0) { w = ((row1.width - ((keycodes.row2.length - 2) * ((topRowWidth) + 5))) / 2) * 0.5; @@ -608,25 +647,45 @@ class Keyboard extends Dialog { } else { w = (topRowWidth) + 5; } - row2.add_child(new St.Button({ - label: i.lowerName, + let params = { height: topRowHeight + 20, width: w - })); - var isMod = false; - for (var j of [42, 54, 29, 125, 56, 100, 97, 58]) { - if (i.code == j) { - isMod = true; + } + let styleClass = "" + switch (i.lowerName) { + case "delete": + case "backspace": + case "tab": + case "capslock": + case "shift": + case "enter": + case "ctrl": + case "super": + case "alt": + case "space": + case "left": + case "up": + case "down": + case "right": + styleClass = i.lowerName; + i._lowerName = i.lowerName; + i._upperName = i.upperName; + i.lowerName = ""; + i.upperName = ""; break; - } + default: + params.label = i.lowerName; + break; + } + row2.add_child(new St.Button(params)); + if (styleClass != "") { + row2.get_children()[num].add_style_class_name(styleClass + "_btn"); + } + i.isMod = false + if ([42, 54, 29, 125, 56, 100, 97, 58].some(j => { return i.code == j })) { + i.isMod = true; } row2.get_children()[num].char = i; - if (!isMod) { - row2.get_children()[num].connect("clicked", () => this.decideMod(i)) - } else { - const modButton = row2.get_children()[num]; - row2.get_children()[num].connect("clicked", () => this.decideMod(i, modButton)) - } } this.keys.push.apply(this.keys, row2.get_children()); row2.add_style_class_name("keysHolder"); @@ -635,6 +694,10 @@ class Keyboard extends Dialog { }); for (var num in keycodes.row3) { const i = keycodes.row3[num] + if (i.lowerName == "") { + i.lowerName = i._lowerName; + i.upperName = i._upperName; + } var w; if (num == 0) { w = ((row1.width - ((keycodes.row3.length - 2) * ((topRowWidth) + 5))) / 2) * 1.1; @@ -643,25 +706,45 @@ class Keyboard extends Dialog { } else { w = (topRowWidth) + 5; } - row3.add_child(new St.Button({ - label: i.lowerName, + let params = { height: topRowHeight + 20, width: w - })); - var isMod = false; - for (var j of [42, 54, 29, 125, 56, 100, 97, 58]) { - if (i.code == j) { - isMod = true; + } + let styleClass = "" + switch (i.lowerName) { + case "delete": + case "backspace": + case "tab": + case "capslock": + case "shift": + case "enter": + case "ctrl": + case "super": + case "alt": + case "space": + case "left": + case "up": + case "down": + case "right": + styleClass = i.lowerName; + i._lowerName = i.lowerName; + i._upperName = i.upperName; + i.lowerName = ""; + i.upperName = ""; break; - } + default: + params.label = i.lowerName; + break; + } + row3.add_child(new St.Button(params)); + if (styleClass != "") { + row3.get_children()[num].add_style_class_name(styleClass + "_btn"); + } + i.isMod = false + if ([42, 54, 29, 125, 56, 100, 97, 58].some(j => { return i.code == j })) { + i.isMod = true; } row3.get_children()[num].char = i; - if (!isMod) { - row3.get_children()[num].connect("clicked", () => this.decideMod(i)) - } else { - const modButton = row3.get_children()[num]; - row3.get_children()[num].connect("clicked", () => this.decideMod(i, modButton)) - } } this.keys.push.apply(this.keys, row3.get_children()); row3.add_style_class_name("keysHolder"); @@ -670,31 +753,55 @@ class Keyboard extends Dialog { }); for (var num in keycodes.row4) { const i = keycodes.row4[num] + if (i.lowerName == "") { + i.lowerName = i._lowerName; + i.upperName = i._upperName; + } var w; if (num == 0 || num == keycodes.row4.length - 1) { w = ((row1.width - ((keycodes.row4.length - 2) * ((topRowWidth) + 5))) / 2); } else { w = (topRowWidth) + 5; } - row4.add_child(new St.Button({ - label: i.lowerName, + let params = { height: topRowHeight + 20, width: w - })); - var isMod = false; - for (var j of [42, 54, 29, 125, 56, 100, 97, 58]) { - if (i.code == j) { - isMod = true; + } + let styleClass = "" + switch (i.lowerName) { + case "delete": + case "backspace": + case "tab": + case "capslock": + case "shift": + case "enter": + case "ctrl": + case "super": + case "alt": + case "space": + case "left": + case "up": + case "down": + case "right": + styleClass = i.lowerName; + i._lowerName = i.lowerName; + i._upperName = i.upperName; + i.lowerName = ""; + i.upperName = ""; break; - } + default: + params.label = i.lowerName; + break; + } + row4.add_child(new St.Button(params)); + if (styleClass != "") { + row4.get_children()[num].add_style_class_name(styleClass + "_btn"); + } + i.isMod = false + if ([42, 54, 29, 125, 56, 100, 97, 58].some(j => { return i.code == j })) { + i.isMod = true; } row4.get_children()[num].char = i; - if (!isMod) { - row4.get_children()[num].connect("clicked", () => this.decideMod(i)) - } else { - const modButton = row4.get_children()[num]; - row4.get_children()[num].connect("clicked", () => this.decideMod(i, modButton)) - } } this.keys.push.apply(this.keys, row4.get_children()); row4.add_style_class_name("keysHolder"); @@ -703,31 +810,55 @@ class Keyboard extends Dialog { }); for (var num in keycodes.row5) { const i = keycodes.row5[num] + if (i.lowerName == "") { + i.lowerName = i._lowerName; + i.upperName = i._upperName; + } var w; if (num == 0 || num == keycodes.row5.length - 1) { w = ((row1.width - ((keycodes.row5.length - 2) * ((topRowWidth) + 5))) / 2); } else { w = (topRowWidth) + 5; } - row5.add_child(new St.Button({ - label: i.lowerName, + let params = { height: topRowHeight + 20, width: w - })); - var isMod = false; - for (var j of [42, 54, 29, 125, 56, 100, 97, 58]) { - if (i.code == j) { - isMod = true; + } + let styleClass = "" + switch (i.lowerName) { + case "delete": + case "backspace": + case "tab": + case "capslock": + case "shift": + case "enter": + case "ctrl": + case "super": + case "alt": + case "space": + case "left": + case "up": + case "down": + case "right": + styleClass = i.lowerName; + i._lowerName = i.lowerName; + i._upperName = i.upperName; + i.lowerName = ""; + i.upperName = ""; break; - } + default: + params.label = i.lowerName; + break; + } + row5.add_child(new St.Button(params)); + if (styleClass != "") { + row5.get_children()[num].add_style_class_name(styleClass + "_btn"); + } + i.isMod = false + if ([42, 54, 29, 125, 56, 100, 97, 58].some(j => { return i.code == j })) { + i.isMod = true; } row5.get_children()[num].char = i; - if (!isMod) { - row5.get_children()[num].connect("clicked", () => this.decideMod(i)) - } else { - const modButton = row5.get_children()[num]; - row5.get_children()[num].connect("clicked", () => this.decideMod(i, modButton)) - } } this.keys.push.apply(this.keys, row5.get_children()); row5.add_style_class_name("keysHolder"); @@ -736,52 +867,72 @@ class Keyboard extends Dialog { }); for (var num in keycodes.row6) { const i = keycodes.row6[num] + if (i.lowerName == "") { + i.lowerName = i._lowerName; + i.upperName = i._upperName; + } var w; if (num == 3) { w = ((row1.width - ((keycodes.row6.length + 1) * ((topRowWidth) + 5)))); - row6.add_child(new St.Button({ - label: i.lowerName, + let params = { height: topRowHeight + 20, width: w - })); - var isMod = false; - for (var j of [42, 54, 29, 125, 56, 100, 97, 58]) { - if (i.code == j) { - isMod = true; + } + let styleClass = "" + switch (i.lowerName) { + case "delete": + case "backspace": + case "tab": + case "capslock": + case "shift": + case "enter": + case "ctrl": + case "super": + case "alt": + case "space": + case "left": + case "up": + case "down": + case "right": + styleClass = i.lowerName; + i._lowerName = i.lowerName; + i._upperName = i.upperName; + i.lowerName = ""; + i.upperName = ""; break; - } + default: + params.label = i.lowerName; + break; + } + row6.add_child(new St.Button(params)); + if (styleClass != "") { + row6.get_children()[num].add_style_class_name(styleClass + "_btn"); + } + i.isMod = false + if ([42, 54, 29, 125, 56, 100, 97, 58].some(j => { return i.code == j })) { + i.isMod = true; } row6.get_children()[num].char = i; this.keys.push(row6.get_children()[num]); - if (!isMod) { - row6.get_children()[num].connect("clicked", () => this.decideMod(i)) - } else { - const modButton = row6.get_children()[num]; - row6.get_children()[num].connect("clicked", () => this.decideMod(i, modButton)) - } } else if (num == keycodes.row6.length - 1) { var gbox = new St.BoxLayout({ pack_start: true }); - var btn1 = new St.Button({ - label: (keycodes.row6[keycodes.row6.length - 1])[0].lowerName - }); + var btn1 = new St.Button(); + btn1.add_style_class_name("left_btn"); gbox.add_child(btn1); var vbox = new St.BoxLayout({ vertical: true }); - var btn2 = new St.Button({ - label: (keycodes.row6[keycodes.row6.length - 1])[1].lowerName - }); - var btn3 = new St.Button({ - label: (keycodes.row6[keycodes.row6.length - 1])[2].lowerName - }); + var btn2 = new St.Button(); + btn2.add_style_class_name("up_btn"); + var btn3 = new St.Button(); + btn3.add_style_class_name("down_btn"); vbox.add_child(btn2); vbox.add_child(btn3); gbox.add_child(vbox); - var btn4 = new St.Button({ - label: (keycodes.row6[keycodes.row6.length - 1])[3].lowerName - }); + var btn4 = new St.Button(); + btn4.add_style_class_name("right_btn"); gbox.add_child(btn4); var btn5 = new St.Button(); btn5.add_style_class_name("move_btn") @@ -791,10 +942,6 @@ class Keyboard extends Dialog { gbox.add_child(btn5); } gbox.add_child(btn6); - btn1.connect("clicked", () => this.decideMod((keycodes.row6[keycodes.row6.length - 1])[0])) - btn2.connect("clicked", () => this.decideMod((keycodes.row6[keycodes.row6.length - 1])[1])) - btn3.connect("clicked", () => this.decideMod((keycodes.row6[keycodes.row6.length - 1])[2])) - btn4.connect("clicked", () => this.decideMod((keycodes.row6[keycodes.row6.length - 1])[3])) btn5.connect("clicked", () => { if (this.settings.get_boolean("enable-drag")) { this.draggable = !this.draggable; @@ -820,13 +967,13 @@ class Keyboard extends Dialog { width: btn5.width * (this.draggable ? 2 : 0.5), duration: 100, mode: Clutter.AnimationMode.EASE_OUT_QUAD, - onComplete: () => {} + onComplete: () => { } }) btn6.ease({ width: this.draggable ? 0 : btn5.width / 2, duration: 100, mode: Clutter.AnimationMode.EASE_OUT_QUAD, - onComplete: () => {} + onComplete: () => { } }) } }) @@ -835,6 +982,14 @@ class Keyboard extends Dialog { btn2.char = (keycodes.row6[keycodes.row6.length - 1])[1] btn3.char = (keycodes.row6[keycodes.row6.length - 1])[2] btn4.char = (keycodes.row6[keycodes.row6.length - 1])[3] + btn1.char.lowerName = "" + btn1.char.upperName = "" + btn2.char.lowerName = "" + btn2.char.upperName = "" + btn3.char.lowerName = "" + btn3.char.upperName = "" + btn4.char.lowerName = "" + btn4.char.upperName = "" btn1.width = Math.round((((topRowWidth) + 5)) * (2 / 3)); btn1.height = topRowHeight + 20; btn2.width = Math.round((((topRowWidth) + 5)) * (2 / 3)); @@ -858,27 +1013,46 @@ class Keyboard extends Dialog { row6.add_child(gbox); } else { w = (topRowWidth) + 5; - row6.add_child(new St.Button({ - label: i.lowerName, + let params = { height: topRowHeight + 20, width: w - })); - - var isMod = false; - for (var j of [42, 54, 29, 125, 56, 100, 97, 58]) { - if (i.code == j) { - isMod = true; + } + let styleClass = "" + switch (i.lowerName) { + case "delete": + case "backspace": + case "tab": + case "capslock": + case "shift": + case "enter": + case "ctrl": + case "super": + case "alt": + case "space": + case "left": + case "up": + case "down": + case "right": + styleClass = i.lowerName; + i._lowerName = i.lowerName; + i._upperName = i.upperName; + i.lowerName = ""; + i.upperName = ""; break; - } + default: + params.label = i.lowerName; + break; + } + row6.add_child(new St.Button(params)); + if (styleClass != "") { + row6.get_children()[num].add_style_class_name(styleClass + "_btn"); + } + i.isMod = false + if ([42, 54, 29, 125, 56, 100, 97, 58].some(j => { return i.code == j })) { + i.isMod = true; } row6.get_children()[num].char = i; this.keys.push(row6.get_children()[num]); - if (!isMod) { - row6.get_children()[num].connect("clicked", () => this.decideMod(i)) - } else { - const modButton = row6.get_children()[num]; - row6.get_children()[num].connect("clicked", () => this.decideMod(i, modButton)) - } } } row6.add_style_class_name("keysHolder"); @@ -889,136 +1063,138 @@ class Keyboard extends Dialog { this.box.add_child(row4); this.box.add_child(row5); this.box.add_child(row6); - var containers_ = this.box.get_children(); - if (this.lightOrDark(this.settings.get_double("background-r"), this.settings.get_double("background-g"), this.settings.get_double("background-b"))) { + if (this.lightOrDark(this.settings.get_double("background-r"), this.settings.get_double("background-g"), this.settings.get_double("background-b"))) { this.box.add_style_class_name("inverted"); } else { this.box.add_style_class_name("regular"); } this.keys.forEach(item => { - item.width -= this.settings.get_int("border-spacing-px") * 2; - item.height -= this.settings.get_int("border-spacing-px") * 2; - item.set_style("margin: " + this.settings.get_int("border-spacing-px") + "px; font-size: " + this.settings.get_int("font-size-px") + "px; border-radius: " + (this.settings.get_boolean("round-key-corners") ? "5px;" : "0;") + "background-size: " + this.settings.get_int("font-size-px") + "px;"); + item.set_scale((item.width - this.settings.get_int("border-spacing-px") * 2) / item.width, (item.height - this.settings.get_int("border-spacing-px") * 2) / item.height); + item.set_style("font-size: " + this.settings.get_int("font-size-px") + "px; border-radius: " + (this.settings.get_boolean("round-key-corners") ? "5px;" : "0;") + "background-size: " + this.settings.get_int("font-size-px") + "px;"); if (this.lightOrDark(this.settings.get_double("background-r"), this.settings.get_double("background-g"), this.settings.get_double("background-b"))) { item.add_style_class_name("inverted"); } else { item.add_style_class_name("regular"); } - let isMod = false - for (var j of [42, 54, 29, 125, 56, 100, 97, 58]) { - try { - if (item.char.code == j) { - isMod = true; - break; - } - } catch { - print(item) - } - } item.set_pivot_point(0.5, 0.5) item.connect("destroy", () => { - if (item.button_pressed !== null){ + if (item.button_pressed !== null) { clearTimeout(item.button_pressed) item.button_pressed == null } - if (item.button_repeat !== null){ + if (item.button_repeat !== null) { clearInterval(item.button_repeat) item.button_repeat == null } - if (item.tap_pressed !== null){ - clearTimeout(item.tap_pressed) - item.tap_pressed == null + if (item.tap_pressed !== null) { + clearTimeout(item.tap_pressed) + item.tap_pressed == null } - if (item.tap_repeat !== null){ + if (item.tap_repeat !== null) { clearInterval(item.tap_repeat) item.tap_repeat == null } }) - item.connect("button-press-event", () => { + let pressEv = (evType) => { + item.space_motion_handler = null item.set_scale(1.2, 1.2) + item.add_style_pseudo_class("pressed") let player if (this.settings.get_boolean("play-sound")) { player = global.display.get_sound_player(); player.play_from_theme("dialog-information", "tap", null) } - item.button_pressed = setTimeout(() => { - if (!isMod) { + if (["delete_btn", "backspace_btn", "up_btn", "down_btn", "left_btn", "right_btn"].some(e => item.has_style_class_name(e))) { + item.button_pressed = setTimeout(() => { const oldModBtns = this.modBtns item.button_repeat = setInterval(() => { if (this.settings.get_boolean("play-sound")) { player.play_from_theme("dialog-information", "tap", null) } this.decideMod(item.char) - + for (var i of oldModBtns) { this.decideMod(i.char, i) } }, 100); - - } - }, 750); - }) - item.connect("button-release-event", () => { + }, 750); + } else if (item.has_style_class_name("space_btn")) { + item.button_pressed = setTimeout(() => { + let lastPos = (item.get_transformed_position()[0] + item.get_transformed_size()[0] / 2) + if (evType == "mouse") { + item.space_motion_handler = item.connect("motion_event", (actor, event) => { + let absX = event.get_coords()[0]; + if (Math.abs(absX - lastPos) > 20) { + if (absX > lastPos) { + this.sendKey([106]) + } else { + this.sendKey([105]) + } + lastPos = absX + } + }) + } else { + item.space_motion_handler = item.connect("touch_event", (actor, event) => { + if (event.type() == Clutter.EventType.TOUCH_UPDATE) { + let absX = event.get_coords()[0]; + if (Math.abs(absX - lastPos) > 20) { + if (absX > lastPos) { + this.sendKey([106]) + } else { + this.sendKey([105]) + } + lastPos = absX + } + } + }) + } + }, 750) + } else { + item.key_pressed = true; + item.button_pressed = setTimeout(() => { + releaseEv() + }, 1000); + } + } + let releaseEv = () => { + item.remove_style_pseudo_class("pressed") item.ease({ - scale_x: 1, - scale_y: 1, + scale_x: (item.width - this.settings.get_int("border-spacing-px") * 2) / item.width, + scale_y: (item.height - this.settings.get_int("border-spacing-px") * 2) / item.height, duration: 100, mode: Clutter.AnimationMode.EASE_OUT_QUAD, - onComplete: () => {item.set_scale(1, 1)} + onComplete: () => { item.set_scale((item.width - this.settings.get_int("border-spacing-px") * 2) / item.width, (item.height - this.settings.get_int("border-spacing-px") * 2) / item.height); } }) - if (item.button_pressed !== null){ + if (item.button_pressed !== null) { clearTimeout(item.button_pressed) item.button_pressed == null } - if (item.button_repeat !== null){ + if (item.button_repeat !== null) { clearInterval(item.button_repeat) item.button_repeat == null } - }) + if (item.space_motion_handler !== null) { + item.disconnect(item.space_motion_handler) + item.space_motion_handler = null; + } else if (item.key_pressed == true || item.space_motion_handler == null) { + try { + if (!item.char.isMod) { + this.decideMod(item.char) + } else { + const modButton = item; + this.decideMod(item.char, modButton) + } + } catch { } + } + item.key_pressed = false; + } + item.connect("button-press-event", () => pressEv("mouse")) + item.connect("button-release-event", releaseEv) item.connect("touch-event", () => { if (Clutter.get_current_event().type() == Clutter.EventType.TOUCH_BEGIN) { - item.set_scale(1.2, 1.2) - let player - if (this.settings.get_boolean("play-sound")) { - player = global.display.get_sound_player(); - player.play_from_theme("dialog-information", "tap", null) - } - - item.tap_pressed = setTimeout(() => { - - - if (!isMod) { - const oldModBtns = this.modBtns - item.tap_repeat = setInterval(() => { - - if (this.settings.get_boolean("play-sound")) { - player.play_from_theme("dialog-information", "tap", null) - } - this.decideMod(item.char) - - for (var i of oldModBtns) { - this.decideMod(i.char, i) - } - }, 100); - - } - }, 750); - } else if (Clutter.get_current_event().type() == Clutter.EventType.TOUCH_END) { - item.ease({ - scale_x: 1, - scale_y: 1, - duration: 100, - mode: Clutter.AnimationMode.EASE_OUT_QUAD, - onComplete: () => {item.set_scale(1, 1)} - }) - if (item.tap_pressed !== null){ - clearTimeout(item.tap_pressed) - item.tap_pressed == null - } - if (item.tap_repeat !== null){ - clearInterval(item.tap_repeat) - item.tap_repeat == null - } + pressEv("touch") + } else if (Clutter.get_current_event().type() == Clutter.EventType.TOUCH_END || Clutter.get_current_event().type() == Clutter.EventType.TOUCH_CANCEL) { + releaseEv() } }) }); @@ -1037,7 +1213,42 @@ class Keyboard extends Dialog { return false; } } + releaseAllKeys() { + let instances = []; + function traverse(obj) { + for (let key in obj) { + if (obj.hasOwnProperty(key)) { + if (key === "code") { + instances.push(obj[key]); + } else if (typeof obj[key] === 'object' && obj[key] !== null) { + traverse(obj[key]); + } + } + } + } + + traverse(keycodes); + instances.forEach(i => { + this.inputDevice.notify_key(Clutter.get_current_event_time(), i, Clutter.KeyState.RELEASED); + }) + + this.keys.forEach(item => { + item.key_pressed = false; + if (item.button_pressed !== null) { + clearTimeout(item.button_pressed) + item.button_pressed == null + } + if (item.button_repeat !== null) { + clearInterval(item.button_repeat) + item.button_repeat == null + } + if (item.space_motion_handler !== null) { + item.disconnect(item.space_motion_handler) + item.space_motion_handler = null; + } + }) + } sendKey(keys) { try { for (var i = 0; i < keys.length; i++) { @@ -1068,23 +1279,6 @@ class Keyboard extends Dialog { } } - sendCommand(command_line) { - try { - let [success, argv] = GLib.shell_parse_argv(command_line); - trySpawn(argv); - } catch (err) { - let source = new imports.ui.messageTray.SystemNotificationSource(); - source.connect('destroy', () => { - source = null; - }) - Main.messageTray.add(source); - let notification = new imports.ui.messageTray.Notification(source, "GJS-OSK: An unknown error occured", "Please report this bug to the Issues page:\n\n" + err) - notification.setTransient(false); - notification.setResident(false); - source.showNotification(notification); - } - } - decideMod(i, mBtn) { if (i.code == 29 || i.code == 97 || i.code == 125) { this.setNormMod(mBtn); diff --git a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/keycodes.json b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/keycodes.json index 29626eb..4ff54b4 100644 --- a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/keycodes.json +++ b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/keycodes.json @@ -87,8 +87,8 @@ }, { "code": 111, - "lowerName": "⌦", - "upperName": "⌦", + "lowerName": "delete", + "upperName": "delete", "altName": "" } ], @@ -173,16 +173,16 @@ }, { "code": 14, - "lowerName": "⌫", - "upperName": "⌫", + "lowerName": "backspace", + "upperName": "backspace", "altName": "" } ], "row3": [ { "code": 15, - "lowerName": "⇥", - "upperName": "⇥", + "lowerName": "tab", + "upperName": "tab", "altName": "" }, { @@ -277,8 +277,8 @@ "row4": [ { "code": 58, - "lowerName": "⇪", - "upperName": "⇪", + "lowerName": "capslock", + "upperName": "capslock", "altName": "" }, { @@ -358,16 +358,16 @@ }, { "code": 28, - "lowerName": "⏎", - "upperName": "⏎", + "lowerName": "enter", + "upperName": "enter", "altName": "" } ], "row5": [ { "code": 42, - "lowerName": "⇧", - "upperName": "⇧", + "lowerName": "shift", + "upperName": "shift", "altName": "" }, { @@ -439,71 +439,71 @@ }, { "code": 54, - "lowerName": "⇧", - "upperName": "⇧", + "lowerName": "shift", + "upperName": "shift", "altName": "" } ], "row6": [ { "code": 29, - "lowerName": "⌃", - "upperName": "⌃", + "lowerName": "ctrl", + "upperName": "ctrl", "altName": "" }, { "code": 125, - "lowerName": "❖", - "upperName": "❖", + "lowerName": "super", + "upperName": "super", "altName": "" }, { "code": 56, - "lowerName": "⌥", - "upperName": "⌥", + "lowerName": "alt", + "upperName": "alt", "altName": "" }, { "code": 57, - "lowerName": "␣", - "upperName": "␣", + "lowerName": "space", + "upperName": "space", "altName": "" }, { "code": 100, - "lowerName": "⌥", - "upperName": "⌥", + "lowerName": "alt", + "upperName": "alt", "altName": "" }, { "code": 97, - "lowerName": "⌃", - "upperName": "⌃", + "lowerName": "ctrl", + "upperName": "ctrl", "altName": "" }, [ { "code": 105, - "lowerName": "←", - "upperName": "←", + "lowerName": "left", + "upperName": "left", "altName": "" }, { "code": 103, - "lowerName": "↑", - "upperName": "↑", + "lowerName": "up", + "upperName": "up", "altName": "" }, { "code": 108, - "lowerName": "↓", - "upperName": "↓", + "lowerName": "down", + "upperName": "down", "altName": "" }, { "code": 106, - "lowerName": "→", - "upperName": "→", + "lowerName": "right", + "upperName": "right", "altName": "" } ] @@ -597,8 +597,8 @@ }, { "code": 111, - "lowerName": "⌦", - "upperName": "⌦", + "lowerName": "delete", + "upperName": "delete", "altName": "" } ], @@ -687,16 +687,16 @@ }, { "code": 14, - "lowerName": "⌫", - "upperName": "⌫", + "lowerName": "backspace", + "upperName": "backspace", "altName": "" } ], "row3": [ { "code": 15, - "lowerName": "⇥", - "upperName": "⇥", + "lowerName": "tab", + "upperName": "tab", "altName": "" }, { @@ -791,8 +791,8 @@ "row4": [ { "code": 58, - "lowerName": "⇪", - "upperName": "⇪", + "lowerName": "capslock", + "upperName": "capslock", "altName": "" }, { @@ -874,16 +874,16 @@ }, { "code": 28, - "lowerName": "⏎", - "upperName": "⏎", + "lowerName": "enter", + "upperName": "enter", "altName": "" } ], "row5": [ { "code": 42, - "lowerName": "⇧", - "upperName": "⇧", + "lowerName": "shift", + "upperName": "shift", "altName": "" }, { @@ -960,71 +960,71 @@ }, { "code": 54, - "lowerName": "⇧", - "upperName": "⇧", + "lowerName": "shift", + "upperName": "shift", "altName": "" } ], "row6": [ { "code": 29, - "lowerName": "⌃", - "upperName": "⌃", + "lowerName": "ctrl", + "upperName": "ctrl", "altName": "" }, { "code": 125, - "lowerName": "❖", - "upperName": "❖", + "lowerName": "super", + "upperName": "super", "altName": "" }, { "code": 56, - "lowerName": "⌥", - "upperName": "⌥", + "lowerName": "alt", + "upperName": "alt", "altName": "" }, { "code": 57, - "lowerName": "␣", - "upperName": "␣", + "lowerName": "space", + "upperName": "space", "altName": "" }, { "code": 100, - "lowerName": "⌥", - "upperName": "⌥", + "lowerName": "alt", + "upperName": "alt", "altName": "" }, { "code": 97, - "lowerName": "⌃", - "upperName": "⌃", + "lowerName": "ctrl", + "upperName": "ctrl", "altName": "" }, [ { "code": 105, - "lowerName": "←", - "upperName": "←", + "lowerName": "left", + "upperName": "left", "altName": "" }, { "code": 103, - "lowerName": "↑", - "upperName": "↑", + "lowerName": "up", + "upperName": "up", "altName": "" }, { "code": 108, - "lowerName": "↓", - "upperName": "↓", + "lowerName": "down", + "upperName": "down", "altName": "" }, { "code": 106, - "lowerName": "→", - "upperName": "→", + "lowerName": "right", + "upperName": "right", "altName": "" } ] @@ -1118,8 +1118,8 @@ }, { "code": 111, - "lowerName": "⌦", - "upperName": "⌦", + "lowerName": "delete", + "upperName": "delete", "altName": "" } ], @@ -1204,16 +1204,16 @@ }, { "code": 14, - "lowerName": "⌫", - "upperName": "⌫", + "lowerName": "backspace", + "upperName": "backspace", "altName": "" } ], "row3": [ { "code": 15, - "lowerName": "⇥", - "upperName": "⇥", + "lowerName": "tab", + "upperName": "tab", "altName": "" }, { @@ -1305,8 +1305,8 @@ "row4": [ { "code": 58, - "lowerName": "⇪", - "upperName": "⇪", + "lowerName": "capslock", + "upperName": "capslock", "altName": "" }, { @@ -1387,16 +1387,16 @@ }, { "code": 28, - "lowerName": "⏎", - "upperName": "⏎", + "lowerName": "enter", + "upperName": "enter", "altName": "" } ], "row5": [ { "code": 42, - "lowerName": "⇧", - "upperName": "⇧", + "lowerName": "shift", + "upperName": "shift", "altName": "" }, { @@ -1470,71 +1470,71 @@ }, { "code": 54, - "lowerName": "⇧", - "upperName": "⇧", + "lowerName": "shift", + "upperName": "shift", "altName": "" } ], "row6": [ { "code": 29, - "lowerName": "⌃", - "upperName": "⌃", + "lowerName": "ctrl", + "upperName": "ctrl", "altName": "" }, { "code": 125, - "lowerName": "❖", - "upperName": "❖", + "lowerName": "super", + "upperName": "super", "altName": "" }, { "code": 56, - "lowerName": "⌥", - "upperName": "⌥", + "lowerName": "alt", + "upperName": "alt", "altName": "" }, { "code": 57, - "lowerName": "␣", - "upperName": "␣", + "lowerName": "space", + "upperName": "space", "altName": "" }, { "code": 100, - "lowerName": "⌥", - "upperName": "⌥", + "lowerName": "alt", + "upperName": "alt", "altName": "" }, { "code": 97, - "lowerName": "⌃", - "upperName": "⌃", + "lowerName": "ctrl", + "upperName": "ctrl", "altName": "" }, [ { "code": 105, - "lowerName": "←", - "upperName": "←", + "lowerName": "left", + "upperName": "left", "altName": "" }, { "code": 103, - "lowerName": "↑", - "upperName": "↑", + "lowerName": "up", + "upperName": "up", "altName": "" }, { "code": 108, - "lowerName": "↓", - "upperName": "↓", + "lowerName": "down", + "upperName": "down", "altName": "" }, { "code": 106, - "lowerName": "→", - "upperName": "→", + "lowerName": "right", + "upperName": "right", "altName": "" } ] @@ -1628,8 +1628,8 @@ }, { "code": 111, - "lowerName": "⌦", - "upperName": "⌦", + "lowerName": "delete", + "upperName": "delete", "altName": "" } ], @@ -1714,16 +1714,16 @@ }, { "code": 14, - "lowerName": "⌫", - "upperName": "⌫", + "lowerName": "backspace", + "upperName": "backspace", "altName": "" } ], "row3": [ { "code": 15, - "lowerName": "⇥", - "upperName": "⇥", + "lowerName": "tab", + "upperName": "tab", "altName": "" }, { @@ -1780,7 +1780,7 @@ "lowerName": "i", "letter": "primary", "upperName": "I", - "altName": "→" + "altName": "right" }, { "code": 24, @@ -1819,8 +1819,8 @@ "row4": [ { "code": 58, - "lowerName": "⇪", - "upperName": "⇪", + "lowerName": "capslock", + "upperName": "capslock", "altName": "" }, { @@ -1902,16 +1902,16 @@ }, { "code": 28, - "lowerName": "⏎", - "upperName": "⏎", + "lowerName": "enter", + "upperName": "enter", "altName": "" } ], "row5": [ { "code": 42, - "lowerName": "⇧", - "upperName": "⇧", + "lowerName": "shift", + "upperName": "shift", "altName": "" }, { @@ -1989,71 +1989,71 @@ }, { "code": 54, - "lowerName": "⇧", - "upperName": "⇧", + "lowerName": "shift", + "upperName": "shift", "altName": "" } ], "row6": [ { "code": 29, - "lowerName": "⌃", - "upperName": "⌃", + "lowerName": "ctrl", + "upperName": "ctrl", "altName": "" }, { "code": 125, - "lowerName": "❖", - "upperName": "❖", + "lowerName": "super", + "upperName": "super", "altName": "" }, { "code": 56, - "lowerName": "⌥", - "upperName": "⌥", + "lowerName": "alt", + "upperName": "alt", "altName": "" }, { "code": 57, - "lowerName": "␣", - "upperName": "␣", + "lowerName": "space", + "upperName": "space", "altName": "" }, { "code": 100, - "lowerName": "⌥", - "upperName": "⌥", + "lowerName": "alt", + "upperName": "alt", "altName": "" }, { "code": 97, - "lowerName": "⌃", - "upperName": "⌃", + "lowerName": "ctrl", + "upperName": "ctrl", "altName": "" }, [ { "code": 105, - "lowerName": "←", - "upperName": "←", + "lowerName": "left", + "upperName": "left", "altName": "" }, { "code": 103, - "lowerName": "↑", - "upperName": "↑", + "lowerName": "up", + "upperName": "up", "altName": "" }, { "code": 108, - "lowerName": "↓", - "upperName": "↓", + "lowerName": "down", + "upperName": "down", "altName": "" }, { "code": 106, - "lowerName": "→", - "upperName": "→", + "lowerName": "right", + "upperName": "right", "altName": "" } ] diff --git a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/prefs.js b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/prefs.js index 7c47227..570da26 100644 --- a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/prefs.js +++ b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/prefs.js @@ -39,6 +39,7 @@ export default class GjsOskPreferences extends ExtensionPreferences { settings.set_double("background-b", b); settings.set_int("font-size-px", numChanger_font.value); settings.set_int("border-spacing-px", numChanger_bord.value); + settings.set_int("snap-spacing-px", numChanger_snap.value) settings.set_boolean("round-key-corners", dragToggle2.active); settings.set_boolean("play-sound", dragToggle3.active); settings.set_int("default-snap", dropDown.selected); @@ -51,7 +52,7 @@ export default class GjsOskPreferences extends ExtensionPreferences { page1.add(group1); const row0 = new Adw.ActionRow({ - title: _('Language') + title: _('Layout') }); group1.add(row0); @@ -163,9 +164,9 @@ export default class GjsOskPreferences extends ExtensionPreferences { group1.add(row4); let posList = [ - _("Top Left"), _("Top Center"), _("Top Right"), - _("Center Left"), _("Center"), _("Center Right"), - _("Bottom Left"), _("Bottom Center"), _("Bottom Right") + _("Top Left"), _("Top Center"), _("Top Right"), + _("Center Left"), _("Center"), _("Center Right"), + _("Bottom Left"), _("Bottom Center"), _("Bottom Right") ]; let dropDown = Gtk.DropDown.new_from_strings(posList); dropDown.valign = Gtk.Align.CENTER; @@ -174,6 +175,19 @@ export default class GjsOskPreferences extends ExtensionPreferences { row4.add_suffix(dropDown); row4.activatable_widget = dropDown; + const row9 = new Adw.ActionRow({ + title: _('Play sound') + }); + group1.add(row9); + + const dragToggle3 = new Gtk.Switch({ + active: settings.get_boolean('play-sound'), + valign: Gtk.Align.CENTER, + }); + + row9.add_suffix(dragToggle3); + row9.activatable_widget = dragToggle3; + const group2 = new Adw.PreferencesGroup({ title: _("Appearance") }); @@ -182,7 +196,7 @@ export default class GjsOskPreferences extends ExtensionPreferences { const row5 = new Adw.ActionRow({ title: _('Color') }); - group2.add(row5);settings.set_boolean("enable-tap-gesture", dragOpt.selected); + group2.add(row5); settings.set_boolean("enable-tap-gesture", dragOpt.selected); let rgba = new Gdk.RGBA(); rgba.parse("rgba(" + settings.get_double("background-r") + ", " + settings.get_double("background-g") + ", " + settings.get_double("background-b") + ", 1)"); @@ -216,6 +230,17 @@ export default class GjsOskPreferences extends ExtensionPreferences { row7.add_suffix(numChanger_bord); row7.activatable_widget = numChanger_bord; + let row1t2 = new Adw.ActionRow({ + title: _('Drag snap spacing (px)') + }); + group2.add(row1t2); + + let numChanger_snap = Gtk.SpinButton.new_with_range(0, 50, 5); + numChanger_snap.value = settings.get_int('snap-spacing-px'); + numChanger_snap.valign = Gtk.Align.CENTER; + row1t2.add_suffix(numChanger_snap); + row1t2.activatable_widget = numChanger_snap; + const row8 = new Adw.ActionRow({ title: _('Round Corners') }); @@ -228,19 +253,6 @@ export default class GjsOskPreferences extends ExtensionPreferences { row8.add_suffix(dragToggle2); row8.activatable_widget = dragToggle2; - - const row9 = new Adw.ActionRow({ - title: _('Play sound') - }); - group2.add(row9); - - const dragToggle3 = new Gtk.Switch({ - active: settings.get_boolean('play-sound'), - valign: Gtk.Align.CENTER, - }); - - row9.add_suffix(dragToggle3); - row9.activatable_widget = dragToggle3; window.add(page1); @@ -288,9 +300,21 @@ export default class GjsOskPreferences extends ExtensionPreferences { uri: "https://github.com/Vishram1123/gjs-osk", }); + let icons_credit = new Adw.ActionRow({ + icon_name: "app-icon-design-symbolic", + title: _("Icons sourced from") + }); + let remixicon_link = new Gtk.LinkButton({ + label: "RemixIcon", + uri: "https://remixicon.com/", + }); + code_row.add_suffix(github_link); code_row.set_activatable_widget(github_link); links_pref_group.add(code_row); + icons_credit.add_suffix(remixicon_link); + icons_credit.set_activatable_widget(remixicon_link); + links_pref_group.add(icons_credit); label_box.append(label); label_box.append(another_label); @@ -317,6 +341,7 @@ export default class GjsOskPreferences extends ExtensionPreferences { settings.set_double("background-b", b); settings.set_int("font-size-px", numChanger_font.value); settings.set_int("border-spacing-px", numChanger_bord.value); + settings.set_int("snap-spacing-px", numChanger_snap.value) settings.set_boolean("round-key-corners", dragToggle2.active); settings.set_boolean("play-sound", dragToggle3.active); settings.set_int("default-snap", dropDown.selected); diff --git a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/schemas/gschemas.compiled b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/schemas/gschemas.compiled index edba05ce5a4a4462c81777cd5cae26d8ba0d6242..ceb5d5f1c1c22240c78afa97201314ee376c4c03 100644 GIT binary patch literal 1592 zcma)6Jxmlq7#$H10R;|!FfslVCU?=@(+&#*u}};aG#WKAI(Iwlt#|IOyNiILu`v;2 zK@3KWki{Qz((4ni223nH_|Z=0_r0P=On_%$bd8!G{Zn;9?1z5~{1K?zD#ULzqaGi{NpTR| z33!2R+OBt5nPEYdN~Ri$lp8vp8=Cf|&6 zD^S~>>!MHH41W*!05IA6^9X(F?eKfReZaHtk4ETI*TO#oz6dO(^f=TU#|Mu9Uozu9 z84K|?+d&LJf6O-=u>l@4LHzN z;OvF#z4WQ$eSy=!=jFb0^r`80g1do3-uXfL)I6^~Fze6vf+&zqWDGi1R4{xM*D{J~*vNZn^s25l8a1A)>x zXTQp689FLHcT5`RvAX|N)gi<&E)4zqJvTB!=bGZ7pz&PkTdH3Ul<*1XMvLc5-!I8w zBV@X1B=h|Dfm>NrqVmq_{?)f4enU~)3#jW36i)dqqUKvf-U&=ieoe9FsOu4*2J_8b bQ8sI-n@Z|fLA+a@uUu75AnS+IqH(T2zjaBC literal 1536 zcmb7EJ!lj`7#(90V}8_J{JBE>DTF&@_YiC>G(qr>q_7ed#LV4J_SQRh*V&CpG>VO2 z#6l!NMGWaonZh(y*VtKzrbr_wq|rhHCYV(E-tOKeh@cLMKD(*unE`3 zZ9r#&448N}dslHhGw%}D#ar+^P|r!toaEhDq_L~m&HmKw=+8goFz|RbI8L9s4So;! z1aRQd++OdSk2k+@qXW&nPr-AlLZJa)JC;S@tHL#S4 z^H4L-Ja_^4yn6N``%}|j1g`*xyh}s$saxT<;7{uSYPW8;abKvL;Ag?dfVmHEj<7#< z7XEo~Kd_ptOU?Ox@F?)A;du}HQ#0p7@C0z-^37iQ)a*YEo&m0neVV0D%{(>mSK!6> zr=#?#8{w~j5lno^kNfngIe!++8mmgz3QE#f#*kx$Wy4pxq>>Uo$^JPf-vVMia7(%O ztP}hVEI+~e*aEOd+5tA!3hM~dBSTzUMOmuY+8cB&L&HKl(<5?LUb(VZRfeUdje5)# z^S-A;EuHWWc`Ob?p0rC@Id(ZrGjC7cCv%3!R85%zVbV9M^J6GW4_&e?6l_IR-ozX`LI&@Q0H@+%L|T zj=}P5f4xi0bVQtYU5Y55r!A$8z?UV*wb#~*t^%z0U-Kg&YpmW_yY;gc-G`{*85Gz@ zpnm62^UfhJ08^9SG8{+UjQ)#Y-k 2 + + 25 + false diff --git a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/stylesheet.css b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/stylesheet.css index dd8d159..629e010 100644 --- a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/stylesheet.css +++ b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/stylesheet.css @@ -1,55 +1,195 @@ -.regular:active { +.regular:pressed { background-color: rgba(255, 255, 255, 0.2); color: white; } - .inverted:active { + +.inverted:pressed { background-color: rgba(0, 0, 0, 0.2); color: black; } - .regular { + +.regular { background-color: rgba(255, 255, 255, 0.05); color: white; } - .inverted { + +.inverted { background-color: rgba(0, 0, 0, 0.05); color: black; } - .keysHolder>* { + +.keysHolder>* { border: 0; background-clip: padding-box; box-sizing: border-box; } - .dr-b { + +.dr-b { border: 0; background-clip: padding-box; margin: inherit; box-sizing: border-box; } - .boxLay.regular:dragging { + +.boxLay.regular:dragging { background-image: url(ui/icons/hicolor/scalable/actions/move.svg); background-size: 100px; } + .boxLay.inverted:dragging { background-image: url(ui/icons/hicolor/scalable/actions/move-dark.svg); background-size: 100px; } -.close_btn, .move_btn { + +.close_btn, +.move_btn, +.delete_btn, +.backspace_btn, +.tab_btn, +.capslock_btn, +.shift_btn, +.enter_btn, +.ctrl_btn, +.super_btn, +.alt_btn, +.space_btn, +.left_btn, +.up_btn, +.down_btn, +.right_btn { background-repeat: no-repeat; background-position: center; } -.close_btn.regular { - background-image: url(ui/icons/hicolor/scalable/actions/close.svg); + +.close_btn.regular, .close_btn.selected.inverted { + background-image: url(ui/icons/hicolor/scalable/actions/close.svg); } -.close_btn.inverted { - background-image: url(ui/icons/hicolor/scalable/actions/close-dark.svg); + +.close_btn.inverted, .close_btn.selected.regular { + background-image: url(ui/icons/hicolor/scalable/actions/close-dark.svg); } -.move_btn.regular { - background-image: url(ui/icons/hicolor/scalable/actions/move.svg); + +.move_btn.regular, .move_btn.selected.inverted { + background-image: url(ui/icons/hicolor/scalable/actions/move.svg); } -.move_btn.inverted { - background-image: url(ui/icons/hicolor/scalable/actions/move-dark.svg); + +.move_btn.inverted, .move_btn.selected.regular { + background-image: url(ui/icons/hicolor/scalable/actions/move-dark.svg); } - .keyActionBtns { + +.delete_btn.regular, .delete_btn.selected.inverted { + background-image: url(ui/icons/hicolor/scalable/actions/delete.svg); +} + +.delete_btn.inverted, .delete_btn.selected.regular { + background-image: url(ui/icons/hicolor/scalable/actions/delete-dark.svg); +} + +.backspace_btn.regular, .backspace_btn.selected.inverted { + background-image: url(ui/icons/hicolor/scalable/actions/backspace.svg); +} + +.backspace_btn.inverted, .backspace_btn.selected.regular { + background-image: url(ui/icons/hicolor/scalable/actions/backspace-dark.svg); +} + +.tab_btn.regular, .tab_btn.selected.inverted { + background-image: url(ui/icons/hicolor/scalable/actions/tab.svg); +} + +.tab_btn.inverted, .tab_btn.selected.regular { + background-image: url(ui/icons/hicolor/scalable/actions/tab-dark.svg); +} + +.capslock_btn.regular, .capslock_btn.selected.inverted { + background-image: url(ui/icons/hicolor/scalable/actions/capslock.svg); +} + +.capslock_btn.inverted, .capslock_btn.selected.regular { + background-image: url(ui/icons/hicolor/scalable/actions/capslock-dark.svg); +} + +.shift_btn.regular, .shift_btn.selected.inverted { + background-image: url(ui/icons/hicolor/scalable/actions/shift.svg); +} + +.shift_btn.inverted, .shift_btn.selected.regular { + background-image: url(ui/icons/hicolor/scalable/actions/shift-dark.svg); +} + +.enter_btn.regular, .enter_btn.selected.inverted { + background-image: url(ui/icons/hicolor/scalable/actions/enter.svg); +} + +.enter_btn.inverted, .enter_btn.selected.regular { + background-image: url(ui/icons/hicolor/scalable/actions/enter-dark.svg); +} + +.ctrl_btn.regular, .ctrl_btn.selected.inverted { + background-image: url(ui/icons/hicolor/scalable/actions/ctrl.svg); +} + +.ctrl_btn.inverted, .ctrl_btn.selected.regular { + background-image: url(ui/icons/hicolor/scalable/actions/ctrl-dark.svg); +} + +.super_btn.regular, .super_btn.selected.inverted { + background-image: url(ui/icons/hicolor/scalable/actions/super.svg); +} + +.super_btn.inverted, .super_btn.selected.regular { + background-image: url(ui/icons/hicolor/scalable/actions/super-dark.svg); +} + +.alt_btn.regular, .alt_btn.selected.inverted { + background-image: url(ui/icons/hicolor/scalable/actions/alt.svg); +} + +.alt_btn.inverted, .alt_btn.selected.regular { + background-image: url(ui/icons/hicolor/scalable/actions/alt-dark.svg); +} + +.space_btn.regular, .space_btn.selected.inverted { + background-image: url(ui/icons/hicolor/scalable/actions/space.svg); +} + +.space_btn.inverted, .space_btn.selected.regular { + background-image: url(ui/icons/hicolor/scalable/actions/space-dark.svg); +} + +.left_btn.regular, .left_btn.selected.inverted { + background-image: url(ui/icons/hicolor/scalable/actions/left.svg); +} + +.left_btn.inverted, .left_btn.selected.regular { + background-image: url(ui/icons/hicolor/scalable/actions/left-dark.svg); +} + +.up_btn.regular, .up_btn.selected.inverted { + background-image: url(ui/icons/hicolor/scalable/actions/up.svg); +} + +.up_btn.inverted, .up_btn.selected.regular { + background-image: url(ui/icons/hicolor/scalable/actions/up-dark.svg); +} + +.down_btn.regular, .down_btn.selected.inverted { + background-image: url(ui/icons/hicolor/scalable/actions/down.svg); +} + +.down_btn.inverted, .down_btn.selected.regular { + background-image: url(ui/icons/hicolor/scalable/actions/down-dark.svg); +} + +.right_btn.regular, .right_btn.selected.inverted { + background-image: url(ui/icons/hicolor/scalable/actions/right.svg); +} + +.right_btn.inverted, .right_btn.selected.regular { + background-image: url(ui/icons/hicolor/scalable/actions/right-dark.svg); +} + +.keyActionBtns { background-color: rgba(255, 255, 255, 0.00); border: 0; border-radius: 0px; @@ -57,20 +197,23 @@ margin: 0px !important; box-sizing: border-box; } - .selected.regular { + +.selected.regular { background-color: rgba(255, 255, 255, 0.7); color: black; } - .selected.inverted { + +.selected.inverted { background-color: rgba(0, 0, 0, 0.7); color: white; } - .db-keyboard-content { + +.db-keyboard-content { background-color: rgba(0, 0, 0, 0); border: 0; } - .boxLay { + +.boxLay { padding: 20px; border-radius: 10px; -} - +} \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/alt-dark.svg b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/alt-dark.svg new file mode 100644 index 0000000..08743bb --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/alt-dark.svg @@ -0,0 +1,51 @@ + + + + + + + + + + + diff --git a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/alt.svg b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/alt.svg new file mode 100644 index 0000000..99fe6ed --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/alt.svg @@ -0,0 +1,69 @@ + + + + + + + + + + + + + diff --git a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/app-icon-design-symbolic.svg b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/app-icon-design-symbolic.svg new file mode 100644 index 0000000..b1f0d5f --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/app-icon-design-symbolic.svg @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/backspace-dark.svg b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/backspace-dark.svg new file mode 100644 index 0000000..0d35547 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/backspace-dark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/backspace.svg b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/backspace.svg new file mode 100644 index 0000000..b878e0c --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/backspace.svg @@ -0,0 +1,36 @@ + + + + + + diff --git a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/capslock-dark.svg b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/capslock-dark.svg new file mode 100644 index 0000000..efed6af --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/capslock-dark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/capslock.svg b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/capslock.svg new file mode 100644 index 0000000..9c85b5b --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/capslock.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/ctrl-dark.svg b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/ctrl-dark.svg new file mode 100644 index 0000000..820835b --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/ctrl-dark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/ctrl.svg b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/ctrl.svg new file mode 100644 index 0000000..31d0467 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/ctrl.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/delete-dark.svg b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/delete-dark.svg new file mode 100644 index 0000000..ed6c0c9 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/delete-dark.svg @@ -0,0 +1,36 @@ + + + + + + diff --git a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/delete.svg b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/delete.svg new file mode 100644 index 0000000..e1b7219 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/delete.svg @@ -0,0 +1,36 @@ + + + + + + diff --git a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/down-dark.svg b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/down-dark.svg new file mode 100644 index 0000000..444ec7c --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/down-dark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/down.svg b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/down.svg new file mode 100644 index 0000000..31317c0 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/enter-dark.svg b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/enter-dark.svg new file mode 100644 index 0000000..5044154 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/enter-dark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/enter.svg b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/enter.svg new file mode 100644 index 0000000..a66e2e7 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/enter.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/left-dark.svg b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/left-dark.svg new file mode 100644 index 0000000..5ca8b9a --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/left-dark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/left.svg b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/left.svg new file mode 100644 index 0000000..6b2c10d --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/left.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/right-dark.svg b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/right-dark.svg new file mode 100644 index 0000000..85f93cc --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/right-dark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/right.svg b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/right.svg new file mode 100644 index 0000000..590cf90 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/right.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/shift-dark.svg b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/shift-dark.svg new file mode 100644 index 0000000..2730129 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/shift-dark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/shift.svg b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/shift.svg new file mode 100644 index 0000000..64204df --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/shift.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/space-dark.svg b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/space-dark.svg new file mode 100644 index 0000000..87ac6ff --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/space-dark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/space.svg b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/space.svg new file mode 100644 index 0000000..5237124 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/space.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/super-dark.svg b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/super-dark.svg new file mode 100644 index 0000000..f454aeb --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/super-dark.svg @@ -0,0 +1,37 @@ + + + + + + diff --git a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/super.svg b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/super.svg new file mode 100644 index 0000000..916d903 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/super.svg @@ -0,0 +1,37 @@ + + + + + + diff --git a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/tab-dark.svg b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/tab-dark.svg new file mode 100644 index 0000000..c262766 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/tab-dark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/tab.svg b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/tab.svg new file mode 100644 index 0000000..f6ebb49 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/tab.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/up-dark.svg b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/up-dark.svg new file mode 100644 index 0000000..f845bf1 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/up-dark.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/up.svg b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/up.svg new file mode 100644 index 0000000..0780671 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/gjsosk@vishram1123.com/ui/icons/hicolor/scalable/actions/up.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/config.js b/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/config.js index 583ad59..6a88a81 100644 --- a/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/config.js +++ b/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/config.js @@ -5,10 +5,10 @@ var PACKAGE_VERSION = 56; var PACKAGE_URL = 'https://github.com/GSConnect/gnome-shell-extension-gsconnect'; var PACKAGE_BUGREPORT = 'https://github.com/GSConnect/gnome-shell-extension-gsconnect/issues/new'; -var PACKAGE_DATADIR = '/usr/local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io'; -var PACKAGE_LOCALEDIR = '/usr/local/share/locale'; -var GSETTINGS_SCHEMA_DIR = '/usr/local/share/glib-2.0/schemas'; -var GNOME_SHELL_LIBDIR = '/usr/local/lib/x86_64-linux-gnu'; +var PACKAGE_DATADIR = '/usr/share/gnome-shell/extensions/gsconnect@andyholmes.github.io'; +var PACKAGE_LOCALEDIR = '/usr/share/locale'; +var GSETTINGS_SCHEMA_DIR = '/usr/share/glib-2.0/schemas'; +var GNOME_SHELL_LIBDIR = '/usr/lib64/'; var APP_ID = 'org.gnome.Shell.Extensions.GSConnect'; var APP_PATH = '/org/gnome/Shell/Extensions/GSConnect'; diff --git a/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/gsconnect-preferences b/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/gsconnect-preferences old mode 100755 new mode 100644 diff --git a/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/locale/he/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo b/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/locale/he/LC_MESSAGES/org.gnome.Shell.Extensions.GSConnect.mo new file mode 100644 index 0000000000000000000000000000000000000000..6643a6ab726552a4e89814684cb1682abedb0056 GIT binary patch literal 19433 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 literal 0 HcmV?d00001 diff --git a/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/metadata.json b/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/metadata.json index df6761a..a2b73c2 100644 --- a/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/metadata.json +++ b/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/metadata.json @@ -1,11 +1,8 @@ { - "_generated": "Generated by SweetTooth, do not edit", - "description": "GSConnect is a complete implementation of KDE Connect especially for GNOME Shell with Nautilus, Chrome and Firefox integration. It does not rely on the KDE Connect desktop application and will not work with it installed.\n\nKDE Connect allows devices to securely share content like notifications or files and other features like SMS messaging and remote control. The KDE Connect team has applications for Linux, BSD, Android, Sailfish, iOS, macOS and Windows.\n\nPlease report issues on Github!", - "name": "GSConnect", - "shell-version": [ - "45" - ], - "url": "https://github.com/GSConnect/gnome-shell-extension-gsconnect/wiki", - "uuid": "gsconnect@andyholmes.github.io", - "version": 56 -} \ No newline at end of file + "uuid": "gsconnect@andyholmes.github.io", + "name": "GSConnect", + "description": "GSConnect is a complete implementation of KDE Connect especially for GNOME Shell with Nautilus, Chrome and Firefox integration. It does not rely on the KDE Connect desktop application and will not work with it installed.\n\nKDE Connect allows devices to securely share content like notifications or files and other features like SMS messaging and remote control. The KDE Connect team has applications for Linux, BSD, Android, Sailfish, iOS, macOS and Windows.\n\nPlease report issues on Github!", + "version": 56, + "shell-version": [ "46" ], + "url": "https://github.com/GSConnect/gnome-shell-extension-gsconnect/wiki" +} diff --git a/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/nautilus-gsconnect.py b/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/nautilus-gsconnect.py index c253612..05a71b0 100644 --- a/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/nautilus-gsconnect.py +++ b/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/nautilus-gsconnect.py @@ -177,24 +177,36 @@ class GSConnectShareExtension(GObject.Object, FileManager.MenuProvider): if not devices: return () - # Context Menu Item - menu = FileManager.MenuItem( - name="GSConnectShareExtension::Devices", - label=_("Send To Mobile Device"), - ) + # If there's exactly 1 device, no submenu + if len(devices) == 1: + name, action_group = devices[0] + menu = FileManager.MenuItem( + name="GSConnectShareExtension::Device" + name, + # TRANSLATORS: Send to , for file manager + # context menu + label=_("Send to %s") % name, + ) + menu.connect("activate", self.send_files, files, action_group) - # Context Submenu - submenu = FileManager.Menu() - menu.set_submenu(submenu) - - # Context Submenu Items - for name, action_group in devices: - item = FileManager.MenuItem( - name="GSConnectShareExtension::Device" + name, label=name + else: + # Context Menu Item + menu = FileManager.MenuItem( + name="GSConnectShareExtension::Devices", + label=_("Send To Mobile Device"), ) - item.connect("activate", self.send_files, files, action_group) + # Context Submenu + submenu = FileManager.Menu() + menu.set_submenu(submenu) - submenu.append_item(item) + # Context Submenu Items + for name, action_group in devices: + item = FileManager.MenuItem( + name="GSConnectShareExtension::Device" + name, label=name + ) + + item.connect("activate", self.send_files, files, action_group) + + submenu.append_item(item) return (menu,) diff --git a/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/org.gnome.Shell.Extensions.GSConnect.gresource b/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/org.gnome.Shell.Extensions.GSConnect.gresource index 04b844ff7bc350876793714811a0d2eed2bbb7de..17fe48519fa929d45ffb39d22bd253d9a46333ad 100644 GIT binary patch delta 46464 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

DEQxAB{wrAo~L;ga7+Vr+xCI3_*_-6~# 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 delta 51429 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

tju#M8?~ql08wZdeRIIE%5eJY`o%EhY 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 diff --git a/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/service/components/input.js b/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/service/components/input.js index 47540d8..121c4d9 100644 --- a/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/service/components/input.js +++ b/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/service/components/input.js @@ -147,18 +147,7 @@ const RemoteSession = GObject.registerClass({ } scrollPointer(dx, dy) { - // NOTE: NotifyPointerAxis only seems to work on Wayland, but maybe - // NotifyPointerAxisDiscrete is the better choice anyways - if (HAVE_WAYLAND) { - this._call( - 'NotifyPointerAxis', - GLib.Variant.new('(ddu)', [dx, dy, 0]) - ); - this._call( - 'NotifyPointerAxis', - GLib.Variant.new('(ddu)', [0, 0, 1]) - ); - } else if (dy > 0) { + if (dy > 0) { this._call( 'NotifyPointerAxisDiscrete', GLib.Variant.new('(ui)', [Gdk.ScrollDirection.UP, 1]) @@ -266,50 +255,6 @@ class Controller { return this._connection; } - /** - * Check if this is a Wayland session, specifically for distributions that - * don't ship pipewire support (eg. Debian/Ubuntu). - * - * FIXME: this is a super ugly hack that should go away - * - * @return {boolean} %true if wayland is not supported - */ - _checkWayland() { - if (HAVE_WAYLAND) { - // eslint-disable-next-line no-global-assign - HAVE_REMOTEINPUT = false; - const service = Gio.Application.get_default(); - - if (service === null) - return true; - - // First we're going to disabled the affected plugins on all devices - for (const device of service.manager.devices.values()) { - const supported = device.settings.get_strv('supported-plugins'); - let index; - - if ((index = supported.indexOf('mousepad')) > -1) - supported.splice(index, 1); - - if ((index = supported.indexOf('presenter')) > -1) - supported.splice(index, 1); - - device.settings.set_strv('supported-plugins', supported); - } - - // Second we need each backend to rebuild its identity packet and - // broadcast the amended capabilities to the network - for (const backend of service.manager.backends.values()) - backend.buildIdentity(); - - service.manager.identify(); - - return true; - } - - return false; - } - _onNameAppeared(connection, name, name_owner) { try { this._connection = connection; @@ -394,10 +339,6 @@ class Controller { if (this.connection === null) { debug('Falling back to Atspi'); - // If we got here in Wayland, we need to re-adjust and bail - if (this._checkWayland()) - return; - const fallback = imports.service.components.atspi; this._session = new fallback.Controller(); diff --git a/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/service/components/pulseaudio.js b/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/service/components/pulseaudio.js index d3f6657..1e09fdb 100644 --- a/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/service/components/pulseaudio.js +++ b/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/service/components/pulseaudio.js @@ -190,7 +190,7 @@ const Mixer = GObject.registerClass({ */ lowerVolume(duration = 1) { try { - if (this.output.volume > 0.15) { + if (this.output && this.output.volume > 0.15) { this._previousVolume = Number(this.output.volume); this.output.fade(0.15, duration); } @@ -204,7 +204,7 @@ const Mixer = GObject.registerClass({ */ muteVolume() { try { - if (this.output.muted) + if (!this.output || this.output.muted) return; this.output.muted = true; @@ -219,7 +219,7 @@ const Mixer = GObject.registerClass({ */ muteMicrophone() { try { - if (this.input.muted) + if (!this.input || this.input.muted) return; this.input.muted = true; @@ -266,4 +266,3 @@ const Mixer = GObject.registerClass({ * The service class for this component */ var Component = Mixer; - diff --git a/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/service/core.js b/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/service/core.js index 2bd4fb1..e3406bf 100644 --- a/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/service/core.js +++ b/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/service/core.js @@ -410,10 +410,6 @@ var ChannelService = GObject.registerClass({ }); for (const name in imports.service.plugins) { - // Exclude mousepad/presenter capability in unsupported sessions - if (!HAVE_REMOTEINPUT && ['mousepad', 'presenter'].includes(name)) - continue; - const meta = imports.service.plugins[name].Metadata; if (meta === undefined) diff --git a/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/service/daemon.js b/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/service/daemon.js old mode 100755 new mode 100644 diff --git a/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/service/device.js b/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/service/device.js index 3402b6d..b0d24de 100644 --- a/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/service/device.js +++ b/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/service/device.js @@ -298,10 +298,6 @@ var Device = GObject.registerClass({ const supported = []; for (const name in imports.service.plugins) { - // Exclude mousepad/presenter plugins in unsupported sessions - if (!HAVE_REMOTEINPUT && ['mousepad', 'presenter'].includes(name)) - continue; - const meta = imports.service.plugins[name].Metadata; if (meta === undefined) diff --git a/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/service/nativeMessagingHost.js b/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/service/nativeMessagingHost.js old mode 100755 new mode 100644 diff --git a/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/service/utils/setup.js b/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/service/utils/setup.js index 2f9f6c1..04449dd 100644 --- a/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/service/utils/setup.js +++ b/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/service/utils/setup.js @@ -99,13 +99,7 @@ for (const path of [Config.CACHEDIR, Config.CONFIGDIR, Config.RUNTIMEDIR]) GLib.mkdir_with_parents(path, 0o755); -/** - * Check if we're in a Wayland session (mostly for input synthesis) - * https://wiki.gnome.org/Accessibility/Wayland#Bugs.2FIssues_We_Must_Address - */ -globalThis.HAVE_REMOTEINPUT = GLib.getenv('GDMSESSION') !== 'ubuntu-wayland'; -globalThis.HAVE_WAYLAND = GLib.getenv('XDG_SESSION_TYPE') === 'wayland'; -globalThis.HAVE_GNOME = GLib.getenv('GNOME_SETUP_DISPLAY') !== null; +globalThis.HAVE_GNOME = GLib.getenv('GSCONNECT_MODE')?.toLowerCase() !== 'cli' && (GLib.getenv('GNOME_SETUP_DISPLAY') !== null || GLib.getenv('XDG_CURRENT_DESKTOP')?.toUpperCase()?.includes('GNOME') || GLib.getenv('XDG_SESSION_DESKTOP')?.toLowerCase() === 'gnome'); /** diff --git a/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/shell/notification.js b/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/shell/notification.js index 573bb97..78b7f54 100644 --- a/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/shell/notification.js +++ b/gnome/.local/share/gnome-shell/extensions/gsconnect@andyholmes.github.io/shell/notification.js @@ -9,6 +9,7 @@ import St from 'gi://St'; import * as Main from 'resource:///org/gnome/shell/ui/main.js'; import * as MessageTray from 'resource:///org/gnome/shell/ui/messageTray.js'; +import * as Calendar from 'resource:///org/gnome/shell/ui/calendar.js'; import * as NotificationDaemon from 'resource:///org/gnome/shell/ui/notificationDaemon.js'; import {gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js'; @@ -44,11 +45,10 @@ const GtkNotificationDaemon = Main.notificationDaemon._gtkNotificationDaemon.con */ const NotificationBanner = GObject.registerClass({ GTypeName: 'GSConnectNotificationBanner', -}, class NotificationBanner extends MessageTray.NotificationBanner { - - _init(notification) { - super._init(notification); +}, class NotificationBanner extends Calendar.NotificationMessage { + constructor(notification) { + super(notification); if (notification.requestReplyId !== undefined) this._addReplyAction(); } @@ -56,7 +56,7 @@ const NotificationBanner = GObject.registerClass({ _addReplyAction() { if (!this._buttonBox) { this._buttonBox = new St.BoxLayout({ - style_class: 'notification-actions', + style_class: 'notification-buttons-bin', x_expand: true, }); this.setActionArea(this._buttonBox); @@ -207,13 +207,10 @@ const Source = GObject.registerClass({ } /* - * Override to control notification spawning + * Parse the id to determine if it's a repliable notification, device + * notification or a regular local notification */ - addNotification(notificationId, notificationParams, showBanner) { - this._notificationPending = true; - - // Parse the id to determine if it's a repliable notification, device - // notification or a regular local notification + _parseNotificationId(notificationId) { let idMatch, deviceId, requestReplyId, remoteId, localId; if ((idMatch = REPLY_REGEX.exec(notificationId))) { @@ -227,42 +224,39 @@ const Source = GObject.registerClass({ } else { localId = notificationId; } + return [idMatch, deviceId, requestReplyId, remoteId, localId]; + } - // Fix themed icons - if (notificationParams.icon) { - let gicon = Gio.Icon.deserialize(notificationParams.icon); - - if (gicon instanceof Gio.ThemedIcon) { - gicon = getIcon(gicon.names[0]); - notificationParams.icon = gicon.serialize(); - } - } - - let notification = this._notifications[localId]; + /* + * Add notification to source or update existing notification with extra + * GsConnect information + */ + _createNotification(notification) { + const [idMatch, deviceId, requestReplyId, remoteId, localId] = this._parseNotificationId(notification.id); + const cachedNotification = this._notifications[localId]; // Check if this is a repeat - if (notification) { - notification.requestReplyId = requestReplyId; + if (cachedNotification) { + cachedNotification.requestReplyId = requestReplyId; // Bail early If @notificationParams represents an exact repeat - const title = notificationParams.title.unpack(); - const body = notificationParams.body - ? notificationParams.body.unpack() + const title = notification.title; + const body = notification.body + ? notification.body : null; - if (notification.title === title && - notification.bannerBodyText === body) { - this._notificationPending = false; - return; - } + if (cachedNotification.title === title && + cachedNotification.body === body) + return cachedNotification; - notification.title = title; - notification.bannerBodyText = body; + cachedNotification.title = title; + cachedNotification.body = body; + + return cachedNotification; + } // Device Notification - } else if (idMatch) { - notification = this._createNotification(notificationParams); - + if (idMatch) { notification.deviceId = deviceId; notification.remoteId = remoteId; notification.requestReplyId = requestReplyId; @@ -272,41 +266,66 @@ const Source = GObject.registerClass({ delete this._notifications[localId]; }); - this._notifications[localId] = notification; - // Service Notification } else { - notification = this._createNotification(notificationParams); notification.connect('destroy', (notification, reason) => { delete this._notifications[localId]; }); - this._notifications[localId] = notification; } - if (showBanner) - this.showNotification(notification); - else - this.pushNotification(notification); + this._notifications[localId] = notification; + return notification; + } + + /* + * Override to control notification spawning + */ + addNotification(notification) { + this._notificationPending = true; + + // Fix themed icons + if (notification.icon) { + let gicon = notification.icon; + + if (gicon instanceof Gio.ThemedIcon) { + gicon = getIcon(gicon.names[0]); + notification.icon = gicon.serialize(); + } + } + + const createdNotification = this._createNotification(notification); + this._addNotificationToMessageTray(createdNotification); this._notificationPending = false; } /* - * Override to raise the usual notification limit (3) + * Reimplementation of MessageTray.addNotification to raise the usual + * notification limit (3) */ - pushNotification(notification) { - if (this.notifications.includes(notification)) + _addNotificationToMessageTray(notification) { + if (this.notifications.includes(notification)) { + notification.acknowledged = false; return; + } - while (this.notifications.length >= 10) - this.notifications.shift().destroy(MessageTray.NotificationDestroyedReason.EXPIRED); + while (this.notifications.length >= 10) { + const [oldest] = this.notifications; + oldest.destroy(MessageTray.NotificationDestroyedReason.EXPIRED); + } notification.connect('destroy', this._onNotificationDestroy.bind(this)); - notification.connect('notify::acknowledged', this.countUpdated.bind(this)); - this.notifications.push(notification); - this.emit('notification-added', notification); + notification.connect('notify::acknowledged', () => { + this.countUpdated(); - this.countUpdated(); + // If acknowledged was set to false try to show the notification again + if (!notification.acknowledged) + this.emit('notification-request-banner', notification); + }); + this.notifications.push(notification); + + this.emit('notification-added', notification); + this.emit('notification-request-banner', notification); } createBanner(notification) { @@ -325,8 +344,10 @@ export function patchGSConnectNotificationSource() { if (source !== undefined) { // Patch in the subclassed methods source._closeGSConnectNotification = Source.prototype._closeGSConnectNotification; + source._parseNotificationId = Source.prototype._parseNotificationId; + source._createNotification = Source.prototype._createNotification; source.addNotification = Source.prototype.addNotification; - source.pushNotification = Source.prototype.pushNotification; + source._addNotificationToMessageTray = Source.prototype._addNotificationToMessageTray; source.createBanner = Source.prototype.createBanner; // Connect to existing notifications @@ -353,8 +374,10 @@ const _ensureAppSource = function (appId) { if (source._appId === APP_ID) { source._closeGSConnectNotification = Source.prototype._closeGSConnectNotification; + source._parseNotificationId = Source.prototype._parseNotificationId; + source._createNotification = Source.prototype._createNotification; source.addNotification = Source.prototype.addNotification; - source.pushNotification = Source.prototype.pushNotification; + source._addNotificationToMessageTray = Source.prototype._addNotificationToMessageTray; source.createBanner = Source.prototype.createBanner; } @@ -378,29 +401,6 @@ export function unpatchGtkNotificationDaemon() { const _addNotification = NotificationDaemon.GtkNotificationDaemonAppSource.prototype.addNotification; export function patchGtkNotificationSources() { - // This should diverge as little as possible from the original - // eslint-disable-next-line func-style - const addNotification = function (notificationId, notificationParams, showBanner) { - this._notificationPending = true; - - if (this._notifications[notificationId]) - this._notifications[notificationId].destroy(MessageTray.NotificationDestroyedReason.REPLACED); - - const notification = this._createNotification(notificationParams); - notification.connect('destroy', (notification, reason) => { - this._withdrawGSConnectNotification(notification, reason); - delete this._notifications[notificationId]; - }); - this._notifications[notificationId] = notification; - - if (showBanner) - this.showNotification(notification); - else - this.pushNotification(notification); - - this._notificationPending = false; - }; - // eslint-disable-next-line func-style const _withdrawGSConnectNotification = function (id, notification, reason) { if (reason !== MessageTray.NotificationDestroyedReason.DISMISSED) @@ -442,7 +442,6 @@ export function patchGtkNotificationSources() { ); }; - NotificationDaemon.GtkNotificationDaemonAppSource.prototype.addNotification = addNotification; NotificationDaemon.GtkNotificationDaemonAppSource.prototype._withdrawGSConnectNotification = _withdrawGSConnectNotification; } diff --git a/gnome/.local/share/gnome-shell/extensions/screen-rotate@shyzus.github.io/extension.js b/gnome/.local/share/gnome-shell/extensions/screen-rotate@shyzus.github.io/extension.js index 326f527..9b5b509 100644 --- a/gnome/.local/share/gnome-shell/extensions/screen-rotate@shyzus.github.io/extension.js +++ b/gnome/.local/share/gnome-shell/extensions/screen-rotate@shyzus.github.io/extension.js @@ -1,5 +1,5 @@ /* extension.js -* Copyright (C) 2023 kosmospredanie, shyzus, Shinigaminai +* Copyright (C) 2024 kosmospredanie, shyzus, Shinigaminai * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -15,17 +15,22 @@ * along with this program. If not, see . */ -import { Extension } from 'resource:///org/gnome/shell/extensions/extension.js'; +import { Extension, gettext as _ } from 'resource:///org/gnome/shell/extensions/extension.js'; import Gio from 'gi://Gio'; +import GObject from 'gi://GObject'; +import GLib from 'gi://GLib'; import * as SystemActions from 'resource:///org/gnome/shell/misc/systemActions.js'; - +import * as Main from 'resource:///org/gnome/shell/ui/main.js'; import * as Rotator from './rotator.js' +import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; const ORIENTATION_LOCK_SCHEMA = 'org.gnome.settings-daemon.peripherals.touchscreen'; const ORIENTATION_LOCK_KEY = 'orientation-lock'; +import { QuickMenuToggle, QuickSettingsMenu, SystemIndicator } from 'resource:///org/gnome/shell/ui/quickSettings.js'; + // Orientation names must match those provided by net.hadess.SensorProxy const Orientation = Object.freeze({ 'normal': 0, @@ -34,6 +39,100 @@ const Orientation = Object.freeze({ 'right-up': 3 }); +const ManualOrientationIndicator = GObject.registerClass( +class ManualOrientationIndicator extends SystemIndicator { + _init(ext_ref) { + super._init(); + this.toggle = new ManualOrientationMenuToggle(ext_ref); + this.quickSettingsItems.push(this.toggle); + } + + destroy() { + this.quickSettingsItems.pop(this.toggle); + this.toggle.destroy(); + } +}); + +const ManualOrientationMenuToggle = GObject.registerClass( +class ManualOrientationMenuToggle extends QuickMenuToggle { + _init(ext) { + super._init({ + title: _('Rotate'), + iconName: 'object-rotate-left-symbolic', + menuEnabled: true, + toggleMode: true, + }); + + this.menu.setHeader('object-rotate-left-symbolic', _('Screen Rotate')); + + this._section = new PopupMenu.PopupMenuSection(); + this.menu.addMenuItem(this._section); + + this.landscapeItem = new PopupMenu.PopupMenuItem('Landscape', { + reactive: true, + can_focus: true, + }); + + this.portraitLeftItem = new PopupMenu.PopupMenuItem('Portrait Left', { + reactive: true, + can_focus: true, + }); + + this.landscapeFlipItem = new PopupMenu.PopupMenuItem('Landscape Flipped', { + reactive: true, + can_focus: true, + }); + + this.portraitRightItem = new PopupMenu.PopupMenuItem('Portrait Right', { + reactive: true, + can_focus: true, + }); + + this.landscapeItem.connect('activate', () => { + this._onItemActivate(this.landscapeItem); + ext.rotate_to('normal'); + }); + this.portraitLeftItem.connect('activate', () => { + this._onItemActivate(this.portraitLeftItem); + ext.rotate_to('left-up'); + }); + this.landscapeFlipItem.connect('activate', () => { + this._onItemActivate(this.landscapeFlipItem); + ext.rotate_to('bottom-up'); + }); + this.portraitRightItem.connect('activate', () => { + this._onItemActivate(this.portraitRightItem); + ext.rotate_to('right-up'); + }); + + this._section.addMenuItem(this.landscapeItem); + this._section.addMenuItem(this.portraitLeftItem); + this._section.addMenuItem(this.landscapeFlipItem); + this._section.addMenuItem(this.portraitRightItem); + + this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); + this.menu.addSettingsAction(_('Extension Settings'), + 'com.mattjakeman.ExtensionManager.desktop'); + + this.connect('clicked', () => { + if (this.checked == true) { + ext.rotate_to('right-up'); + } else { + ext.rotate_to('normal'); + } + }); + } + + _onItemActivate(item) { + this.landscapeItem.setOrnament(PopupMenu.Ornament.HIDDEN); + this.portraitLeftItem.setOrnament(PopupMenu.Ornament.HIDDEN); + this.landscapeFlipItem.setOrnament(PopupMenu.Ornament.HIDDEN); + this.portraitRightItem.setOrnament(PopupMenu.Ornament.HIDDEN); + + item.setOrnament(PopupMenu.Ornament.CHECK); + } +}); + class SensorProxy { constructor(rotate_cb) { this._rotate_cb = rotate_cb; @@ -207,17 +306,72 @@ export default class ScreenAutoRotateExtension extends Extension { enable() { this._settings = this.getSettings(); this._ext = new ScreenAutorotate(this._settings); + + this._settings.connect('changed::manual-flip', (settings, key) => { + if (settings.get_boolean(key)) { + this._add_manual_flip(); + } else { + this._remove_manual_flip(); + } + }); + + this._settings.connect('changed::hide-lock-rotate', (settings, key) => { + this._set_hide_lock_rotate(settings.get_boolean(key)); + }); + + if (this._settings.get_boolean('manual-flip')) { + this._add_manual_flip(); + } else { + this._remove_manual_flip(); + } + + /* Timeout needed due to unknown race condition causing 'Auto Rotate' + * Quick Toggle to be undefined for a brief moment. + */ + this._timeoutId = setTimeout(() => { + this._set_hide_lock_rotate(this._settings.get_boolean('hide-lock-rotate')); + }, 1000); + } + + _set_hide_lock_rotate(state) { + const autoRotateIndicator = Main.panel.statusArea.quickSettings._autoRotate; + + if (state) { + Main.panel.statusArea.quickSettings._indicators.remove_child(autoRotateIndicator); + Main.panel.statusArea.quickSettings.menu._grid.remove_child(autoRotateIndicator.quickSettingsItems[0]); + } else { + Main.panel.statusArea.quickSettings._indicators.add_child(autoRotateIndicator); + Main.panel.statusArea.quickSettings._addItemsBefore( + autoRotateIndicator.quickSettingsItems, + Main.panel.statusArea.quickSettings._rfkill.quickSettingsItems[0] + ); + } + } + + _add_manual_flip() { + this.flipIndicator = new ManualOrientationIndicator(this._ext); + Main.panel.statusArea.quickSettings.addExternalIndicator(this.flipIndicator); + } + + _remove_manual_flip() { + if (this.flipIndicator != null) { + this.flipIndicator.destroy(); + this.flipIndicator = null; + } } disable() { /* Comment for unlock-dialog usage: - The unlock-dialog sesson-mode is usefull for this extension as it allows + The unlock-dialog session-mode is useful for this extension as it allows the user to rotate their screen or lock rotation after their device may have auto-locked. This provides the ability to log back in regardless of the orientation of the device in tablet mode. */ this._settings = null; + clearTimeout(this._timeoutId); + this._timeoutId = null; + this._remove_manual_flip(); this._ext.destroy(); this._ext = null; } diff --git a/gnome/.local/share/gnome-shell/extensions/screen-rotate@shyzus.github.io/metadata.json b/gnome/.local/share/gnome-shell/extensions/screen-rotate@shyzus.github.io/metadata.json index 8a53079..69547d5 100644 --- a/gnome/.local/share/gnome-shell/extensions/screen-rotate@shyzus.github.io/metadata.json +++ b/gnome/.local/share/gnome-shell/extensions/screen-rotate@shyzus.github.io/metadata.json @@ -9,9 +9,10 @@ ], "settings-schema": "org.gnome.shell.extensions.screen-rotate", "shell-version": [ - "45" + "45", + "46" ], "url": "https://github.com/shyzus/gnome-shell-extension-screen-autorotate", "uuid": "screen-rotate@shyzus.github.io", - "version": 15 + "version": 19 } \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/screen-rotate@shyzus.github.io/prefs.js b/gnome/.local/share/gnome-shell/extensions/screen-rotate@shyzus.github.io/prefs.js index 862423e..85c2e6c 100644 --- a/gnome/.local/share/gnome-shell/extensions/screen-rotate@shyzus.github.io/prefs.js +++ b/gnome/.local/share/gnome-shell/extensions/screen-rotate@shyzus.github.io/prefs.js @@ -1,5 +1,5 @@ /* prefs.js -* Copyright (C) 2023 kosmospredanie, shyzus, Shinigaminai +* Copyright (C) 2024 kosmospredanie, shyzus, Shinigaminai * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,6 +33,10 @@ export default class MyExtensionPreferences extends ExtensionPreferences { orientationGroup.set_title('Orientation Settings') page.add(orientationGroup); + const shellMenuGroup = new Adw.PreferencesGroup(); + shellMenuGroup.set_title('GNOME Shell Menu Settings'); + page.add(shellMenuGroup); + const debugGroup = new Adw.PreferencesGroup(); debugGroup.set_title('Debug Settings'); page.add(debugGroup); @@ -62,6 +66,17 @@ export default class MyExtensionPreferences extends ExtensionPreferences { orientationGroup.add(setOffsetRow); + const enableManualFlipRow = new Adw.ActionRow({ + title: 'Enable manual flip', + subtitle: 'Enable a toggle in the GNOME Shell System Menu to manually flip between landscape and portrait.' + }); + shellMenuGroup.add(enableManualFlipRow); + + const hideLockRotateRow = new Adw.ActionRow({ + title: 'Hide the "Auto Rotate" quick toggle' + }); + shellMenuGroup.add(hideLockRotateRow); + const toggleLoggingRow = new Adw.ActionRow({ title: 'Enable debug logging', subtitle: 'Use "journalctl /usr/bin/gnome-shell -f" to see log output.' @@ -86,6 +101,16 @@ export default class MyExtensionPreferences extends ExtensionPreferences { const setOffsetSpinButton = Gtk.SpinButton.new_with_range(0, 3, 1); setOffsetSpinButton.value = window._settings.get_int('orientation-offset'); + const manualFlipSwitch = new Gtk.Switch({ + active: window._settings.get_boolean('manual-flip'), + valign: Gtk.Align.CENTER, + }); + + const hideLockRotateSwitch = new Gtk.Switch({ + active: window._settings.get_boolean('hide-lock-rotate'), + valign: Gtk.Align.CENTER, + }); + const toggleLoggingSwitch = new Gtk.Switch({ active: window._settings.get_boolean('debug-logging'), valign: Gtk.Align.CENTER @@ -103,6 +128,12 @@ export default class MyExtensionPreferences extends ExtensionPreferences { window._settings.bind('orientation-offset', setOffsetSpinButton, 'value', Gio.SettingsBindFlags.DEFAULT); + window._settings.bind('manual-flip', + manualFlipSwitch, 'active', Gio.SettingsBindFlags.DEFAULT); + + window._settings.bind('hide-lock-rotate', + hideLockRotateSwitch, 'active', Gio.SettingsBindFlags.DEFAULT); + window._settings.bind('debug-logging', toggleLoggingSwitch, 'active', Gio.SettingsBindFlags.DEFAULT); @@ -118,7 +149,13 @@ export default class MyExtensionPreferences extends ExtensionPreferences { setOffsetRow.add_suffix(setOffsetSpinButton); setOffsetRow.activatable_widget = setOffsetSpinButton; + enableManualFlipRow.add_suffix(manualFlipSwitch); + enableManualFlipRow.activatable_widget = manualFlipSwitch; + + hideLockRotateRow.add_suffix(hideLockRotateSwitch); + hideLockRotateRow.activatable_widget = hideLockRotateSwitch; + toggleLoggingRow.add_suffix(toggleLoggingSwitch); toggleLoggingRow.activatable_widget = toggleLoggingSwitch; } -} \ No newline at end of file +} diff --git a/gnome/.local/share/gnome-shell/extensions/screen-rotate@shyzus.github.io/rotator.js b/gnome/.local/share/gnome-shell/extensions/screen-rotate@shyzus.github.io/rotator.js index 5f6ff13..6a104ee 100644 --- a/gnome/.local/share/gnome-shell/extensions/screen-rotate@shyzus.github.io/rotator.js +++ b/gnome/.local/share/gnome-shell/extensions/screen-rotate@shyzus.github.io/rotator.js @@ -64,8 +64,11 @@ export function get_state() { export function rotate_to(transform) { this.get_state().then(state => { - let builtin_monitor = state.builtin_monitor; - let logical_monitor = state.get_logical_monitor_for(builtin_monitor.connector); + let target_monitor = state.builtin_monitor; + if (target_monitor == undefined) { + target_monitor = state.monitors[0] + } + let logical_monitor = state.get_logical_monitor_for(target_monitor.connector); logical_monitor.transform = transform; let variant = state.pack_to_apply(BusUtils.Methods['temporary']); call_dbus_method('ApplyMonitorsConfig', variant); diff --git a/gnome/.local/share/gnome-shell/extensions/screen-rotate@shyzus.github.io/schemas/gschemas.compiled b/gnome/.local/share/gnome-shell/extensions/screen-rotate@shyzus.github.io/schemas/gschemas.compiled index 6833ea0a92be308f606d1b7f7e6830852f273556..4e7e3665a5c81ed86f10aa0ec18a54be6d4a921b 100644 GIT binary patch delta 368 zcmX@WvW9g+2xG^@P~&<|1_)pTQp`}y0;Ji1m>mgAbI;7>0P;J43b`4|7-j(Jxj=lN zwvPKh5P;aMK=Bno`YI6jU$%b-QV(J)0mXj+>AygH^6tkcAaM{|fT66OL4b*YK@^A; z9*FdTBtUFlpau;ftqa7d$^s%FaS&SwDDD8HJ%Cug@}nR~9K==uiWdOsQXm!#PF4kp zgV;a|7&?G-FA%eeGBAJ~3Su)b_%KWW(rcJ_85nXC^GXwQbklM&3nmvcI!z8>RAtsk z(ww}N(O|MFll0_2jB0iuEkLo1%#>8!oc!c$-J<-G#FA8yFi0Fog2D_GexNV|g&o)y IAk7NI0HRJnyZ`_I delta 257 zcmZ3(dVpm@2xGv+P~&=b1_)pTQZUR6WU~MS4 z{tpBoHY-rP14wTL;*)njJ^`r*u?2wQCxG->AXa!F(gzX;v3Y^w4}kPjMg~s?R#659 zkU>BW5cn{>0MdVeSibV3AV>p0 Experiment with this offset in case orientation is incorrect. + + false + Enable a toggle in the GNOME Shell System Menu to manually flip between landscape and portrait. + + false + Hide the 'Auto Rotate' quick toggle. + false Toggle debug logging. diff --git a/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/CHANGELOG.md b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/CHANGELOG.md new file mode 100644 index 0000000..7a7be63 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/CHANGELOG.md @@ -0,0 +1,278 @@ +# Changelog + + + +## [Unreleased] +- Sorry for my English, I use a translator. :) + +## [v1] - 2022-02-03 +### Added +- Initial release. + +## [v2] - 2022-02-04 +### Fixed +- Change GLib.idle_add() to 'realize' signal in buildPrefsWidget (prefs.js). +- Add settings-schema and gettext-domain in metadata.json. +- Remove unnecessary imports. +- Fix indentations. +- Elimination of unnecessary logs. +- Thanks JustPerfection!!! + +## [v3] - 2022-02-05 +### Added +- Add alernatives thresholds paths. +- Add available flag and the _init code is restructured according to this addition... Now the submenu is shown even if the thresholds are not available. +### Fixed +- Fix _available function. The test whether the files exist points to the start file twice! + +## [v4] - 2022-02-21 +### Added +- Add icon type option (symbolic/color). + +## [v5] - 2022-02-21 +### Fixed +- Fix icon type on start. + +## [v6] - 2022-03-16 +### Added +- Threshold related functions have been moved to a library and optimized. +- The option to apply the thresholds to the battery of the dock is implemented if it is available (try this, I don't have a dock!!!) +- Added option to show/hide current values in menu. +- Added tooltips in menu icons. +### Changed +- The settings are applied immediately except for the thresholds that will be applied the next time they are activated from this extension or using the button for this purpose in the preferences window. +- Remove thresholds limits. +### Performance +- Function to apply thresholds now use promise (async) and can catch errors. +- Function to apply thresholds now checks if are available to determine what can be applied (more compatibility?). +### Fixed +### Other +- Reformat strings. +- Icons are redesigned... something. +- Minor cosmetic changes. + +## [v7] - 2022-03-21 +### Fixed +- If the action of applying the thresholds is canceled, now it does not throw an error. +- Update error notification message. +- Fixed the problem that the state switch was not updated to the correct state in case of an error. +- Fixed texts. +### Other +- Change schema settings types. +- Preferences UI was moved to a .ui file and Gtk4 is implemented with cosmetic improvements. +- Files names changed. +### Changed +- The buttons to apply the thresholds on the settings page are removed... I didn't like it :) +- Validate availability before applying the threshold in extension.js. +- Update metadata information. +### Performance +- Improvements to file monitors to avoid repeated execution of the callback. +- Change GtkComboBoxText to GtkDroopDown. +### Added +- Added an option to show/hide tooltips. +- Gnome 42 and libadwaita compatibility. + +## [v8] - 2022-03-27 +### Performance +- Threshold write performance improvements (fewer writes). Inspired by [TLP](https://github.com/linrunner/TLP/blob/main/bat.d/05-thinkpad) +- Russian translation update (Andrey Sitnik) + +## [v9] - 2022-03-28 +### Fixed +- Russian translation update (Andrey Sitnik) + +## [v10] - 2022-05-25 +### Added +- Gnome 42 icons +- Added a menu to apply the configured values +- Added option to disable notifications +### Changed +- Revert switch to menu +### Other +- Update icons + +## [v11] - 2022-05-30 +### Fixed +- Russian translation update (Andrey Sitnik) + +## [v12] - 2022-10-08 +### Added +- Add option to show icon on inactive thresholds (based on the proposal of [Riccardo Massidda](https://gitlab.com/marcosdalvarez/thinkpad-battery-threshold-extension/-/issues/3)) +- Gnome 43 compatibility (QuickSettings) - First attempt... many TODOs +### Fixed +- Dock battery callbacks + +## [v13] - 2022-10-16 +### Fixed +- Issue [#5](https://gitlab.com/marcosdalvarez/thinkpad-battery-threshold-extension/-/issues/5): Bad function name +- Warnings fixes + +## [v14] - 2022-11-28 +### Performance +- Completely rewrites the "driver" using (or trying to) the GObject model +- Part of the "indicator" is rewritten +- Some text strings were modified to adapt them (The driver does not show text) +### Changed +- Thresholds can now be adjusted with 1% intervals +### Removed +- Support for versions older than Gnome 43 is removed. (Older versions of the extension are functional on Gnome 41/42) + +## [v15] - 2022-12-01 +### Fixed +- Fix platform detection (wrong regular expression) + +## [v16] - 2022-12-23 +### Added +- Added the option to reset the recommended thresholds on the preferences page +- Added the option to reset all preferences +### Other +- Move preference pages to separate classes +- Moved links to preferences window menu. Based on the excellent [GNOME Shell Extension - Blur my Shell](https://github.com/aunetx/blur-my-shell): All credits to [Aurélien Hamy](https://github.com/aunetx) + +## [v17] - 2022-12-27 +### Other +- Update translations + +## [v18] - 2023-01-03 +### Other +- Update translations + +## [v19] - 2023-01-24 +### Fixed +- Issue [#8](https://gitlab.com/marcosdalvarez/thinkpad-battery-threshold-extension/-/issues/8): On some models the start threshold 0 is not allowed, instead 95 is used (Ex: E14 Gen 3) +### Other +- Update translations + +## [v20] - 2023-01-27 +### Other +- Update translations + +## [v21] - 2023-03-07 +### Added +- Environment object (kernel, product) +### Fixed +- Kernel version check + +## [v22] - 2023-03-10 +### Fixed +- Fix error "batteries is null" if platform is not supported +### Added +- Added support for Gnome 44 + +## [v23] - 2023-03-11 +### Fixed +- Remove duplicate kernel version message with debugging enabled +- Fixed error when checking if there are pending changes to apply in the driver +### Other +- (dis)connectObject is changed to connect/disconnect in the driver and battery classes because they are not GJS standards and it is not possible to use these classes in the preferences +### Added +- Suggestion [#11](https://gitlab.com/marcosdalvarez/thinkpad-battery-threshold-extension/-/issues/11): Added buttons in preferences window to apply thresholds (if battery is available) +### Changed +- Now, the reset thresholds button in preferences window also tries to apply the values +- Now, the pending-changes property is true even if the thresholds are not active + +## [v24] - 2023-03-13 +### Added +- Added dialog messages to the reset buttons in the preferences window +### Changed +- Debug mode now takes effect immediately without the need to restart the extension +- The "Force compatible models" option is renamed to "Disable model compatibility check" and the value is also reversed (false = check compatibility - default) + +## [v25] - 2023-03-15 +### Other +- Update translations + +## [v26] - 2023-03-17 +### Other +- Update translations + +## [v27] - 2023-04-01 +### Fixed +- Fixed non-detection of attribute changes of the threshold files + +## [v28] - 2023-04-03 +### Other +- Update translations + +## [v29] - 2023-04-10 +### Fixed +- Fixed bug in preferences window if platform is not supported + +## [v30] - 2023-04-15 +### Other +- Update translations + +## [v31] - 2023-04-19 +### Fixed +- Fixed signal assignment in preferences window + +## [v32] - 2023-04-24 +### Fixed +- Issue [#15](https://gitlab.com/marcosdalvarez/thinkpad-battery-threshold-extension/-/issues/15): Incorrect positioning on gnome 44 (Thanks @KayJay7) + +## [v33] - 2023-06-06 +### Other +- Update translations + +## [v34] - 2023-09-22 +### Fixed +- Preferences window is modified (About tab added) + +## [v35] - 2023-10-10 +### Added +- Gnome 45 support +### Removed +- Removed debug option +- Removed disable compatibility check option (unnecessary) +### Other +- Design changes in the preferences window +- Update strings + +## [v36] - 2023-10-10 +### Fixed +- Remove "this" in prefs.js (Thanks Just Perfection) +- Remove "run_dispose()" in driver.js and inicator.js (Thanks Just Perfection) + +## [v37] - 2023-10-13 +### Performance +- Object references in the preferences window are optimized +- Minor changes in implementations +### Other +- Update translations (German) + +## [v38] - 2023-11-12 +### Other +- Update translations (Russian) + +## [v39] - 2023-12-01 +### Other +- Update translations (Portuguese - Brazil) + +## [v40] - 2023-12-05 +### Other +- Update translations (Japanese) + +## [v41] - 2023-12-07 +### Other +- Update translations (Czech) + +## [v42] - 2023-12-19 +### Other +- Update translations (Portuguese) + +## [v43] - 2024-02-23 +### Other +- Update translations (Italian) + +## [v44] - 2024-03-20 +### Added +- Gnome 46 support \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/LICENSE b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/LICENSE new file mode 100644 index 0000000..76893fd --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + Thinkpad Battery Threshold Extension + Copyright (C) 2022 Marcos + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) 2022 Marcos + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/extension.js b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/extension.js new file mode 100644 index 0000000..be4e993 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/extension.js @@ -0,0 +1,35 @@ +/* + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * SPDX-License-Identifier: GPL-2.0-or-later + * + * CHANGELOG: https://gitlab.com/marcosdalvarez/thinkpad-battery-threshold-extension/blob/main/CHANGELOG.md + */ + +'use strict'; + +import { Extension } from 'resource:///org/gnome/shell/extensions/extension.js'; + +import { ThresholdIndicator } from './libs/indicator.js'; + +export default class ExtensionManager extends Extension { + enable() { + this._indicator = new ThresholdIndicator(this); + } + + disable() { + this._indicator?.destroy(); + this._indicator = null; + } +} \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-active-symbolic.svg b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-active-symbolic.svg new file mode 100644 index 0000000..6484d27 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-active-symbolic.svg @@ -0,0 +1,47 @@ + + + + + + + diff --git a/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-active.svg b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-active.svg new file mode 100644 index 0000000..a3bc8be --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-active.svg @@ -0,0 +1,47 @@ + + + + + + + diff --git a/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-app-symbolic.svg b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-app-symbolic.svg new file mode 100644 index 0000000..6bb7b61 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-app-symbolic.svg @@ -0,0 +1,47 @@ + + + + + + + diff --git a/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-error-symbolic.svg b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-error-symbolic.svg new file mode 100644 index 0000000..9b7e2b4 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-error-symbolic.svg @@ -0,0 +1,4 @@ + + + + diff --git a/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-error.svg b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-error.svg new file mode 100644 index 0000000..84f5f4e --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-error.svg @@ -0,0 +1,39 @@ + + + + + + diff --git a/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-inactive-symbolic.svg b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-inactive-symbolic.svg new file mode 100644 index 0000000..3b712bd --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-inactive-symbolic.svg @@ -0,0 +1,45 @@ + + + + + + + diff --git a/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-inactive.svg b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-inactive.svg new file mode 100644 index 0000000..a32eb26 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-inactive.svg @@ -0,0 +1,45 @@ + + + + + + + diff --git a/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-unknown-symbolic.svg b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-unknown-symbolic.svg new file mode 100644 index 0000000..4097173 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-unknown-symbolic.svg @@ -0,0 +1,45 @@ + + + + + + + diff --git a/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-unknown.svg b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-unknown.svg new file mode 100644 index 0000000..4136530 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/icons/threshold-unknown.svg @@ -0,0 +1,45 @@ + + + + + + + diff --git a/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/libs/driver.js b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/libs/driver.js new file mode 100644 index 0000000..f19e4e0 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/libs/driver.js @@ -0,0 +1,857 @@ +/** + * Driver for handling thresholds in Lenovo ThinkPad series for models since 2011 + * + * Based on information from https://linrunner.de/tlp/faq/battery.html + * + * Original sources: https://github.com/linrunner/TLP/blob/main/bat.d/05-thinkpad + */ +'use strict'; + +import GLib from 'gi://GLib'; +import GObject from 'gi://GObject'; +import Gio from 'gi://Gio'; + +// Driver constants +const BASE_PATH = '/sys/class/power_supply'; +const START_FILE_OLD = 'charge_start_threshold'; // kernel 4.17 and newer +const END_FILE_OLD = 'charge_stop_threshold'; // kernel 4.17 and newer +const START_FILE_NEW = 'charge_control_start_threshold'; // kernel 5.9 and newer +const END_FILE_NEW = 'charge_control_end_threshold'; // kernel 5.9 and newer + +/** + * Read file contents + * + * @param {string} path Path of file + * @returns {string} File contents + */ +const readFile = function(path) { + try { + const f = Gio.File.new_for_path(path); + const [, contents,] = f.load_contents(null); + const decoder = new TextDecoder('utf-8'); + return decoder.decode(contents); + } catch (e) { + return null; + } +} + +/** + * Read integer value from file + * + * @param {string} path Path of file + * @returns {number|null} Return a integer or null + */ +const readFileInt = function(path) { + try { + const v = readFile(path); + if (v) { + return parseInt(v); + } else { + return null; + } + } catch (e) { + return null; + } +} + +/** + * Test file/direcory exists + * + * @param {string} path File/directory path + * @returns {boolean} + */ +const fileExists = function(path) { + try { + const f = Gio.File.new_for_path(path); + return f.query_exists(null); + } catch (e) { + return false; + } +} + +/** + * Environment object + */ +const Environment = GObject.registerClass({ + GTypeName: 'Environment', +}, class Environment extends GObject.Object { + + get productVersion() { + if (this._productVersion === undefined) { + const tmp = readFile('/sys/class/dmi/id/product_version'); + if (tmp) { + // Remove non-alphanumeric characters + const sanitize = /([^ A-Za-z0-9])+/g; + this._productVersion = tmp.replace(sanitize, ''); + } else { + this._productVersion = null; + } + } + return this._productVersion; + } + + get kernelRelease() { + if (this._kernelRelease === undefined) { + try { + let proc = Gio.Subprocess.new( + ['uname', '-r'], + Gio.SubprocessFlags.STDOUT_PIPE | Gio.SubprocessFlags.STDERR_PIPE + ); + const [ok, stdout, stderr] = proc.communicate_utf8(null, null); + proc = null; + this._kernelRelease = stdout.trim(); + } catch (e) { + logError(e); + } + } + return this._kernelRelease; + } + + get kernelMajorVersion() { + if (this._kernelMajorVersion === undefined) { + [this._kernelMajorVersion , this._kernelMinorVersion] = this.kernelRelease.split('.', 2); + } + return this._kernelMajorVersion; + } + + get kernelMinorVersion() { + if (this._kernelMinorVersion === undefined) { + [this._kernelMajorVersion , this._kernelMinorVersion] = this.kernelRelease.split('.', 2); + } + return this._kernelMinorVersion; + } + + checkMinKernelVersion(major, minor) { + return ( + this.kernelMajorVersion > major || + (this,this.kernelMajorVersion === major && this.kernelMinorVersion >= minor) + ); + } + +}); + +/** + * Execute a command and generate events based on its result + * + * @param {string} command Command to execute + * @param {boolean} asRoot True to run with elevated permissions + */ +const Runnable = GObject.registerClass({ + GTypeName: 'Runnable', + Signals: { + 'command-completed': { + param_types: [GObject.TYPE_JSOBJECT /* erro */] + } + } +}, class Runnable extends GObject.Object { + constructor(command, asRoot = false) { + super(); + if (!command) { + throw Error('The command cannot be an empty string'); + } + this._command = command; + this._asRoot = asRoot; + } + + run() { + const argv = ['sh', '-c', this._command]; + + if (this._asRoot) { + argv.unshift('pkexec'); + } + + try { + const [, pid] = GLib.spawn_async(null, argv, null, GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD, null); + + GLib.child_watch_add(GLib.PRIORITY_DEFAULT_IDLE, pid, (pid, status) => { + try { + GLib.spawn_check_exit_status(status); + this.emit('command-completed', null); + } catch(e) { + if (e.code == 126) { + // Cancelled + } else { + logError(e); + this.emit('command-completed', e); + } + } + GLib.spawn_close_pid(pid); + }); + } catch (e) { + logError(e); + this.emit('command-completed', e); + } + } +}); + +/** + * ThinkPad battery object + */ +export const ThinkPadBattery = GObject.registerClass({ + GTypeName: 'ThinkPadBattery', + Properties: { + 'environment': GObject.ParamSpec.object( + 'environment', + 'Environment', + 'Environment', + GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY, + Environment.$gtype + ), + 'name': GObject.ParamSpec.string( + 'name', + 'Name', + 'Battery name', + GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY, + null + ), + 'auth-required': GObject.ParamSpec.boolean( + 'auth-required', + 'Auth required', + 'Authorization is required to write the values', + GObject.ParamFlags.READABLE, + false + ), + 'is-active': GObject.ParamSpec.boolean( + 'is-active', + 'Is active', + 'Indicates if the thresholds are active or not', + GObject.ParamFlags.READABLE, + false + ), + 'is-available': GObject.ParamSpec.boolean( + 'is-available', + 'Is available', + 'Indicates if the battery are available or not', + GObject.ParamFlags.READABLE, + false + ), + 'pending-changes': GObject.ParamSpec.boolean( + 'pending-changes', + 'Pending changes', + 'Indicates if the current values do not match the configured values', + GObject.ParamFlags.READABLE, + false + ), + 'start-value': GObject.ParamSpec.int( + 'start-value', + 'Start value', + 'Current start value', + GObject.ParamFlags.READABLE, + 0, 100, + 0 + ), + 'end-value': GObject.ParamSpec.int( + 'end-value', + 'End value', + 'Current end value', + GObject.ParamFlags.READABLE, + 0, 100, + 100 + ), + 'settings': GObject.ParamSpec.object( + 'settings', + 'Settings', + 'Settings', + GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY, + Gio.Settings.$gtype + ), + }, + Signals: { + 'enable-completed': { + param_types: [GObject.TYPE_JSOBJECT /* error */] + }, + 'disable-completed': { + param_types: [GObject.TYPE_JSOBJECT /* error */] + }, + }, +}, class ThinkPadBattery extends GObject.Object { + constructor(constructProperties = {}) { + super(constructProperties); + + if (!this.name) { + throw Error('Battery name not defined'); + } + + // Signals handlers IDs + this._monitorId = null; + this._settingStartId = null; + this._settingEndId = null; + this._startId = null; + this._endId = null; + + // Battery directory + this._baseDirectoryPath = `${BASE_PATH}/${this.name}`; + this._baseDirectory = Gio.File.new_for_path(this._baseDirectoryPath); + + // Set paths + if (this.environment.checkMinKernelVersion(5, 9)) { // kernel 5.9 and newer + this._startFilePath = `${BASE_PATH}/${this.name}/${START_FILE_NEW}`; + this._endFilePath = `${BASE_PATH}/${this.name}/${END_FILE_NEW}`; + } else if (this.environment.checkMinKernelVersion(4, 17)) { // kernel 4.17 and newer + this._startFilePath = `${BASE_PATH}/${this.name}/${START_FILE_OLD}`; + this._endFilePath = `${BASE_PATH}/${this.name}/${END_FILE_OLD}`; + } else { // Unsupported kernel + throw Error(`Unsupported kernel version (${this.environment.kernelRelease}). A kernel version greater than or equal to 4.17 is required.`); + } + + // Activate the directory monitor + try { + this._baseMonitor = this._baseDirectory.monitor_directory(Gio.FileMonitorFlags.NONE, null); + this._monitorId = this._baseMonitor.connect( + 'changed', (obj, file, otherFile, eventType) => { + const filePath = file.get_path(); + switch (eventType) { + case Gio.FileMonitorEvent.CHANGES_DONE_HINT: + case Gio.FileMonitorEvent.CREATED: + case Gio.FileMonitorEvent.DELETED: + switch (filePath) { + case this._startFilePath: + this.startValue = readFileInt(this._startFilePath); + break; + case this._endFilePath: + this.endValue = readFileInt(this._endFilePath); + break; + case this._baseDirectoryPath: + this.startValue = readFileInt(this._startFilePath); + this.endValue = readFileInt(this._endFilePath); + break; + default: + break; + } + break; + case Gio.FileMonitorEvent.ATTRIBUTE_CHANGED: + this.authRequired = this._checkAuthRequired(); + break; + default: + break; + } + } + ); + } catch (e) { + logError(e, this.name); + } + + // Update flags on changes in threshold values + this._startId = this.connect( + 'notify::start-value', () => { + this.isActive = this._checkActive(); + this.isAvailable = this.startValue !== null || this.endValue !== null; + this.pendingChanges = this._checkPendingChanges(); + } + ); + this._endId = this.connect( + 'notify::end-value', () => { + this.isActive = this._checkActive(); + this.isAvailable = this.startValue !== null || this.endValue !== null; + this.pendingChanges = this._checkPendingChanges(); + } + ); + + // Update pending changes flag on changes to setting values + this._settingStartId = this.settings.connect( + `changed::start-${this.name.toLowerCase()}`, () => { + this.pendingChanges = this._checkPendingChanges(); + } + ); + this._settingEndId = this.settings.connect( + `changed::end-${this.name.toLowerCase()}`, () => { + this.pendingChanges = this._checkPendingChanges(); + } + ); + + // Load initial values + this.startValue = readFileInt(this._startFilePath); + this.endValue = readFileInt(this._endFilePath); + this.authRequired = this._checkAuthRequired(); + } + + /** + * Check if thresholds is active + * + * @returns {boolean} Returns true if the battery has active thresholds + */ + _checkActive() { + // RegExs + /* On some models the start threshold 0 is not allowed, instead 95 is used (Ex: E14 Gen 3) + * See issue #8: https://gitlab.com/marcosdalvarez/thinkpad-battery-threshold-extension/-/issues/8 + */ + const disableStart95 = /(Think[pP]ad) (E14 Gen 3)/; + + if (this.environment.productVersion.search(disableStart95) >= 0) { + return (this.startValue !== 95 && this.startValue !== null) || (this.endValue !== 100 && this.endValue !== null); + } else { + return (this.startValue !== 0 && this.startValue !== null) || (this.endValue !== 100 && this.endValue !== null); + } + } + + /** + * Check if there are changes to the settings that need to be applied + * + * @returns {boolean} Returns true if there are changes to the settings that need to be applied + */ + _checkPendingChanges() { + const startSetting = this.settings.get_int(`start-${this.name.toLowerCase()}`); + const endSetting = this.settings.get_int(`end-${this.name.toLowerCase()}`); + return ((this.startValue != null && this.startValue !== startSetting) || (this.endValue != null && this.endValue !== endSetting)); + } + + /** + * Check if authentication is required to apply the changes + * + * @returns {boolean} Returns true if authentication is required to apply the changes + */ + _checkAuthRequired() { + try { + const f = Gio.File.new_for_path(this._startFilePath); + const info = f.query_info('access::*', Gio.FileQueryInfoFlags.NONE, null); + if (!info.get_attribute_boolean('access::can-write')) { + return true; + } + } catch (e) { + // Ignored + } + + try { + const f = Gio.File.new_for_path(this._endFilePath); + const info = f.query_info('access::*', Gio.FileQueryInfoFlags.NONE, null); + if (!info.get_attribute_boolean('access::can-write')) { + return true; + } + } catch (e) { + // Ignored + } + return false; + } + + get authRequired() { + return this._authRequired; + } + + set authRequired(value) { + if (this.authRequired !== value) { + this._authRequired = value; + this.notify('auth-required'); + } + } + + get isActive() { + return this._isActive; + } + + set isActive(value) { + if (this.isActive !== value) { + this._isActive = value; + this.notify('is-active'); + } + } + + get isAvailable() { + return this._isAvaialble; + } + + set isAvailable(value) { + if (this.isAvailable !== value) { + this._isAvaialble = value; + this.notify('is-available'); + } + } + + get startValue() { + return this._startValue; + } + + set startValue(value) { + if (this.startValue !== value) { + this._startValue = value; + this.notify('start-value'); + } + } + + get endValue() { + return this._endValue; + } + + set endValue(value) { + if (this.endValue !== value) { + this._endValue = value; + this.notify('end-value'); + } + } + + get pendingChanges() { + return this._pendingChanges; + } + + set pendingChanges(value) { + if (this.pendingChanges !== value) { + this._pendingChanges = value; + this.notify('pending-changes'); + } + } + + /** + * Returns the command to set the thresholds. + * This function does not run the command, it just returns the string corresponding to the command. + * Passed values are not validated by the function, it is your responsibility to validate them first. + * + * @param {number} start Start value + * @param {number} end End value + * @returns {string|null} Command to modify the thresholds + */ + _getSetterCommand(start, end) { + if (!this.isAvailable) { + return null; + } + + if (!Number.isInteger(start) || !Number.isInteger(end)) { + throw TypeError(`Thresholds (${start}/${end}) on battery (${this.name}) are not integer`); + } + + if (start < 0 || end > 100 || start >= end) { + throw RangeError(`Thresholds (${start}/${end}) on battery (${this.name}) out of range`); + } + + // Commands + const setStart = `echo ${start.toString()} > ${this._startFilePath}`; + const setEnd = `echo ${end.toString()} > ${this._endFilePath}`; + + let oldStart = this.startValue; + let oldEnd = this.endValue; + + if ((oldStart === start || oldStart === null) && (oldEnd === end || oldEnd === null)) { + // Same thresholds + return null; + } + + if (oldStart >= oldEnd) { + // Invalid threshold reading, happens on ThinkPad E/L series + oldStart = null; + oldEnd = null; + } + + let command = null; + + if (fileExists(this._startFilePath) && fileExists(this._endFilePath)) { + if (oldStart === start) { // Same start, apply only stop + command = setEnd; + } else if (oldEnd === end) { // Same stop, apply only start + command = setStart; + } else { + // Determine sequence + let startStopSequence = true; + if (oldEnd != null && start > oldEnd) { + startStopSequence = false; + } + if (startStopSequence) { + command = setStart + ' && ' + setEnd; + } else { + command = setEnd + ' && ' + setStart; + } + } + } else if (fileExists(this._startFilePath)) { // Only start available + command = setStart; + } else if (fileExists(this._endFilePath)) { // Only stop available + command = setEnd; + } + + return command; + } + + /** + * Get the command string to enable the configured thresholds + * + * @returns {string|null} Enable thresholds command string + */ + get enableCommand() { + const startSetting = this.settings.get_int(`start-${this.name.toLowerCase()}`); + const endSetting = this.settings.get_int(`end-${this.name.toLowerCase()}`); + return this._getSetterCommand(startSetting, endSetting); + } + + /** + * Get the command string to disable the thresholds + * + * @returns {string|null} Enable thresholds command string + */ + get disableCommand() { + return this._getSetterCommand(0, 100); + } + + /** + * Enable the configured thresholds + */ + enable() { + const command = this.enableCommand; + if (!command) { + return; + } + const runnable = new Runnable(command, this.authRequired); + runnable.connect('command-completed', (obj, error) => { + this.emit('enable-completed', error); + }) + runnable.run(); + } + + /** + * Disable thresholds + */ + disable() { + const command = this.disableCommand; + if (!command) { + return; + } + const runnable = new Runnable(command, this.authRequired); + runnable.connect('command-completed', (obj, error) => { + this.emit('disable-completed', error); + }) + runnable.run(); + } + + /** + * Toggle thresholds status + */ + toggle() { + this.isActive ? this.disable() : this.enable(); + } + + destroy() { + if (this._startId) { + this.disconnect(this._startId); + } + if (this._endId) { + this.disconnect(this._endId); + } + if (this._settingStartId) { + this.settings.disconnect(this._settingStartId); + } + if (this._settingEndId) { + this.settings.disconnect(this._settingEndId); + } + if (this._monitorId) { + this._baseMonitor.disconnect(this._monitorId); + } + this._baseMonitor.cancel(); + this._baseMonitor = null; + this._baseDirectory = null; + } +}); + +export const ThinkPad = GObject.registerClass({ + GTypeName: 'ThinkPad', + Properties: { + 'environment': GObject.ParamSpec.object( + 'environment', + 'Environment', + 'Environment', + GObject.ParamFlags.READABLE, + Environment.$gtype + ), + 'is-active': GObject.ParamSpec.boolean( + 'is-active', + 'Is active', + 'Indicates if the thresholds are active or not', + GObject.ParamFlags.READABLE, + false + ), + 'is-available': GObject.ParamSpec.boolean( + 'is-available', + 'Is available', + 'Indicates if the battery are available or not', + GObject.ParamFlags.READABLE, + false + ), + 'batteries': GObject.ParamSpec.jsobject( + 'batteries', + 'Batteries', + 'Batteries object', + GObject.ParamFlags.READWRITE, + [] + ), + 'settings': GObject.ParamSpec.object( + 'settings', + 'Settings', + 'Settings', + GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY, + Gio.Settings.$gtype + ), + }, + Signals: { + 'enable-battery-completed': { + param_types: [GObject.TYPE_OBJECT /* battery */, GObject.TYPE_JSOBJECT /* error */] + }, + 'disable-battery-completed': { + param_types: [GObject.TYPE_OBJECT /* battery */, GObject.TYPE_JSOBJECT /* error */] + }, + 'enable-all-completed': { + param_types: [GObject.TYPE_JSOBJECT /* error */] + }, + 'disable-all-completed': { + param_types: [GObject.TYPE_JSOBJECT /* error */] + }, + }, +}, class ThinkPad extends GObject.Object { + constructor(constructProperties = {}) { + super(constructProperties); + + if (!this.environment.checkMinKernelVersion(4, 17)) { + logError(new Error(`Kernel ${this.environment.kernelRelease} not supported`)); + this.batteries = []; + return; + } + + // Signals handlers IDs + this._batteriesId = {}; + + // Define batteries + this.batteries = [ + new ThinkPadBattery({ + 'environment': this.environment, + 'name': 'BAT0', + 'settings': this.settings + }), + new ThinkPadBattery({ + 'environment': this.environment, + 'name': 'BAT1', + 'settings': this.settings + }), + ]; + + // Connect the signals from the batteries to update the flags and notify commands + this.batteries.forEach(battery => { + const isAvailableId = battery.connect( + 'notify::is-available', (bat) => { + this.isAvailable = this._checkAvailable(); + } + ); + const isActiveId = battery.connect( + 'notify::is-active', (bat) => { + this.isActive = this._checkActive(); + } + ); + const enableCompletedId = battery.connect( + 'enable-completed', (bat, error) => { + this.emit('enable-battery-completed', bat, error); + } + ); + const disableCompletedId = battery.connect( + 'disable-completed', (bat, error) => { + this.emit('disable-battery-completed', bat, error); + } + ); + this._batteriesId[battery.name] = [isAvailableId, isActiveId, enableCompletedId, disableCompletedId]; + }); + + // Load initial values + this.isAvailable = this._checkAvailable(); + this.isActive = this._checkActive(); + } + + get environment() { + if (this._environment === undefined) { + this._environment = new Environment(); + } + return this._environment; + } + + get isAvailable() { + return this._isAvaialble; + } + + set isAvailable(value) { + if (this.isAvailable !== value) { + this._isAvaialble = value; + this.notify('is-available'); + } + } + + get isActive() { + return this._isActive; + } + + set isActive(value) { + if (this.isActive !== value) { + this._isActive = value; + this.notify('is-active'); + } + } + + /** + * Check if at least one battery has the thresholds active + * + * @returns {boolean} Returns true if at least one battery has the thresholds active + */ + _checkActive() { + return this.batteries.some(bat => { + return bat.isActive && bat.isAvailable; + }); + } + + /** + * Check if at least one battery is available to apply the thresholds + * + * @returns {boolean} Returns true if at least one battery is available to apply the thresholds + */ + _checkAvailable() { + return this.batteries.some(bat => { + return bat.isAvailable; + }); + } + + /** + * Enable all configured thresholds + */ + enableAll() { + let command = ''; + let authRequired = false; + this.batteries.forEach(battery => { + const batteryCommand = battery.enableCommand; + if (batteryCommand) { + command = `${command}${command ? ' && ' : ''}${batteryCommand}`; + authRequired = authRequired || battery.authRequired; + } + }); + if (!command) { + return; + } + const runnable = new Runnable(command, authRequired); + runnable.connect('command-completed', (obj, error) => { + this.emit('enable-all-completed', error); + }) + runnable.run(); + } + + /** + * Disable all thresholds + */ + disableAll() { + let command = ''; + let authRequired = false; + this.batteries.forEach(battery => { + const batteryCommand = battery.disableCommand; + if (batteryCommand) { + command = `${command}${command ? ' && ' : ''}${batteryCommand}`; + authRequired = authRequired || battery.authRequired; + } + }); + if (!command) { + return; + } + const runnable = new Runnable(command, authRequired); + runnable.connect('command-completed', (obj, error) => { + this.emit('disable-all-completed', error); + }) + runnable.run(); + } + + destroy() { + if (this._batteriesId) { + this.batteries.forEach(battery => { + const ids = this._batteriesId[battery.name]; + ids.forEach(id => { + battery.disconnect(id); + }); + battery.destroy() + }); + } + } +}); \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/libs/indicator.js b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/libs/indicator.js new file mode 100644 index 0000000..4e27e13 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/libs/indicator.js @@ -0,0 +1,431 @@ +'use strict'; + +import Clutter from 'gi://Clutter'; +import St from 'gi://St'; +import GObject from 'gi://GObject'; +import GLib from 'gi://GLib'; +import Gio from 'gi://Gio'; + +import {gettext as _, ngettext} from 'resource:///org/gnome/shell/extensions/extension.js'; +import * as Main from 'resource:///org/gnome/shell/ui/main.js'; +import * as MessageTray from 'resource:///org/gnome/shell/ui/messageTray.js'; +import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; +import * as QuickSettings from 'resource:///org/gnome/shell/ui/quickSettings.js'; +import * as Config from 'resource://org/gnome/shell/misc/config.js'; + +import { ThinkPad } from './driver.js'; + +const ICONS_PATH = GLib.Uri.resolve_relative(import.meta.url, '../icons', GLib.UriFlags.NONE); +const SHELL_VERSION = Number(Config.PACKAGE_VERSION.split('.', 1)); + +/** + * Get icon + * + * @param {string} iconName Icon name + * @param {boolean} colorMode Color mode or symbolic + * @returns {Gio.Icon} + */ +function getIcon(iconName, colorMode = false) { + return Gio.icon_new_for_string(`${ICONS_PATH}/${iconName}${colorMode ? '' : '-symbolic'}.svg`); +} + +const BatteryItem = GObject.registerClass({ + GTypeName: 'BatteryItem', +}, class BatteryItem extends PopupMenu.PopupImageMenuItem { + constructor(battery, settings) { + super('', null); + + this._settings = settings; + this._battery = battery; + + // Flag to prevent the PopupImageMenuItem from being activated when the reload icon is clicked + this._reloading = false; + + const box = new St.BoxLayout({ + 'opacity': 128, + 'x_expand': true, + 'x_align': Clutter.ActorAlign.END, + 'style': 'spacing: 5px;', + }); + + this.add_child(box); + + // Reload icon + this._reload = new St.Icon({ + 'icon-size': 16, + 'reactive': true, + 'icon-name': 'view-refresh-symbolic', + }); + this._reload.connectObject( + 'button-press-event', () => { + this._reloading = true; + this._battery.enable(); + return true; // Does not prevent event propagation??? + }, + this + ); + box.add_child(this._reload); + + this._valuesLabel = new St.Label({ + 'y_align': Clutter.ActorAlign.CENTER, + 'style': 'font-size: 0.75em;', + }); + box.add_child(this._valuesLabel); + + // Battery signals + this._battery.connectObject( + 'notify', () => { + this._update(); + }, + this + ); + + // Settings changes + this._settings.connectObject( + 'changed', () => { + this._update(); + }, + this + ); + + // Menu item action + this.connectObject( + 'activate', () => { + if (!this._reloading) { + this._battery.toggle(); + } + this._reloading = false; + }, + 'destroy', () => { + this._settings.disconnectObject(this); + this._battery.disconnectObject(this); + this._reload.disconnectObject(this); + this.disconnectObject(this); + this._valuesLabel.destroy(); + this._valuesLabel = null; + this._reload.destroy(); + this._reload = null; + this._battery = null; + this._settings = null; + }, + this + ); + + this._update(); + } + + /** + * Update UI + */ + _update() { + const colorMode = this._settings.get_boolean('color-mode'); + // Menu text and icon + if (this._battery.isActive) { + // TRANSLATORS: %s is the name of the battery. + this.label.text = _('Disable thresholds (%s)').format(this._battery.name); + this.setIcon(getIcon('threshold-active', colorMode)); + // Status text + const showCurrentValues = this._settings.get_boolean('show-current-values'); + if (showCurrentValues) { + // TRANSLATORS: %d/%d are the [start/end] threshold values. The string %% is the percent symbol (may need to be escaped depending on the language) + this._valuesLabel.text = _('%d/%d %%').format(this._battery.startValue || 0, this._battery.endValue || 100); + this._valuesLabel.visible = true; + } else { + this._valuesLabel.visible = false; + } + } else { + // TRANSLATORS: %s is the name of the battery. + this.label.text = _('Enable thresholds (%s)').format(this._battery.name); + this.setIcon(getIcon('threshold-inactive', colorMode )); + this._valuesLabel.visible = false; + } + // Reload 'button' + this._reload.visible = this._battery.pendingChanges && this._battery.isActive; + // Menu item visibility + this.visible = this._battery.isAvailable; + } +}); + +const ThresholdToggle = GObject.registerClass({ + GTypeName: 'ThresholdToggle', +}, class ThresholdToggle extends QuickSettings.QuickMenuToggle { + constructor(driver, extensionObject) { + super({ + 'title': _('Thresholds'), + 'gicon': getIcon('threshold-app'), + 'toggle-mode': false, + //'subtitle': 'subtitle' + }); + + // Header + this.menu.setHeader( + getIcon('threshold-app'), // Icon + _('Battery Threshold'), // Title + driver.environment.productVersion ? driver.environment.productVersion : _('Unknown model')// Subtitle + ); + + // Unavailable + this.unavailableMenuItem = new PopupMenu.PopupImageMenuItem(_('Thresholds not available'), getIcon('threshold-unknown')); + this.unavailableMenuItem.sensitive = false; + this.unavailableMenuItem.visible = false; + this.menu.addMenuItem(this.unavailableMenuItem); + + // Batteries + driver.batteries.forEach(battery => { + // Battery menu item + const item = new BatteryItem(battery, extensionObject.getSettings()); + this.menu.addMenuItem(item); + }); + + // Unavailable status + this.unavailableMenuItem.visible = !driver.isAvailable; + + // Checked status + this.checked = driver.isActive; + + // Driver signals + driver.connectObject( + 'notify::is-active', () => { + this.checked = driver.isActive; + }, + 'notify::is-available', () => { + this.unavailableMenuItem.visible = !driver.isAvailable; + }, + this + ); + + // Signals + this.connectObject( + 'clicked', () => { + if (driver.isActive) { + driver.disableAll(); + } else { + driver.enableAll(); + } + }, + 'destroy', () => { + this.disconnectObject(this); + driver.disconnectObject(this); + this.menu.removeAll(); + }, + this + ); + + // Add an entry-point for more getSettings() + this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); + const settingsItem = this.menu.addAction(_('Thresholds settings'), + () => extensionObject.openPreferences()); + + // Ensure the getSettings() are unavailable when the screen is locked + settingsItem.visible = Main.sessionMode.allowSettings; + this.menu._settingsActions[extensionObject.uuid] = settingsItem; + } +}); + +export const ThresholdIndicator = GObject.registerClass({ + GTypeName: 'ThresholdIndicator', +}, class ThresholdIndicator extends QuickSettings.SystemIndicator { + constructor(extensionObject) { + super(); + + this._settings = extensionObject.getSettings(); + this._driver = new ThinkPad({'settings': this._settings}) + this._name = extensionObject.metadata.name; + + this._indicator = this._addIndicator(); + this._indicator.gicon = getIcon('threshold-unknown'); + + this.quickSettingsItems.push(new ThresholdToggle(this._driver, extensionObject)); + + Main.panel.statusArea.quickSettings.addExternalIndicator(this); + + this._updateIndicator(); + + // Driver signals + this._driver.connectObject( + 'notify::is-available', () => { + this._updateIndicator(); + }, + 'notify::is-active', () => { + this._updateIndicator(); + }, + 'enable-battery-completed', (driver, battery, error) => { + if (!error) { + this._notifyEnabled( + // TRANSLATORS: %s is the name of the battery. %d/%d are the [start/end] threshold values. The string %% is the percent symbol (may need to be escaped depending on the language) + _('Battery (%s) charge thresholds enabled at %d/%d %%').format( + battery.name, battery.startValue || 0, battery.endValue || 100 + ) + ); + } else { + this._notifyError( + // TRANSLATORS: The first %s is the name of the battery. The second %s is the error message. \n is new line. + _('Failed to enable thresholds on battery %s. \nError: %s').format( + battery.name, error.message + ) + ); + } + }, + 'disable-battery-completed', (driver, battery, error) => { + if (!error) { + this._notifyDisabled( + // TRANSLATORS: %s is the name of the battery. + _('Battery (%s) charge thresholds disabled').format( + battery.name + ) + ); + } else { + this._notifyError( + // TRANSLATORS: The first %s is the name of the battery. The second %s is the error message. \n is new line. + _('Failed to disable thresholds on battery %s. \nError: %s').format( + battery.name, error.message + ) + ); + } + }, + 'enable-all-completed', (driver, error) => { + if (!error) { + this._notifyEnabled(_('Thresholds enabled for all batteries')) + } else { + this._notifyError( + // TRANSLATORS: %s is the error message. \n is new line. + _('Failed to enable thresholds for all batteries. \nError: %s').format( + error.message + ) + ); + } + }, + 'disable-all-completed', (driver, error) => { + if (!error) { + this._notifyDisabled(_('Thresholds disabled for all batteries')); + } else { + this._notifyError( + // TRANSLATORS: %s is the error message. \n is new line. + _('Failed to disable thresholds for all batteries. \nError: %s').format( + error.message + ) + ); + } + }, + this + ); + + // Settings signals + this._settings.connectObject( + 'changed::color-mode', () => { + this._updateIndicator(); + }, + 'changed::indicator-mode', () => { + this._updateIndicator(); + }, + this + ); + + this.connect('destroy', () => { + this.quickSettingsItems.forEach(item => item.destroy()); + this._settings.disconnectObject(this); + this._settings = null; + this._driver.disconnectObject(this); + this._driver.destroy(); + this._driver = null; + this._extension = null; + }); + } + + /** + * Update indicator (tray-icon) + */ + _updateIndicator() { + const colorMode = this._settings.get_boolean('color-mode'); + if (this._driver.isAvailable) { + if (this._driver.isActive) { + this._indicator.gicon = getIcon('threshold-active', colorMode); + } else { + this._indicator.gicon = getIcon('threshold-inactive', colorMode); + } + } else { + this._indicator.gicon = getIcon('threshold-unknown', colorMode); + } + + const indicatorMode = this._settings.get_enum('indicator-mode'); + switch (indicatorMode) { + case 0: // Active + this._indicator.visible = this._driver.isActive; + break; + case 1: // Inactive + this._indicator.visible = !this._driver.isActive; + break; + case 2: // Always + this._indicator.visible = true; + break; + case 3: // Never + this._indicator.visible = false; + break; + default: + this._indicator.visible = true; + break; + } + } + + /** + * Show notificaion. + * + * @param {string} msg Title + * @param {string} details Message + * @param {string} iconName Icon name + */ + _notify(msg, details, iconName) { + if (!this._settings.get_boolean('show-notifications')) return; + const colorMode = this._settings.get_boolean('color-mode'); + if (SHELL_VERSION === 45) { + const source = new MessageTray.Source(this._name); + Main.messageTray.add(source); + const notification = new MessageTray.Notification( + source, + msg, + details, + {gicon: getIcon(iconName, colorMode)} + ); + notification.setTransient(true); + source.showNotification(notification); + } else { + const source = new MessageTray.Source({'title': this._name}); + Main.messageTray.add(source); + const notification = new MessageTray.Notification({ + source: source, + title: msg, + body: details, + isTransient: true, + gicon: getIcon(iconName, colorMode) + }); + source.addNotification(notification); + } + } + + /** + * Show error notification + * + * @param {string} message Message + */ + _notifyError(message) { + this._notify(_('Battery Threshold'), message, 'threshold-error'); + } + + /** + * Show enabled notification + * + * @param {string} message Message + */ + _notifyEnabled(message) { + this._notify(_('Battery Threshold'), message, 'threshold-active'); + } + + /** + * Show disabled notification + * + * @param {string} message Message + */ + _notifyDisabled(message) { + this._notify(_('Battery Threshold'), message, 'threshold-inactive'); + } +}); \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/locale/cs/LC_MESSAGES/thinkpad-battery-threshold@marcosdalvarez.org.mo b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/locale/cs/LC_MESSAGES/thinkpad-battery-threshold@marcosdalvarez.org.mo new file mode 100644 index 0000000000000000000000000000000000000000..0592953c0dd20b0fb3f73385205cc992498710f6 GIT binary patch literal 4711 zcmb`KUu+yl9mfY6{`6X)l>Y_VDaFBVyFS}#(r}4u94B!s>e$4W6h)EH-0t{xeS0&@ z?CiRCkw8L7Ak;{G;US8IdXE({{lg0s8Wo*S@P-gbc|Zz6qEAS?L_&9%Agn;A`Lqz&F58gKvQ! z1aB4Nx52OA{cqqLct0k899#e^;5R^;e+B#`=z^aBpD*|V_!+#v1d{w;fHm;<;4!d* z#a{&%!K2_+@I&Bh1%C-*D*Fvca(`RA{~5d&?|%jF1OE=*5B{t8eh5My!FvUyeIEx& z??v!S;0E{rm=@zd06&ZO>mb?rI`|OyHux||&iW|u2>2j44br}g;4HWb&Vb(qzYe|% zrr>|TZ-FtCC4c=9oB(fwUj`3hkoKJd$-YzIN5D%U?dO3|fyLl0#PBKzk!%CT;*nhe z$-X8?e)t8^ccL$`n--|!X;6va!umP@s zKLxLX{{$&+--dFe_a8u#cMBvv{tc2{4?{UTvZEkGvt@TwCYpO|2a4V_rF=-MC^R&rN|+DMNFu2wNy47WuGh@!B= zP6=zJ>F~*kc#6BeFipv=Z)EK2(2Kbj#G(;O@7?A}l}+Qq@}Ux?=z1xRol2VA$VeN@ zmV|O;$d+iwKs9-6g|R#pVIs!|bySXxn*a@ETe8!+a^w1v8SG4^%%0)1B7h~_>e8z5 z8JpU05r({x`6H0=G_Ra7Mw=R+h}nTlwJKJ1F!e6Wa{s)S4fn3R`+mz(Nh3n`Y~V^2 zOHj39wkm>=hLfij>oZgAyiBEGYl;iX5lK&hDxTMk-jc56abP98AY*CsznOpJ^A@55 z=nxsXDUC!Jz2m~RJ^%#v&l1Gu@-LFHuuhH==R95nJVNA_N8zimm=VO5UnoNv6(wg<{DwZK;8W7!WpzNZU}&nkP|fs>E`T%_nU)DOp3m;PcG zRZHn@#oO9L1H2eZ%1HF!P2oy*Ng66HR@9)g;yJ}o4W^@ z)>)04f#;y(#!g+=cx8RfxggVkq&uf^DAf4e%-j)YcFvhO#^>g0GfzJ;gRAnah^+``&q8$o;QY77$ZhbA5T_xJnZuc3iQO!g&rBj!pUE@n#iRmYO zYooYUt@=8)(wp9v4M>#J+BB;WDl&dK>Yy5a4u$A>NLGyIZYSWHu zTt(SyJb&Z_&mZR})%^VI6kp&oyv8ThGxKx&@L{e_&Ob$ivlyH^QTe8mcj3%;&*e7r zqtizmPo|a83B88?shdW$6Sl5X9R?OjZe*(ZFY}GxEtL(bWfEt{~lhSDj5SCFT2&}&J93{xobB2q?o2fhBz;5x-^G&Ogw7@N5; z{5V=Y9P%`N)g`;vAmnB4XURf}2!HU(a890~r83#u0y}LIzu$X@y*S5LF%(PQ)eR%M z8oyz)q!B#jkx(*B@&lY*&c35`M9Y;tiF8*RwR?jM8T(|DelH}a{*PY6DRhRnkkvTE zhhzH-D@0F#a~~ZjK+&?xSseZ! zg4!?}KXhas{S@2kX!nNIDXOf@84Qxwb=s#g%x&RHHZwnM{!y7NIF}VrrT%`L4vjCXsF#^c0FQPX9f7k5a8zIm{F#_Stfn zd;7~@&w6C`w`eI@wd`pnIDV-q7WI7K93{76c-X@kmqb+1=SQVQ&PM*9$3fZewfk=t RNB#xfr366uakO_O`!C|dc&Y#Z literal 0 HcmV?d00001 diff --git a/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/locale/de/LC_MESSAGES/thinkpad-battery-threshold@marcosdalvarez.org.mo b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/locale/de/LC_MESSAGES/thinkpad-battery-threshold@marcosdalvarez.org.mo new file mode 100644 index 0000000000000000000000000000000000000000..532a68e3d7c6e7966fcffeaaca45f3ca5b7359cb GIT binary patch literal 5001 zcmbuCO^h5z6@Uv^LYRcV@E87)3b3&^aqpj<#Edb^ti8K7?Ape=j=@4gHPf{-&GuA} z`e)bc91s$SOD;s>fP@4{h;zarBFG0|k#a#o!u$v!S+WGDa03Ymp@{EQPtVMHe=M1n zdcN-Js#ov5dhb=u?MKGGr?{Tu{y6s^-lEib_~P66;d*&YsR!XJ@a^yy@I&yI@B#Se ze*0~Bg!jL}S@;3n?!gun12R;PffDgle_rH%JQ09FKirx+QNw^B% z3pe}i-+_CcpH8ij?pOdPC&759=;1c4`sd(qJqlc4r}-VM5LO-Sn1Ca8ZxrdDtE`Otexy&i?fXnztu0axM2U;&T7??Q>^*Wf4M zpPm!zx2 zi}+G<`GeeYiI3z8xHY%CBypJOFv?6bw&A_{S?9ZHlk0&JmFTrfoSHA%I<>td&D9y>S~gZ^WX8y~b(Whn z*PA9T>}X@stJ+3QKttQL>TIdpsJ>!`TJXy3XQL^hk$ zwS_cI(z+hc)S*KY*B`Y_*8_%?{<)tC_l`Vxz9s8yYGSno&D4V>a@A zq;;;}Jkr!}No_0XcC8C#IjZO=7rK%)Xx`f}r&by7LPOY=%SHHN*31MSa=q2D4yjh3 zr<2Z8v#kl{A`Z3b^{h!TR4=)tOPupft#*@*Q2Hln*?S)WKBf`o1Kekr#QQ+Yn3afilp$`+}tMf`~qVf^NWLqKGsD4dYW{7GYeCwH4!WQ@gdc~=DZ!Xot#YI?7SQV9tV>(Rqc2ejqBaTg|PYzjyo!f6((R7fN zqdJ!p?=$V8@+&Qvs(P&IL8$jsfze)7jXSgx0iew$l}75}=;+E{>WbTN$(GaIB%}ad z$*e>qHF({$ta{$2l3c2vgTeVQ=r`3dopkP*Fz5$;Fj&7}xGXcZ%f7${D_J`V11fG7 ztR;0_yL2(QY&Rp39-L)UsO#D3+2g^?bTD&VPoJpIoOpVgtF~;iJXlMO%VG)Zx?aeE z)s5W5#_7)*Pv7?Wc9OJX+r`>Rmi}{$b?w5mZLnrdx2~6L+La-lJnv=osi{tqpHZxmGdhLL+8v)PS?&5Mx<)6w%xubq;-9=8RfN0aX}Rg7L&A_)wS#S*X;D{DP2CE zcKV6adgfH^%RyOjy`Qd@X6a`pXM)gf)`q+B&JUUt+eMQ$BX-x-?QS!P$;=HZZzL5| zou?S4s^PYzBs$gD*eLvl94wpAX06VajbqE#l)XH()j&4*!#WPSQ3j&nt}J8r%2kWD z6WbI$qgDsO%_iAQAthP~O+s{!Ch8)c_x(T_>KeVibCa5~+h(%t>a7}ky$=+DDW@79&O~Al{3M$ zBHg*!+908j$#D{=FQi-YDJ|F$n2tP;W1d;J8~b!VxWk-UIQXMl==RnV;?$8vyCZ4$ zEcg9!PF)i_hOXgEu@p5a=}tB)r$dvK=L!xHA<^#-5gb`lPy1aP)N?PU1|@v&FPJJ_VyTy^uwY=Y^#I-4+`sli>eya=P~4 z?-n9cRo|}q5;A!8XA+J~Gkd{X6Gg)V?QzYjl;avqwXowLWf1#>gYz11-igX5*-|IV(PqCZ%+nW9d-4JbvrjX z0;L<7>5Ak`%7Q=3NYJvJhsUfb)AHTL>7x?ltqw=4ogc=O8n4Xmu$!3F zD?6`Jg-~@BVH_Lsb;F^<&F!a>%r{^C`Pd!Y_f+SQnRe@RcLDZAdZcQOZZ5k=?kTXo xF0g&E`n$C)D=&X95Z-PY4#vB_kES=fOVe(US2-uv6*&*Z>a0nt>M=MC{ST!x!KDBI literal 0 HcmV?d00001 diff --git a/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/locale/es/LC_MESSAGES/thinkpad-battery-threshold@marcosdalvarez.org.mo b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/locale/es/LC_MESSAGES/thinkpad-battery-threshold@marcosdalvarez.org.mo new file mode 100644 index 0000000000000000000000000000000000000000..8a8c6634ac16cdec7699ac9dbe19e451dddb803b GIT binary patch literal 4921 zcmbuBU1%j&9l(zoKYFcN>qq^l_H;FN)Ar^jS^Kefn`W~~b_w0sb(5?`1UYx+OtIz5+iAe+l0O z|4{bdfcMdU3(mmX8T>&w2OIE_x0dJ%ICVVga3%nivv;2JwA@|U3Kw0;GD0hB$RdM;WS)0v10!d@Z)eD%DA-T4*Wdr z=in^-85H~f4n_Yl77;mjL0MmyJPpO}%VoOk{5lMwC?|SaI0X~f zgg<~9{szkWe}(+1+X$k>@oxUfyeUZ7{3HI6$LCY=>F0SMhHGh>r3+z$^Pxd@avsctvk{WdBU_ zN}fp!W_VBWj`7~dTRpPx@8y*`Gg)@N9g3en#Y@Why)FKKn3vQUKKJt_`Ju+c)_ADL z$JKl%9pq|0$fIqOTOFivn%PiCL7F%YT}Qo9*h8<8DF+nq< z%X!PCZEMNSk1})VswQvlW};2sd|j*?B&|7{~hJpplO?*}svcJ>N}W25L>j%6NQ8HLy7?B#y#Q zmk4sQpAZ&h3>!tYFj}9Ck{}+0#e!8)nRrl#soqToddG-kQ|eQKtbv_7Y+2ECxGU>A z7YiS@|Rjqo=(!8MEBB=0=Vw1 zWF$3s!vt1cv6*ZxRqny&a@Z`p+L+FE?whb#CVg`lzveJ3jmy5gHdkCX3Y*kh*IY~6 zx^d~r=4HDbiR|VgM?zcAOwF8XPEYa2XM1M)fhnHGMdR}3T4oX#OH#M>i4~Itsnd&- zdOqGZnZ0^KKi2bop(#4fc6-=6N$?+Me$pM7u5GSa(`)P1zDXjtsUO?S^S*1hTAQiM zZ8*7OJIJ?_Y1VD^i*n;yN88t8fuviRftsm_~dE-(%ppZ7tr&-Unb<+1uH#>7i z7oW3B{$05bOIJ!~ris4!zzeGtCL>#N7o}(Z7CNrVe+Z&+PY|pp$UOHg?qIE@i z%JiTz+@I$2{uXm{uRoh9Nh~_FKhrTD9nO};sV<>$c#Zm6x^4dveG77MP~Gb{o$*5f zl~4aKEshX!ybAk{{U9=2fMSY?lS^BXDgBH>9QARR9F%hY50bzXxtJ1T@A;Grq~7Dv zn8Q8YoasFCR$sFAxWOjY-zEBz;Sq>FR zz@p-Fd+-T=)SR1Csf(K%ImX#wAUBDK-Bes5mWKA~V6gW>!ci4ke~?oA@PfuWMf%Fl z@rl7bX3M9wzgDOfYFx%Wqq+;QHIiZ%o1pj}4iT*?tJpom)FmDR+4{qQ#frn`e$m73 zQj}WYc9UF11ydA`3{#9)g6;{|J#2~-3{kA=P`U`$K z_rIvv)3xarF)J{=P6VCYL3}~OnS`#`zk!q) zBRPdsnQOKNXza@)VJMG48Ev#1jQr}aC1tjh7m}zFQ8}C|$?LD8fW=|OUBqN_N2;(- zadh5SU07XyucBIC{m@0$%VJlr+{20{dLC8AMiZ){aciTiDouXM#iySp5&N66o+cYn omt(JRc`Y5uFKU91kd*BJ_fa$amE|g7(*rkP2c^a3g#f7k0EY^W)&Kwi literal 0 HcmV?d00001 diff --git a/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/locale/fr/LC_MESSAGES/thinkpad-battery-threshold@marcosdalvarez.org.mo b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/locale/fr/LC_MESSAGES/thinkpad-battery-threshold@marcosdalvarez.org.mo new file mode 100644 index 0000000000000000000000000000000000000000..4e7e86999a7b17af0ed474254676f9d29690326c GIT binary patch literal 4783 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 literal 0 HcmV?d00001 diff --git a/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/locale/ja/LC_MESSAGES/thinkpad-battery-threshold@marcosdalvarez.org.mo b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/locale/ja/LC_MESSAGES/thinkpad-battery-threshold@marcosdalvarez.org.mo new file mode 100644 index 0000000000000000000000000000000000000000..fd934647b6579801a9e882db2495882be1ce2fa5 GIT binary patch literal 5301 zcmb`JTWlOx8OIM`Zrf5I+^;II&ab;?N6D>ZDXiAn^bXAn|~RRF2nnghU>A-~k@^e`jXA z7dvjKI@0WK&Y5$*`*&uqtg1T1aD5B+mvR63eT+4OLm$8ouBj@`+CHO_K0DcvuVBG@T3a$ccLDJg@)`Klz9rzRQyWkYq z4gME=6m(%M#p_RCHFyR523Unj(pv+Pf1AONfe(YE&j4WpbHN$p@Cgti*?Krj`x?R9 z!CfF+XMV&1km9-@Yyy7|k{`D~I3Ae>ejH4JB4-lDzmEAs5ifw`$KSx6;6@ln zchKnql6YO z%HbDiRBa@y4PIT%8r$rg#~Ra~*{yqmr|pdG2!oqx+j3cBrbq7uve`^8+pK$@aC-Ub zYPW``J9Vc+aIe!5Zl|3wTyB`I-j)%@JFOFzTE=ycFB%bxZjHsU&AATlh^*~+tVy@h zBEy>Bc?XnfO+E%oy7fY|REsW2*QMh#H_4VB^EaB)G_Mn*- zmMcK(ahJ8|X3@gcn;To}YS{Ngw{X})7T2jp1U;En^t{cncZ;;gUDFe6yKsdU{;K$h zJsw1xup#S+cHs!5(JgsjGP^07E}4pE9FexWx`bs=I^yaG6CKN1oL)MyiS59C%g|A_ zVY*PhaI3xsFFfAUDJ)18ycvtQ=jgp0#hl9+T+e2O?!Zxgzh!r!&hd`z=(KxO6wn&n zvOTliOzR#Tbi-HaoC7DlqMdGRsM={-2CcW9aP=|*R82#eDsa_dRPT#cW{`;tH(lN) zGO)z!#ADb7J3LhX3LEq`yPKMIaYHMd#(JwmxV*=tVix3c#zdIgdeM0*!Eg@xDL};- zb5wu3V|S@(BqqmNNi3~L3~?F=4v7BOv3Qql-~im|3aUt)!R>llu!n_1&BdY~)S3+~no7ZS zv~yNBw5aH{#r$c-wA3fIs{>YRaXU;y!-?x^t#*nhwmqb67u_aF*Y3kdA;lZ&8rEp_ z4O-n=Uf+uIfyZn+sM>lAnGUj0!+H-D7l_Y|M+%{sPcTV3$97HR(u z_E{Y{y+dfNLhnlP2lT9Np>Fs+ot~F-?^k0#|E7CtO zcWj`r??Pedu*@Hk{vaz%PtP6k+1321`DZ7X4ED<)kikzE$rQU_2?Ti z|D4PZLqVYrYR=6+c^sl-ejK8f-?`kjp~cTP$JWrCJq=-L#y9~)Y<92h5pkhkyEPJQ4%Qj3mBt}@pKMP$LS3Q<(arP(@+0buFVXv zh2sYED#-Z@Y(Ri?DSyaDC!4?)5MbF3IUE1UEHwn`d*nwEtPGEkFj_| zVQgUT=&Lx6WnaGH(La!pbSosXPEH^!ta30tI(EOG z#Q3miA2z>pG3STou3K6~1?a#^yZ1v&A6gP;o>GV75bol;MxUCfn8L^|HLIe$DieES zHm$6<*bHTTxkNLpEiOeV$6pfi;{V$jpNP@UQmN-=FTIIRw~9^ivr*ob`Lkh1;4~VQ v!P7FBoShz?`}s2%pHxNty82beBbtdmgUAogGSo92qWDvQ{}Iz+1F`=BWf*yo literal 0 HcmV?d00001 diff --git a/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/locale/nb_NO/LC_MESSAGES/thinkpad-battery-threshold@marcosdalvarez.org.mo b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/locale/nb_NO/LC_MESSAGES/thinkpad-battery-threshold@marcosdalvarez.org.mo new file mode 100644 index 0000000000000000000000000000000000000000..f852e262a677d97433de92e02be9117f455ce3c6 GIT binary patch literal 2282 zcma)+%WqsY6vhpN*YIqC0_7niHKGx^nVE>9Xwp<9ZBio0L(Q~+SRl{%WX8FU@0IPD zF#iH<=z3zHLx;K z#xn;_;(Hl90a}pfyA1OBS3sWcbMQN8{RU*6A3_}e{{&>6*YM(gUxK{e_uz5xXOMOM z4n6`NfjItt7UX%(fIQE6kafNRvQG+ReHMHW9DwZ8+aT-w2)qycV#IGjUiU|k_5Cv9 zaV)~?yo}cgunDr>0mys#0myM)19_jWgS@4@78l4ZeCIkO2-vq@*k2yY`-$bm6L>fV z_Kyqe;_^5i&KWN30qbM0ST7e|cU&Go1tAEeLs2+J*2!M5Z(P_9F{!JQT24-ig?2Q3 z6-l-;n|adGv@;jPg56bvAQn}O~o7Xx|Nj7->4Z4x7&lNFs@A|GH% zg9CPHu5>bTJK5jsgx-qexRKpEqoI^4;?bs$e;`Ve1KkkmyAb;z{` z(=I!Mfv(fTchV%a)8GNS)G-*kn58?zJu6RlW6VRNTJ2&2($l-t!V)x{`A#)2^D0#T zS!8twxmtCtH`msy2dgz?(NbAmSzS7?sy*o*rxH#5%AxBZD zR(m7XhI=>%9DG^DrBHkzSHm`?(IJ4+8Q0vaqN;XhwE T<6RSrzL%2kz_LKWnHa^NlkRi8 literal 0 HcmV?d00001 diff --git a/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/locale/pt/LC_MESSAGES/thinkpad-battery-threshold@marcosdalvarez.org.mo b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/locale/pt/LC_MESSAGES/thinkpad-battery-threshold@marcosdalvarez.org.mo new file mode 100644 index 0000000000000000000000000000000000000000..da9e2efb98682087896b5a1b55c95c8b7d8bf53e GIT binary patch literal 4816 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 literal 0 HcmV?d00001 diff --git a/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/locale/pt_BR/LC_MESSAGES/thinkpad-battery-threshold@marcosdalvarez.org.mo b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/locale/pt_BR/LC_MESSAGES/thinkpad-battery-threshold@marcosdalvarez.org.mo new file mode 100644 index 0000000000000000000000000000000000000000..fc4192c97bf329aeaae159bcc32e5bb0ba437b87 GIT binary patch literal 4803 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 literal 0 HcmV?d00001 diff --git a/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/locale/ru/LC_MESSAGES/thinkpad-battery-threshold@marcosdalvarez.org.mo b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/locale/ru/LC_MESSAGES/thinkpad-battery-threshold@marcosdalvarez.org.mo new file mode 100644 index 0000000000000000000000000000000000000000..b09ee32808a1f8e9b234ae07bd7d0645bb76d116 GIT binary patch literal 6240 zcmb`JTWlOx8OMi`7V4HuOSyzwPXVWP+FkEDO)s0c#<^7yO%r0L@KAxqyC?P}>zUQe ztX-2zMAg-ZOsGc(>b zS-VN;*k}K9&V1*)f8RM*ZeR1f#q$8;qm19b&9ZiaC*IBvPi>85y%U@TZv^MT4}d=f zZvy|AtX~1|X8u>OAG{Uf+rUAv3;Zl7^iP0yfJN|q;FAfS06)n5d!X=dfCcb(;Qe41 zn;!y)z>VM`@Ezc6f)_wYt)GFy_t(k%PvFhW{{r3u{vEs({CDzw4NUH2-UW)>^`PiI z1bzY>2Hy)#ChO0FA7cJ(Q0$xoKMcMGejF5My&Jd_ydBJfB6kSPgS)^S_+{`jU=5rE z{{wyz3{Y15^$OSxUI9M^u3=H+_JU&H7Vur*pL9zdr;5zVC@LuqBQ1n_4v8?X~WqlH?fG>gj z!8_h#Sn?`$8Hu$#H!w&I z>thV@!$yYq@qPv=w)Cv$ZLQ3@OMTrX)!l6kje6D48Y+g)q#bHi^va&EOUfyFZeR_S zr|fBI~iHrtnu-9Urx!NA&OJ1q@+whWErdacLwr1q`duCgUZw7fZP^1jFS z4(MX20w>hgULEK#{x$y5Plm8|(4pe%{o2=rF=+eVwmO(Bw=E?rzAkzb6WT3FIMVEh z1D*0(TE2Q=&>CjHTe3;pI9#MJX61YN5UQzh?ZQ>7oe-(ex2F}!TrHQBU8!i>$58c% z>rIg7e6xnfy(!}bN<+C`=&)y5#+*`yUK(UZJeK$D&g|8bj_k{9qum!&f3AN+CZEsb`&B+y z$mQ@^@co+RV>#M{)B=DN0$9+Y5aWV(WJAvxGrDYJQ#sSX@Fuy15X=D`-7 z*hp{6YF5d&*V1V`hivPXqMKvor!@hay zxU0=mLVPw22dmKD3Nr!7cHzC$l{Iq{ir%Eam88_<&UB4pmM6!m&gq!W zZ=J!{tx3m9TEX-glh1X@-S3hD&zKrLFKI^#5#i%R+En_CM4D8ZGrt#BaIv`?apfa& zaW*Ec;dyp1L=Cfxgq1D>Gb>tJzl31)ZvXZo3m2M4(`HpSUria#(ilj;IAtZ(mn|g8 z78e{9F2vCVu|n}$!zi+hx42D-o!7d5umdfv432F=I?!BBn}B%W9OYo7OB;=Q#W{+K z8g3q!0y!_~ls3!gLI-vo>$wA6ODthC&AWNbI76J@z?g5K0YpSbT7&eFh2{w(o~AR4 z7Ia5Zl`fOqd86+@ZemJUc%3Ik=V6^57E3+IwDdVb!S2J&r(s%;NSe#g%PYBHMK8%$ z@ds`&9iM)}gr3^K3$bfVki=~rj27pd>7azM1O=o~%ZatjqtZ{WgBKhwp`s+SxPv2U z1)0a%jlnGOD7n>1zfSUn_5~An5g4Dm?R{TPNIA60;Z_WdZRsJ(0f5ZtC(@(8DykAE z8t?xYFGo~*>eW!0K=8YoJPDB5Vt5-FDAAJ8(r5WmMWudgc^KvUtehWgNy<9CE|{Zt z$wH~kRx_y4l^QFifFz6QETp3;c|0JIYBW!psUmXHw=T!G3{ui0R`aA4{aCyt1xace z3%UA;_l~spgH^goG{0gYM;EX1JWD;eIz4XX=#~;P1xchjRA_HjML&Q-jG;JV_bi%% zS-?tjCQ-%LXvXTYmespd>UG){HLgwBnND|+>$%ero#ZAcfg*fwe9&GG`?d%rIeAWc z)Bh>PbUAZO93$r3GUH-jc5bZLmbe6wm*>%}Zn9L`0}5RvXC!rL+1$g)@jB<4bO3@U PiF{60rTNM^dCK}P#vUgX literal 0 HcmV?d00001 diff --git a/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/metadata.json b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/metadata.json new file mode 100644 index 0000000..3f2d6bf --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/metadata.json @@ -0,0 +1,14 @@ +{ + "_generated": "Generated by SweetTooth, do not edit", + "description": "Enable/Disable battery threshold on Lenovo Thinkpad laptops.\n\nIf you mainly use the system with the AC power adapter connected and only use the battery sporadically, you can increase battery life by setting the maximum charge value to less than 100%. This is useful because batteries that are used sporadically have a longer lifespan when kept at less than full charge.", + "gettext-domain": "thinkpad-battery-threshold@marcosdalvarez.org", + "name": "Thinkpad Battery Threshold", + "settings-schema": "org.gnome.shell.extensions.thinkpad-battery-threshold", + "shell-version": [ + "45", + "46" + ], + "url": "https://gitlab.com/marcosdalvarez/thinkpad-battery-threshold-extension", + "uuid": "thinkpad-battery-threshold@marcosdalvarez.org", + "version": 44 +} \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/preferences/about.js b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/preferences/about.js new file mode 100644 index 0000000..d547b1a --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/preferences/about.js @@ -0,0 +1,55 @@ +'use strict' + +import GLib from 'gi://GLib'; +import Adw from 'gi://Adw'; +import GObject from 'gi://GObject'; +import Gio from 'gi://Gio'; +import Gtk from 'gi://Gtk'; +import Gdk from 'gi://Gdk'; + +export const About = GObject.registerClass({ + GTypeName: 'AboutPrefs', + Template: GLib.Uri.resolve_relative(import.meta.url, '../ui/about.ui',GLib.UriFlags.NONE), + InternalChildren: [ + 'app_icon_image', + 'app_name_label', + 'version_label', + ] +}, class About extends Adw.PreferencesPage { + constructor(window) { + super({}); + + this._app_icon_image.gicon = Gio.icon_new_for_string(`${GLib.Uri.resolve_relative(import.meta.url, '../icons/threshold-active.svg',GLib.UriFlags.NONE)}`); + this._app_name_label.label = window._metadata.name; + this._version_label.label = window._metadata.version.toString(); + + // setup menu actions + const actionGroup = new Gio.SimpleActionGroup(); + window.insert_action_group('prefs', actionGroup); + + // a list of actions with their associated link + const actions = [ + { + name: 'open-bug-report', + link: 'https://gitlab.com/marcosdalvarez/thinkpad-battery-threshold-extension/-/issues' + }, + { + name: 'open-readme', + link: 'https://gitlab.com/marcosdalvarez/thinkpad-battery-threshold-extension/' + }, + { + name: 'open-license', + link: 'https://gitlab.com/marcosdalvarez/thinkpad-battery-threshold-extension/-/blob/main/LICENSE' + }, + ]; + + actions.forEach(action => { + let act = new Gio.SimpleAction({ name: action.name }); + act.connect( + 'activate', + _ => Gtk.show_uri(window, action.link, Gdk.CURRENT_TIME) + ); + actionGroup.add_action(act); + }); + } +}); \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/preferences/general.js b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/preferences/general.js new file mode 100644 index 0000000..59eb0f9 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/preferences/general.js @@ -0,0 +1,75 @@ +'use strict' + +import GLib from 'gi://GLib'; +import Adw from 'gi://Adw'; +import GObject from 'gi://GObject'; +import Gio from 'gi://Gio'; + +import * as Utils from './utils.js'; + +export const General = GObject.registerClass({ + GTypeName: 'GeneralPrefs', + Template: GLib.Uri.resolve_relative(import.meta.url, '../ui/general.ui',GLib.UriFlags.NONE), + InternalChildren: [ + 'indicator_mode', + 'color_mode', + 'show_values', + 'show_notifications', + 'reset_all', + 'reset_dialog', + ], +}, class General extends Adw.PreferencesPage { + constructor(window) { + super({}); + + Utils.bindAdwComboRow(this._indicator_mode, window._settings, 'indicator-mode'); + window._settings.bind( + 'color-mode', + this._color_mode, + 'active', + Gio.SettingsBindFlags.DEFAULT + ); + window._settings.bind( + 'show-current-values', + this._show_values, + 'active', + Gio.SettingsBindFlags.DEFAULT + ); + window._settings.bind( + 'show-notifications', + this._show_notifications, + 'active', + Gio.SettingsBindFlags.DEFAULT + ); + + this._reset_dialog.connect('response', (obj, response, data) => { + if (response === 'reset') { + this._resetSettings(window._settings); + window._driver.enableAll(); + } + }); + + this._reset_all.connect('clicked', () => { + this._reset_dialog.transientFor = this.root; + this._reset_dialog.present(); + }); + } + + /** + * Reset all (recursively) settings values to default + * + * @param {Gio.Settings} settings Settings to reset + */ + _resetSettings(settings) { + const keys = settings.settings_schema.list_keys(); + keys.forEach(key => { + settings.reset(key); + }); + + const childrens = settings.settings_schema.list_children(); + childrens.forEach(children => { + const childrenSettings = settings.get_child(children); + this._resetSettings(childrenSettings); + }); + } +}); \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/preferences/thinkpad.js b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/preferences/thinkpad.js new file mode 100644 index 0000000..133ad85 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/preferences/thinkpad.js @@ -0,0 +1,119 @@ +'use strict' + +import GLib from 'gi://GLib'; +import Adw from 'gi://Adw'; +import GObject from 'gi://GObject'; +import Gio from 'gi://Gio'; + +export const Thinkpad = GObject.registerClass({ + GTypeName: 'ThinkpadPrefs', + Template: GLib.Uri.resolve_relative(import.meta.url, '../ui/thinkpad.ui',GLib.UriFlags.NONE), + InternalChildren: [ + 'start_bat0', + 'end_bat0', + 'start_bat1', + 'end_bat1', + 'reset', + 'apply_bat0', + 'apply_bat1', + 'reset_thresholds_dialog' + ], +}, class Thinkpad extends Adw.PreferencesPage { + constructor(window) { + super({}); + + window._settings.bind( + 'start-bat0', + this._start_bat0, + 'value', + Gio.SettingsBindFlags.DEFAULT + ); + window._settings.bind( + 'end-bat0', + this._end_bat0, + 'value', + Gio.SettingsBindFlags.DEFAULT + ); + window._settings.bind( + 'start-bat1', + this._start_bat1, + 'value', + Gio.SettingsBindFlags.DEFAULT + ); + window._settings.bind( + 'end-bat1', + this._end_bat1, + 'value', + Gio.SettingsBindFlags.DEFAULT + ); + + window._settings.connect('changed::start-bat0', () => { + if (this._start_bat0.value >= this._end_bat0.value) { + this._end_bat0.value = this._start_bat0.value + 1; + } + }); + window._settings.connect('changed::end-bat0', () => { + if (this._start_bat0.value >= this._end_bat0.value) { + this._start_bat0.value = this._end_bat0.value - 1; + } + }); + window._settings.connect('changed::start-bat1', () => { + if (this._start_bat1.value >= this._end_bat1.value) { + this._end_bat1.value = this._start_bat1.value + 1; + } + }); + window._settings.connect('changed::end-bat1', () => { + if (this._start_bat1.value >= this._end_bat1.value) { + this._start_bat1.value = this._end_bat1.value - 1; + } + }); + + const bat0 = window._driver.batteries.find(battery => battery.name === 'BAT0'); + const bat1 = window._driver.batteries.find(battery => battery.name === 'BAT1'); + + this._apply_bat0.connect('clicked', () => { + bat0.enable(); + }); + this._apply_bat1.connect('clicked', () => { + bat1.enable(); + }); + + this._apply_bat0.visible = bat0.isAvailable; + bat0.connect('notify::is-available', () => { + this._apply_bat0.visible = bat0.isAvailable; + }); + this._apply_bat0.sensitive = bat0.pendingChanges; + bat0.connect('notify::pending-changes', () => { + this._apply_bat0.sensitive = bat0.pendingChanges; + }); + + this._apply_bat1.visible = bat1.isAvailable; + bat1.connect('notify::is-available', () => { + this._apply_bat1.visible = bat1.isAvailable; + }); + this._apply_bat1.sensitive = bat1.pendingChanges; + bat1.connect('notify::pending-changes', () => { + this._apply_bat1.sensitive = bat1.pendingChanges; + }); + + this._reset_thresholds_dialog.connect('response', (obj, response, data) => { + if (response === 'reset') { + const keys = [ + 'start-bat0', + 'end-bat0', + 'start-bat1', + 'end-bat1' + ]; + keys.forEach(key => { + window._settings.reset(key); + }); + window._driver.enableAll(); + } + }); + + this._reset.connect('clicked', () => { + this._reset_thresholds_dialog.transientFor = this.root; + this._reset_thresholds_dialog.present(); + }); + } +}); \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/preferences/utils.js b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/preferences/utils.js new file mode 100644 index 0000000..05988ca --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/preferences/utils.js @@ -0,0 +1,20 @@ +'use strict' + +/** + * Bind AdwComboRow item + * + * @param {Adw.comboRow} comboRow Adw combo row item + * @param {Gio.Settings} settings Settings object + * @param {string} key Key name + */ +export function bindAdwComboRow(comboRow, settings, key) { + comboRow.selected = settings.get_enum(key); + settings.connect( + `changed::${key}`, () => { + comboRow.selected = settings.get_enum(key); + } + ); + comboRow.connect('notify::selected', () => { + settings.set_enum(key, comboRow.selected); + }); +} \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/prefs.js b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/prefs.js new file mode 100644 index 0000000..565b71b --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/prefs.js @@ -0,0 +1,23 @@ +'use strict'; + +import { ExtensionPreferences } from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; + +import { General } from './preferences/general.js'; +import { Thinkpad } from './preferences/thinkpad.js'; +import { About } from './preferences/about.js'; + +import { ThinkPad } from './libs/driver.js'; + +export default class ThinkpadPreferences extends ExtensionPreferences { + fillPreferencesWindow(window) { + window._settings = this.getSettings(); + window._driver = new ThinkPad({'settings': window._settings}); + window._metadata = this.metadata; + + window.add(new General(window)); + window.add(new Thinkpad(window)); + window.add(new About(window)); + + window.search_enabled = true; + } +} \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/schemas/gschemas.compiled b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/schemas/gschemas.compiled new file mode 100644 index 0000000000000000000000000000000000000000..bb8abf8276eedccc0d9cc0974c705190a88e4583 GIT binary patch literal 792 zcmZ`%%}N_l82$PaOjGE>R>(%FbTe7ZOk7l48YHMxL>h_h@|xUchK_f_%#DAb&)`De zp-_Yt`T#ycmxV6c7ZBVC-A&KAnb2%{;mkR6=FI*1zPsL4S*(nea@4`^#@c&WdJpK; zel0kLek~hv0saD`GAB}C%sygxOJ0EMK$;DLfk_W^kViU60)1??$>Y@IfsJDGaj5$K zzOq(lC%%m`okwZX=M*AdZOrb;H92(!n3=*8XyzvCb1z(<{2gfi`T3O&byW`K2lzLz zyu7FAQ`g|%f$xE(GEdFC;P6#oecr!jo|^eO_$9DW`qcEB;1%HJ?EER~L0y5r3O)ro zpIj`b}3Pw=jRZ=K5#ed=fMZ@{cENcaP5!Wyt9Rp2qe8foL| z+T4K_FK+bGB+dMTw6AIKUvIxrhL-T|YK~lPRc6_dri;lN(zMU;WWW!G%0_q((df`M zI&_T=|1~=Nf1^W@934OMd!sDV#`=dU8R;DJx&66MCbjX0xTh>H&Df7kpT_ioT5G$T z-8Rl$?yZ;@xR$I_vAI2Q3f8V@ZSA$*cbG0%!(zMLZNHUbM!eiRQKLqKpG5uwb^xS% literal 0 HcmV?d00001 diff --git a/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/schemas/org.gnome.shell.extensions.battery-threshold.gschema.xml b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/schemas/org.gnome.shell.extensions.battery-threshold.gschema.xml new file mode 100644 index 0000000..e9c4b22 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/schemas/org.gnome.shell.extensions.battery-threshold.gschema.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + "ACTIVE" +

Set when the Icon tray should appear in Gnome tray +
+ + true + Show current threshold values in labels + + + true + Show notifications + + + true + Color mode + + + + + 75 + Start charging when the level is below this value + + + 80 + Stop charging when the level is above this value + + + 0 + Start charging when the level is below this value + + + 100 + Stop charging when the level is above this value + + + diff --git a/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/ui/about.ui b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/ui/about.ui new file mode 100644 index 0000000..b0c116e --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/ui/about.ui @@ -0,0 +1,101 @@ + + + + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/ui/general.ui b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/ui/general.ui new file mode 100644 index 0000000..d178f50 --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/ui/general.ui @@ -0,0 +1,84 @@ + + + + + + + On active + On inactive + Always + Never + + + + + Reset all preferences? + This action resets all extension settings to their recommended values (including thresholds), do you want to continue? + cancel + cancel + true + true + true + + Cancel + Reset + + + \ No newline at end of file diff --git a/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/ui/thinkpad.ui b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/ui/thinkpad.ui new file mode 100644 index 0000000..1f1a30a --- /dev/null +++ b/gnome/.local/share/gnome-shell/extensions/thinkpad-battery-threshold@marcosdalvarez.org/ui/thinkpad.ui @@ -0,0 +1,148 @@ + + + + + + Reset thresholds? + This action resets the batteries thresholds to the recommended values, do you want to continue? + cancel + cancel + true + true + true + + Cancel + Reset + + + + + 5.0 + 1.0 + 99.0 + 0.0 + 75.0 + + + 5.0 + 1.0 + 100.0 + 1.0 + 80.0 + + + 5.0 + 1.0 + 99.0 + 0.0 + 75.0 + + + 5.0 + 1.0 + 100.0 + 1.0 + 80.0 + + \ No newline at end of file